aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-02-28 20:21:24 +0800
committerPo Lu2022-02-28 20:21:24 +0800
commitcde8e5afbb651f1be04b5e79db984d00d751ca04 (patch)
treea7a9f6e95ea9da25db5e5efd401346b732f776a1 /src
parent122b189219054f0c4a625e9707d2c0d37f472760 (diff)
downloademacs-cde8e5afbb651f1be04b5e79db984d00d751ca04.tar.gz
emacs-cde8e5afbb651f1be04b5e79db984d00d751ca04.zip
Clean up input extension event handling code
* src/xterm.c (handle_one_xevent): Fix usages of event structures of the wrong type.
Diffstat (limited to 'src')
-rw-r--r--src/xterm.c371
1 files changed, 192 insertions, 179 deletions
diff --git a/src/xterm.c b/src/xterm.c
index f5bb9908bce..64c340e4dc5 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -11229,6 +11229,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
11229 case DestroyNotify: 11229 case DestroyNotify:
11230 xft_settings_event (dpyinfo, event); 11230 xft_settings_event (dpyinfo, event);
11231 break; 11231 break;
11232
11232#ifdef HAVE_XINPUT2 11233#ifdef HAVE_XINPUT2
11233 case GenericEvent: 11234 case GenericEvent:
11234 { 11235 {
@@ -11248,11 +11249,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
11248 } 11249 }
11249 11250
11250 XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; 11251 XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
11251 XILeaveEvent *leave = (XILeaveEvent *) xi_event;
11252 XIEnterEvent *enter = (XIEnterEvent *) xi_event;
11253 XIFocusInEvent *focusin = (XIFocusInEvent *) xi_event;
11254 XIFocusOutEvent *focusout = (XIFocusOutEvent *) xi_event;
11255 XIDeviceChangedEvent *device_changed = (XIDeviceChangedEvent *) xi_event;
11256#ifdef HAVE_XINPUT2_1 11252#ifdef HAVE_XINPUT2_1
11257 XIValuatorState *states; 11253 XIValuatorState *states;
11258 double *values; 11254 double *values;
@@ -11273,229 +11269,245 @@ handle_one_xevent (struct x_display_info *dpyinfo,
11273 switch (event->xcookie.evtype) 11269 switch (event->xcookie.evtype)
11274 { 11270 {
11275 case XI_FocusIn: 11271 case XI_FocusIn:
11276 any = x_any_window_to_frame (dpyinfo, focusin->event); 11272 {
11273 XIFocusInEvent *focusin = (XIFocusInEvent *) xi_event;
11274
11275 any = x_any_window_to_frame (dpyinfo, focusin->event);
11277#ifdef USE_GTK 11276#ifdef USE_GTK
11278 /* Some WMs (e.g. Mutter in Gnome Shell), don't unmap 11277 /* Some WMs (e.g. Mutter in Gnome Shell), don't unmap
11279 minimized/iconified windows; thus, for those WMs we won't get 11278 minimized/iconified windows; thus, for those WMs we won't get
11280 a MapNotify when unminimizing/deiconifying. Check here if we 11279 a MapNotify when unminimizing/deiconifying. Check here if we
11281 are deiconizing a window (Bug42655). 11280 are deiconizing a window (Bug42655).
11282 11281
11283 But don't do that by default on GTK since it may cause a plain 11282 But don't do that by default on GTK since it may cause a plain
11284 invisible frame get reported as iconified, compare 11283 invisible frame get reported as iconified, compare
11285 https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html. 11284 https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html.
11286 That is fixed above but bites us here again. 11285 That is fixed above but bites us here again.
11287 11286
11288 The option x_set_frame_visibility_more_laxly allows to override 11287 The option x_set_frame_visibility_more_laxly allows to override
11289 the default behavior (Bug#49955, Bug#53298). */ 11288 the default behavior (Bug#49955, Bug#53298). */
11290 if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in) 11289 if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in)
11291 || EQ (x_set_frame_visibility_more_laxly, Qt)) 11290 || EQ (x_set_frame_visibility_more_laxly, Qt))
11292#endif /* USE_GTK */ 11291#endif /* USE_GTK */
11293 { 11292 {
11294 f = any; 11293 f = any;
11295 if (f && FRAME_ICONIFIED_P (f)) 11294 if (f && FRAME_ICONIFIED_P (f))
11296 { 11295 {
11297 SET_FRAME_VISIBLE (f, 1); 11296 SET_FRAME_VISIBLE (f, 1);
11298 SET_FRAME_ICONIFIED (f, false); 11297 SET_FRAME_ICONIFIED (f, false);
11299 f->output_data.x->has_been_visible = true; 11298 f->output_data.x->has_been_visible = true;
11300 inev.ie.kind = DEICONIFY_EVENT; 11299 inev.ie.kind = DEICONIFY_EVENT;
11301 XSETFRAME (inev.ie.frame_or_window, f); 11300 XSETFRAME (inev.ie.frame_or_window, f);
11302 } 11301 }
11303 } 11302 }
11304 x_detect_focus_change (dpyinfo, any, event, &inev.ie); 11303 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
11305 goto XI_OTHER; 11304 goto XI_OTHER;
11305 }
11306 11306
11307 case XI_FocusOut: 11307 case XI_FocusOut:
11308 any = x_any_window_to_frame (dpyinfo, focusout->event); 11308 {
11309 x_detect_focus_change (dpyinfo, any, event, &inev.ie); 11309 XIFocusOutEvent *focusout = (XIFocusOutEvent *) xi_event;
11310 goto XI_OTHER; 11310
11311 any = x_any_window_to_frame (dpyinfo, focusout->event);
11312 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
11313 goto XI_OTHER;
11314 }
11311 11315
11312 case XI_Enter: 11316 case XI_Enter:
11313 any = x_top_window_to_frame (dpyinfo, enter->event); 11317 {
11314 ev.x = lrint (enter->event_x); 11318 XIEnterEvent *enter = (XIEnterEvent *) xi_event;
11315 ev.y = lrint (enter->event_y); 11319
11316 ev.window = enter->event; 11320 any = x_top_window_to_frame (dpyinfo, enter->event);
11317 x_display_set_last_user_time (dpyinfo, xi_event->time); 11321 ev.x = lrint (enter->event_x);
11322 ev.y = lrint (enter->event_y);
11323 ev.window = enter->event;
11324 x_display_set_last_user_time (dpyinfo, xi_event->time);
11318 11325
11319#ifdef USE_MOTIF 11326#ifdef USE_MOTIF
11320 use_copy = true; 11327 use_copy = true;
11321
11322 copy.xcrossing.type = EnterNotify;
11323 copy.xcrossing.serial = enter->serial;
11324 copy.xcrossing.send_event = enter->send_event;
11325 copy.xcrossing.display = dpyinfo->display;
11326 copy.xcrossing.window = enter->event;
11327 copy.xcrossing.root = enter->root;
11328 copy.xcrossing.subwindow = enter->child;
11329 copy.xcrossing.time = enter->time;
11330 copy.xcrossing.x = lrint (enter->event_x);
11331 copy.xcrossing.y = lrint (enter->event_y);
11332 copy.xcrossing.x_root = lrint (enter->root_x);
11333 copy.xcrossing.y_root = lrint (enter->root_y);
11334 copy.xcrossing.mode = enter->mode;
11335 copy.xcrossing.detail = enter->detail;
11336 copy.xcrossing.focus = enter->focus;
11337 copy.xcrossing.state = 0;
11338 copy.xcrossing.same_screen = True;
11339#endif
11340
11341 /* There is no need to handle entry/exit events for
11342 passive focus from non-top windows at all, since they
11343 are an inferiors of the frame's top window, which will
11344 get virtual events. */
11345 if (any)
11346 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
11347 11328
11348 if (!any) 11329 copy.xcrossing.type = EnterNotify;
11349 any = x_any_window_to_frame (dpyinfo, enter->event); 11330 copy.xcrossing.serial = enter->serial;
11331 copy.xcrossing.send_event = enter->send_event;
11332 copy.xcrossing.display = dpyinfo->display;
11333 copy.xcrossing.window = enter->event;
11334 copy.xcrossing.root = enter->root;
11335 copy.xcrossing.subwindow = enter->child;
11336 copy.xcrossing.time = enter->time;
11337 copy.xcrossing.x = lrint (enter->event_x);
11338 copy.xcrossing.y = lrint (enter->event_y);
11339 copy.xcrossing.x_root = lrint (enter->root_x);
11340 copy.xcrossing.y_root = lrint (enter->root_y);
11341 copy.xcrossing.mode = enter->mode;
11342 copy.xcrossing.detail = enter->detail;
11343 copy.xcrossing.focus = enter->focus;
11344 copy.xcrossing.state = 0;
11345 copy.xcrossing.same_screen = True;
11346#endif
11347
11348 /* There is no need to handle entry/exit events for
11349 passive focus from non-top windows at all, since they
11350 are an inferiors of the frame's top window, which will
11351 get virtual events. */
11352 if (any)
11353 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
11354
11355 if (!any)
11356 any = x_any_window_to_frame (dpyinfo, enter->event);
11350 11357
11351#ifdef HAVE_XINPUT2_1 11358#ifdef HAVE_XINPUT2_1
11352 xi_reset_scroll_valuators_for_device_id (dpyinfo, enter->deviceid, 11359 xi_reset_scroll_valuators_for_device_id (dpyinfo, enter->deviceid,
11353 true); 11360 true);
11354#endif 11361#endif
11355 11362
11356 { 11363 {
11357#ifdef HAVE_XWIDGETS 11364#ifdef HAVE_XWIDGETS
11358 struct xwidget_view *xwidget_view = xwidget_view_from_window (enter->event); 11365 struct xwidget_view *xwidget_view = xwidget_view_from_window (enter->event);
11359#endif 11366#endif
11360 11367
11361#ifdef HAVE_XWIDGETS 11368#ifdef HAVE_XWIDGETS
11362 if (xwidget_view) 11369 if (xwidget_view)
11363 { 11370 {
11364 xwidget_motion_or_crossing (xwidget_view, event); 11371 xwidget_motion_or_crossing (xwidget_view, event);
11365 11372
11366 goto XI_OTHER; 11373 goto XI_OTHER;
11367 } 11374 }
11368#endif 11375#endif
11369 } 11376 }
11370 11377
11371 f = any; 11378 f = any;
11372 11379
11373 if (f && x_mouse_click_focus_ignore_position) 11380 if (f && x_mouse_click_focus_ignore_position)
11374 ignore_next_mouse_click_timeout = xi_event->time + 200; 11381 ignore_next_mouse_click_timeout = xi_event->time + 200;
11375 11382
11376 /* EnterNotify counts as mouse movement, 11383 /* EnterNotify counts as mouse movement,
11377 so update things that depend on mouse position. */ 11384 so update things that depend on mouse position. */
11378 if (f && !f->output_data.x->hourglass_p) 11385 if (f && !f->output_data.x->hourglass_p)
11379 x_note_mouse_movement (f, &ev); 11386 x_note_mouse_movement (f, &ev);
11380#ifdef USE_GTK 11387#ifdef USE_GTK
11381 /* We may get an EnterNotify on the buttons in the toolbar. In that 11388 /* We may get an EnterNotify on the buttons in the toolbar. In that
11382 case we moved out of any highlighted area and need to note this. */ 11389 case we moved out of any highlighted area and need to note this. */
11383 if (!f && dpyinfo->last_mouse_glyph_frame) 11390 if (!f && dpyinfo->last_mouse_glyph_frame)
11384 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev); 11391 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev);
11385#endif 11392#endif
11386 goto XI_OTHER; 11393 goto XI_OTHER;
11394 }
11387 11395
11388 case XI_Leave: 11396 case XI_Leave:
11389 ev.x = lrint (leave->event_x); 11397 {
11390 ev.y = lrint (leave->event_y); 11398 XILeaveEvent *leave = (XILeaveEvent *) xi_event;
11391 ev.window = leave->event;
11392 any = x_top_window_to_frame (dpyinfo, leave->event);
11393 11399
11394 /* This allows us to catch LeaveNotify events generated by 11400 ev.x = lrint (leave->event_x);
11395 popup menu grabs. FIXME: this is right when there is a 11401 ev.y = lrint (leave->event_y);
11396 focus menu, but implicit focus tracking can get screwed 11402 ev.window = leave->event;
11397 up if we get this and no XI_Enter event later. */ 11403 any = x_top_window_to_frame (dpyinfo, leave->event);
11404
11405 /* This allows us to catch LeaveNotify events generated by
11406 popup menu grabs. FIXME: this is right when there is a
11407 focus menu, but implicit focus tracking can get screwed
11408 up if we get this and no XI_Enter event later. */
11398 11409
11399#ifdef USE_X_TOOLKIT 11410#ifdef USE_X_TOOLKIT
11400 if (popup_activated () 11411 if (popup_activated ()
11401 && leave->mode == XINotifyPassiveUngrab) 11412 && leave->mode == XINotifyPassiveUngrab)
11402 any = x_any_window_to_frame (dpyinfo, leave->event); 11413 any = x_any_window_to_frame (dpyinfo, leave->event);
11403#endif 11414#endif
11404 11415
11405#ifdef USE_MOTIF 11416#ifdef USE_MOTIF
11406 use_copy = true; 11417 use_copy = true;
11407 11418
11408 copy.xcrossing.type = LeaveNotify; 11419 copy.xcrossing.type = LeaveNotify;
11409 copy.xcrossing.serial = leave->serial; 11420 copy.xcrossing.serial = leave->serial;
11410 copy.xcrossing.send_event = leave->send_event; 11421 copy.xcrossing.send_event = leave->send_event;
11411 copy.xcrossing.display = dpyinfo->display; 11422 copy.xcrossing.display = dpyinfo->display;
11412 copy.xcrossing.window = leave->event; 11423 copy.xcrossing.window = leave->event;
11413 copy.xcrossing.root = leave->root; 11424 copy.xcrossing.root = leave->root;
11414 copy.xcrossing.subwindow = leave->child; 11425 copy.xcrossing.subwindow = leave->child;
11415 copy.xcrossing.time = leave->time; 11426 copy.xcrossing.time = leave->time;
11416 copy.xcrossing.x = lrint (leave->event_x); 11427 copy.xcrossing.x = lrint (leave->event_x);
11417 copy.xcrossing.y = lrint (leave->event_y); 11428 copy.xcrossing.y = lrint (leave->event_y);
11418 copy.xcrossing.x_root = lrint (leave->root_x); 11429 copy.xcrossing.x_root = lrint (leave->root_x);
11419 copy.xcrossing.y_root = lrint (leave->root_y); 11430 copy.xcrossing.y_root = lrint (leave->root_y);
11420 copy.xcrossing.mode = leave->mode; 11431 copy.xcrossing.mode = leave->mode;
11421 copy.xcrossing.detail = leave->detail; 11432 copy.xcrossing.detail = leave->detail;
11422 copy.xcrossing.focus = leave->focus; 11433 copy.xcrossing.focus = leave->focus;
11423 copy.xcrossing.state = 0; 11434 copy.xcrossing.state = 0;
11424 copy.xcrossing.same_screen = True; 11435 copy.xcrossing.same_screen = True;
11425#endif 11436#endif
11426 11437
11427 /* One problem behind the design of XInput 2 scrolling is 11438 /* One problem behind the design of XInput 2 scrolling is
11428 that valuators are not unique to each window, but only 11439 that valuators are not unique to each window, but only
11429 the window that has grabbed the valuator's device or 11440 the window that has grabbed the valuator's device or
11430 the window that the device's pointer is on top of can 11441 the window that the device's pointer is on top of can
11431 receive motion events. There is also no way to 11442 receive motion events. There is also no way to
11432 retrieve the value of a valuator outside of each motion 11443 retrieve the value of a valuator outside of each motion
11433 event. 11444 event.
11434 11445
11435 As such, to prevent wildly inaccurate results when the 11446 As such, to prevent wildly inaccurate results when the
11436 valuators have changed outside Emacs, we reset our 11447 valuators have changed outside Emacs, we reset our
11437 records of each valuator's value whenever the pointer 11448 records of each valuator's value whenever the pointer
11438 moves out of a frame (and not into one of its 11449 moves out of a frame (and not into one of its
11439 children, which we know about). */ 11450 children, which we know about). */
11440#ifdef HAVE_XINPUT2_1 11451#ifdef HAVE_XINPUT2_1
11441 if (leave->detail != XINotifyInferior && any) 11452 if (leave->detail != XINotifyInferior && any)
11442 xi_reset_scroll_valuators_for_device_id (dpyinfo, 11453 xi_reset_scroll_valuators_for_device_id (dpyinfo,
11443 enter->deviceid, false); 11454 leave->deviceid, false);
11444#endif 11455#endif
11445 11456
11446 x_display_set_last_user_time (dpyinfo, xi_event->time); 11457 x_display_set_last_user_time (dpyinfo, xi_event->time);
11447 11458
11448#ifdef HAVE_XWIDGETS 11459#ifdef HAVE_XWIDGETS
11449 { 11460 {
11450 struct xwidget_view *xvw 11461 struct xwidget_view *xvw
11451 = xwidget_view_from_window (leave->event); 11462 = xwidget_view_from_window (leave->event);
11452 11463
11453 if (xvw) 11464 if (xvw)
11454 { 11465 {
11455 *finish = X_EVENT_DROP; 11466 *finish = X_EVENT_DROP;
11456 xwidget_motion_or_crossing (xvw, event); 11467 xwidget_motion_or_crossing (xvw, event);
11457 11468
11458 goto XI_OTHER; 11469 goto XI_OTHER;
11459 } 11470 }
11460 } 11471 }
11461#endif 11472#endif
11462 11473
11463 if (any) 11474 if (any)
11464 x_detect_focus_change (dpyinfo, any, event, &inev.ie); 11475 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
11465 11476
11466#ifndef USE_X_TOOLKIT 11477#ifndef USE_X_TOOLKIT
11467 f = x_top_window_to_frame (dpyinfo, leave->event); 11478 f = x_top_window_to_frame (dpyinfo, leave->event);
11468#else 11479#else
11469 /* On Xt builds that have XI2, the enter and leave event 11480 /* On Xt builds that have XI2, the enter and leave event
11470 masks are set on the frame widget's window. */ 11481 masks are set on the frame widget's window. */
11471 f = x_window_to_frame (dpyinfo, leave->event); 11482 f = x_window_to_frame (dpyinfo, leave->event);
11472 11483
11473 if (!f) 11484 if (!f)
11474 f = x_top_window_to_frame (dpyinfo, leave->event); 11485 f = x_top_window_to_frame (dpyinfo, leave->event);
11475#endif 11486#endif
11476 if (f) 11487 if (f)
11477 { 11488 {
11478 if (f == hlinfo->mouse_face_mouse_frame) 11489 if (f == hlinfo->mouse_face_mouse_frame)
11479 { 11490 {
11480 /* If we move outside the frame, then we're 11491 /* If we move outside the frame, then we're
11481 certainly no longer on any text in the frame. */ 11492 certainly no longer on any text in the frame. */
11482 clear_mouse_face (hlinfo); 11493 clear_mouse_face (hlinfo);
11483 hlinfo->mouse_face_mouse_frame = 0; 11494 hlinfo->mouse_face_mouse_frame = 0;
11484 } 11495 }
11485 11496
11486 /* Generate a nil HELP_EVENT to cancel a help-echo. 11497 /* Generate a nil HELP_EVENT to cancel a help-echo.
11487 Do it only if there's something to cancel. 11498 Do it only if there's something to cancel.
11488 Otherwise, the startup message is cleared when 11499 Otherwise, the startup message is cleared when
11489 the mouse leaves the frame. */ 11500 the mouse leaves the frame. */
11490 if (any_help_event_p) 11501 if (any_help_event_p)
11491 do_help = -1; 11502 do_help = -1;
11492 } 11503 }
11493#ifdef USE_GTK 11504#ifdef USE_GTK
11494 /* See comment in EnterNotify above */ 11505 /* See comment in EnterNotify above */
11495 else if (dpyinfo->last_mouse_glyph_frame) 11506 else if (dpyinfo->last_mouse_glyph_frame)
11496 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev); 11507 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev);
11497#endif 11508#endif
11498 goto XI_OTHER; 11509 goto XI_OTHER;
11510 }
11499 11511
11500 case XI_Motion: 11512 case XI_Motion:
11501 { 11513 {
@@ -12496,6 +12508,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
12496 12508
12497 case XI_DeviceChanged: 12509 case XI_DeviceChanged:
12498 { 12510 {
12511 XIDeviceChangedEvent *device_changed = (XIDeviceChangedEvent *) xi_event;
12499 struct xi_device_t *device; 12512 struct xi_device_t *device;
12500#ifdef HAVE_XINPUT2_2 12513#ifdef HAVE_XINPUT2_2
12501 struct xi_touch_point_t *tem, *last; 12514 struct xi_touch_point_t *tem, *last;