1010#include < QCursor>
1111#include < QDebug>
1212#include < QMouseEvent>
13+ #include < QScreen>
1314#include < QStyle>
1415
1516// local includes
1920 #include " WindowsAppearance.h"
2021#endif
2122
23+ namespace {
24+ constexpr int DEFAULT_PANEL_THICKNESS = 24 ;
25+ constexpr int CURSOR_POSITION_TOLERANCE = 2 ;
26+
27+ bool positionsAreClose (const QPoint &first, const QPoint &second) {
28+ return (first - second).manhattanLength () <= CURSOR_POSITION_TOLERANCE ;
29+ }
30+
31+ bool fallbackTrayIconPosition (QPoint *position) {
32+ const QScreen *screen = QGuiApplication::primaryScreen ();
33+ if (screen == nullptr ) {
34+ return false ;
35+ }
36+
37+ const QRect screenGeometry = screen->geometry ();
38+ const QRect availableGeometry = screen->availableGeometry ();
39+ const int topInset = availableGeometry.top () - screenGeometry.top ();
40+ const int bottomInset = screenGeometry.bottom () - availableGeometry.bottom ();
41+ const int rightInset = screenGeometry.right () - availableGeometry.right ();
42+ const int leftInset = availableGeometry.left () - screenGeometry.left ();
43+
44+ if (topInset > 0 ) {
45+ *position = QPoint (screenGeometry.right () - (topInset / 2 ), screenGeometry.top () + (topInset / 2 ));
46+ } else if (bottomInset > 0 ) {
47+ *position = QPoint (screenGeometry.right () - (bottomInset / 2 ), screenGeometry.bottom () - (bottomInset / 2 ));
48+ } else if (rightInset > 0 ) {
49+ *position = QPoint (screenGeometry.right () - (rightInset / 2 ), screenGeometry.bottom () - (rightInset / 2 ));
50+ } else if (leftInset > 0 ) {
51+ *position = QPoint (screenGeometry.left () + (leftInset / 2 ), screenGeometry.bottom () - (leftInset / 2 ));
52+ } else {
53+ #if defined(_WIN32)
54+ *position = QPoint (screenGeometry.right () - (DEFAULT_PANEL_THICKNESS / 2 ), screenGeometry.bottom () - (DEFAULT_PANEL_THICKNESS / 2 ));
55+ #else
56+ *position = QPoint (screenGeometry.right () - (DEFAULT_PANEL_THICKNESS / 2 ), screenGeometry.top () + (DEFAULT_PANEL_THICKNESS / 2 ));
57+ #endif
58+ }
59+ return true ;
60+ }
61+ } // namespace
62+
2263QtTrayMenu::QtTrayMenu (QObject *parent, const bool debug):
2364 QtTrayMenu(-1 , nullptr , parent, debug) {
2465 };
@@ -349,18 +390,23 @@ bool QtTrayMenu::positionMouseOverIcon() {
349390 }
350391
351392 const QRect iconGeometry = trayIcon->geometry ();
352- if (!iconGeometry.isValid ()) {
353- qWarning (" QtTrayMenu: tray icon geometry is unavailable" );
393+ QPoint targetPosition;
394+ if (iconGeometry.isValid ()) {
395+ targetPosition = iconGeometry.center ();
396+ } else if (!fallbackTrayIconPosition (&targetPosition)) {
397+ qWarning (" QtTrayMenu: tray icon geometry and screen-edge fallback are unavailable" );
354398 return false ;
399+ } else {
400+ qWarning (" QtTrayMenu: tray icon geometry is unavailable; using the system panel edge" );
355401 }
356402
357403 if (!mousePositionSaved) {
358404 savedMousePosition = QCursor::pos ();
359405 mousePositionSaved = true ;
360406 }
361- const QPoint targetPosition = iconGeometry.center ();
362407 QCursor::setPos (targetPosition);
363- const bool positioned = QCursor::pos () == targetPosition;
408+ const QPoint currentPosition = QCursor::pos ();
409+ const bool positioned = iconGeometry.isValid () ? iconGeometry.contains (currentPosition) : positionsAreClose (currentPosition, targetPosition);
364410 if (!positioned) {
365411 qWarning (" QtTrayMenu: could not position the mouse over the tray icon" );
366412 }
@@ -374,7 +420,7 @@ bool QtTrayMenu::restoreMousePosition() {
374420
375421 QCursor::setPos (savedMousePosition);
376422 mousePositionSaved = false ;
377- const bool restored = QCursor::pos () == savedMousePosition;
423+ const bool restored = positionsAreClose ( QCursor::pos (), savedMousePosition) ;
378424 if (!restored) {
379425 qWarning (" QtTrayMenu: could not restore the saved mouse position" );
380426 }
0 commit comments