1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-26 07:11:34 -08:00

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.
This commit is contained in:
Po Lu 2021-11-04 18:51:28 +08:00 committed by Lars Ingebrigtsen
parent c9c1b436ae
commit b39f1f158b
6 changed files with 117 additions and 5 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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");