mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-06 05:52:32 -08:00
Allow handling smooth scroll events in xwidgets
* src/xterm.c (handle_one_xevent): Pass through XI2 motion events to xwidgets. * src/xterm.c (xwidget_button): Don't handle legacy scroll events on XInput 2. (xwidget_motion_notify, xwidget_scroll): New functions.
This commit is contained in:
parent
f16bb8693f
commit
39f3604e22
3 changed files with 151 additions and 0 deletions
32
src/xterm.c
32
src/xterm.c
|
|
@ -9927,6 +9927,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
|
||||
x_display_set_last_user_time (dpyinfo, xi_event->time);
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
struct xwidget_view *xv = xwidget_view_from_window (xev->event);
|
||||
double xv_total_x = 0.0;
|
||||
double xv_total_y = 0.0;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < states->mask_len * 8; i++)
|
||||
{
|
||||
if (XIMaskIsSet (states->mask, i))
|
||||
|
|
@ -9939,6 +9945,18 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
|
||||
if (delta != DBL_MAX)
|
||||
{
|
||||
#ifdef HAVE_XWIDGETS
|
||||
if (xv)
|
||||
{
|
||||
if (val->horizontal)
|
||||
xv_total_x += delta;
|
||||
else
|
||||
xv_total_y += -delta;
|
||||
|
||||
found_valuator = true;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (!f)
|
||||
{
|
||||
f = x_any_window_to_frame (dpyinfo, xev->event);
|
||||
|
|
@ -9999,6 +10017,20 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
inev.ie.kind = NO_EVENT;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
if (xv)
|
||||
{
|
||||
if (found_valuator)
|
||||
xwidget_scroll (xv, xev->event_x, xev->event_y,
|
||||
xv_total_x, xv_total_y, xev->mods.effective,
|
||||
xev->time);
|
||||
else
|
||||
xwidget_motion_notify (xv, xev->event_x, xev->event_y,
|
||||
xev->mods.effective, xev->time);
|
||||
|
||||
goto XI_OTHER;
|
||||
}
|
||||
#endif
|
||||
if (found_valuator)
|
||||
goto XI_OTHER;
|
||||
|
||||
|
|
|
|||
113
src/xwidget.c
113
src/xwidget.c
|
|
@ -40,10 +40,15 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include <JavaScriptCore/JavaScript.h>
|
||||
#include <cairo.h>
|
||||
#include <X11/Xlib.h>
|
||||
#ifdef HAVE_XINPUT2
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#endif
|
||||
#elif defined NS_IMPL_COCOA
|
||||
#include "nsxwidget.h"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
static Lisp_Object id_to_xwidget_map;
|
||||
static Lisp_Object internal_xwidget_view_list;
|
||||
static Lisp_Object internal_xwidget_list;
|
||||
|
|
@ -912,7 +917,12 @@ xwidget_button (struct xwidget_view *view,
|
|||
|
||||
if (button < 4 || button > 8)
|
||||
xwidget_button_1 (view, down_p, x, y, button, modifier_state, time);
|
||||
#ifndef HAVE_XINPUT2
|
||||
else
|
||||
#else
|
||||
else if (!FRAME_DISPLAY_INFO (view->frame)->supports_xi2
|
||||
|| FRAME_DISPLAY_INFO (view->frame)->xi2_version < 1)
|
||||
#endif
|
||||
{
|
||||
GdkEvent *xg_event = gdk_event_new (GDK_SCROLL);
|
||||
struct xwidget *model = XXWIDGET (view->model);
|
||||
|
|
@ -955,6 +965,93 @@ xwidget_button (struct xwidget_view *view,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
void
|
||||
xwidget_motion_notify (struct xwidget_view *view,
|
||||
double x, double y, uint state, Time time)
|
||||
{
|
||||
GdkEvent *xg_event;
|
||||
GtkWidget *target;
|
||||
struct xwidget *model = XXWIDGET (view->model);
|
||||
int target_x, target_y;
|
||||
|
||||
if (NILP (model->buffer))
|
||||
return;
|
||||
|
||||
record_osr_embedder (view);
|
||||
|
||||
target = find_widget_at_pos (model->widgetwindow_osr,
|
||||
lrint (x), lrint (y),
|
||||
&target_x, &target_y);
|
||||
|
||||
if (!target)
|
||||
{
|
||||
target_x = lrint (x);
|
||||
target_y = lrint (y);
|
||||
target = model->widget_osr;
|
||||
}
|
||||
|
||||
xg_event = gdk_event_new (GDK_MOTION_NOTIFY);
|
||||
xg_event->any.window = gtk_widget_get_window (target);
|
||||
xg_event->motion.x = target_x;
|
||||
xg_event->motion.y = target_y;
|
||||
xg_event->motion.x_root = lrint (x);
|
||||
xg_event->motion.y_root = lrint (y);
|
||||
xg_event->motion.time = time;
|
||||
xg_event->motion.state = state;
|
||||
xg_event->motion.device = find_suitable_pointer (view->frame);
|
||||
|
||||
g_object_ref (xg_event->any.window);
|
||||
|
||||
gtk_main_do_event (xg_event);
|
||||
gdk_event_free (xg_event);
|
||||
}
|
||||
|
||||
void
|
||||
xwidget_scroll (struct xwidget_view *view, double x, double y,
|
||||
double dx, double dy, uint state, Time time)
|
||||
{
|
||||
GdkEvent *xg_event;
|
||||
GtkWidget *target;
|
||||
struct xwidget *model = XXWIDGET (view->model);
|
||||
int target_x, target_y;
|
||||
|
||||
if (NILP (model->buffer))
|
||||
return;
|
||||
|
||||
record_osr_embedder (view);
|
||||
|
||||
target = find_widget_at_pos (model->widgetwindow_osr,
|
||||
lrint (x), lrint (y),
|
||||
&target_x, &target_y);
|
||||
|
||||
if (!target)
|
||||
{
|
||||
target_x = lrint (x);
|
||||
target_y = lrint (y);
|
||||
target = model->widget_osr;
|
||||
}
|
||||
|
||||
xg_event = gdk_event_new (GDK_SCROLL);
|
||||
xg_event->any.window = gtk_widget_get_window (target);
|
||||
xg_event->scroll.direction = GDK_SCROLL_SMOOTH;
|
||||
xg_event->scroll.x = target_x;
|
||||
xg_event->scroll.y = target_y;
|
||||
xg_event->scroll.x_root = lrint (x);
|
||||
xg_event->scroll.y_root = lrint (y);
|
||||
xg_event->scroll.time = time;
|
||||
xg_event->scroll.state = state;
|
||||
xg_event->scroll.delta_x = dx;
|
||||
xg_event->scroll.delta_y = dy;
|
||||
xg_event->scroll.device = find_suitable_pointer (view->frame);
|
||||
|
||||
g_object_ref (xg_event->any.window);
|
||||
|
||||
gtk_main_do_event (xg_event);
|
||||
gdk_event_free (xg_event);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
|
||||
{
|
||||
|
|
@ -1705,6 +1802,22 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
|
|||
clip_bottom - clip_top, 0,
|
||||
CopyFromParent, CopyFromParent,
|
||||
CopyFromParent, CWEventMask, &a);
|
||||
#ifdef HAVE_XINPUT2
|
||||
XIEventMask mask;
|
||||
ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
|
||||
unsigned char *m;
|
||||
|
||||
if (FRAME_DISPLAY_INFO (s->f)->supports_xi2)
|
||||
{
|
||||
mask.mask = m = alloca (l);
|
||||
memset (m, 0, l);
|
||||
mask.mask_len = l;
|
||||
mask.deviceid = XIAllMasterDevices;
|
||||
|
||||
XISetMask (m, XI_Motion);
|
||||
XISelectEvents (xv->dpy, xv->wdesc, &mask, 1);
|
||||
}
|
||||
#endif
|
||||
XLowerWindow (xv->dpy, xv->wdesc);
|
||||
XDefineCursor (xv->dpy, xv->wdesc, xv->cursor);
|
||||
xv->cr_surface = cairo_xlib_surface_create (xv->dpy,
|
||||
|
|
|
|||
|
|
@ -195,6 +195,12 @@ extern void xwidget_button (struct xwidget_view *, bool, int,
|
|||
int, int, int, Time);
|
||||
extern void xwidget_motion_or_crossing (struct xwidget_view *,
|
||||
const XEvent *);
|
||||
#ifdef HAVE_XINPUT2
|
||||
extern void xwidget_motion_notify (struct xwidget_view *, double,
|
||||
double, uint, Time);
|
||||
extern void xwidget_scroll (struct xwidget_view *, double, double,
|
||||
double, double, uint, Time);
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
INLINE_HEADER_BEGIN
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue