summaryrefslogtreecommitdiff
path: root/src/xfns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xfns.c')
-rw-r--r--src/xfns.c305
1 files changed, 268 insertions, 37 deletions
diff --git a/src/xfns.c b/src/xfns.c
index 785ae3baca5..bfa88b1c8cd 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -57,6 +57,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <X11/extensions/Xdbe.h>
#endif
+#ifdef HAVE_XINPUT2
+#include <X11/extensions/XInput2.h>
+#endif
+
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>
@@ -2912,6 +2916,68 @@ initial_set_up_x_back_buffer (struct frame *f)
unblock_input ();
}
+#if defined HAVE_XINPUT2
+static void
+setup_xi_event_mask (struct frame *f)
+{
+ XIEventMask mask;
+ ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
+ unsigned char *m;
+
+ mask.mask = m = alloca (l);
+ memset (m, 0, l);
+ mask.mask_len = l;
+
+ block_input ();
+#ifndef USE_GTK
+ mask.deviceid = XIAllMasterDevices;
+
+ XISetMask (m, XI_ButtonPress);
+ XISetMask (m, XI_ButtonRelease);
+ XISetMask (m, XI_KeyPress);
+ XISetMask (m, XI_KeyRelease);
+ XISetMask (m, XI_Motion);
+ XISetMask (m, XI_Enter);
+ XISetMask (m, XI_Leave);
+#if 0
+ XISetMask (m, XI_FocusIn);
+ XISetMask (m, XI_FocusOut);
+#endif
+ XISelectEvents (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ &mask, 1);
+
+ memset (m, 0, l);
+#endif /* !USE_GTK */
+
+ mask.deviceid = XIAllDevices;
+
+ XISetMask (m, XI_PropertyEvent);
+ XISetMask (m, XI_HierarchyChanged);
+ XISetMask (m, XI_DeviceChanged);
+#ifdef XI_TouchBegin
+ if (FRAME_DISPLAY_INFO (f)->xi2_version >= 2)
+ {
+ XISetMask (m, XI_TouchBegin);
+ XISetMask (m, XI_TouchUpdate);
+ XISetMask (m, XI_TouchEnd);
+#ifdef XI_GesturePinchBegin
+ if (FRAME_DISPLAY_INFO (f)->xi2_version >= 4)
+ {
+ XISetMask (m, XI_GesturePinchBegin);
+ XISetMask (m, XI_GesturePinchUpdate);
+ XISetMask (m, XI_GesturePinchEnd);
+ }
+#endif
+ }
+#endif
+ XISelectEvents (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ &mask, 1);
+ unblock_input ();
+}
+#endif
+
#ifdef USE_X_TOOLKIT
/* Create and set up the X widget for frame F. */
@@ -3074,6 +3140,11 @@ x_window (struct frame *f, long window_prompting)
class_hints.res_class = SSDATA (Vx_resource_class);
XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
+#ifdef HAVE_XINPUT2
+ if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+ setup_xi_event_mask (f);
+#endif
+
#ifdef HAVE_X_I18N
FRAME_XIC (f) = NULL;
if (use_xim)
@@ -3200,6 +3271,11 @@ x_window (struct frame *f)
unblock_input ();
}
#endif
+
+#ifdef HAVE_XINPUT2
+ if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+ setup_xi_event_mask (f);
+#endif
}
#else /*! USE_GTK */
@@ -3254,6 +3330,11 @@ x_window (struct frame *f)
}
#endif /* HAVE_X_I18N */
+#ifdef HAVE_XINPUT2
+ if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+ setup_xi_event_mask (f);
+#endif
+
validate_x_resource_name ();
class_hints.res_name = SSDATA (Vx_resource_name);
@@ -4416,7 +4497,8 @@ For GNU and Unix system, the first 2 numbers are the version of the X
Protocol used on TERMINAL and the 3rd number is the distributor-specific
release number. For MS Windows, the 3 numbers report the OS major and
minor version and build number. For Nextstep, the first 2 numbers are
-hard-coded and the 3rd represents the OS version.
+hard-coded and the 3rd represents the OS version. For Haiku, all 3
+numbers are hard-coded.
See also the function `x-server-vendor'.
@@ -4432,6 +4514,27 @@ If omitted or nil, that stands for the selected frame's display. */)
VendorRelease (dpy));
}
+DEFUN ("x-server-input-extension-version", Fx_server_input_extension_version,
+ Sx_server_input_extension_version, 0, 1, 0,
+ doc: /* Return the version of the X Input Extension supported by TERMINAL.
+The value is nil if TERMINAL's X server doesn't support the X Input
+Extension extension, or if Emacs doesn't support the version present
+on that server. Otherwise, the return value is a list of the the
+major and minor versions of the X Input Extension extension running on
+that server. */)
+ (Lisp_Object terminal)
+{
+#ifdef HAVE_XINPUT2
+ struct x_display_info *dpyinfo = check_x_display_info (terminal);
+
+ return (dpyinfo->supports_xi2
+ ? list2i (2, dpyinfo->xi2_version)
+ : Qnil);
+#else
+ return Qnil;
+#endif
+}
+
DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
doc: /* Return the number of screens on the X server of display TERMINAL.
The optional argument TERMINAL specifies which display to ask about.
@@ -4830,6 +4933,70 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
int i, n_monitors, primary = -1;
RROutput pxid = None;
struct MonitorInfo *monitors;
+ bool randr15_p = false;
+
+#if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 5)
+ 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))
+ {
+ XRectangle workarea;
+ char *name;
+
+ rr_monitors = XRRGetMonitors (dpyinfo->display,
+ dpyinfo->root_window,
+ True, &n_monitors);
+ if (!rr_monitors)
+ goto fallback;
+
+ monitors = xzalloc (n_monitors * sizeof *monitors);
+
+ for (int i = 0; i < n_monitors; ++i)
+ {
+ monitors[i].geom.x = rr_monitors[i].x;
+ monitors[i].geom.y = rr_monitors[i].y;
+ monitors[i].geom.width = rr_monitors[i].width;
+ monitors[i].geom.height = rr_monitors[i].height;
+ monitors[i].mm_width = rr_monitors[i].mwidth;
+ monitors[i].mm_height = rr_monitors[i].mheight;
+
+ name = XGetAtomName (dpyinfo->display, rr_monitors[i].name);
+ if (name)
+ {
+ monitors[i].name = xstrdup (name);
+ XFree (name);
+ }
+ else
+ monitors[i].name = xstrdup ("Unknown Monitor");
+
+ if (rr_monitors[i].primary)
+ primary = i;
+
+ if (rr_monitors[i].primary
+ && x_get_net_workarea (dpyinfo, &workarea))
+ {
+ monitors[i].work = workarea;
+ if (!gui_intersect_rectangles (&monitors[i].geom,
+ &monitors[i].work,
+ &monitors[i].work))
+ monitors[i].work = monitors[i].geom;
+ }
+ else
+ monitors[i].work = monitors[i].geom;
+ }
+
+ XRRFreeMonitors (rr_monitors);
+ randr15_p = true;
+ goto out;
+ }
+
+ fallback:;
+#endif
#define RANDR13_LIBRARY \
(RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
@@ -4918,12 +5085,16 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
XRRFreeOutputInfo (info);
}
XRRFreeScreenResources (resources);
-
+#if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 5)
+ out:
+#endif
attributes_list = x_make_monitor_attribute_list (monitors,
n_monitors,
primary,
dpyinfo,
- "XRandr");
+ (randr15_p
+ ? "XRandR 1.5"
+ : "XRandr"));
free_monitors (monitors, n_monitors);
return attributes_list;
}
@@ -4938,17 +5109,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);
@@ -4973,6 +5136,65 @@ 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;
+
+ attrs = x_get_monitor_attributes (dpyinfo);
+
+ for (tem = attrs; CONSP (tem); tem = XCDR (tem))
+ {
+ int sx, sy, swidth, sheight;
+ val = assq_no_quit (Qworkarea, 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);
+
+ if (!dpyinfo)
+ emacs_abort ();
+
+ block_input ();
+ xlw_monitor_dimensions_at_pos_1 (dpyinfo, screen, src_x, src_y,
+ x, y, width, height);
+
+ unblock_input ();
+}
+#endif
+
+
DEFUN ("x-display-monitor-attributes-list", Fx_display_monitor_attributes_list,
Sx_display_monitor_attributes_list,
0, 1, 0,
@@ -5569,8 +5791,25 @@ The coordinates X and Y are interpreted in pixels relative to a position
int yval = check_integer_range (y, INT_MIN, INT_MAX);
block_input ();
- XWarpPointer (FRAME_X_DISPLAY (f), None, DefaultRootWindow (FRAME_X_DISPLAY (f)),
- 0, 0, 0, 0, xval, yval);
+#ifdef HAVE_XINPUT2
+ int deviceid;
+
+ if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+ {
+ XGrabServer (FRAME_X_DISPLAY (f));
+ if (XIGetClientPointer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ &deviceid))
+ {
+ XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
+ DefaultRootWindow (FRAME_X_DISPLAY (f)),
+ 0, 0, 0, 0, xval, yval);
+ }
+ XUngrabServer (FRAME_X_DISPLAY (f));
+ }
+ else
+#endif
+ XWarpPointer (FRAME_X_DISPLAY (f), None, DefaultRootWindow (FRAME_X_DISPLAY (f)),
+ 0, 0, 0, 0, xval, yval);
unblock_input ();
return Qnil;
@@ -7095,7 +7334,8 @@ Text larger than the specified size is clipped. */)
try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
/* Calculate size of tooltip window. */
size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
- make_fixnum (w->pixel_height), Qnil);
+ make_fixnum (w->pixel_height), Qnil,
+ Qnil);
/* Add the frame's internal border to calculated size. */
width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
@@ -7374,7 +7614,7 @@ Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
selection box, if specified. If MUSTMATCH is non-nil, the returned file
or directory must exist.
-This function is defined only on NS, MS Windows, and X Windows with the
+This function is defined only on NS, Haiku, MS Windows, and X Windows with the
Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
Otherwise, if ONLY-DIR-P is non-nil, the user can select only directories.
On MS Windows 7 and later, the file selection dialog "remembers" the last
@@ -7512,27 +7752,11 @@ present and mapped to the usual X keysyms. */)
struct frame *f = decode_window_system_frame (frame);
Display *dpy = FRAME_X_DISPLAY (f);
Lisp_Object have_keys;
- int major, minor, op, event, error_code;
- block_input ();
+ if (!FRAME_DISPLAY_INFO (f)->supports_xkb)
+ return Qlambda;
- /* Check library version in case we're dynamically linked. */
- major = XkbMajorVersion;
- minor = XkbMinorVersion;
- if (!XkbLibraryVersion (&major, &minor))
- {
- unblock_input ();
- return Qlambda;
- }
-
- /* Check that the server supports XKB. */
- major = XkbMajorVersion;
- minor = XkbMinorVersion;
- if (!XkbQueryExtension (dpy, &op, &event, &error_code, &major, &minor))
- {
- unblock_input ();
- return Qlambda;
- }
+ block_input ();
/* In this code we check that the keyboard has physical keys with names
that start with BKSP (Backspace) and DELE (Delete), and that they
@@ -8038,6 +8262,12 @@ eliminated in future versions of Emacs. */);
/* Tell Emacs about this window system. */
Fprovide (Qx, Qnil);
+#ifdef HAVE_XINPUT2
+ DEFSYM (Qxinput2, "xinput2");
+
+ Fprovide (Qxinput2, Qnil);
+#endif
+
#ifdef USE_X_TOOLKIT
Fprovide (intern_c_string ("x-toolkit"), Qnil);
#ifdef USE_MOTIF
@@ -8095,6 +8325,7 @@ eliminated in future versions of Emacs. */);
defsubr (&Sx_server_max_request_size);
defsubr (&Sx_server_vendor);
defsubr (&Sx_server_version);
+ defsubr (&Sx_server_input_extension_version);
defsubr (&Sx_display_pixel_width);
defsubr (&Sx_display_pixel_height);
defsubr (&Sx_display_mm_width);