From 5fbc1dff0e2e248d61e43c362606c3f5e5255f7d Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Thu, 21 Nov 2024 11:52:22 +0100 Subject: [PATCH 3/7] Xm/MenuShell: Use Xinerama to place menus v2: If we have a pulldown button, use the location of that button to keep the menu on the same monitor as that button so that the menu doesn't eventually end up on another monitor entirely. Signed-off-by: Olivier Fourdan --- lib/Xm/MenuShell.c | 47 +++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/lib/Xm/MenuShell.c b/lib/Xm/MenuShell.c index 483cc95a..c78bfb08 100644 --- a/lib/Xm/MenuShell.c +++ b/lib/Xm/MenuShell.c @@ -41,6 +41,7 @@ static char rcsid[] = "$TOG: MenuShell.c /main/24 1999/07/08 16:49:59 vipin $" #include #include #include +#include #include #include #include @@ -913,7 +914,9 @@ ForceMenuPaneOnScreen( register Position *y ) { Position rightEdgeOfMenu, bottomEdgeOfMenu; - Dimension dispWidth, dispHeight; + Position dispX, dispY, dispMaxX, dispMaxY; + Position x1 = *x; + Position y1 = *y; Widget pulldown_button = RC_CascadeBtn(rowcol); Dimension RowColBorderWidth = rowcol->core.border_width << 1; Dimension CascadeBorderWidth = 0; @@ -925,8 +928,18 @@ ForceMenuPaneOnScreen( rightEdgeOfMenu = *x + RowColBorderWidth + rowcol->core.width; bottomEdgeOfMenu = *y + RowColBorderWidth + rowcol->core.height; - dispWidth = WidthOfScreen (XtScreen(rowcol)); - dispHeight = HeightOfScreen (XtScreen(rowcol)); +#ifdef HAVE_LIBXINERAMA + if (pulldown_button) + { + /* If we have a pulldown button, use the location of that button to + * keep the menu on the same monitor as that button so that the menu + * doesn't eventually end up on another monitor entirely. + */ + XtTranslateCoords((Widget) pulldown_button, + XtX(pulldown_button), XtY(pulldown_button), &x1, &y1); + } +#endif + _XmScreenGetBoundariesAtpoint(XtScreen(rowcol), x1, y1, &dispX, &dispY, &dispMaxX, &dispMaxY); /* * For OPTION menus, if the submenu is [partially] offscreen, offset it @@ -937,9 +950,9 @@ ForceMenuPaneOnScreen( (RC_Type(XtParent(pulldown_button)) == XmMENU_OPTION)) { Position old_x = *x; - if (bottomEdgeOfMenu >= (Position)dispHeight) + if (bottomEdgeOfMenu >= dispMaxY) { - *y = dispHeight - rowcol->core.height - RowColBorderWidth - 1; + *y = dispMaxY - rowcol->core.height - RowColBorderWidth - 1; if (LayoutIsRtoLM(rowcol)) *x = old_x - rowcol->core.width - (rowcol->core.border_width <<1); else @@ -948,9 +961,9 @@ ForceMenuPaneOnScreen( bottomEdgeOfMenu = *y + RowColBorderWidth + rowcol->core.height; } - if (*y < 0) + if (*y < dispY) { - *y = 0; + *y = dispY; /* Consider CascadeBtn as well as RowCol width to allow multi * column RowColumn @@ -963,13 +976,13 @@ ForceMenuPaneOnScreen( bottomEdgeOfMenu = *y + RowColBorderWidth + rowcol->core.height; } - if (rightEdgeOfMenu >= (Position)dispWidth) + if (rightEdgeOfMenu >= dispMaxX) { *x = old_x - rowcol->core.width + RowColBorderWidth; rightEdgeOfMenu = *x + RowColBorderWidth + rowcol->core.width; } - if (*x < 0) + if (*x < dispX) { if (LayoutIsRtoLM(rowcol)) *x = old_x + pulldown_button->core.width + CascadeBorderWidth; @@ -982,10 +995,10 @@ ForceMenuPaneOnScreen( /* * If the submenu is offscreen force it completely on. */ - if (rightEdgeOfMenu >= (Position)dispWidth) - *x -= (rightEdgeOfMenu - dispWidth + 1); + if (rightEdgeOfMenu >= dispMaxX) + *x -= (rightEdgeOfMenu - dispMaxX + 1); - if (bottomEdgeOfMenu >= (Position)dispHeight) + if (bottomEdgeOfMenu >= dispMaxY) { if (pulldown_button && XtParent(pulldown_button) && (RC_Type(XtParent(pulldown_button)) == XmMENU_BAR)) @@ -1005,15 +1018,15 @@ ForceMenuPaneOnScreen( *y = y_temp; } else - *y -= (bottomEdgeOfMenu - dispHeight + 1); + *y -= (bottomEdgeOfMenu - dispMaxY + 1); } /* Make sure that the top left corner os on screen! */ - if (*x < 0) - *x = 0; + if (*x < dispX) + *x = dispX; - if (*y < 0) - *y = 0; + if (*y < dispY) + *y = dispY; } /* -- 2.49.0