summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lwlib/xlwmenu.c73
-rw-r--r--src/xfns.c137
-rw-r--r--src/xterm.c15
-rw-r--r--src/xterm.h4
4 files changed, 195 insertions, 34 deletions
diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c
index a0a10d13db5..a065c53310d 100644
--- a/lwlib/xlwmenu.c
+++ b/lwlib/xlwmenu.c
@@ -1390,27 +1390,40 @@ fit_to_screen (XlwMenuWidget mw,
window_state *previous_ws,
Boolean horizontal_p)
{
- unsigned int screen_width = WidthOfScreen (XtScreen (mw));
- unsigned int screen_height = HeightOfScreen (XtScreen (mw));
+ int screen_width, screen_height;
+ int screen_x, screen_y;
+
+#ifdef emacs
+ xlw_monitor_dimensions_at_pos (XtDisplay (mw), XtScreen (mw),
+ ws->x, ws->y, &screen_x, &screen_y,
+ &screen_width, &screen_height);
+#else
+ screen_width = WidthOfScreen (XtScreen (mw));
+ screen_height = HeightOfScreen (XtScreen (mw));
+ screen_x = 0;
+ screen_y = 0;
+#endif
/* 1 if we are unable to avoid an overlap between
this menu and the parent menu in the X dimension. */
int horizontal_overlap = 0;
- if (ws->x < 0)
+ if (ws->x < screen_x)
ws->x = 0;
- else if (ws->x + ws->width > screen_width)
+ else if (ws->x + ws->width > screen_x + screen_width)
{
if (!horizontal_p)
/* The addition of shadow-thickness for a sub-menu's position is
to reflect a similar adjustment when the menu is displayed to
the right of the invoking menu-item; it makes the sub-menu
look more `attached' to the menu-item. */
- ws->x = previous_ws->x - ws->width + mw->menu.shadow_thickness;
+ ws->x = screen_x + (previous_ws->x
+ - ws->width
+ + mw->menu.shadow_thickness);
else
- ws->x = screen_width - ws->width;
- if (ws->x < 0)
+ ws->x = screen_x + (screen_width - ws->width);
+ if (ws->x < screen_x)
{
- ws->x = 0;
+ ws->x = screen_x;
horizontal_overlap = 1;
}
}
@@ -1427,16 +1440,16 @@ fit_to_screen (XlwMenuWidget mw,
ws->y = previous_ws->y - ws->height;
}
- if (ws->y < 0)
- ws->y = 0;
- else if (ws->y + ws->height > screen_height)
+ if (ws->y < screen_y)
+ ws->y = screen_y;
+ else if (ws->y + ws->height > screen_y + screen_height)
{
if (horizontal_p)
- ws->y = previous_ws->y - ws->height;
+ ws->y = screen_y + (previous_ws->y - ws->height);
else
- ws->y = screen_height - ws->height;
- if (ws->y < 0)
- ws->y = 0;
+ ws->y = screen_y + (screen_height - ws->height);
+ if (ws->y < screen_y)
+ ws->y = screen_y;
}
}
@@ -2626,7 +2639,21 @@ pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent *event)
int borderwidth = mw->menu.shadow_thickness;
Screen* screen = XtScreen (mw);
Display *display = XtDisplay (mw);
+ int screen_x;
+ int screen_y;
+ int screen_w;
+ int screen_h;
+#ifdef emacs
+ xlw_monitor_dimensions_at_pos (display, screen, x, y,
+ &screen_x, &screen_y,
+ &screen_w, &screen_h);
+#else
+ screen_x = 0;
+ screen_y = 0;
+ screen_w = WidthOfScreen (screen);
+ screen_h = HeightOfScreen (screen);
+#endif
next_release_must_exit = 0;
mw->menu.inside_entry = NULL;
@@ -2640,14 +2667,14 @@ pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent *event)
x -= borderwidth;
y -= borderwidth;
- if (x < borderwidth)
- x = borderwidth;
- if (x + w + 2 * borderwidth > WidthOfScreen (screen))
- x = WidthOfScreen (screen) - w - 2 * borderwidth;
- if (y < borderwidth)
- y = borderwidth;
- if (y + h + 2 * borderwidth> HeightOfScreen (screen))
- y = HeightOfScreen (screen) - h - 2 * borderwidth;
+ if (x < screen_x + borderwidth)
+ x = screen_x + borderwidth;
+ if (x + w + 2 * borderwidth > screen_x + screen_w)
+ x = (screen_x + screen_w) - w - 2 * borderwidth;
+ if (y < screen_y + borderwidth)
+ y = screen_y + borderwidth;
+ if (y + h + 2 * borderwidth > screen_y + screen_h)
+ y = (screen_y + screen_h) - h - 2 * borderwidth;
mw->menu.popped_up = True;
if (XtIsShell (XtParent ((Widget)mw)))
diff --git a/src/xfns.c b/src/xfns.c
index ad77ebc8f43..8dc383ddfa8 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -5041,17 +5041,9 @@ x_get_monitor_attributes (struct x_display_info *dpyinfo)
(void) dpy; /* Suppress unused variable warning. */
#ifdef HAVE_XRANDR
- int xrr_event_base, xrr_error_base;
- bool xrr_ok = false;
- xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base);
- if (xrr_ok)
- {
- XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
- &dpyinfo->xrandr_minor_version);
- xrr_ok = ((dpyinfo->xrandr_major_version == 1
- && dpyinfo->xrandr_minor_version >= 2)
- || dpyinfo->xrandr_major_version > 1);
- }
+ bool xrr_ok = ((dpyinfo->xrandr_major_version == 1
+ && dpyinfo->xrandr_minor_version >= 2)
+ || dpyinfo->xrandr_major_version > 1);
if (xrr_ok)
attributes_list = x_get_monitor_attributes_xrandr (dpyinfo);
@@ -5076,6 +5068,129 @@ x_get_monitor_attributes (struct x_display_info *dpyinfo)
#endif /* !USE_GTK */
+#ifdef USE_LUCID
+/* This is used by the Lucid menu widget, but it's defined here so we
+ can make use of a great deal of existing code. */
+static void
+xlw_monitor_dimensions_at_pos_1 (struct x_display_info *dpyinfo,
+ Screen *screen, int src_x, int src_y,
+ int *x, int *y, int *width, int *height)
+{
+ Lisp_Object attrs, tem, val;
+#ifdef HAVE_XRANDR
+#if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 5)
+ int num_rr_monitors;
+ XRRMonitorInfo *rr_monitors;
+
+ /* If RandR 1.5 or later is available, use that instead, as some
+ video drivers don't report correct dimensions via other versions
+ of RandR. */
+ if (dpyinfo->xrandr_major_version > 1
+ || (dpyinfo->xrandr_major_version == 1
+ && dpyinfo->xrandr_minor_version >= 5))
+ {
+ rr_monitors = XRRGetMonitors (dpyinfo->display,
+ RootWindowOfScreen (screen),
+ True, &num_rr_monitors);
+ if (!rr_monitors)
+ goto fallback;
+
+ for (int i = 0; i < num_rr_monitors; ++i)
+ {
+ if (rr_monitors[i].x <= src_x
+ && src_x < (rr_monitors[i].x
+ + rr_monitors[i].width)
+ && rr_monitors[i].y <= src_y
+ && src_y < (rr_monitors[i].y
+ + rr_monitors[i].height))
+ {
+ *x = rr_monitors[i].x;
+ *y = rr_monitors[i].y;
+ *width = rr_monitors[i].width;
+ *height = rr_monitors[i].height;
+
+ XRRFreeMonitors (rr_monitors);
+ return;
+ }
+ }
+ XRRFreeMonitors (rr_monitors);
+ }
+
+ fallback:
+#endif
+#endif
+
+ attrs = x_get_monitor_attributes (dpyinfo);
+
+ for (tem = attrs; CONSP (tem); tem = XCDR (tem))
+ {
+ int sx, sy, swidth, sheight;
+ val = assq_no_quit (Qgeometry, XCAR (tem));
+ if (!NILP (val))
+ {
+ sx = XFIXNUM (XCAR (XCDR (val)));
+ sy = XFIXNUM (XCAR (XCDR (XCDR (val))));
+ swidth = XFIXNUM (XCAR (XCDR (XCDR (XCDR (val)))));
+ sheight = XFIXNUM (XCAR (XCDR (XCDR (XCDR (XCDR (val))))));
+
+ if (sx <= src_x && src_x < (sx + swidth)
+ && sy <= src_y && src_y < (sy + swidth))
+ {
+ *x = sx;
+ *y = sy;
+ *width = swidth;
+ *height = sheight;
+ return;
+ }
+ }
+ }
+
+ *x = 0;
+ *y = 0;
+ *width = WidthOfScreen (screen);
+ *height = HeightOfScreen (screen);
+}
+
+void
+xlw_monitor_dimensions_at_pos (Display *dpy, Screen *screen, int src_x,
+ int src_y, int *x, int *y, int *width, int *height)
+{
+ struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
+ XRectangle rect, workarea, intersection;
+ int dim_x, dim_y, dim_w, dim_h;
+
+ if (!dpyinfo)
+ emacs_abort ();
+
+ block_input ();
+ xlw_monitor_dimensions_at_pos_1 (dpyinfo, screen, src_x, src_y,
+ &dim_x, &dim_y, &dim_w, &dim_h);
+ rect.x = dim_x;
+ rect.y = dim_y;
+ rect.width = dim_w;
+ rect.height = dim_h;
+
+ if (!x_get_net_workarea (dpyinfo, &workarea))
+ memset (&workarea, 0, sizeof workarea);
+ unblock_input ();
+
+ if (!gui_intersect_rectangles (&rect, &workarea, &intersection))
+ {
+ *x = 0;
+ *y = 0;
+ *width = 0;
+ *height = 0;
+ return;
+ }
+
+ *x = intersection.x;
+ *y = intersection.y;
+ *width = intersection.width;
+ *height = intersection.height;
+}
+#endif
+
+
DEFUN ("x-display-monitor-attributes-list", Fx_display_monitor_attributes_list,
Sx_display_monitor_attributes_list,
0, 1, 0,
diff --git a/src/xterm.c b/src/xterm.c
index 698c1eba8b7..3fdf214c3da 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -46,6 +46,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <X11/extensions/XInput2.h>
#endif
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+
/* Load sys/types.h if not already loaded.
In some systems loading it twice is suicidal. */
#ifndef makedev
@@ -14803,6 +14807,17 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
dpyinfo->xi2_version = minor;
#endif
+#ifdef HAVE_XRANDR
+ int xrr_event_base, xrr_error_base;
+ bool xrr_ok = false;
+ xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base);
+ if (xrr_ok)
+ {
+ XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
+ &dpyinfo->xrandr_minor_version);
+ }
+#endif
+
#ifdef HAVE_XKB
dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display,
XkbAllComponentsMask,
diff --git a/src/xterm.h b/src/xterm.h
index d9ace002d58..5615a55d6b9 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1240,6 +1240,10 @@ extern void x_change_tool_bar_height (struct frame *, int);
extern void x_implicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_scroll_bar_default_width (struct frame *);
extern void x_set_scroll_bar_default_height (struct frame *);
+#ifdef USE_LUCID
+extern void xlw_monitor_dimensions_at_pos (Display *, Screen *, int, int,
+ int *, int *, int *, int *);
+#endif
/* Defined in xselect.c. */