plyght's own C++ browser for macOS
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

up

plyght c5ecd31d d25aed3e

+57 -22
+49 -18
src/app/BrowserWindow.cpp
··· 435 435 const int next = qBound(0, current + direction, list.size() - 1); 436 436 if (next == current || next < 0 || next >= list.size()) return; 437 437 const QString profile = list.at(next); 438 + if (m_sidebarPreviewProfile == profile) return; 439 + m_sidebarPreviewProfile = profile; 438 440 m_sidebarPreviewIcon->setIcon(mac::sfSymbolIcon(m_profiles.iconName(profile), 18.0, m_theme.foreground)); 441 + m_sidebarPreviewTabs->setUpdatesEnabled(false); 439 442 m_sidebarPreviewTabs->clear(); 440 443 const QStringList titles = m_profileTabSnapshots.value(profile, QStringList{QStringLiteral("New tab")}); 441 444 for (const QString &title : titles) { ··· 443 446 item->setIcon(0, mac::sfSymbolIcon("globe", 12.0, m_theme.muted)); 444 447 m_sidebarPreviewTabs->addTopLevelItem(item); 445 448 } 449 + m_sidebarPreviewTabs->setUpdatesEnabled(true); 446 450 } 447 451 448 452 void BrowserWindow::setSidebarSwipeOffset(int offset) { 449 453 if (!m_sidebarPage || !m_sidebarViewport) return; 450 454 const int width = qMax(1, m_sidebarViewport->width()); 451 455 const QRect bounds(QPoint(0, 0), m_sidebarViewport->size()); 452 - if (m_sidebarStrip) m_sidebarStrip->setGeometry(bounds); 453 456 m_sidebarViewport->setMask(QRegion(bounds)); 454 457 m_sidebarSwipeOffset = qBound(-width, offset, width); 455 - m_sidebarPage->setGeometry(bounds.translated(m_sidebarSwipeOffset, 0)); 456 - if (m_sidebarPreviewPage) { 457 - if (m_sidebarSwipeOffset == 0) { 458 - m_sidebarPreviewPage->hide(); 459 - } else { 460 - const int direction = m_sidebarSwipeOffset < 0 ? 1 : -1; 461 - updateSidebarPreview(direction); 462 - m_sidebarPreviewPage->setGeometry(bounds.translated(direction > 0 ? width + m_sidebarSwipeOffset : -width + m_sidebarSwipeOffset, 0)); 463 - m_sidebarPreviewPage->show(); 464 - } 458 + if (!m_sidebarStrip) return; 459 + if (m_sidebarSwipeOffset == 0) { 460 + m_sidebarStrip->setGeometry(bounds); 461 + m_sidebarPage->setGeometry(bounds); 462 + if (m_sidebarPreviewPage) m_sidebarPreviewPage->hide(); 463 + return; 464 + } 465 + const int direction = m_sidebarSwipeDirection != 0 ? m_sidebarSwipeDirection : (m_sidebarSwipeOffset < 0 ? 1 : -1); 466 + updateSidebarPreview(direction); 467 + m_sidebarStrip->setGeometry(direction > 0 ? m_sidebarSwipeOffset : m_sidebarSwipeOffset - width, 468 + 0, width * 2, bounds.height()); 469 + if (direction > 0) { 470 + m_sidebarPage->setGeometry(0, 0, width, bounds.height()); 471 + if (m_sidebarPreviewPage) m_sidebarPreviewPage->setGeometry(width, 0, width, bounds.height()); 472 + } else { 473 + if (m_sidebarPreviewPage) m_sidebarPreviewPage->setGeometry(0, 0, width, bounds.height()); 474 + m_sidebarPage->setGeometry(width, 0, width, bounds.height()); 465 475 } 476 + if (m_sidebarPreviewPage) m_sidebarPreviewPage->show(); 466 477 } 467 478 468 479 void BrowserWindow::settleSidebarSwipe(bool commit) { ··· 474 485 m_sidebarSwipeAnim = nullptr; 475 486 } 476 487 const int width = m_sidebarWidget ? qMax(160, m_sidebarWidget->width()) : 240; 477 - const int direction = m_sidebarSwipeOffset < 0 ? 1 : -1; 478 488 const int startOffset = m_sidebarSwipeOffset; 489 + const int direction = startOffset < 0 ? 1 : -1; 479 490 const QStringList list = orderedProfiles(); 480 491 const int current = qMax(0, list.indexOf(m_profiles.currentName())); 481 492 const int next = qBound(0, current + direction, list.size() - 1); ··· 484 495 m_sidebarSwipeAnim = driver; 485 496 driver->setStartValue(startOffset); 486 497 driver->setEndValue(commit ? (direction > 0 ? -width : width) : 0); 487 - driver->setDuration(commit ? 190 : 150); 498 + driver->setDuration(commit ? 160 : 120); 488 499 driver->setEasingCurve(QEasingCurve::OutCubic); 489 500 m_sidebarSwipeSettling = true; 490 501 connect(driver, &QVariantAnimation::valueChanged, this, [this](const QVariant &value) { ··· 499 510 m_sidebarSwipeActive = false; 500 511 m_sidebarSwipeSettling = false; 501 512 m_profileSwipeRemainder = 0; 513 + m_sidebarSwipeDirection = 0; 514 + m_sidebarPreviewProfile.clear(); 502 515 m_sidebarSwipeAnim = nullptr; 503 516 driver->deleteLater(); 504 517 }); ··· 744 757 m_sidebar->setSidebarContent(m_sidebarViewport, sideLayout); 745 758 m_sidebarSwipeSettleTimer = new QTimer(this); 746 759 m_sidebarSwipeSettleTimer->setSingleShot(true); 747 - m_sidebarSwipeSettleTimer->setInterval(420); 760 + m_sidebarSwipeSettleTimer->setInterval(180); 748 761 connect(m_sidebarSwipeSettleTimer, &QTimer::timeout, this, [this] { 749 762 if (!m_sidebarSwipeActive) return; 750 763 settleSidebarSwipe(qAbs(m_profileSwipeRemainder) >= qMax(160, m_sidebarWidget ? m_sidebarWidget->width() : 240) / 3); ··· 1144 1157 auto *wheel = static_cast<QWheelEvent *>(ev); 1145 1158 const QPoint pixel = wheel->pixelDelta(); 1146 1159 const QPoint angle = wheel->angleDelta(); 1160 + const bool highResolutionTrackpad = !pixel.isNull(); 1161 + if (wheel->phase() == Qt::ScrollBegin && !m_sidebarSwipeSettling) { 1162 + if (m_sidebarSwipeSettleTimer) m_sidebarSwipeSettleTimer->stop(); 1163 + m_profileSwipeRemainder = m_sidebarSwipeOffset; 1164 + } 1165 + if (wheel->phase() == Qt::ScrollEnd && m_sidebarSwipeActive) { 1166 + settleSidebarSwipe(qAbs(m_sidebarSwipeOffset) >= qMax(160, m_sidebarWidget->width()) / 4); 1167 + return true; 1168 + } 1147 1169 const int horizontal = pixel.x() != 0 ? pixel.x() : angle.x() / 2; 1148 1170 const int vertical = pixel.y() != 0 ? pixel.y() : angle.y() / 2; 1149 1171 if (qAbs(horizontal) > qAbs(vertical) && horizontal != 0) { 1150 - if (m_sidebarSwipeSettleTimer) m_sidebarSwipeSettleTimer->stop(); 1151 1172 const int width = qMax(160, m_sidebarWidget->width()); 1173 + if (m_sidebarSwipeSettleTimer) m_sidebarSwipeSettleTimer->stop(); 1152 1174 const int intended = m_profileSwipeRemainder + horizontal; 1153 - const int intendedDirection = intended < 0 ? 1 : -1; 1175 + if (m_sidebarSwipeDirection != 0 && ((m_sidebarSwipeDirection > 0 && intended > 0) || (m_sidebarSwipeDirection < 0 && intended < 0))) { 1176 + m_profileSwipeRemainder = 0; 1177 + setSidebarSwipeOffset(0); 1178 + m_sidebarSwipeActive = true; 1179 + return true; 1180 + } 1181 + const int intendedDirection = m_sidebarSwipeDirection != 0 ? m_sidebarSwipeDirection : (intended < 0 ? 1 : -1); 1154 1182 const QStringList list = orderedProfiles(); 1155 1183 const int profileIndex = qMax(0, list.indexOf(m_profiles.currentName())); 1156 1184 const int targetIndex = profileIndex + intendedDirection; 1157 1185 if (targetIndex < 0 || targetIndex >= list.size()) { 1158 1186 m_profileSwipeRemainder = 0; 1187 + m_sidebarSwipeDirection = 0; 1159 1188 setSidebarSwipeOffset(0); 1160 1189 m_sidebarSwipeActive = false; 1190 + m_sidebarPreviewProfile.clear(); 1161 1191 return true; 1162 1192 } 1193 + m_sidebarSwipeDirection = intendedDirection; 1163 1194 m_profileSwipeRemainder = qBound(-width, intended, width); 1164 1195 const int sign = m_profileSwipeRemainder < 0 ? -1 : 1; 1165 1196 const int magnitude = qAbs(m_profileSwipeRemainder); ··· 1172 1203 settleSidebarSwipe(true); 1173 1204 } else if (wheel->phase() == Qt::ScrollEnd) { 1174 1205 settleSidebarSwipe(magnitude >= width / 4); 1175 - } else if (wheel->phase() == Qt::NoScrollPhase && m_sidebarSwipeSettleTimer) { 1176 - m_sidebarSwipeSettleTimer->start(qAbs(horizontal) >= 18 ? 520 : 420); 1206 + } else if (!highResolutionTrackpad && m_sidebarSwipeSettleTimer) { 1207 + m_sidebarSwipeSettleTimer->start(180); 1177 1208 } 1178 1209 return true; 1179 1210 }
+2
src/app/BrowserWindow.hpp
··· 102 102 QTimer *m_sidebarSwipeSettleTimer = nullptr; 103 103 int m_profileSwipeRemainder = 0; 104 104 int m_sidebarSwipeOffset = 0; 105 + int m_sidebarSwipeDirection = 0; 105 106 bool m_sidebarSwipeActive = false; 106 107 bool m_sidebarSwipeSettling = false; 108 + QString m_sidebarPreviewProfile; 107 109 QHash<QString, QStringList> m_profileTabSnapshots; 108 110 QHash<QString, QToolButton *> m_extensionActionButtons; 109 111 QLineEdit *m_addressBar = nullptr;
+6 -4
src/web/WebView.mm
··· 7 7 #import <WebKit/WKWebView.h> 8 8 #import <WebKit/WKWebViewConfiguration.h> 9 9 10 + #include <QPointer> 10 11 #include <QRegularExpression> 11 12 #import <WebKit/WKWebsiteDataStore.h> 12 13 #import <WebKit/WKNavigationDelegate.h> ··· 242 243 } 243 244 244 245 WebView::~WebView() { 246 + if (m_impl->bridge) m_impl->bridge.owner = nullptr; 245 247 if (m_impl->observedHost) { 246 248 [[NSNotificationCenter defaultCenter] removeObserver:m_impl->bridge 247 249 name:NSViewFrameDidChangeNotification ··· 391 393 @" } catch(e) {}" 392 394 @" return '';" 393 395 @"})()"; 394 - Impl *impl = m_impl; 395 - WebView *self = this; 396 + QPointer<WebView> guard(this); 396 397 [m_impl->wk evaluateJavaScript:kSniff completionHandler:^(id result, NSError *error) { 397 398 (void)error; 398 - if (!self || !impl) return; 399 + WebView *self = guard.data(); 400 + if (!self || !self->m_impl || !self->m_impl->wk) return; 399 401 NSString *s = [result isKindOfClass:[NSString class]] ? (NSString *)result : nil; 400 402 QColor color; 401 403 if (s && s.length > 0) { ··· 411 413 } 412 414 } 413 415 } 414 - impl->cachedTopColor = color; 416 + self->m_impl->cachedTopColor = color; 415 417 emit self->themeColorChanged(color); 416 418 }]; 417 419 }