Skip to content

Commit

Permalink
fix: use alternative clipboard change monitor on macOS
Browse files Browse the repository at this point in the history
QClipboard cannot monitor data changes on mac unless an application is focused
  • Loading branch information
shenlebantongying committed Feb 18, 2023
1 parent 737d442 commit 452b6bd
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ if (APPLE)
texttospeechsource.cc
texttospeechsource.hh
texttospeechsource.ui
src/platform/gd_clipboard.cpp
src/platform/gd_clipboard.h
)
endif ()

Expand Down
6 changes: 4 additions & 2 deletions goldendict.pro
Original file line number Diff line number Diff line change
Expand Up @@ -559,9 +559,11 @@ win32 {
mac {
HEADERS += macmouseover.hh \
texttospeechsource.hh \
speechclient.hh
speechclient.hh \
src/platform/gd_clipboard.h
FORMS += texttospeechsource.ui
SOURCES += texttospeechsource.cc
SOURCES += texttospeechsource.cc \
src/platform/gd_clipboard.cpp
}

unix:!mac {
Expand Down
36 changes: 28 additions & 8 deletions mainwindow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
#include "mruqmenu.hh"
#include "gestures.hh"
#include "dictheadwords.hh"
#include <limits.h>
#include <QDebug>
#include <QTextStream>
#include <QDir>
#include <QUrl>
Expand All @@ -36,7 +34,6 @@
#include <QThreadPool>
#include <QSslConfiguration>

#include <limits.h>
#include <set>
#include <map>
#include "gddebug.hh"
Expand Down Expand Up @@ -859,7 +856,28 @@ MainWindow::MainWindow( Config::Class & cfg_ ):

inspector.reset( new ArticleInspector( this ));

connect( QApplication::clipboard(), &QClipboard::changed, this, &MainWindow::clipboardChange );
// Clipboard related
#ifdef Q_OS_MAC
macClipboard = new gd_clipboard();
connect(macClipboard, &gd_clipboard::changed, this, &MainWindow::clipboardChange );
connect(enableScanningAction,&QAction::changed,[this](){
if (enableScanningAction->isChecked()){
macClipboard->start();
} else {
macClipboard->stop();
}
});
#else
connect(enableScanningAction,&QAction::changed,[this](){
if (enableScanningAction->isChecked()){
connect( QApplication::clipboard(), &QClipboard::changed, this, &MainWindow::clipboardChange );
} else {
disconnect(QApplication::clipboard(), &QClipboard::changed, this, &MainWindow::clipboardChange);
}
});
#endif



#ifdef Q_OS_WIN
// Regiser and update URL Scheme for windows
Expand All @@ -879,9 +897,9 @@ MainWindow::MainWindow( Config::Class & cfg_ ):

void MainWindow::clipboardChange( QClipboard::Mode m)
{
if( scanPopup && enableScanningAction->isChecked() )
if( scanPopup )
{
#ifdef HAVE_X11
#if defined(HAVE_X11)
if(m == QClipboard::Clipboard){
if(!cfg.preferences.trackClipboardScan) return;
scanPopup->translateWordFromClipboard();
Expand Down Expand Up @@ -918,10 +936,12 @@ void MainWindow::clipboardChange( QClipboard::Mode m)
// Use delay show to prevent multiple popups while selection in progress
scanPopup->selectionDelayTimer.start();
}
#elif defined(Q_OS_MAC)
scanPopup->translateWord(macClipboard->text());
#else
scanPopup ->translateWordFromClipboard();
scanPopup->translateWordFromClipboard();
#endif
}
}
}

void MainWindow::ctrlTabPressed()
Expand Down
8 changes: 8 additions & 0 deletions mainwindow.hh
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
#include <fixx11h.h>
#endif

#if defined(Q_OS_MAC)
#include "platform/gd_clipboard.h"
#endif

using std::string;
using std::vector;

Expand Down Expand Up @@ -182,6 +186,10 @@ private:
IframeSchemeHandler * iframeSchemeHandler;
ResourceSchemeHandler * resourceSchemeHandler;

#ifdef Q_OS_MAC
gd_clipboard * macClipboard;
#endif

/// Applies the custom Qt stylesheet
void applyQtStyleSheet( QString const & addonStyle, QString const & displayStyle ,bool const & darkMode );

Expand Down
35 changes: 35 additions & 0 deletions src/platform/gd_clipboard.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "gd_clipboard.h"

gd_clipboard::gd_clipboard(QObject *parent)
: QObject{parent},
sysClipboard(QGuiApplication::clipboard()) {

connect(&m_monitoringTimer, &QTimer::timeout, this, [this]() {
updateClipboard();
});
}

QString gd_clipboard::text() const {
return m_currentContent;
}

void gd_clipboard::updateClipboard() {
const QString newContent = this->sysClipboard->text().trimmed();

// get rid of change if new clipboard content is equal to previous version
if (newContent == m_currentContent ||
newContent.length() == 0) { // avoid spaces
return;
}

m_currentContent = newContent;
emit changed(QClipboard::Clipboard);
}

void gd_clipboard::stop() {
m_monitoringTimer.stop();
}

void gd_clipboard::start() {
m_monitoringTimer.start(1000); // 1s
}
39 changes: 39 additions & 0 deletions src/platform/gd_clipboard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include <QClipboard>
#include <QGuiApplication>
#include <QObject>
#include <QString>
#include <QTimer>

/**
A custom clipboard monitor that read keep reading clipboard in background.
QClipboard on macOS only triggers when the app is focused.
Code was inspired by
https://github.com/KDE/kdeconnect-kde/blob/v22.12.2/plugins/clipboard/clipboardlistener.cpp
*/

class gd_clipboard : public QObject {
Q_OBJECT
public:
explicit gd_clipboard(QObject * parent = nullptr);

[[nodiscard]] QString text() const;

void stop();

void start();

private:

QClipboard * sysClipboard;
QString curClipboardContent;

QTimer m_monitoringTimer;
QString m_currentContent;
void updateClipboard();

signals:
void changed(QClipboard::Mode mode);
};

0 comments on commit 452b6bd

Please sign in to comment.