emacs-diffs
[Top][All Lists]
Advanced

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

master b39f1f1 07/35: Implement function for sending events to widgets


From: Lars Ingebrigtsen
Subject: master b39f1f1 07/35: Implement function for sending events to widgets
Date: Sat, 6 Nov 2021 22:01:55 -0400 (EDT)

branch: master
commit b39f1f158ba38d9db43fc714cf3041125ec0fa8a
Author: Po Lu <luangruo@yahoo.com>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Implement function for sending events to widgets
    
    * doc/lispref/display.texi (Xwidgets): Document changes.
    * src/keyboard.c (lispy_function_keys): Make non-static on X.
    * src/keyboard.h (lispy_function_keys): Expose lispy_function_keys on
    X.
    * src/xterm.c (x_emacs_to_x_modifiers): Export function.
    * src/xterm.h (x_emacs_to_x_modifiers): Likewise.
    * src/xwidget.c (Fxwidget_perform_lispy_event)
    (find_suitable_keyboard): New functions.
    (syms_of_xwidget): Define new subr.
---
 doc/lispref/display.texi | 15 ++++++++
 src/keyboard.c           |  2 +-
 src/keyboard.h           |  2 +-
 src/xterm.c              |  4 +-
 src/xterm.h              |  1 +
 src/xwidget.c            | 98 +++++++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 117 insertions(+), 5 deletions(-)

diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 22528a1..eab2c56 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -6878,6 +6878,21 @@ This function returns the current setting of 
@var{xwidget}s
 query-on-exit flag, either @code{t} or @code{nil}.
 @end defun
 
+@defun xwidget-perform-lispy-event xwidget event frame
+Send an input event @var{event} to @var{xwidget}.  The precise action
+performed is platform-specific.  See @ref{Input Events}.
+
+You can optionally pass the frame the event was generated from via
+@var{frame}.  On X11, modifier keys in key events will not be
+considered if @var{frame} is @code{nil}, and the selected frame is not
+an X-Windows frame.
+
+On GTK, only keyboard and function key events are implemented.  Mouse,
+motion, and click events are dispatched to the xwidget without going
+through Lisp code, and as such shouldn't require this function to be
+sent.
+@end defun
+
 @node Buttons
 @section Buttons
 @cindex buttons in buffers
diff --git a/src/keyboard.c b/src/keyboard.c
index aa6a4b9..46dce57 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4897,7 +4897,7 @@ static const char *const lispy_kana_keys[] =
 
 /* You'll notice that this table is arranged to be conveniently
    indexed by X Windows keysym values.  */
-static const char *const lispy_function_keys[] =
+const char *const lispy_function_keys[] =
   {
     /* X Keysym value */
 
diff --git a/src/keyboard.h b/src/keyboard.h
index 8bdffaa..21c51ec 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -491,7 +491,7 @@ extern void process_pending_signals (void);
 extern struct timespec timer_check (void);
 extern void mark_kboards (void);
 
-#ifdef HAVE_NTGUI
+#if defined HAVE_NTGUI || defined HAVE_X_WINDOWS
 extern const char *const lispy_function_keys[];
 #endif
 
diff --git a/src/xterm.c b/src/xterm.c
index 12dad6a..fa7dd9b 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -5087,7 +5087,7 @@ x_x_to_emacs_modifiers (struct x_display_info *dpyinfo, 
int state)
             | ((state & dpyinfo->hyper_mod_mask)       ? mod_hyper     : 0));
 }
 
-static int
+int
 x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, intmax_t state)
 {
   EMACS_INT mod_ctrl = ctrl_modifier;
@@ -9278,7 +9278,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                            event->xbutton.x, event->xbutton.y,
                            event->xbutton.button, event->xbutton.state,
                            event->xbutton.time);
-
+           goto OTHER;
          }
 #endif
         /* If we decide we want to generate an event to be seen
diff --git a/src/xterm.h b/src/xterm.h
index de6ea50..9d9534d 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1108,6 +1108,7 @@ extern void x_mouse_leave (struct x_display_info *);
 extern int x_dispatch_event (XEvent *, Display *);
 #endif
 extern int x_x_to_emacs_modifiers (struct x_display_info *, int);
+extern int x_emacs_to_x_modifiers (struct x_display_info *, intmax_t);
 #ifdef USE_CAIRO
 extern void x_cr_destroy_frame_context (struct frame *);
 extern void x_cr_update_surface_desired_size (struct frame *, int, int);
diff --git a/src/xwidget.c b/src/xwidget.c
index 5a4cb36..ff7d095 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -47,7 +47,8 @@ static uint32_t xwidget_counter = 0;
 #ifdef USE_GTK
 static Lisp_Object x_window_to_xwv_map;
 static gboolean offscreen_damage_event (GtkWidget *, GdkEvent *, gpointer);
-static void synthesize_focus_in_event (GtkWidget *offscreen_window);
+static void synthesize_focus_in_event (GtkWidget *);
+static GdkDevice *find_suitable_keyboard (struct frame *);
 #endif
 
 static struct xwidget *
@@ -208,6 +209,88 @@ Returns the newly constructed xwidget, or nil if 
construction fails.  */)
   return val;
 }
 
