From e88305d984d2c2eafef37b0e4043471c9d2998d5 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 5 Mar 2017 23:18:27 +0300 Subject: [PATCH] Fixed freezes in macOS clipboard requests. Sometimes QClipboard::text() unexpectedly freezes on macOS, no known causes for that. But before we were requesting the clipboard text after each change in any text field to update macOS global menu items. Now we use Cocoa API directly to find out if there were any changes to the clipboard content and query text through Qt only if we have changes. That way it should almost never freeze (at least) or even really never. --- .../platform/mac/main_window_mac.mm | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.mm b/Telegram/SourceFiles/platform/mac/main_window_mac.mm index 37fa98cdb0..f9379c5396 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.mm +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.mm @@ -67,6 +67,8 @@ public: void initCustomTitle(NSWindow *window, NSView *view); + bool clipboardHasText(); + ~Private(); private: @@ -74,6 +76,9 @@ private: friend class MainWindow; MainWindowObserver *_observer; + NSPasteboard *_generalPasteboard = nullptr; + int _generalPasteboardChangeCount = -1; + bool _generalPasteboardHasText = false; }; @@ -127,6 +132,8 @@ namespace Platform { MainWindow::Private::Private(MainWindow *window) : _public(window) , _observer([[MainWindowObserver alloc] init:this]) { + _generalPasteboard = [NSPasteboard generalPasteboard]; + @autoreleasepool { [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:_observer selector:@selector(activeSpaceDidChange:) name:NSWorkspaceActiveSpaceDidChangeNotification object:nil]; @@ -167,6 +174,15 @@ void MainWindow::Private::initCustomTitle(NSWindow *window, NSView *view) { #endif // !OS_MAC_OLD } +bool MainWindow::Private::clipboardHasText() { + auto currentChangeCount = static_cast([_generalPasteboard changeCount]); + if (_generalPasteboardChangeCount != currentChangeCount) { + _generalPasteboardChangeCount = currentChangeCount; + _generalPasteboardHasText = !Application::clipboard()->text().isEmpty(); + } + return _generalPasteboardHasText; +} + void MainWindow::Private::willEnterFullScreen() { _public->setTitleVisible(false); } @@ -503,18 +519,19 @@ void MainWindow::updateGlobalMenuHook() { auto focused = QApplication::focusWidget(); bool isLogged = !!App::self(), canUndo = false, canRedo = false, canCut = false, canCopy = false, canPaste = false, canDelete = false, canSelectAll = false; + auto clipboardHasText = _private->clipboardHasText(); if (auto edit = qobject_cast(focused)) { canCut = canCopy = canDelete = edit->hasSelectedText(); canSelectAll = !edit->text().isEmpty(); canUndo = edit->isUndoAvailable(); canRedo = edit->isRedoAvailable(); - canPaste = !Application::clipboard()->text().isEmpty(); + canPaste = clipboardHasText; } else if (auto edit = qobject_cast(focused)) { canCut = canCopy = canDelete = edit->textCursor().hasSelection(); canSelectAll = !edit->document()->isEmpty(); canUndo = edit->document()->isUndoAvailable(); canRedo = edit->document()->isRedoAvailable(); - canPaste = !Application::clipboard()->text().isEmpty(); + canPaste = clipboardHasText; } else if (auto list = qobject_cast(focused)) { canCopy = list->canCopySelected(); canDelete = list->canDeleteSelected();