[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master f52f772 04/35: Allow xwidgets to accept motion and button events
From: |
Lars Ingebrigtsen |
Subject: |
master f52f772 04/35: Allow xwidgets to accept motion and button events |
Date: |
Sat, 6 Nov 2021 22:01:54 -0400 (EDT) |
branch: master
commit f52f7725305506a75ea4709aff56f3190455b7de
Author: Po Lu <luangruo@yahoo.com>
Commit: Lars Ingebrigtsen <larsi@gnus.org>
Allow xwidgets to accept motion and button events
* src/xterm.c (handle_one_xevent): Pass through some events to
xwidgets.
* src/xwidget.c (synthesize_focus_in_event)
(find_suitable_pointer, xwidget_button_1)
(xwidget_button, xwidget_motion_or_crossing): New functions.
(xwidget_view_from_window): Draw offscreen window instead of the
widget.
(x_draw_xwidget_glyph_string): Set appropriate event masks.
* src/xwidget.h (xwidget_button, xwidget_motion_or_crossing): New
functions.
---
src/xterm.c | 41 +++++++++++++++++
src/xwidget.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/xwidget.h | 4 ++
3 files changed, 187 insertions(+), 2 deletions(-)
diff --git a/src/xterm.c b/src/xterm.c
index 3e8cfb8..12dad6a 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -8893,6 +8893,18 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_display_set_last_user_time (dpyinfo, event->xcrossing.time);
x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+#ifdef HAVE_XWIDGETS
+ {
+ struct xwidget_view *xvw = xwidget_view_from_window
(event->xcrossing.window);
+
+ if (xvw)
+ {
+ xwidget_motion_or_crossing (xvw, event);
+ goto OTHER;
+ }
+ }
+#endif
+
f = any;
if (f && x_mouse_click_focus_ignore_position)
@@ -8936,6 +8948,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
goto OTHER;
case LeaveNotify:
+#ifdef HAVE_XWIDGETS
+ {
+ struct xwidget_view *xvw = xwidget_view_from_window
(event->xcrossing.window);
+
+ if (xvw)
+ {
+ xwidget_motion_or_crossing (xvw, event);
+ goto OTHER;
+ }
+ }
+#endif
x_display_set_last_user_time (dpyinfo, event->xcrossing.time);
x_detect_focus_change (dpyinfo, any, event, &inev.ie);
@@ -8986,6 +9009,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (f && xg_event_is_for_scrollbar (f, event))
f = 0;
#endif
+#ifdef HAVE_XWIDGETS
+ struct xwidget_view *xvw = xwidget_view_from_window
(event->xmotion.window);
+
+ if (xvw)
+ xwidget_motion_or_crossing (xvw, event);
+#endif
if (f)
{
/* Maybe generate a SELECT_WINDOW_EVENT for
@@ -9240,6 +9269,18 @@ handle_one_xevent (struct x_display_info *dpyinfo,
case ButtonRelease:
case ButtonPress:
{
+#ifdef HAVE_XWIDGETS
+ struct xwidget_view *xvw = xwidget_view_from_window
(event->xmotion.window);
+
+ if (xvw)
+ {
+ xwidget_button (xvw, event->type == ButtonPress,
+ event->xbutton.x, event->xbutton.y,
+ event->xbutton.button, event->xbutton.state,
+ event->xbutton.time);
+
+ }
+#endif
/* If we decide we want to generate an event to be seen
by the rest of Emacs, we put it here. */
Lisp_Object tab_bar_arg = Qnil;
diff --git a/src/xwidget.c b/src/xwidget.c
index fe66401..b25f95c 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -47,6 +47,7 @@ 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);
#endif
static struct xwidget *
@@ -170,6 +171,7 @@ Returns the newly constructed xwidget, or nil if
construction fails. */)
gtk_widget_show (xw->widget_osr);
gtk_widget_show (xw->widgetwindow_osr);
+ synthesize_focus_in_event (xw->widgetwindow_osr);
/* Store some xwidget data in the gtk widgets for convenient
retrieval in the event handlers. */
@@ -251,6 +253,143 @@ xwidget_from_id (uint32_t id)
#ifdef USE_GTK
+static GdkDevice *
+find_suitable_pointer (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_pointer (seat);
+}
+
+static void
+xwidget_button_1 (struct xwidget_view *view,
+ bool down_p, int x, int y, int button,
+ int modifier_state, Time time)
+{
+ GdkEvent *xg_event = gdk_event_new (down_p ? GDK_BUTTON_PRESS :
GDK_BUTTON_RELEASE);
+ struct xwidget *model = XXWIDGET (view->model);
+
+ /* X and Y should be relative to the origin of view->wdesc. */
+ x += view->clip_left;
+ y += view->clip_top;
+
+ xg_event->any.window = gtk_widget_get_window (model->widget_osr);
+ g_object_ref (xg_event->any.window); /* The window will be unrefed
+ later by gdk_event_free. */
+
+ xg_event->button.x = x;
+ xg_event->button.x_root = x;
+ xg_event->button.y = y;
+ xg_event->button.y_root = y;
+ xg_event->button.button = button;
+ xg_event->button.state = modifier_state;
+ xg_event->button.time = time;
+ xg_event->button.device = find_suitable_pointer (view->frame);
+
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+}
+
+void
+xwidget_button (struct xwidget_view *view,
+ bool down_p, int x, int y, int button,
+ int modifier_state, Time time)
+{
+ if (button < 4 || button > 8)
+ xwidget_button_1 (view, down_p, x, y, button, modifier_state, time);
+ else
+ {
+ GdkEvent *xg_event = gdk_event_new (GDK_SCROLL);
+ struct xwidget *model = XXWIDGET (view->model);
+
+ xg_event->any.window = gtk_widget_get_window (model->widget_osr);
+ g_object_ref (xg_event->any.window); /* The window will be unrefed
+ later by gdk_event_free. */
+ if (button == 4)
+ xg_event->scroll.direction = GDK_SCROLL_UP;
+ else if (button == 5)
+ xg_event->scroll.direction = GDK_SCROLL_DOWN;
+ else if (button == 6)
+ xg_event->scroll.direction = GDK_SCROLL_LEFT;
+ else
+ xg_event->scroll.direction = GDK_SCROLL_RIGHT;
+
+ xg_event->scroll.device = find_suitable_pointer (view->frame);
+
+ xg_event->scroll.x = x;
+ xg_event->scroll.x_root = x;
+ xg_event->scroll.y = y;
+ xg_event->scroll.y_root = y;
+ xg_event->scroll.state = modifier_state;
+ xg_event->scroll.time = time;
+
+ xg_event->scroll.delta_x = 0;
+ xg_event->scroll.delta_y = 0;
+
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+ }
+}
+
+void
+xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
+{
+ GdkEvent *xg_event = gdk_event_new (event->type == MotionNotify ?
GDK_MOTION_NOTIFY :
+ (event->type == LeaveNotify ?
GDK_LEAVE_NOTIFY :
+ GDK_ENTER_NOTIFY));
+ struct xwidget *model = XXWIDGET (view->model);
+
+ xg_event->any.window = gtk_widget_get_window (model->widget_osr);
+ g_object_ref (xg_event->any.window); /* The window will be unrefed
+ later by gdk_event_free. */
+
+ if (event->type == MotionNotify)
+ {
+ xg_event->motion.x = event->xmotion.x + view->clip_left;
+ xg_event->motion.y = event->xmotion.y + view->clip_top;
+ xg_event->motion.x_root = event->xmotion.x_root;
+ xg_event->motion.y_root = event->xmotion.y_root;
+ xg_event->motion.time = event->xmotion.time;
+ xg_event->motion.device = find_suitable_pointer (view->frame);
+ }
+ else
+ {
+ xg_event->crossing.detail = min (5, event->xcrossing.detail);
+ xg_event->crossing.time = event->xcrossing.time;
+ xg_event->crossing.x = event->xcrossing.x + view->clip_left;
+ xg_event->crossing.y = event->xcrossing.y + view->clip_top;
+ xg_event->crossing.x_root = event->xcrossing.x_root;
+ xg_event->crossing.y_root = event->xcrossing.y_root;
+ }
+
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+}
+
+static void
+synthesize_focus_in_event (GtkWidget *offscreen_window)
+{
+ GdkWindow *wnd;
+ GdkEvent *focus_event;
+
+ if (!gtk_widget_get_realized (offscreen_window))
+ gtk_widget_realize (offscreen_window);
+
+ wnd = gtk_widget_get_window (offscreen_window);
+
+ focus_event = gdk_event_new (GDK_FOCUS_CHANGE);
+ focus_event->any.window = wnd;
+ focus_event->focus_change.in = TRUE;
+ g_object_ref (wnd);
+
+ gtk_main_do_event (focus_event);
+ gdk_event_free (focus_event);
+}
+
struct xwidget_view *
xwidget_view_from_window (Window wdesc)
{
@@ -291,7 +430,7 @@ xv_do_draw (struct xwidget_view *xw, struct xwidget *w)
cairo_save (xw->cr_context);
cairo_translate (xw->cr_context, -xw->clip_left,
-xw->clip_top);
- gtk_widget_draw (w->widget_osr, xw->cr_context);
+ gtk_widget_draw (w->widgetwindow_osr, xw->cr_context);
cairo_restore (xw->cr_context);
unblock_input ();
@@ -704,7 +843,8 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
Lisp_Object xvw;
XSETXWIDGET_VIEW (xvw, xv);
XSetWindowAttributes a;
- a.event_mask = ExposureMask;
+ a.event_mask = (ExposureMask | ButtonPressMask | ButtonReleaseMask
+ | PointerMotionMask);
xv->wdesc = XCreateWindow (xv->dpy, FRAME_X_WINDOW (s->f),
x + clip_left, y + clip_top,
diff --git a/src/xwidget.h b/src/xwidget.h
index f51921d..50d8271 100644
--- a/src/xwidget.h
+++ b/src/xwidget.h
@@ -172,6 +172,10 @@ void xwidget_expose (struct xwidget_view *xv);
extern struct xwidget *xwidget_from_id (uint32_t id);
extern void kill_frame_xwidget_views (struct frame *f);
+extern void xwidget_button (struct xwidget_view *, bool, int,
+ int, int, int, Time);
+extern void xwidget_motion_or_crossing (struct xwidget_view *,
+ const XEvent *);
#else
INLINE_HEADER_BEGIN
INLINE void syms_of_xwidget (void) {}
- master updated (d69b5a9 -> 5b7ab89), Lars Ingebrigtsen, 2021/11/06
- master 61d049a 01/35: Use an X window to display xwidgets on X11, Lars Ingebrigtsen, 2021/11/06
- master 5c387ad 02/35: Enable scrolling optimization for xwidgets, Lars Ingebrigtsen, 2021/11/06
- master 9c9e15a 03/35: Destroy xwidgets when destroying frames, Lars Ingebrigtsen, 2021/11/06
- master 1e16fc2 05/35: Prefer XMoveResizeWindow to XMoveWindow for resizing xwidgets, Lars Ingebrigtsen, 2021/11/06
- master b39f1f1 07/35: Implement function for sending events to widgets, Lars Ingebrigtsen, 2021/11/06
- master f52f772 04/35: Allow xwidgets to accept motion and button events,
Lars Ingebrigtsen <=
- master c9c1b43 06/35: Use gtk_widget_queue_draw instead of xv_do_draw, Lars Ingebrigtsen, 2021/11/06
- master b48a89f 11/35: Fix special events in xwidgets, Lars Ingebrigtsen, 2021/11/06
- master 32b9df6 10/35: Fix drag on xwidget motion events, Lars Ingebrigtsen, 2021/11/06
- master 6ed7454 12/35: Add xwidget-webkit-edit-mode to make using the WebKit browser easier, Lars Ingebrigtsen, 2021/11/06
- master 8ddeebb 13/35: Allow enabling xwidget-webkit-edit-mode via a binding, Lars Ingebrigtsen, 2021/11/06
- master 74711c0 22/35: Display page titles in xwidget webkit header line, Lars Ingebrigtsen, 2021/11/06
- master eb5a079 24/35: Fix cursor for new widget views, Lars Ingebrigtsen, 2021/11/06
- master 1a84537 29/35: Add xwidget-webkit-isearch to the menu bar and tool bar, Lars Ingebrigtsen, 2021/11/06
- master e750329 28/35: Add xwidget-webkit-isearch-mode, Lars Ingebrigtsen, 2021/11/06
- master e111a5f 08/35: Draw offscreen surface, Lars Ingebrigtsen, 2021/11/06