+DEFUN ("xwidget-perform-lispy-event",
+       Fxwidget_perform_lispy_event, Sxwidget_perform_lispy_event,
+       2, 3, 0, doc: /* Send a lispy event to XWIDGET.
+EVENT should be the event that will be sent.  FRAME should be the
+frame which generated the event, or nil.  On X11, modifier keys will
+not be processed if FRAME is nil and the selected frame is not an
+X-Windows frame.  */)
+  (Lisp_Object xwidget, Lisp_Object event, Lisp_Object frame)
+{
+  struct xwidget *xw;
+  struct frame *f = NULL;
+  int character = -1, keycode = -1;
+  int modifiers = 0;
+  GdkEvent *xg_event;
+
+  CHECK_XWIDGET (xwidget);
+  xw = XXWIDGET (xwidget);
+
+  if (!NILP (frame))
+    f = decode_window_system_frame (frame);
+  else if (FRAME_X_P (SELECTED_FRAME ()))
+    f = SELECTED_FRAME ();
+
+#ifdef USE_GTK
+  if (RANGED_FIXNUMP (0, event, INT_MAX))
+    {
+      character = XFIXNUM (event);
+      modifiers = x_emacs_to_x_modifiers (FRAME_DISPLAY_INFO (f), character);
+    }
+  else if (SYMBOLP (event))
+    {
+      Lisp_Object decoded = parse_modifiers (event);
+      Lisp_Object decoded_name = SYMBOL_NAME (XCAR (decoded));
+      int off = 0;
+      bool found = false;
+
+      while (off < 256)
+       {
+         puts (SSDATA (decoded_name));
+         if (lispy_function_keys[off]
+             && !strcmp (lispy_function_keys[off],
+                         SSDATA (decoded_name)))
+           {
+             found = true;
+             break;
+           }
+         ++off;
+       }
+
+      if (found)
+       keycode = off + 0xff00;
+    }
+
+  if (character == -1 && keycode == -1)
+    return Qnil;
+
+  block_input ();
+  xg_event = gdk_event_new (GDK_KEY_PRESS);
+  xg_event->any.window = gtk_widget_get_window (xw->widget_osr);
+  g_object_ref (xg_event->any.window);
+
+  if (character > -1)
+    xg_event->key.keyval = gdk_unicode_to_keyval (character & ~(1 << 21));
+  else if (keycode > -1)
+    xg_event->key.keyval = keycode;
+
+  xg_event->key.state = modifiers;
+
+  if (f)
+    gdk_event_set_device (xg_event,
+                         find_suitable_keyboard (SELECTED_FRAME ()));
+
+  gtk_main_do_event (xg_event);
+  xg_event->type = GDK_KEY_RELEASE;
+  gtk_main_do_event (xg_event);
+  gdk_event_free (xg_event);
+  unblock_input ();
+#endif
+
+  return Qnil;
+}
+
 DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets, Sget_buffer_xwidgets,
        1, 1, 0,
        doc: /* Return a list of xwidgets associated with BUFFER.
@@ -265,6 +348,18 @@ find_suitable_pointer (struct frame *f)
   return gdk_seat_get_pointer (seat);
 }
 
+static GdkDevice *
+find_suitable_keyboard (struct frame *f)
+{
+  GdkSeat *seat = gdk_display_get_default_seat
+    (gtk_widget_get_display (FRAME_GTK_WIDGET (f)));
+
+  if (!seat)
+    return NULL;
+
+  return gdk_seat_get_keyboard (seat);
+}
+
 static void
 xwidget_button_1 (struct xwidget_view *view,
                  bool down_p, int x, int y, int button,
@@ -1382,6 +1477,7 @@ syms_of_xwidget (void)
   defsubr (&Sxwidget_plist);
   defsubr (&Sxwidget_buffer);
   defsubr (&Sset_xwidget_plist);
+  defsubr (&Sxwidget_perform_lispy_event);
 
   DEFSYM (QCxwidget, ":xwidget");
   DEFSYM (QCtitle, ":title");



reply via email to

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