aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-09-24 16:27:42 +0800
committerPo Lu2022-09-24 16:30:37 +0800
commit54876bf498f5e6b4f7a66a051b105c3ddd308945 (patch)
tree48de4eac951b7cb9866d37011faeb55ee260ff0d /src
parent767a10cc63de8ce9f85ac688be33555278b4f3fb (diff)
downloademacs-54876bf498f5e6b4f7a66a051b105c3ddd308945.tar.gz
emacs-54876bf498f5e6b4f7a66a051b105c3ddd308945.zip
Reduce complexity of scroll bar window protection code
It turns out my previous theories of why ClientMessages were generated were wrong, and they are just generated so we can set finish to X_EVENT_GOTO_OUT to have them delivered immediately. This allows for the code to be simplified greatly, by not unpacking pointers to the raw window into the client messages. * src/xterm.c (x_unprotect_window_for_callback): Return the window removed from the queue, or nil if none. (x_scroll_bar_to_input_event) (x_horizontal_scroll_bar_to_input_event): Use window provided by x_unprotect_window_for_callback. (handle_one_xevent): Pass dpyinfo to functions that need it. (x_free_frame_resources): Remove "first scroll bar request" code. * src/xterm.h (struct x_display_info): Likewise.
Diffstat (limited to 'src')
-rw-r--r--src/xterm.c104
-rw-r--r--src/xterm.h9
2 files changed, 54 insertions, 59 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 2d366e5511f..527c26f0da3 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -14385,17 +14385,23 @@ x_protect_window_for_callback (struct x_display_info *dpyinfo,
14385 return true; 14385 return true;
14386} 14386}
14387 14387
14388static void 14388static Lisp_Object
14389x_unprotect_window_for_callback (struct x_display_info *dpyinfo) 14389x_unprotect_window_for_callback (struct x_display_info *dpyinfo)
14390{ 14390{
14391 Lisp_Object window;
14392
14391 if (!dpyinfo->n_protected_windows) 14393 if (!dpyinfo->n_protected_windows)
14392 emacs_abort (); 14394 return Qnil;
14395
14396 window = dpyinfo->protected_windows[0];
14393 14397
14394 dpyinfo->n_protected_windows--; 14398 dpyinfo->n_protected_windows--;
14395 14399
14396 if (dpyinfo->n_protected_windows) 14400 if (dpyinfo->n_protected_windows)
14397 memmove (dpyinfo->protected_windows, &dpyinfo->protected_windows[1], 14401 memmove (dpyinfo->protected_windows, &dpyinfo->protected_windows[1],
14398 sizeof (Lisp_Object) * dpyinfo->n_protected_windows); 14402 sizeof (Lisp_Object) * dpyinfo->n_protected_windows);
14403
14404 return window;
14399} 14405}
14400 14406
14401/* Send a client message with message type Xatom_Scrollbar for a 14407/* Send a client message with message type Xatom_Scrollbar for a
@@ -14462,30 +14468,34 @@ x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
14462 in *IEVENT. */ 14468 in *IEVENT. */
14463 14469
14464static void 14470static void
14465x_scroll_bar_to_input_event (const XEvent *event, 14471x_scroll_bar_to_input_event (struct x_display_info *dpyinfo,
14472 const XEvent *event,
14466 struct input_event *ievent) 14473 struct input_event *ievent)
14467{ 14474{
14468 const XClientMessageEvent *ev = &event->xclient;
14469 Lisp_Object window; 14475 Lisp_Object window;
14470 struct window *w;
14471 14476
14472 /* See the comment in the function above. */ 14477 /* Every time a scroll bar ClientMessage event is sent, the window
14473 intptr_t iw0 = ev->data.l[0]; 14478 is pushed onto a queue that is traced for garbage collection.
14474 intptr_t iw1 = ev->data.l[1]; 14479 Every time we need a window for a read scroll bar event, we
14475 intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu); 14480 simply read from the other side of the queue. */
14476 w = (struct window *) iw; 14481 window = x_unprotect_window_for_callback (dpyinfo);
14477 14482
14478 XSETWINDOW (window, w); 14483 if (NILP (window))
14484 {
14485 /* This means we are getting extra scroll bar events for some
14486 reason, and shouldn't be possible in practice. */
14487 EVENT_INIT (*ievent);
14488 return;
14489 }
14479 14490
14480 ievent->kind = SCROLL_BAR_CLICK_EVENT; 14491 ievent->kind = SCROLL_BAR_CLICK_EVENT;
14481 ievent->frame_or_window = window; 14492 ievent->frame_or_window = window;
14482 ievent->arg = Qnil; 14493 ievent->arg = Qnil;
14483 ievent->timestamp 14494 ievent->timestamp = x_get_last_toolkit_time (dpyinfo);
14484 = x_get_last_toolkit_time (FRAME_DISPLAY_INFO (XFRAME (w->frame)));
14485 ievent->code = 0; 14495 ievent->code = 0;
14486 ievent->part = ev->data.l[2]; 14496 ievent->part = event->xclient.data.l[2];
14487 ievent->x = make_fixnum (ev->data.l[3]); 14497 ievent->x = make_fixnum (event->xclient.data.l[3]);
14488 ievent->y = make_fixnum (ev->data.l[4]); 14498 ievent->y = make_fixnum (event->xclient.data.l[4]);
14489 ievent->modifiers = 0; 14499 ievent->modifiers = 0;
14490} 14500}
14491 14501
@@ -14493,30 +14503,34 @@ x_scroll_bar_to_input_event (const XEvent *event,
14493 input event in *IEVENT. */ 14503 input event in *IEVENT. */
14494 14504
14495static void 14505static void
14496x_horizontal_scroll_bar_to_input_event (const XEvent *event, 14506x_horizontal_scroll_bar_to_input_event (struct x_display_info *dpyinfo,
14507 const XEvent *event,
14497 struct input_event *ievent) 14508 struct input_event *ievent)
14498{ 14509{
14499 const XClientMessageEvent *ev = &event->xclient;
14500 Lisp_Object window; 14510 Lisp_Object window;
14501 struct window *w;
14502 14511
14503 /* See the comment in the function above. */ 14512 /* Every time a scroll bar ClientMessage event is sent, the window
14504 intptr_t iw0 = ev->data.l[0]; 14513 is pushed onto a queue that is traced for garbage collection.
14505 intptr_t iw1 = ev->data.l[1]; 14514 Every time we need a window for a read scroll bar event, we
14506 intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu); 14515 simply read from the other side of the queue. */
14507 w = (struct window *) iw; 14516 window = x_unprotect_window_for_callback (dpyinfo);
14508 14517
14509 XSETWINDOW (window, w); 14518 if (NILP (window))
14519 {
14520 /* This means we are getting extra scroll bar events for some
14521 reason, and shouldn't be possible in practice. */
14522 EVENT_INIT (*ievent);
14523 return;
14524 }
14510 14525
14511 ievent->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT; 14526 ievent->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
14512 ievent->frame_or_window = window; 14527 ievent->frame_or_window = window;
14513 ievent->arg = Qnil; 14528 ievent->arg = Qnil;
14514 ievent->timestamp 14529 ievent->timestamp = x_get_last_toolkit_time (dpyinfo);
14515 = x_get_last_toolkit_time (FRAME_DISPLAY_INFO (XFRAME (w->frame)));
14516 ievent->code = 0; 14530 ievent->code = 0;
14517 ievent->part = ev->data.l[2]; 14531 ievent->part = event->xclient.data.l[2];
14518 ievent->x = make_fixnum (ev->data.l[3]); 14532 ievent->x = make_fixnum (event->xclient.data.l[3]);
14519 ievent->y = make_fixnum (ev->data.l[4]); 14533 ievent->y = make_fixnum (event->xclient.data.l[4]);
14520 ievent->modifiers = 0; 14534 ievent->modifiers = 0;
14521} 14535}
14522 14536
@@ -18104,28 +18118,21 @@ handle_one_xevent (struct x_display_info *dpyinfo,
18104 we construct an input_event. */ 18118 we construct an input_event. */
18105 if (event->xclient.message_type == dpyinfo->Xatom_Scrollbar) 18119 if (event->xclient.message_type == dpyinfo->Xatom_Scrollbar)
18106 { 18120 {
18107 x_scroll_bar_to_input_event (event, &inev.ie); 18121 /* Convert the scroll bar event to an input event using
18108 18122 the first window entered into the scroll bar event
18109 /* Unprotect the first window to be sent in a 18123 queue. */
18110 ClientMessage event, since it is now on the stack and 18124 x_scroll_bar_to_input_event (dpyinfo, event, &inev.ie);
18111 thereby subject to garbage collection. */
18112 if (event->xclient.serial
18113 >= dpyinfo->first_valid_scroll_bar_req)
18114 x_unprotect_window_for_callback (dpyinfo);
18115 18125
18116 *finish = X_EVENT_GOTO_OUT; 18126 *finish = X_EVENT_GOTO_OUT;
18117 goto done; 18127 goto done;
18118 } 18128 }
18119 else if (event->xclient.message_type == dpyinfo->Xatom_Horizontal_Scrollbar) 18129 else if (event->xclient.message_type == dpyinfo->Xatom_Horizontal_Scrollbar)
18120 { 18130 {
18121 x_horizontal_scroll_bar_to_input_event (event, &inev.ie); 18131 /* Convert the horizontal scroll bar event to an input
18122 18132 event using the first window entered into the scroll
18123 /* Unprotect the first window to be sent in a 18133 bar event queue. */
18124 ClientMessage event, since it is now on the stack and 18134 x_horizontal_scroll_bar_to_input_event (dpyinfo, event,
18125 thereby subject to garbage collection. */ 18135 &inev.ie);
18126 if (event->xclient.serial
18127 >= dpyinfo->first_valid_scroll_bar_req)
18128 x_unprotect_window_for_callback (dpyinfo);
18129 18136
18130 *finish = X_EVENT_GOTO_OUT; 18137 *finish = X_EVENT_GOTO_OUT;
18131 goto done; 18138 goto done;
@@ -27347,11 +27354,8 @@ x_free_frame_resources (struct frame *f)
27347#ifdef USE_TOOLKIT_SCROLL_BARS 27354#ifdef USE_TOOLKIT_SCROLL_BARS
27348 /* Since the frame was destroyed, we can no longer guarantee 27355 /* Since the frame was destroyed, we can no longer guarantee
27349 that scroll bar events will be received. Clear 27356 that scroll bar events will be received. Clear
27350 protected_windows, and ignore any preceding scroll bar events 27357 protected_windows. */
27351 that happen to still be deliverable. */
27352 dpyinfo->n_protected_windows = 0; 27358 dpyinfo->n_protected_windows = 0;
27353 dpyinfo->first_valid_scroll_bar_req
27354 = XNextRequest (dpyinfo->display);
27355#endif 27359#endif
27356 } 27360 }
27357 27361
diff --git a/src/xterm.h b/src/xterm.h
index d1671621c78..d6ff15e40f7 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -839,15 +839,6 @@ struct x_display_info
839 server_time_monotonic_p will be true). */ 839 server_time_monotonic_p will be true). */
840 int_fast64_t server_time_offset; 840 int_fast64_t server_time_offset;
841#endif 841#endif
842
843#if defined USE_TOOLKIT_SCROLL_BARS
844 /* Serial number of the first scroll bar event to start listening
845 to. This is necessary because protected_windows is display
846 local, but the destruction of a frame's edit window may cause
847 event windows to vanish before they are delivered, leading to
848 windows remaining protected indefinitely. */
849 unsigned long first_valid_scroll_bar_req;
850#endif
851}; 842};
852 843
853#ifdef HAVE_X_I18N 844#ifdef HAVE_X_I18N