summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Webster <[email protected]>2020-05-29 23:48:50 -0400
committerLuke from DC <[email protected]>2021-03-08 02:34:39 +0000
commita52f5c91c2fdc1a8f213f0ec322a46cf071eb277 (patch)
tree1e8fed20c7b6f47210ab6d3e39fee88b120e2fc2
parentcd01551bfaf24989f4ae373fd8c42bc080fe0da6 (diff)
downloadmarco-a52f5c91c2fdc1a8f213f0ec322a46cf071eb277.tar.bz2
marco-a52f5c91c2fdc1a8f213f0ec322a46cf071eb277.tar.xz
compositor-xrender.c: Make sure tooltips are visible when the source
widget is close to the edge of the work area. See inline comments - as of 3.24 tooltip positioning is handled differently, and under certain conditions in hidpi, tooltips for the bottom panel applets can end up off the bottom of the work area. To reproduce, in hidpi, set the bottom panel to approximately 30px tall and try to activate a tooltip for an applet on that panel.
-rw-r--r--src/compositor/compositor-xrender.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/compositor/compositor-xrender.c b/src/compositor/compositor-xrender.c
index 37440a79..13e8e620 100644
--- a/src/compositor/compositor-xrender.c
+++ b/src/compositor/compositor-xrender.c
@@ -42,6 +42,8 @@
#include "display.h"
#include "../core/display-private.h"
+#include "../core/screen-private.h"
+#include "../core/workspace.h"
#include "screen.h"
#include "frame.h"
#include "errors.h"
@@ -49,6 +51,7 @@
#include "compositor-private.h"
#include "compositor-xrender.h"
#include "xprops.h"
+#include "core.h"
#include <X11/Xatom.h>
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
@@ -1856,6 +1859,87 @@ free_win (MetaCompWindow *cw,
}
static void
+constrain_tooltip_onscreen (MetaDisplay *display,
+ MetaScreen *screen,
+ MetaCompWindow *cw,
+ Window id)
+{
+ MetaWorkspace *workspace;
+ MetaRectangle work_area, win_rect;
+ const MetaXineramaScreenInfo* xinerama;
+ gint new_x, new_y;
+ gint active_workspace_num;
+
+ /* Why this is here:
+ * As of gtk 3.24, tooltips are positioned differently, and can end up off the
+ * screen in certain situations in hidpi.
+ *
+ * See: https://github.com/GNOME/gtk/commit/14d22cb3233e
+ *
+ * If the panel is too tall (around > 25 or so), tooltip positioning fails both
+ * tests in gdkwindowimpl.c (maybe_flip_position()) skipping repositioning of the
+ * tooltip inside the workarea. This only occurs on bottom panels.
+ *
+ * Since the calculations are based upon the monitor's workarea and the 'attach'
+ * (gdk) window's rectangle, there's no way to compensate for or fool gtk into
+ * displaying it correctly. So here, we do our own check and adjustment. */
+
+ active_workspace_num = meta_core_get_active_workspace (cw->attrs.screen);
+
+ workspace = meta_screen_get_workspace_by_index (screen,
+ active_workspace_num);
+
+ win_rect.x = cw->attrs.x;
+ win_rect.y = cw->attrs.y;
+ win_rect.width = cw->attrs.width;
+ win_rect.height = cw->attrs.height;
+
+ xinerama = meta_screen_get_xinerama_for_rect (screen,
+ &win_rect);
+
+ meta_workspace_get_work_area_for_xinerama (workspace,
+ xinerama->number,
+ &work_area);
+
+ new_x = win_rect.x;
+ new_y = win_rect.y;
+
+ /* Valid tooltip positions seem to cheat into the panel by a few pixels - maybe
+ * accounting for shadow margin. There's no reason the fix these, but they'd
+ * be caught here otherwise, so 10px of overshoot in the direction of the panel
+ * is allowed. The tooltips we're out to catch are the ones on the complete other
+ * side of the panel (off screren), so there won't be any confusion. */
+ if (win_rect.y < work_area.y - 10)
+ {
+ new_y = work_area.y;
+ }
+ else if (win_rect.y + win_rect.height > work_area.y + work_area.height + 10)
+ {
+ new_y = (work_area.y + work_area.height - win_rect.height);
+ }
+
+ if (win_rect.x < work_area.x - 10)
+ {
+ new_x = work_area.x;
+ }
+ else if (win_rect.x + win_rect.width > work_area.x + work_area.width + 10)
+ {
+ new_x = (work_area.x + work_area.width - win_rect.width);
+ }
+
+ if (new_x != win_rect.x || new_y != win_rect.y)
+ {
+ if (DISPLAY_COMPOSITOR (display)->debug)
+ {
+ fprintf(stderr, "Constraining tooltip onscreen x:%d -> %d, y:%d -> %d\n",
+ win_rect.x,new_x, win_rect.y,new_y);
+ }
+
+ XMoveWindow (display->xdisplay, cw->id, new_x, new_y);
+ }
+}
+
+static void
map_win (MetaDisplay *display,
MetaScreen *screen,
Window id)
@@ -1866,6 +1950,11 @@ map_win (MetaDisplay *display,
if (cw == NULL)
return;
+ if (cw->type == META_COMP_WINDOW_TOOLTIP)
+ {
+ constrain_tooltip_onscreen (display, screen, cw, id);
+ }
+
/* The reason we deallocate this here and not in unmap
is so that we will still have a valid pixmap for
whenever the window is unmapped */