diff options
| author | Po Lu | 2021-12-31 10:07:30 +0800 |
|---|---|---|
| committer | Po Lu | 2021-12-31 10:07:30 +0800 |
| commit | 337005af0bf21244cabdc0b2a2c11d0095ecd0fa (patch) | |
| tree | 3d0036ea1abdcc26546f7e284533978cff80206d | |
| parent | 77f17649d81b2fbe8917264e6b253a95a3f2eea1 (diff) | |
| download | emacs-337005af0bf21244cabdc0b2a2c11d0095ecd0fa.tar.gz emacs-337005af0bf21244cabdc0b2a2c11d0095ecd0fa.zip | |
Add pinch event support to xwidgets
* src/xterm.c (handle_one_xevent): Pass through pinch events to
xwidgets and provide root coordinates when translating motion
events.
* src/xwidget.c (xwidget_motion_notify): Use provided root
window coordinates.
(xwidget_pinch): New function.
* src/xwidget.h (xwidget_motion_notify): Update prototype.
(xwidget_pinch): New function prototype.
| -rw-r--r-- | src/xterm.c | 27 | ||||
| -rw-r--r-- | src/xwidget.c | 77 | ||||
| -rw-r--r-- | src/xwidget.h | 9 |
3 files changed, 106 insertions, 7 deletions
diff --git a/src/xterm.c b/src/xterm.c index afac07e7ff2..d3d85a9e0de 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -10268,7 +10268,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 10268 | && xv_total_y == 0.0)); | 10268 | && xv_total_y == 0.0)); |
| 10269 | else | 10269 | else |
| 10270 | xwidget_motion_notify (xv, xev->event_x, xev->event_y, | 10270 | xwidget_motion_notify (xv, xev->event_x, xev->event_y, |
| 10271 | state, xev->time); | 10271 | xev->root_x, xev->root_y, state, |
| 10272 | xev->time); | ||
| 10272 | 10273 | ||
| 10273 | goto XI_OTHER; | 10274 | goto XI_OTHER; |
| 10274 | } | 10275 | } |
| @@ -11112,6 +11113,17 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 11112 | if (!device || !device->master_p) | 11113 | if (!device || !device->master_p) |
| 11113 | goto XI_OTHER; | 11114 | goto XI_OTHER; |
| 11114 | 11115 | ||
| 11116 | #ifdef HAVE_XWIDGETS | ||
| 11117 | struct xwidget_view *xvw = xwidget_view_from_window (pev->event); | ||
| 11118 | |||
| 11119 | if (xvw) | ||
| 11120 | { | ||
| 11121 | *finish = X_EVENT_DROP; | ||
| 11122 | xwidget_pinch (xvw, pev); | ||
| 11123 | goto XI_OTHER; | ||
| 11124 | } | ||
| 11125 | #endif | ||
| 11126 | |||
| 11115 | any = x_any_window_to_frame (dpyinfo, pev->event); | 11127 | any = x_any_window_to_frame (dpyinfo, pev->event); |
| 11116 | if (any) | 11128 | if (any) |
| 11117 | { | 11129 | { |
| @@ -11133,8 +11145,17 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 11133 | goto XI_OTHER; | 11145 | goto XI_OTHER; |
| 11134 | } | 11146 | } |
| 11135 | case XI_GesturePinchEnd: | 11147 | case XI_GesturePinchEnd: |
| 11136 | *finish = X_EVENT_DROP; | 11148 | { |
| 11137 | goto XI_OTHER; | 11149 | #if defined HAVE_XWIDGETS && HAVE_USABLE_XI_GESTURE_PINCH_EVENT |
| 11150 | XIGesturePinchEvent *pev = (XIGesturePinchEvent *) xi_event; | ||
| 11151 | struct xwidget_view *xvw = xwidget_view_from_window (pev->event); | ||
| 11152 | |||
| 11153 | if (xvw) | ||
| 11154 | xwidget_pinch (xvw, pev); | ||
| 11155 | #endif | ||
| 11156 | *finish = X_EVENT_DROP; | ||
| 11157 | goto XI_OTHER; | ||
| 11158 | } | ||
| 11138 | #endif | 11159 | #endif |
| 11139 | default: | 11160 | default: |
| 11140 | goto XI_OTHER; | 11161 | goto XI_OTHER; |
diff --git a/src/xwidget.c b/src/xwidget.c index 05997bb9d5e..4f14152833e 100644 --- a/src/xwidget.c +++ b/src/xwidget.c | |||
| @@ -1162,7 +1162,9 @@ xwidget_button (struct xwidget_view *view, | |||
| 1162 | #ifdef HAVE_XINPUT2 | 1162 | #ifdef HAVE_XINPUT2 |
| 1163 | void | 1163 | void |
| 1164 | xwidget_motion_notify (struct xwidget_view *view, | 1164 | xwidget_motion_notify (struct xwidget_view *view, |
| 1165 | double x, double y, uint state, Time time) | 1165 | double x, double y, |
| 1166 | double root_x, double root_y, | ||
| 1167 | uint state, Time time) | ||
| 1166 | { | 1168 | { |
| 1167 | GdkEvent *xg_event; | 1169 | GdkEvent *xg_event; |
| 1168 | GtkWidget *target; | 1170 | GtkWidget *target; |
| @@ -1190,8 +1192,8 @@ xwidget_motion_notify (struct xwidget_view *view, | |||
| 1190 | xg_event->any.window = gtk_widget_get_window (target); | 1192 | xg_event->any.window = gtk_widget_get_window (target); |
| 1191 | xg_event->motion.x = target_x; | 1193 | xg_event->motion.x = target_x; |
| 1192 | xg_event->motion.y = target_y; | 1194 | xg_event->motion.y = target_y; |
| 1193 | xg_event->motion.x_root = lrint (x); | 1195 | xg_event->motion.x_root = root_x; |
| 1194 | xg_event->motion.y_root = lrint (y); | 1196 | xg_event->motion.y_root = root_y; |
| 1195 | xg_event->motion.time = time; | 1197 | xg_event->motion.time = time; |
| 1196 | xg_event->motion.state = state; | 1198 | xg_event->motion.state = state; |
| 1197 | xg_event->motion.device = find_suitable_pointer (view->frame); | 1199 | xg_event->motion.device = find_suitable_pointer (view->frame); |
| @@ -1248,6 +1250,70 @@ xwidget_scroll (struct xwidget_view *view, double x, double y, | |||
| 1248 | gtk_main_do_event (xg_event); | 1250 | gtk_main_do_event (xg_event); |
| 1249 | gdk_event_free (xg_event); | 1251 | gdk_event_free (xg_event); |
| 1250 | } | 1252 | } |
| 1253 | |||
| 1254 | #ifdef HAVE_USABLE_XI_GESTURE_PINCH_EVENT | ||
| 1255 | void | ||
| 1256 | xwidget_pinch (struct xwidget_view *view, XIGesturePinchEvent *xev) | ||
| 1257 | { | ||
| 1258 | #if GTK_CHECK_VERSION (3, 18, 0) | ||
| 1259 | GdkEvent *xg_event; | ||
| 1260 | GtkWidget *target; | ||
| 1261 | struct xwidget *model = XXWIDGET (view->model); | ||
| 1262 | int target_x, target_y; | ||
| 1263 | double x = xev->event_x; | ||
| 1264 | double y = xev->event_y; | ||
| 1265 | |||
| 1266 | if (NILP (model->buffer)) | ||
| 1267 | return; | ||
| 1268 | |||
| 1269 | record_osr_embedder (view); | ||
| 1270 | |||
| 1271 | target = find_widget_at_pos (model->widgetwindow_osr, | ||
| 1272 | lrint (x + view->clip_left), | ||
| 1273 | lrint (y + view->clip_top), | ||
| 1274 | &target_x, &target_y); | ||
| 1275 | |||
| 1276 | if (!target) | ||
| 1277 | { | ||
| 1278 | target_x = lrint (x); | ||
| 1279 | target_y = lrint (y); | ||
| 1280 | target = model->widget_osr; | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | xg_event = gdk_event_new (GDK_TOUCHPAD_PINCH); | ||
| 1284 | xg_event->any.window = gtk_widget_get_window (target); | ||
| 1285 | xg_event->touchpad_pinch.x = target_x; | ||
| 1286 | xg_event->touchpad_pinch.y = target_y; | ||
| 1287 | xg_event->touchpad_pinch.dx = xev->delta_x; | ||
| 1288 | xg_event->touchpad_pinch.dy = xev->delta_y; | ||
| 1289 | xg_event->touchpad_pinch.angle_delta = xev->delta_angle; | ||
| 1290 | xg_event->touchpad_pinch.scale = xev->scale; | ||
| 1291 | xg_event->touchpad_pinch.x_root = xev->root_x; | ||
| 1292 | xg_event->touchpad_pinch.y_root = xev->root_y; | ||
| 1293 | xg_event->touchpad_pinch.state = xev->mods.effective; | ||
| 1294 | xg_event->touchpad_pinch.n_fingers = 2; | ||
| 1295 | |||
| 1296 | switch (xev->evtype) | ||
| 1297 | { | ||
| 1298 | case XI_GesturePinchBegin: | ||
| 1299 | xg_event->touchpad_pinch.phase = GDK_TOUCHPAD_GESTURE_PHASE_BEGIN; | ||
| 1300 | break; | ||
| 1301 | case XI_GesturePinchUpdate: | ||
| 1302 | xg_event->touchpad_pinch.phase = GDK_TOUCHPAD_GESTURE_PHASE_UPDATE; | ||
| 1303 | break; | ||
| 1304 | case XI_GesturePinchEnd: | ||
| 1305 | xg_event->touchpad_pinch.phase = GDK_TOUCHPAD_GESTURE_PHASE_END; | ||
| 1306 | break; | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | gdk_event_set_device (xg_event, find_suitable_pointer (view->frame)); | ||
| 1310 | |||
| 1311 | g_object_ref (xg_event->any.window); | ||
| 1312 | gtk_main_do_event (xg_event); | ||
| 1313 | gdk_event_free (xg_event); | ||
| 1314 | #endif | ||
| 1315 | } | ||
| 1316 | #endif | ||
| 1251 | #endif | 1317 | #endif |
| 1252 | 1318 | ||
| 1253 | #ifdef HAVE_XINPUT2 | 1319 | #ifdef HAVE_XINPUT2 |
| @@ -2180,6 +2246,11 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) | |||
| 2180 | XISetMask (m, XI_ButtonRelease); | 2246 | XISetMask (m, XI_ButtonRelease); |
| 2181 | XISetMask (m, XI_Enter); | 2247 | XISetMask (m, XI_Enter); |
| 2182 | XISetMask (m, XI_Leave); | 2248 | XISetMask (m, XI_Leave); |
| 2249 | #ifdef XI_GesturePinchBegin | ||
| 2250 | XISetMask (m, XI_GesturePinchBegin); | ||
| 2251 | XISetMask (m, XI_GesturePinchUpdate); | ||
| 2252 | XISetMask (m, XI_GesturePinchEnd); | ||
| 2253 | #endif | ||
| 2183 | XISelectEvents (xv->dpy, xv->wdesc, &mask, 1); | 2254 | XISelectEvents (xv->dpy, xv->wdesc, &mask, 1); |
| 2184 | } | 2255 | } |
| 2185 | #endif | 2256 | #endif |
diff --git a/src/xwidget.h b/src/xwidget.h index ab60b9ed34f..0c6ed1a3813 100644 --- a/src/xwidget.h +++ b/src/xwidget.h | |||
| @@ -43,6 +43,10 @@ struct window; | |||
| 43 | #import "nsxwidget.h" | 43 | #import "nsxwidget.h" |
| 44 | #endif | 44 | #endif |
| 45 | 45 | ||
| 46 | #ifdef HAVE_XINPUT2 | ||
| 47 | #include <X11/extensions/XInput2.h> | ||
| 48 | #endif | ||
| 49 | |||
| 46 | struct xwidget | 50 | struct xwidget |
| 47 | { | 51 | { |
| 48 | union vectorlike_header header; | 52 | union vectorlike_header header; |
| @@ -210,9 +214,12 @@ extern void xwidget_motion_or_crossing (struct xwidget_view *, | |||
| 210 | const XEvent *); | 214 | const XEvent *); |
| 211 | #ifdef HAVE_XINPUT2 | 215 | #ifdef HAVE_XINPUT2 |
| 212 | extern void xwidget_motion_notify (struct xwidget_view *, double, | 216 | extern void xwidget_motion_notify (struct xwidget_view *, double, |
| 213 | double, uint, Time); | 217 | double, double, double, uint, Time); |
| 214 | extern void xwidget_scroll (struct xwidget_view *, double, double, | 218 | extern void xwidget_scroll (struct xwidget_view *, double, double, |
| 215 | double, double, uint, Time, bool); | 219 | double, double, uint, Time, bool); |
| 220 | #ifdef HAVE_USABLE_XI_GESTURE_PINCH_EVENT | ||
| 221 | extern void xwidget_pinch (struct xwidget_view *, XIGesturePinchEvent *); | ||
| 222 | #endif | ||
| 216 | #endif | 223 | #endif |
| 217 | #endif | 224 | #endif |
| 218 | #else | 225 | #else |