emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master edf9700c3c: Add a hook run upon monitor configuration changes


From: Po Lu
Subject: master edf9700c3c: Add a hook run upon monitor configuration changes
Date: Fri, 20 May 2022 23:17:48 -0400 (EDT)

branch: master
commit edf9700c3ca65d92bdfca59306845ffc0717d690
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Add a hook run upon monitor configuration changes
    
    * doc/lispref/frames.texi (Multiple Terminals): Document new
    hook `display-monitors-changed-functions'.
    * etc/NEWS: Announce new abnormal hook.
    
    * src/keyboard.c (kbd_buffer_get_event): Handle
    MONITORS_CHANGED_EVENT.
    (syms_of_keyboard): New hook and defsyms.
    * src/termhooks.h (enum event_kind): Add new event
    `MONITORS_CHANGED_EVENT'.
    
    * src/xterm.c (handle_one_xevent): Handle RRNotify and
    RRScreenChangeNotify events.
    (x_term_init): Select for RRScreenChange, RRCrtcChange and
    RROutputChange.
    * src/xterm.h (struct x_display_info): Improve RandR version
    detection.
---
 doc/lispref/frames.texi | 10 ++++++++++
 etc/NEWS                |  5 +++++
 src/keyboard.c          | 23 ++++++++++++++++++++++
 src/termhooks.h         | 11 +++++++++--
 src/xterm.c             | 52 +++++++++++++++++++++++++++++++++++++++++++++----
 src/xterm.h             |  3 +++
 6 files changed, 98 insertions(+), 6 deletions(-)

diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 5ea060871f..7d600b5a0c 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -458,6 +458,16 @@ monitor, the same string as returned by the function
 @var{display} should be the name of an X display (a string).
 @end deffn
 
+@cindex monitor change functions
+@defvar display-monitors-changed-functions
+This variable is an abnormal hook run when the monitor configuration
+changes, which can happen if a monitor is rotated, moved, added or
+removed from a multiple-monitor setup, if the primary monitor changes,
+or if the resolution of a monitor changes.  It is called with a single
+argument consisting of the terminal on which the monitor configuration
+changed.
+@end defvar
+
 @node Frame Geometry
 @section Frame Geometry
 @cindex frame geometry
diff --git a/etc/NEWS b/etc/NEWS
index 70f2c0e6da..5eab8e23bb 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1850,6 +1850,11 @@ functions.
 
 * Lisp Changes in Emacs 29.1
 
++++
+** New hook 'display-monitors-changed-functions'.
+It is called whenever the configuration of different monitors on a
+display changes.
+
 +++
 ** 'prin1' and 'prin1-to-string' now take an optional OVERRIDES parameter.
 This parameter can be used to override values of print-related settings.
diff --git a/src/keyboard.c b/src/keyboard.c
index 481633f92f..a2322f1b49 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4058,6 +4058,18 @@ kbd_buffer_get_event (KBOARD **kbp,
        }
 #endif
 
