diff options
Diffstat (limited to 'src/compositor/compositor-xrender.c')
-rw-r--r-- | src/compositor/compositor-xrender.c | 89 |
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 */ |