File Calculate-first-clickable-point-from-the-top-left.patch of Package plasma5-workspace
From 989a7759a969c7b4dd677e5e1944d849a72450fa Mon Sep 17 00:00:00 2001
From: Konrad Materka <kmaterka@wp.pl>
Date: Wed, 28 Aug 2019 15:07:18 +0100
Subject: Calculate first clickable point, from the top-left
Summary:
Wine is using XWindow Shape Extension for transparent tray icons.
We need to find first clickable point starting from top-left.
BUG: 399234
Test Plan:
Bug fix test:
1. Enable KWin compositing;
2. Download this test program (SHA-1: 63ae606aee64259091e7f82436d4ecdf3a6e9047): https://www.nirsoft.net/utils/tflash210.zip
3. Run the .exe with Wine **Staging**
4. Right click on the icon
5. Context menu should show
Regression test:
1. Run XChat
2. Right click
3. Context menu should show in the same place as without patch
Reviewers: davidedmundson, #plasma_workspaces
Reviewed By: davidedmundson, #plasma_workspaces
Subscribers: davidedmundson, plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D22767
---
xembed-sni-proxy/sniproxy.cpp | 58 ++++++++++++++++++++++++++++++++++++++-----
xembed-sni-proxy/sniproxy.h | 2 ++
2 files changed, 54 insertions(+), 6 deletions(-)
diff --git a/xembed-sni-proxy/sniproxy.cpp b/xembed-sni-proxy/sniproxy.cpp
index 5b687c4..46ebb4c 100644
--- a/xembed-sni-proxy/sniproxy.cpp
+++ b/xembed-sni-proxy/sniproxy.cpp
@@ -373,6 +373,51 @@ QImage SNIProxy::convertFromNative(xcb_image_t *xcbImage) const
return image;
}
+/*
+ Wine is using XWindow Shape Extension for transparent tray icons.
+ We need to find first clickable point starting from top-left.
+*/
+QPoint SNIProxy::calculateClickPoint() const
+{
+ QPoint clickPoint = QPoint(0, 0);
+
+ auto c = QX11Info::connection();
+
+ // request extent to check if shape has been set
+ xcb_shape_query_extents_cookie_t extentsCookie = xcb_shape_query_extents(c, m_windowId);
+ // at the same time make the request for rectangles (even if this request isn't needed)
+ xcb_shape_get_rectangles_cookie_t rectaglesCookie = xcb_shape_get_rectangles(c, m_windowId, XCB_SHAPE_SK_BOUNDING);
+
+ QScopedPointer<xcb_shape_query_extents_reply_t, QScopedPointerPodDeleter>
+ extentsReply(xcb_shape_query_extents_reply(c, extentsCookie, nullptr));
+ QScopedPointer<xcb_shape_get_rectangles_reply_t, QScopedPointerPodDeleter>
+ rectanglesReply(xcb_shape_get_rectangles_reply(c, rectaglesCookie, nullptr));
+
+ if (!extentsReply || !rectanglesReply || !extentsReply->bounding_shaped) {
+ return clickPoint;
+ }
+
+ xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(rectanglesReply.data());
+ if (!rectangles) {
+ return clickPoint;
+ }
+
+ const QImage image = getImageNonComposite();
+
+ double minLength = sqrt(pow(image.height(), 2) + pow(image.width(), 2));
+ const int nRectangles = xcb_shape_get_rectangles_rectangles_length(rectanglesReply.data());
+ for (int i = 0; i < nRectangles; ++i) {
+ double length = sqrt(pow(rectangles[i].x, 2) + pow(rectangles[i].y, 2));
+ if (length < minLength) {
+ minLength = length;
+ clickPoint = QPoint(rectangles[i].x, rectangles[i].y);
+ }
+ }
+
+ qCDebug(SNIPROXY) << "Click point:" << clickPoint;
+ return clickPoint;
+}
+
//____________properties__________
QString SNIProxy::Category() const
@@ -474,6 +519,7 @@ void SNIProxy::sendClick(uint8_t mouseButton, int x, int y)
//move our window so the mouse is within its geometry
uint32_t configVals[2] = {0, 0};
+ const QPoint clickPoint = calculateClickPoint();
if (mouseButton >= XCB_BUTTON_INDEX_4) {
//scroll event, take pointer position
configVals[0] = pointer->root_x;
@@ -482,11 +528,11 @@ void SNIProxy::sendClick(uint8_t mouseButton, int x, int y)
if (pointer->root_x > x + clientGeom->width)
configVals[0] = pointer->root_x - clientGeom->width + 1;
else
- configVals[0] = static_cast<uint32_t>(x);
+ configVals[0] = static_cast<uint32_t>(x - clickPoint.x());
if (pointer->root_y > y + clientGeom->height)
configVals[1] = pointer->root_y - clientGeom->height + 1;
else
- configVals[1] = static_cast<uint32_t>(y);
+ configVals[1] = static_cast<uint32_t>(y - clickPoint.y());
}
xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, configVals);
@@ -505,8 +551,8 @@ void SNIProxy::sendClick(uint8_t mouseButton, int x, int y)
event->root = QX11Info::appRootWindow();
event->root_x = x;
event->root_y = y;
- event->event_x = 0;
- event->event_y = 0;
+ event->event_x = static_cast<int16_t>(clickPoint.x());
+ event->event_y = static_cast<int16_t>(clickPoint.y());
event->child = 0;
event->state = 0;
event->detail = mouseButton;
@@ -529,8 +575,8 @@ void SNIProxy::sendClick(uint8_t mouseButton, int x, int y)
event->root = QX11Info::appRootWindow();
event->root_x = x;
event->root_y = y;
- event->event_x = 0;
- event->event_y = 0;
+ event->event_x = static_cast<int16_t>(clickPoint.x());
+ event->event_y = static_cast<int16_t>(clickPoint.y());
event->child = 0;
event->state = 0;
event->detail = mouseButton;
diff --git a/xembed-sni-proxy/sniproxy.h b/xembed-sni-proxy/sniproxy.h
index 1f4d56e..8496a4c 100644
--- a/xembed-sni-proxy/sniproxy.h
+++ b/xembed-sni-proxy/sniproxy.h
@@ -26,6 +26,7 @@
#include <QDBusConnection>
#include <QDBusObjectPath>
#include <QPixmap>
+#include <QPoint>
#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
@@ -149,6 +150,7 @@ private:
QImage getImageNonComposite() const;
bool isTransparentImage(const QImage &image) const;
QImage convertFromNative(xcb_image_t *xcbImage) const;
+ QPoint calculateClickPoint() const;
QDBusConnection m_dbus;
xcb_window_t m_windowId;
--
cgit v1.1