+      case MONITORS_CHANGED_EVENT:
+       {
+         kbd_fetch_ptr = next_kbd_event (event);
+         input_pending = readable_events (0);
+
+         CALLN (Frun_hook_with_args,
+                Qdisplay_monitors_changed_functions,
+                event->ie.arg);
+
+         break;
+       }
+
 #ifdef HAVE_EXT_MENU_BAR
       case MENU_BAR_ACTIVATE_EVENT:
        {
@@ -12609,6 +12621,8 @@ See also `pre-command-hook'.  */);
   DEFSYM (Qtouchscreen_end, "touchscreen-end");
   DEFSYM (Qtouchscreen_update, "touchscreen-update");
   DEFSYM (Qpinch, "pinch");
+  DEFSYM (Qdisplay_monitors_changed_functions,
+         "display-monitors-changed-functions");
 
   DEFSYM (Qcoding, "coding");
 
@@ -12953,6 +12967,15 @@ Otherwise, a wheel event will be sent every time the 
mouse wheel is
 moved.  */);
   mwheel_coalesce_scroll_events = true;
 
+  DEFVAR_LISP ("display-monitors-changed-functions", 
Vdisplay_monitors_changed_functions,
+    doc: /* Abnormal hook run when the monitor configuration changes.
+This can happen if a monitor is rotated, moved, plugged in or removed
+from a multi-monitor setup, if the primary monitor changes, or if the
+resolution of a monitor changes.  The hook should accept a single
+argument, which is the terminal on which the monitor configuration
+changed.  */);
+  Vdisplay_monitors_changed_functions = Qnil;
+
   pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper);
 }
 
diff --git a/src/termhooks.h b/src/termhooks.h
index 08bde0aec0..d7190e7736 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -31,7 +31,8 @@ struct glyph;
 
 INLINE_HEADER_BEGIN
 
-enum scroll_bar_part {
+enum scroll_bar_part
+{
   scroll_bar_nowhere,
   scroll_bar_above_handle,
   scroll_bar_handle,
@@ -301,8 +302,9 @@ enum event_kind
 #endif
 
 #ifdef HAVE_XWIDGETS
-  /* events generated by xwidgets*/
+  /* An event generated by an xwidget to tell us something.  */
    , XWIDGET_EVENT
+
    /* Event generated when WebKit asks us to display another widget.  */
    , XWIDGET_DISPLAY_EVENT
 #endif
@@ -349,6 +351,11 @@ enum event_kind
          positive delta represents a change clockwise, and a negative
          delta represents a change counter-clockwise.  */
   , PINCH_EVENT
+
+  /* In a MONITORS_CHANGED_EVENT, .arg gives the terminal on which the
+     monitor configuration changed.  .timestamp gives the time on
+     which the monitors changed.  */
+  , MONITORS_CHANGED_EVENT
 };
 
 /* Bit width of an enum event_kind tag at the start of structs and unions.  */
diff --git a/src/xterm.c b/src/xterm.c
index cbe6426447..b321f43da1 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -20103,6 +20103,38 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                }
            }
        }
+#endif
+#ifdef HAVE_XRANDR
+      if (dpyinfo->xrandr_supported_p
+         && (event->type == (dpyinfo->xrandr_event_base
+                             + RRScreenChangeNotify)
+             || event->type == (dpyinfo->xrandr_event_base
+                                + RRNotify)))
+       {
+         union buffered_input_event *ev;
+         Time timestamp;
+
+         if (event->type == (dpyinfo->xrandr_event_base
+                             + RRScreenChangeNotify))
+           timestamp = ((XRRScreenChangeNotifyEvent *) event)->timestamp;
+         else
+           timestamp = 0;
+
+         ev = (kbd_store_ptr == kbd_buffer
+               ? kbd_buffer + KBD_BUFFER_SIZE - 1
+               : kbd_store_ptr - 1);
+
+         if (kbd_store_ptr != kbd_fetch_ptr
+             && ev->ie.kind == MONITORS_CHANGED_EVENT
+             && XTERMINAL (ev->ie.arg) == dpyinfo->terminal)
+           /* Don't store a MONITORS_CHANGED_EVENT if there is
+              already an undelivered event on the queue.  */
+           goto OTHER;
+
+         inev.ie.kind = MONITORS_CHANGED_EVENT;
+         inev.ie.timestamp = timestamp;
+         XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
+       }
 #endif
     OTHER:
 #ifdef USE_X_TOOLKIT
@@ -24405,13 +24437,25 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
 #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)
+  dpyinfo->xrandr_supported_p
+    = XRRQueryExtension (dpy, &dpyinfo->xrandr_event_base,
+                        &dpyinfo->xrandr_error_base);
+  if (dpyinfo->xrandr_supported_p)
     {
       XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
                       &dpyinfo->xrandr_minor_version);
+
+      if (dpyinfo->xrandr_major_version == 1
+         && dpyinfo->xrandr_minor_version >= 2)
+       XRRSelectInput (dpyinfo->display,
+                       dpyinfo->root_window,
+                       (RRScreenChangeNotifyMask
+                        | RRCrtcChangeNotifyMask
+                        | RROutputChangeNotifyMask
+                        /* Emacs doesn't actually need this, but GTK
+                           selects for it when the display is
+                           initialized.  */
+                        | RROutputPropertyNotifyMask));
     }
 #endif
 
diff --git a/src/xterm.h b/src/xterm.h
index a05bc404f6..8571bd9d39 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -602,6 +602,9 @@ struct x_display_info
   XModifierKeymap *modmap;
 
 #ifdef HAVE_XRANDR
+  bool xrandr_supported_p;
+  int xrandr_event_base;
+  int xrandr_error_base;
   int xrandr_major_version;
   int xrandr_minor_version;
 #endif



reply via email to

[Prev in Thread] Current Thread [Next in Thread]