aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2021-11-04 18:51:28 +0800
committerLars Ingebrigtsen2021-11-07 02:59:40 +0100
commitb39f1f158ba38d9db43fc714cf3041125ec0fa8a (patch)
tree70b3ea84ed72f137e60fd78f43fd87d59a32993b
parentc9c1b436ae638cc7f54e203674c61a9a2633d4ec (diff)
downloademacs-b39f1f158ba38d9db43fc714cf3041125ec0fa8a.tar.gz
emacs-b39f1f158ba38d9db43fc714cf3041125ec0fa8a.zip
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.
-rw-r--r--doc/lispref/display.texi15
-rw-r--r--src/keyboard.c2
-rw-r--r--src/keyboard.h2
-rw-r--r--src/xterm.c4
-rw-r--r--src/xterm.h1
-rw-r--r--src/xwidget.c98
6 files changed, 117 insertions, 5 deletions
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 22528a1b0fd..eab2c56dffa 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
6878query-on-exit flag, either @code{t} or @code{nil}. 6878query-on-exit flag, either @code{t} or @code{nil}.
6879@end defun 6879@end defun
6880 6880
6881@defun xwidget-perform-lispy-event xwidget event frame
6882Send an input event @var{event} to @var{xwidget}. The precise action
6883performed is platform-specific. See @ref{Input Events}.
6884
6885You can optionally pass the frame the event was generated from via
6886@var{frame}. On X11, modifier keys in key events will not be
6887considered if @var{frame} is @code{nil}, and the selected frame is not
6888an X-Windows frame.
6889
6890On GTK, only keyboard and function key events are implemented. Mouse,
6891motion, and click events are dispatched to the xwidget without going
6892through Lisp code, and as such shouldn't require this function to be
6893sent.
6894@end defun
6895
6881@node Buttons 6896@node Buttons
6882@section Buttons 6897@section Buttons
6883@cindex buttons in buffers 6898@cindex buttons in buffers
diff --git a/src/keyboard.c b/src/keyboard.c
index aa6a4b9e976..46dce5755a8 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4897,7 +4897,7 @@ static const char *const lispy_kana_keys[] =
4897 4897
4898/* You'll notice that this table is arranged to be conveniently 4898/* You'll notice that this table is arranged to be conveniently
4899 indexed by X Windows keysym values. */ 4899 indexed by X Windows keysym values. */
4900static const char *const lispy_function_keys[] = 4900const char *const lispy_function_keys[] =
4901 { 4901 {
4902 /* X Keysym value */ 4902 /* X Keysym value */
4903 4903
diff --git a/src/keyboard.h b/src/keyboard.h
index 8bdffaa2bff..21c51ec3862 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -491,7 +491,7 @@ extern void process_pending_signals (void);
491extern struct timespec timer_check (void); 491extern struct timespec timer_check (void);
492extern void mark_kboards (void); 492extern void mark_kboards (void);
493 493
494#ifdef HAVE_NTGUI 494#if defined HAVE_NTGUI || defined HAVE_X_WINDOWS
495extern const char *const lispy_function_keys[]; 495extern const char *const lispy_function_keys[];
496#endif 496#endif
497 497
diff --git a/src/xterm.c b/src/xterm.c
index 12dad6ae806..fa7dd9b9ca0 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)
5087 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0)); 5087 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
5088} 5088}
5089 5089
5090static int 5090int
5091x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, intmax_t state) 5091x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, intmax_t state)
5092{ 5092{
5093 EMACS_INT mod_ctrl = ctrl_modifier; 5093 EMACS_INT mod_ctrl = ctrl_modifier;
@@ -9278,7 +9278,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
9278 event->xbutton.x, event->xbutton.y, 9278 event->xbutton.x, event->xbutton.y,
9279 event->xbutton.button, event->xbutton.state, 9279 event->xbutton.button, event->xbutton.state,
9280 event->xbutton.time); 9280 event->xbutton.time);
9281 9281 goto OTHER;
9282 } 9282 }
9283#endif 9283#endif
9284 /* If we decide we want to generate an event to be seen 9284 /* If we decide we want to generate an event to be seen
diff --git a/src/xterm.h b/src/xterm.h
index de6ea50385d..9d9534dd629 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1108,6 +1108,7 @@ extern void x_mouse_leave (struct x_display_info *);
1108extern int x_dispatch_event (XEvent *, Display *); 1108extern int x_dispatch_event (XEvent *, Display *);
1109#endif 1109#endif
1110extern int x_x_to_emacs_modifiers (struct x_display_info *, int); 1110extern int x_x_to_emacs_modifiers (struct x_display_info *, int);
1111extern int x_emacs_to_x_modifiers (struct x_display_info *, intmax_t);
1111#ifdef USE_CAIRO 1112#ifdef USE_CAIRO
1112extern void x_cr_destroy_frame_context (struct frame *); 1113extern void x_cr_destroy_frame_context (struct frame *);
1113extern void x_cr_update_surface_desired_size (struct frame *, int, int); 1114extern void x_cr_update_surface_desired_size (struct frame *, int, int);
diff --git a/src/xwidget.c b/src/xwidget.c
index 5a4cb36ee47..ff7d09549bf 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -47,7 +47,8 @@ static uint32_t xwidget_counter = 0;
47#ifdef USE_GTK 47#ifdef USE_GTK
48static Lisp_Object x_window_to_xwv_map; 48static Lisp_Object x_window_to_xwv_map;
49static gboolean offscreen_damage_event (GtkWidget *, GdkEvent *, gpointer); 49static gboolean offscreen_damage_event (GtkWidget *, GdkEvent *, gpointer);
50static void synthesize_focus_in_event (GtkWidget *offscreen_window); 50static void synthesize_focus_in_event (GtkWidget *);
51static GdkDevice *find_suitable_keyboard (struct frame *);
51#endif 52#endif
52 53
53static struct xwidget * 54static struct xwidget *
@@ -208,6 +209,88 @@ Returns the newly constructed xwidget, or nil if construction fails. */)
208 return val; 209 return val;
209} 210}
210 211
212DEFUN ("xwidget-perform-lispy-event",
213 Fxwidget_perform_lispy_event, Sxwidget_perform_lispy_event,
214 2, 3, 0, doc: /* Send a lispy event to XWIDGET.
215EVENT should be the event that will be sent. FRAME should be the
216frame which generated the event, or nil. On X11, modifier keys will
217not be processed if FRAME is nil and the selected frame is not an
218X-Windows frame. */)
219 (Lisp_Object xwidget, Lisp_Object event, Lisp_Object frame)
220{
221 struct xwidget *xw;
222 struct frame *f = NULL;
223 int character = -1, keycode = -1;
224 int modifiers = 0;
225 GdkEvent *xg_event;
226
227 CHECK_XWIDGET (xwidget);
228 xw = XXWIDGET (xwidget);
229
230 if (!NILP (frame))
231 f = decode_window_system_frame (frame);
232 else if (FRAME_X_P (SELECTED_FRAME ()))
233 f = SELECTED_FRAME ();
234
235#ifdef USE_GTK
236 if (RANGED_FIXNUMP (0, event, INT_MAX))
237 {
238 character = XFIXNUM (event);
239 modifiers = x_emacs_to_x_modifiers (FRAME_DISPLAY_INFO (f), character);
240 }
241 else if (SYMBOLP (event))
242 {
243 Lisp_Object decoded = parse_modifiers (event);
244 Lisp_Object decoded_name = SYMBOL_NAME (XCAR (decoded));
245 int off = 0;
246 bool found = false;
247
248 while (off < 256)
249 {
250 puts (SSDATA (decoded_name));
251 if (lispy_function_keys[off]
252 && !strcmp (lispy_function_keys[off],
253 SSDATA (decoded_name)))
254 {
255 found = true;
256 break;
257 }
258 ++off;
259 }
260
261 if (found)
262 keycode = off + 0xff00;
263 }
264
265 if (character == -1 && keycode == -1)
266 return Qnil;
267
268 block_input ();
269 xg_event = gdk_event_new (GDK_KEY_PRESS);
270 xg_event->any.window = gtk_widget_get_window (xw->widget_osr);
271 g_object_ref (xg_event->any.window);
272
273 if (character > -1)
274 xg_event->key.keyval = gdk_unicode_to_keyval (character & ~(1 << 21));
275 else if (keycode > -1)
276 xg_event->key.keyval = keycode;
277
278 xg_event->key.state = modifiers;
279
280 if (f)
281 gdk_event_set_device (xg_event,
282 find_suitable_keyboard (SELECTED_FRAME ()));
283
284 gtk_main_do_event (xg_event);
285 xg_event->type = GDK_KEY_RELEASE;
286 gtk_main_do_event (xg_event);
287 gdk_event_free (xg_event);
288 unblock_input ();
289#endif
290
291 return Qnil;
292}
293
211DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets, Sget_buffer_xwidgets, 294DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets, Sget_buffer_xwidgets,
212 1, 1, 0, 295 1, 1, 0,
213 doc: /* Return a list of xwidgets associated with BUFFER. 296 doc: /* Return a list of xwidgets associated with BUFFER.
@@ -265,6 +348,18 @@ find_suitable_pointer (struct frame *f)
265 return gdk_seat_get_pointer (seat); 348 return gdk_seat_get_pointer (seat);
266} 349}
267 350
351static GdkDevice *
352find_suitable_keyboard (struct frame *f)
353{
354 GdkSeat *seat = gdk_display_get_default_seat
355 (gtk_widget_get_display (FRAME_GTK_WIDGET (f)));
356
357 if (!seat)
358 return NULL;
359
360 return gdk_seat_get_keyboard (seat);
361}
362
268static void 363static void
269xwidget_button_1 (struct xwidget_view *view, 364xwidget_button_1 (struct xwidget_view *view,
270 bool down_p, int x, int y, int button, 365 bool down_p, int x, int y, int button,
@@ -1382,6 +1477,7 @@ syms_of_xwidget (void)
1382 defsubr (&Sxwidget_plist); 1477 defsubr (&Sxwidget_plist);
1383 defsubr (&Sxwidget_buffer); 1478 defsubr (&Sxwidget_buffer);
1384 defsubr (&Sset_xwidget_plist); 1479 defsubr (&Sset_xwidget_plist);
1480 defsubr (&Sxwidget_perform_lispy_event);
1385 1481
1386 DEFSYM (QCxwidget, ":xwidget"); 1482 DEFSYM (QCxwidget, ":xwidget");
1387 DEFSYM (QCtitle, ":title"); 1483 DEFSYM (QCtitle, ":title");