From e5b7862511036a456361edf4f0e61ea4c748fa8d Mon Sep 17 00:00:00 2001 From: zeqi Date: Thu, 1 Oct 2026 16:31:32 +0000 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9C=A8=20x11=20=E4=B8=8B?= =?UTF-8?q?=E5=8F=96=E8=89=B2=E5=99=A8=E6=95=88=E6=9E=9C=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zeqi --- src/colormenu.cpp | 7 +- src/main.cpp | 30 +++++--- src/picker.cpp | 184 ++++++++++++++++++++++++++++++++-------------- 3 files changed, 154 insertions(+), 67 deletions(-) diff --git a/src/colormenu.cpp b/src/colormenu.cpp index a3204b9..8a0805e 100644 --- a/src/colormenu.cpp +++ b/src/colormenu.cpp @@ -63,7 +63,12 @@ ColorMenu::ColorMenu(int x, int y, int size, QColor color, QWidget *parent) : QW this->setGraphicsEffect(effect); // Build menu and menu actions. - colorMenu = new QMenu(this); + if (isWayland) { + colorMenu = new QMenu(this); + }else{ + colorMenu = new QMenu(); + } + connect(colorMenu, &QMenu::aboutToHide, this, [&]() { QTimer::singleShot(200, this, [&]() { if (!clickMenuItem) { diff --git a/src/main.cpp b/src/main.cpp index ad23884..5c2503b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -97,6 +97,12 @@ int main(int argc, char *argv[]) Clipboard clipboard; QPointer picker = new Picker(isLaunchByDBus); + if (!isWayland) { + if (!isLaunchByDBus) { + picker->StartPick(""); + } + } + EventMonitor eventMonitor; QObject::connect(qApp, &DApplication::destroyed, [&] { if (eventMonitor.isRunning()) eventMonitor.terminate(); }); @@ -148,15 +154,19 @@ int main(int argc, char *argv[]) } } - if (!isLaunchByDBus) { - QTimer::singleShot(0, picker.data(), [picker] { - if (picker) { - picker->StartPick(""); - } - }); - } + if (isWayland) { + if (!isLaunchByDBus) { + QTimer::singleShot(0, picker.data(), [picker] { + if (picker) { + picker->StartPick(""); + } + }); + } - const int result = app.exec(); - delete picker.data(); - return result; + const int result = app.exec(); + delete picker.data(); + return result; + }else{ + return app.exec(); + } } diff --git a/src/picker.cpp b/src/picker.cpp index ecc5ae1..e9cb8ed 100644 --- a/src/picker.cpp +++ b/src/picker.cpp @@ -75,20 +75,33 @@ Picker::Picker(bool launchByDBus) updateScreenshotTimer->setSingleShot(true); connect(updateScreenshotTimer, SIGNAL(timeout()), this, SLOT(updateScreenshot())); - QScreen *screen = QApplication::primaryScreen(); - if (screen) { - resize(screen->geometry().size()); - move(screen->geometry().topLeft()); - cursorX = screen->geometry().center().x(); - cursorY = screen->geometry().center().y(); + if (isWayland) { + QScreen *screen = QApplication::primaryScreen(); + if (screen) { + resize(screen->geometry().size()); + move(screen->geometry().topLeft()); + cursorX = screen->geometry().center().x(); + cursorY = screen->geometry().center().y(); + } + }else{ + screenPixmap = QApplication::primaryScreen()->grabWindow(0); + resize(screenPixmap.size()); + move(0, 0); } + } Picker::~Picker() { - restoreSystemCursor(); - delete animation; - delete menu; + if (isWayland) { + restoreSystemCursor(); + delete animation; + delete menu; + }else{ + animation->deleteLater(); + menu->deleteLater(); + updateScreenshotTimer->deleteLater(); + } } void Picker::paintEvent(QPaintEvent *) @@ -108,8 +121,10 @@ void Picker::paintEvent(QPaintEvent *) void Picker::handleMouseMove(int x, int y) { - cursorX = x; - cursorY = y; + if (isWayland) { + cursorX = x; + cursorY = y; + } if (updateScreenshotTimer->isActive()) { updateScreenshotTimer->stop(); @@ -121,39 +136,62 @@ void Picker::updateScreenshot() { if (!displayCursorDot && isVisible()) { QScreen *screen = QApplication::primaryScreen(); - if (!screen || screenPixmap.isNull()) { - return; + if (isWayland) { + if (!screen || screenPixmap.isNull()) { + return; + } + }else{ + cursorX = QCursor::pos().x(); + cursorY = QCursor::pos().y(); } // Need add offset to make drop shadow's position correctly. int offsetX = (windowWidth - width) / 2; int offsetY = (windowHeight - height) / 2; - // Get image under cursor. - const qreal devicePixelRatio = screen->devicePixelRatio(); - const QRect screenGeometry = screen->geometry(); - const qreal scaleX = qreal(screenPixmap.width()) / screenGeometry.width(); - const qreal scaleY = qreal(screenPixmap.height()) / screenGeometry.height(); - const int pixelX = qRound((cursorX - screenGeometry.left()) * scaleX); - const int pixelY = qRound((cursorY - screenGeometry.top()) * scaleY); + QPixmap cursorPixmap; + + if (isWayland) { + // Get image under cursor. + const qreal devicePixelRatio = screen->devicePixelRatio(); + const QRect screenGeometry = screen->geometry(); + const qreal scaleX = qreal(screenPixmap.width()) / screenGeometry.width(); + const qreal scaleY = qreal(screenPixmap.height()) / screenGeometry.height(); + const int pixelX = qRound((cursorX - screenGeometry.left()) * scaleX); + const int pixelY = qRound((cursorY - screenGeometry.top()) * scaleY); - const int sourceWidth = screenshotSize; - const int sourceHeight = screenshotSize; - const QRect source(pixelX - sourceWidth / 2, pixelY - sourceHeight / 2, + const int sourceWidth = screenshotSize; + const int sourceHeight = screenshotSize; + const QRect source(pixelX - sourceWidth / 2, pixelY - sourceHeight / 2, sourceWidth, sourceHeight); - screenshotPixmap = QPixmap::fromImage(screenPixmap.toImage().copy(source)); - screenshotPixmap = screenshotPixmap.scaled(qRound(width * devicePixelRatio), + screenshotPixmap = QPixmap::fromImage(screenPixmap.toImage().copy(source)); + screenshotPixmap = screenshotPixmap.scaled(qRound(width * devicePixelRatio), qRound(height * devicePixelRatio), Qt::KeepAspectRatio, Qt::FastTransformation); - screenshotPixmap.setDevicePixelRatio(devicePixelRatio); - - QPixmap cursorPixmap = shadowPixmap.scaled( - qRound(windowWidth * devicePixelRatio), - qRound(windowHeight * devicePixelRatio), - Qt::IgnoreAspectRatio, - Qt::SmoothTransformation); - cursorPixmap.setDevicePixelRatio(devicePixelRatio); + screenshotPixmap.setDevicePixelRatio(devicePixelRatio); + + cursorPixmap = shadowPixmap.scaled( + qRound(windowWidth * devicePixelRatio), + qRound(windowHeight * devicePixelRatio), + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation); + cursorPixmap.setDevicePixelRatio(devicePixelRatio); + }else{ + qreal devicePixelRatio = qApp->devicePixelRatio(); + int size = screenshotSize / devicePixelRatio; + screenshotPixmap = QApplication::primaryScreen()->grabWindow( + 0, + cursorX - size / 2, + cursorY - size / 2, + size, + size).scaled(width * devicePixelRatio, height * devicePixelRatio); + + // Clip screenshot pixmap to circle. + // NOTE: need copy pixmap here, otherwise we will got bad circle. + cursorPixmap = shadowPixmap; + } + QPainter painter(&cursorPixmap); painter.setRenderHint(QPainter::Antialiasing, true); @@ -161,7 +199,11 @@ void Picker::updateScreenshot() QPainterPath circlePath; circlePath.addEllipse(2 + offsetX, 2 + offsetY, width - 4, height - 4); painter.setClipPath(circlePath); - painter.setRenderHint(QPainter::SmoothPixmapTransform, false); + + if (isWayland) { + painter.setRenderHint(QPainter::SmoothPixmapTransform, false); + } + painter.drawPixmap(1 + offsetX, 1 + offsetY, screenshotPixmap); painter.restore(); @@ -197,7 +239,7 @@ void Picker::updateScreenshot() } else { // A widget-local cursor avoids leaking one application override // cursor per motion event. - setCursor(QCursor(cursorPixmap)); + QApplication::setOverrideCursor(QCursor(cursorPixmap)); } } } @@ -208,8 +250,13 @@ void Picker::handleLeftButtonPress(int x, int y) // Rest cursor and hide window. // NOTE: Don't call hide() at here, let process die, // Otherwise mouse event will pass to application window under picker. - restoreSystemCursor(); - unsetCursor(); + + if (!isWayland) { + QApplication::setOverrideCursor(Qt::ArrowCursor); + }else{ + restoreSystemCursor(); + unsetCursor(); + } // Rest color type to hex if config file not exist. Settings settings; @@ -234,12 +281,23 @@ void Picker::handleRightButtonRelease(int x, int y) cursorColor = getColorAtCursor(x, y); // Popup color menu window. - menu = new ColorMenu( - x - blockWidth / 2, - y - blockHeight / 2, - blockWidth, - cursorColor, - this); + qreal devicePixelRatio = qApp->devicePixelRatio(); + + if (isWayland) { + menu = new ColorMenu( + x - blockWidth / 2, + y - blockHeight / 2, + blockWidth, + cursorColor, + this); + }else{ + menu = new ColorMenu( + x / devicePixelRatio - blockWidth / 2, + y / devicePixelRatio - blockHeight / 2, + blockWidth, + cursorColor); + } + connect(menu, &ColorMenu::copyColor, this, &Picker::copyColor, Qt::QueuedConnection); connect(menu, &ColorMenu::exit, this, &Picker::exit, Qt::QueuedConnection); menu->show(); @@ -256,12 +314,21 @@ void Picker::handleRightButtonRelease(int x, int y) } // Display animation before poup color menu. - animation = new Animation(x, y, screenshotPixmap, cursorColor); + if (isWayland) { + animation = new Animation(x, y, screenshotPixmap, cursorColor); + }else{ + animation = new Animation(x / devicePixelRatio, y / devicePixelRatio, screenshotPixmap, cursorColor); + } + connect(animation, &Animation::finish, this, &Picker::popupColorMenu, Qt::QueuedConnection); // Rest cursor to default cursor. - restoreSystemCursor(); - unsetCursor(); + if (isWayland) { + restoreSystemCursor(); + unsetCursor(); + }else{ + QApplication::setOverrideCursor(Qt::ArrowCursor); + } // Show animation after rest cursor to avoid flash screen. animation->show(); @@ -270,19 +337,24 @@ void Picker::handleRightButtonRelease(int x, int y) QColor Picker::getColorAtCursor(int x, int y) { - QScreen *screen = QApplication::primaryScreen(); - if (!screen || screenPixmap.isNull()) { - return QColor(); - } + if (isWayland) { + QScreen *screen = QApplication::primaryScreen(); + if (!screen || screenPixmap.isNull()) { + return QColor(); + } - const QRect geometry = screen->geometry(); - const qreal scaleX = qreal(screenPixmap.width()) / geometry.width(); - const qreal scaleY = qreal(screenPixmap.height()) / geometry.height(); - const int pixelX = qBound(0, qRound((x - geometry.left()) * scaleX), + const QRect geometry = screen->geometry(); + const qreal scaleX = qreal(screenPixmap.width()) / geometry.width(); + const qreal scaleY = qreal(screenPixmap.height()) / geometry.height(); + const int pixelX = qBound(0, qRound((x - geometry.left()) * scaleX), screenPixmap.width() - 1); - const int pixelY = qBound(0, qRound((y - geometry.top()) * scaleY), + const int pixelY = qBound(0, qRound((y - geometry.top()) * scaleY), screenPixmap.height() - 1); - return QColor(screenPixmap.toImage().pixel(pixelX, pixelY)); + return QColor(screenPixmap.toImage().pixel(pixelX, pixelY)); + }else{ + screenPixmap = QApplication::primaryScreen()->grabWindow(0); + return QColor(screenPixmap.copy(x, y, 1, 1).toImage().pixel(0, 0)); + } } void Picker::popupColorMenu() -- Gitee