]> git.eshelyaron.com Git - emacs.git/commitdiff
Keep track of keyboard state during drag and drop
authorPo Lu <luangruo@yahoo.com>
Thu, 14 Apr 2022 11:02:13 +0000 (19:02 +0800)
committerPo Lu <luangruo@yahoo.com>
Thu, 14 Apr 2022 11:02:13 +0000 (19:02 +0800)
* src/xterm.c (x_dnd_cleanup_drag_and_drop): Deselect for
keyboard state changes.
(x_dnd_begin_drag_and_drop): Select for keyboard state changes
when XKB is available.
(x_dnd_update_state, handle_one_xevent): Use current XKB state
if it is available.
(x_term_init): Reformat code a little.

src/xterm.c

index 94f8ce33bb010cc1cd4bb4ff93cef6781fe33019..da4af8bff75c4bc8312e9a28f751ea91da189686 100644 (file)
@@ -986,6 +986,11 @@ static struct frame *x_dnd_movement_frame;
    with.  */
 static int x_dnd_movement_x, x_dnd_movement_y;
 
+#ifdef HAVE_XKB
+/* The keyboard state during the drag-and-drop operation.  */
+static unsigned int x_dnd_keyboard_state;
+#endif
+
 struct x_client_list_window
 {
   Window window;
@@ -3608,6 +3613,11 @@ x_dnd_cleanup_drag_and_drop (void *frame)
   XSelectInput (FRAME_X_DISPLAY (f),
                FRAME_DISPLAY_INFO (f)->root_window,
                x_dnd_old_window_attrs.your_event_mask);
+
+#ifdef HAVE_XKB
+  XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
+                  XkbStateNotifyMask, 0);
+#endif
   unblock_input ();
 
   x_dnd_frame = NULL;
@@ -9447,6 +9457,9 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
   XTextProperty prop;
   xm_drop_start_message dmsg;
   Lisp_Object frame_object, x, y, frame, local_value;
+#ifdef HAVE_XKB
+  XkbStateRec keyboard_state;
+#endif
 
   if (!FRAME_VISIBLE_P (f))
     {
@@ -9557,6 +9570,20 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
   x_dnd_toplevels = NULL;
   x_dnd_allow_current_frame = allow_current_frame;
   x_dnd_movement_frame = NULL;
+#ifdef HAVE_XKB
+  x_dnd_keyboard_state = 0;
+
+  if (FRAME_DISPLAY_INFO (f)->supports_xkb)
+    {
+      XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
+                      XkbStateNotifyMask, XkbStateNotifyMask);
+      XkbGetState (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
+                  &keyboard_state);
+
+      x_dnd_keyboard_state = (keyboard_state.mods
+                             | keyboard_state.ptr_buttons);
+    }
+#endif
 
   if (x_dnd_use_toplevels)
     {
@@ -9573,10 +9600,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
   if (EQ (return_frame, Qnow))
     x_dnd_return_frame = 2;
 
-#ifdef USE_GTK
-  current_count = 0;
-#endif
-
   /* Now select for SubstructureNotifyMask and PropertyNotifyMask on
      the root window, so we can get notified when window stacking
      changes, a common operation during drag-and-drop.  */
@@ -9600,6 +9623,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
 #ifdef USE_GTK
       current_finish = X_EVENT_NORMAL;
       current_hold_quit = &hold_quit;
+      current_count = 0;
 #endif
 
       block_input ();
@@ -9735,6 +9759,10 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
          XSelectInput (FRAME_X_DISPLAY (f),
                        FRAME_DISPLAY_INFO (f)->root_window,
                        root_window_attrs.your_event_mask);
+#ifdef HAVE_XKB
+         XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
+                          XkbStateNotifyMask, 0);
+#endif
          quit ();
        }
     }
@@ -9752,6 +9780,10 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
   XSelectInput (FRAME_X_DISPLAY (f),
                FRAME_DISPLAY_INFO (f)->root_window,
                root_window_attrs.your_event_mask);
+#ifdef HAVE_XKB
+  XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
+                  XkbStateNotifyMask, 0);
+#endif
   unblock_input ();
 
   if (x_dnd_return_frame == 3
@@ -13506,7 +13538,13 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp)
                             x_dnd_last_protocol_version,
                             root_x, root_y,
                             x_dnd_selection_timestamp,
-                            x_dnd_wanted_action, 0, 0);
+                            x_dnd_wanted_action, 0,
+#ifdef HAVE_XKB
+                            x_dnd_keyboard_state
+#else
+                            0
+#endif
+                            );
       else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None)
        {
          if (!x_dnd_motif_setup_p)
@@ -18531,6 +18569,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              XkbRefreshKeyboardMapping (&xkbevent->map);
              x_find_modifier_meanings (dpyinfo);
            }
+         else if (x_dnd_in_progress
+                  && xkbevent->any.xkb_type == XkbStateNotify)
+           x_dnd_keyboard_state = (xkbevent->state.mods
+                                   | xkbevent->state.ptr_buttons);
        }
 #endif
 #ifdef HAVE_XSHAPE
@@ -23001,8 +23043,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
                     XkbGroupNamesMask | XkbVirtualModNamesMask,
                     dpyinfo->xkb_desc);
 
-      XkbSelectEvents (dpyinfo->display,
-                      XkbUseCoreKbd,
+      XkbSelectEvents (dpyinfo->display, XkbUseCoreKbd,
                       XkbNewKeyboardNotifyMask | XkbMapNotifyMask,
                       XkbNewKeyboardNotifyMask | XkbMapNotifyMask);
     }