commit 278bacad691f4d5ba05b55c83e3e8ccd7f524e59 (HEAD, refs/remotes/origin/master) Author: Po Lu Date: Sat Jan 29 07:35:48 2022 +0000 Write a dummy event on each popup menu event * src/haiku_io.c (haiku_len): Add new event. * src/haiku_support.cc (be_popup_menu_thread_entry): (Highlight): Write a dummy event to the event port. * src/haiku_support.h (enum haiku_event_type): New `DUMMY_EVENT' type. (struct haiku_dummy_event): New structure. * src/haikuterm.c (haiku_read_socket): Handle dummy events. diff --git a/src/haiku_io.c b/src/haiku_io.c index 109aca782a..185bd5e9ff 100644 --- a/src/haiku_io.c +++ b/src/haiku_io.c @@ -94,6 +94,8 @@ haiku_len (enum haiku_event_type type) return sizeof (struct haiku_refs_event); case APP_QUIT_REQUESTED_EVENT: return sizeof (struct haiku_app_quit_requested_event); + case DUMMY_EVENT: + return sizeof (struct haiku_dummy_event); } emacs_abort (); diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 05bc410eb2..2284953517 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -149,6 +149,7 @@ static int32 be_popup_menu_thread_entry (void *thread_data) { struct be_popup_menu_data *data; + struct haiku_dummy_event dummy; BMenuItem *it; data = (struct be_popup_menu_data *) thread_data; @@ -160,6 +161,7 @@ be_popup_menu_thread_entry (void *thread_data) else popup_track_message = NULL; + haiku_write (DUMMY_EVENT, &dummy); return 0; } @@ -1697,6 +1699,7 @@ class EmacsMenuItem : public BMenuItem Highlight (bool highlight_p) { struct haiku_menu_bar_help_event rq; + struct haiku_dummy_event dummy; BMenu *menu = Menu (); BRect r; BPoint pt; @@ -1719,7 +1722,10 @@ class EmacsMenuItem : public BMenuItem if (menu_bar_id > 0) haiku_write (MENU_BAR_HELP_EVENT, &rq); else - haiku_write_without_signal (MENU_BAR_HELP_EVENT, &rq, true); + { + haiku_write_without_signal (MENU_BAR_HELP_EVENT, &rq, true); + haiku_write (DUMMY_EVENT, &dummy); + } } } @@ -2490,16 +2496,13 @@ BMenu_run (void *menu, int x, int y, while (true) { + process_pending_signals_function (); + if ((stat = wait_for_objects_etc ((object_wait_info *) &infos, 2, B_RELATIVE_TIMEOUT, 10000)) < B_OK) { - if (stat == B_INTERRUPTED) + if (stat == B_INTERRUPTED || stat == B_TIMED_OUT) continue; - else if (stat == B_TIMED_OUT) - { - process_pending_signals_function (); - continue; - } else gui_abort ("Failed to wait for popup"); } diff --git a/src/haiku_support.h b/src/haiku_support.h index 4b0456168d..b98fa56415 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -86,7 +86,8 @@ enum haiku_event_type MENU_BAR_HELP_EVENT, ZOOM_EVENT, REFS_EVENT, - APP_QUIT_REQUESTED_EVENT + APP_QUIT_REQUESTED_EVENT, + DUMMY_EVENT }; struct haiku_quit_requested_event @@ -123,6 +124,11 @@ struct haiku_app_quit_requested_event char dummy; }; +struct haiku_dummy_event +{ + char dummy; +}; + #define HAIKU_MODIFIER_ALT (1) #define HAIKU_MODIFIER_CTRL (1 << 1) #define HAIKU_MODIFIER_SHIFT (1 << 2) diff --git a/src/haikuterm.c b/src/haikuterm.c index 11b75fdde2..c6c92227b8 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -3263,6 +3263,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) } case APP_QUIT_REQUESTED_EVENT: case KEY_UP: + case DUMMY_EVENT: default: break; } commit c4e66bb2b567f9dced364013a84ba415dd55290d Author: Eli Zaretskii Date: Sat Jan 29 09:12:30 2022 +0200 Fix compiler warning due to a recent change * src/data.c (Ffset): Avoid compiler warning about 'function'. diff --git a/src/data.c b/src/data.c index 039e6c3113..a5a76a2755 100644 --- a/src/data.c +++ b/src/data.c @@ -836,7 +836,6 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0, doc: /* Set SYMBOL's function definition to DEFINITION, and return DEFINITION. */) (register Lisp_Object symbol, Lisp_Object definition) { - register Lisp_Object function; CHECK_SYMBOL (symbol); /* Perhaps not quite the right error signal, but seems good enough. */ if (NILP (symbol) && !NILP (definition)) @@ -844,11 +843,11 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0, think this one little sanity check is worth its cost, but anyway. */ xsignal1 (Qsetting_constant, symbol); - function = XSYMBOL (symbol)->u.s.function; - eassert (valid_lisp_object_p (definition)); #ifdef HAVE_NATIVE_COMP + register Lisp_Object function = XSYMBOL (symbol)->u.s.function; + if (comp_enable_subr_trampolines && SUBRP (function) && !SUBR_NATIVE_COMPILEDP (function)) commit 7e17749ada101fbfb772a79deda5f7087ba9e96d Author: Po Lu Date: Sat Jan 29 14:05:49 2022 +0800 Fix a default value of the `:underline' face attribute * lisp/cus-face.el (custom-face-attributes): Add `:position' t default value of "On" for underlines. diff --git a/lisp/cus-face.el b/lisp/cus-face.el index 12ad3910fc..80d0aaa0d5 100644 --- a/lisp/cus-face.el +++ b/lisp/cus-face.el @@ -133,7 +133,7 @@ :help-echo "Control text underlining." (const :tag "Off" nil) (list :tag "On" - :value (:color foreground-color :style line) + :value (:color foreground-color :style line :position nil) (const :format "" :value :color) (choice :tag "Color" (const :tag "Foreground Color" foreground-color) commit 166556f464e7642b218a5488837512c4af77f227 Author: Po Lu Date: Sat Jan 29 05:50:32 2022 +0000 Improve menu drag tracking on Haiku * src/haikuterm.c (haiku_read_socket): Ignore all button events when popup_activated_p. diff --git a/src/haikuterm.c b/src/haikuterm.c index 5ff348fa5d..11b75fdde2 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -2844,7 +2844,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) int tab_bar_p = 0, tool_bar_p = 0; bool up_okay_p = false; - if (!f) + if (popup_activated_p || !f) continue; struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); @@ -3324,6 +3324,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) flush_dirty_back_buffers (); unblock_input (); + return message_count; } commit b616e14c351cd92f6dd75f9ace65a190e5752d00 Author: Po Lu Date: Sat Jan 29 05:24:04 2022 +0000 Make menus on Haiku work better * src/haikuterm.c (haiku_read_socket): Don't send up events for ungrabbed buttons. diff --git a/src/haikuterm.c b/src/haikuterm.c index 6a84e61add..5ff348fa5d 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -2842,6 +2842,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) struct frame *f = haiku_window_to_frame (b->window); Lisp_Object tab_bar_arg = Qnil; int tab_bar_p = 0, tool_bar_p = 0; + bool up_okay_p = false; if (!f) continue; @@ -2894,10 +2895,12 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) if (type == BUTTON_UP) { inev.modifiers |= up_modifier; + up_okay_p = (dpyinfo->grabbed & (1 << b->btn_no)); dpyinfo->grabbed &= ~(1 << b->btn_no); } else { + up_okay_p = true; inev.modifiers |= down_modifier; dpyinfo->last_mouse_frame = f; dpyinfo->grabbed |= (1 << b->btn_no); @@ -2907,7 +2910,9 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) f->last_tool_bar_item = -1; } - if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p) + if (up_okay_p + && !(tab_bar_p && NILP (tab_bar_arg)) + && !tool_bar_p) inev.kind = MOUSE_CLICK_EVENT; inev.arg = tab_bar_arg; inev.code = b->btn_no; commit 95ccd1ba47771349e23aedf0981861fd5074bd7e Author: Po Lu Date: Sat Jan 29 05:06:02 2022 +0000 Implement real menu help-echo text on Haiku * lisp/tooltip.el (tooltip-show-help): Remove Haiku-specific conditional since that's now taken care of by C code. * src/haiku_io.c (haiku_read_size): (haiku_read_with_timeout): (haiku_write_without_signal): Add parameter `popup_p'. All callers changed. (port_popup_menu_to_emacs): New variable. * src/haiku_support.cc (struct be_popup_menu_data): New structure. (be_popup_menu_thread_entry): New function. (class EmacsMenuItem): New field `menu_ptr'. (Highlight): Send help text to the popup port if this item isn't for a menu bar. (BMenu_add_item): Set menu_ptr appropriately. (BMenu_run): Complete rewrite that allows to read help text from the menu bar port. * src/haiku_support.h (struct haiku_menu_bar_help_event): New fields for popup menus. * src/haikumenu.c (digest_menu_items): Only set help tooltip on popup menus when system tooltips are enabled. (haiku_menu_show_help): (haiku_process_pending_signals_for_menu): New functions. (haiku_menu_show): Pass new callbacks. diff --git a/lisp/tooltip.el b/lisp/tooltip.el index 2aa487d045..9d523e7967 100644 --- a/lisp/tooltip.el +++ b/lisp/tooltip.el @@ -375,12 +375,7 @@ It is also called if Tooltip mode is on, for text-only displays." (defun tooltip-show-help (msg) "Function installed as `show-help-function'. MSG is either a help string to display, or nil to cancel the display." - (if (and (display-graphic-p) - ;; On Haiku, system tooltips can't be displayed above - ;; menus. - (or (not (and (eq window-system 'haiku) - haiku-use-system-tooltips)) - (not (menu-or-popup-active-p)))) + (if (and (display-graphic-p)) (let ((previous-help tooltip-help-message)) (setq tooltip-help-message msg) (cond ((null msg) diff --git a/src/haiku_io.c b/src/haiku_io.c index cb7750634c..109aca782a 100644 --- a/src/haiku_io.c +++ b/src/haiku_io.c @@ -36,6 +36,10 @@ along with GNU Emacs. If not, see . */ Emacs. */ port_id port_application_to_emacs; +/* The port used to send popup menu messages from the application + thread to Emacs. */ +port_id port_popup_menu_to_emacs; + void haiku_io_init (void) { @@ -98,9 +102,11 @@ haiku_len (enum haiku_event_type type) /* Read the size of the next message into len, returning -1 if the query fails or there is no next message. */ void -haiku_read_size (ssize_t *len) +haiku_read_size (ssize_t *len, bool popup_menu_p) { - port_id from = port_application_to_emacs; + port_id from = (popup_menu_p + ? port_popup_menu_to_emacs + : port_application_to_emacs); ssize_t size; size = port_buffer_size_etc (from, B_TIMEOUT, 0); @@ -129,13 +135,16 @@ haiku_read (enum haiku_event_type *type, void *buf, ssize_t len) } /* The same as haiku_read, but time out after TIMEOUT microseconds. + POPUP_MENU_P means to read from the popup menu port instead. Input is blocked when an attempt to read is in progress. */ int haiku_read_with_timeout (enum haiku_event_type *type, void *buf, ssize_t len, - time_t timeout) + time_t timeout, bool popup_menu_p) { int32 typ; - port_id from = port_application_to_emacs; + port_id from = (popup_menu_p + ? port_popup_menu_to_emacs + : port_application_to_emacs); block_input (); if (read_port_etc (from, &typ, buf, len, @@ -165,9 +174,12 @@ haiku_write (enum haiku_event_type type, void *buf) } int -haiku_write_without_signal (enum haiku_event_type type, void *buf) +haiku_write_without_signal (enum haiku_event_type type, void *buf, + bool popup_menu_p) { - port_id to = port_application_to_emacs; + port_id to = (popup_menu_p + ? port_popup_menu_to_emacs + : port_application_to_emacs); if (write_port (to, (int32_t) type, buf, haiku_len (type)) < B_OK) return -1; diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 41e5b71182..05bc410eb2 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -114,6 +114,8 @@ static BLocker child_frame_lock; static BLocker movement_locker; +static BMessage volatile *popup_track_message; + /* This could be a private API, but it's used by (at least) the Qt port, so it's probably here to stay. */ extern status_t get_subpixel_antialiasing (bool *); @@ -137,6 +139,30 @@ gui_abort (const char *msg) emacs_abort (); } +struct be_popup_menu_data +{ + int x, y; + BPopUpMenu *menu; +}; + +static int32 +be_popup_menu_thread_entry (void *thread_data) +{ + struct be_popup_menu_data *data; + BMenuItem *it; + + data = (struct be_popup_menu_data *) thread_data; + + it = data->menu->Go (BPoint (data->x, data->y)); + + if (it) + popup_track_message = it->Message (); + else + popup_track_message = NULL; + + return 0; +} + /* Convert a raw character RAW produced by the keycode KEY into a key symbol and place it in KEYSYM. @@ -656,8 +682,10 @@ class EmacsWindow : public BWindow else if (msg->GetPointer ("menuptr")) { struct haiku_menu_bar_select_event rq; + rq.window = this; rq.ptr = (void *) msg->GetPointer ("menuptr"); + haiku_write (MENU_BAR_SELECT_EVENT, &rq); } else if (msg->what == 'FPSE' @@ -1607,6 +1635,7 @@ class EmacsMenuItem : public BMenuItem { public: int menu_bar_id = -1; + void *menu_ptr = NULL; void *wind_ptr = NULL; char *key = NULL; char *help = NULL; @@ -1675,16 +1704,23 @@ class EmacsMenuItem : public BMenuItem if (help) menu->SetToolTip (highlight_p ? help : NULL); - else if (menu_bar_id >= 0) + else { rq.window = wind_ptr; rq.mb_idx = highlight_p ? menu_bar_id : -1; + rq.highlight_p = highlight_p; + rq.data = menu_ptr; r = Frame (); menu->GetMouse (&pt, &buttons); if (!highlight_p || r.Contains (pt)) - haiku_write (MENU_BAR_HELP_EVENT, &rq); + { + if (menu_bar_id > 0) + haiku_write (MENU_BAR_HELP_EVENT, &rq); + else + haiku_write_without_signal (MENU_BAR_HELP_EVENT, &rq, true); + } } BMenuItem::Highlight (highlight_p); @@ -2353,6 +2389,7 @@ BMenu_add_item (void *menu, const char *label, void *ptr, bool enabled_p, it->menu_bar_id = (intptr_t) ptr; it->wind_ptr = mbw_ptr; } + it->menu_ptr = ptr; if (ptr) msg->AddPointer ("menuptr", ptr); m->AddItem (it); @@ -2397,20 +2434,109 @@ BMenu_new_menu_bar_submenu (void *menu, const char *label) data of the selected item (if one exists), or NULL. X, Y should be in the screen coordinate system. */ void * -BMenu_run (void *menu, int x, int y) +BMenu_run (void *menu, int x, int y, + void (*run_help_callback) (void *, void *), + void (*block_input_function) (void), + void (*unblock_input_function) (void), + void (*process_pending_signals_function) (void), + void *run_help_callback_data) { BPopUpMenu *mn = (BPopUpMenu *) menu; + enum haiku_event_type type; + void *buf; + void *ptr = NULL; + struct be_popup_menu_data data; + struct object_wait_info infos[2]; + struct haiku_menu_bar_help_event *event; + BMessage *msg; + ssize_t stat; + + block_input_function (); + port_popup_menu_to_emacs = create_port (1800, "popup menu port"); + data.x = x; + data.y = y; + data.menu = mn; + unblock_input_function (); + + if (port_popup_menu_to_emacs < B_OK) + return NULL; + + block_input_function (); mn->SetRadioMode (0); - BMenuItem *it = mn->Go (BPoint (x, y)); - if (it) + buf = alloca (200); + + infos[0].object = port_popup_menu_to_emacs; + infos[0].type = B_OBJECT_TYPE_PORT; + infos[0].events = B_EVENT_READ; + + infos[1].object = spawn_thread (be_popup_menu_thread_entry, + "Menu tracker", B_DEFAULT_MEDIA_PRIORITY, + (void *) &data); + infos[1].type = B_OBJECT_TYPE_THREAD; + infos[1].events = B_EVENT_INVALID; + unblock_input_function (); + + if (infos[1].object < B_OK) { - BMessage *mg = it->Message (); - if (mg) - return (void *) mg->GetPointer ("menuptr"); - else - return NULL; + block_input_function (); + delete_port (port_popup_menu_to_emacs); + unblock_input_function (); + return NULL; + } + + block_input_function (); + resume_thread (infos[1].object); + unblock_input_function (); + + while (true) + { + if ((stat = wait_for_objects_etc ((object_wait_info *) &infos, 2, + B_RELATIVE_TIMEOUT, 10000)) < B_OK) + { + if (stat == B_INTERRUPTED) + continue; + else if (stat == B_TIMED_OUT) + { + process_pending_signals_function (); + continue; + } + else + gui_abort ("Failed to wait for popup"); + } + + if (infos[0].events & B_EVENT_READ) + { + if (!haiku_read_with_timeout (&type, buf, 200, 1000000, true)) + { + switch (type) + { + case MENU_BAR_HELP_EVENT: + event = (struct haiku_menu_bar_help_event *) buf; + run_help_callback (event->highlight_p + ? event->data + : NULL, run_help_callback_data); + break; + default: + gui_abort ("Unknown popup menu event"); + } + } + } + + if (infos[1].events & B_EVENT_INVALID) + { + block_input_function (); + msg = (BMessage *) popup_track_message; + if (popup_track_message) + ptr = (void *) msg->GetPointer ("menuptr"); + + delete_port (port_popup_menu_to_emacs); + unblock_input_function (); + return ptr; + } + + infos[0].events = B_EVENT_READ; + infos[1].events = B_EVENT_INVALID; } - return NULL; } /* Delete the entire menu hierarchy of MENU, and then delete MENU @@ -2864,7 +2990,7 @@ be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p, int enum haiku_event_type type; char *ptr = NULL; - if (!haiku_read_with_timeout (&type, buf, 200, 1000000)) + if (!haiku_read_with_timeout (&type, buf, 200, 1000000, false)) { block_input_function (); if (type != FILE_PANEL_EVENT) @@ -2878,7 +3004,7 @@ be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p, int ssize_t b_s; block_input_function (); - haiku_read_size (&b_s); + haiku_read_size (&b_s, false); if (!b_s || ptr || panel->Window ()->IsHidden ()) { c_unbind_to_nil_from_cxx (idx); diff --git a/src/haiku_support.h b/src/haiku_support.h index 8d4dddd90f..4b0456168d 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -200,6 +200,8 @@ struct haiku_menu_bar_help_event { void *window; int mb_idx; + void *data; + bool highlight_p; }; struct haiku_zoom_event @@ -358,25 +360,27 @@ extern "C" #endif extern port_id port_application_to_emacs; + extern port_id port_popup_menu_to_emacs; extern void haiku_io_init (void); extern void haiku_io_init_in_app_thread (void); extern void - haiku_read_size (ssize_t *len); + haiku_read_size (ssize_t *len, bool popup_menu_p); extern int haiku_read (enum haiku_event_type *type, void *buf, ssize_t len); extern int haiku_read_with_timeout (enum haiku_event_type *type, void *buf, ssize_t len, - time_t timeout); + time_t timeout, bool popup_menu_p); extern int haiku_write (enum haiku_event_type type, void *buf); extern int - haiku_write_without_signal (enum haiku_event_type type, void *buf); + haiku_write_without_signal (enum haiku_event_type type, void *buf, + bool popup_menu_p); extern void rgb_color_hsl (uint32_t rgb, double *h, double *s, double *l); @@ -679,7 +683,12 @@ extern "C" BMenu_item_at (void *menu, int idx); extern void * - BMenu_run (void *menu, int x, int y); + BMenu_run (void *menu, int x, int y, + void (*run_help_callback) (void *, void *), + void (*block_input_function) (void), + void (*unblock_input_function) (void), + void (*process_pending_signals_function) (void), + void *run_help_callback_data); extern void BPopUpMenu_delete (void *menu); diff --git a/src/haikumenu.c b/src/haikumenu.c index 875f1afb6a..26eb3dbfe1 100644 --- a/src/haikumenu.c +++ b/src/haikumenu.c @@ -150,11 +150,20 @@ digest_menu_items (void *first_menu, int start, int menu_items_used, else if (NILP (def) && menu_separator_name_p (SSDATA (item_name))) BMenu_add_separator (menu); else if (!mbar_p) - BMenu_add_item (menu, SSDATA (item_name), - !NILP (def) ? aref_addr (menu_items, i) : NULL, - !NILP (enable), !NILP (selected), 0, window, - !NILP (descrip) ? SSDATA (descrip) : NULL, - STRINGP (help) ? SSDATA (help) : NULL); + { + if (!use_system_tooltips || NILP (Fsymbol_value (Qtooltip_mode))) + BMenu_add_item (menu, SSDATA (item_name), + !NILP (def) ? aref_addr (menu_items, i) : NULL, + !NILP (enable), !NILP (selected), 0, window, + !NILP (descrip) ? SSDATA (descrip) : NULL, + NULL); + else + BMenu_add_item (menu, SSDATA (item_name), + !NILP (def) ? aref_addr (menu_items, i) : NULL, + !NILP (enable), !NILP (selected), 0, window, + !NILP (descrip) ? SSDATA (descrip) : NULL, + STRINGP (help) ? SSDATA (help) : NULL); + } else if (!use_system_tooltips || NILP (Fsymbol_value (Qtooltip_mode))) BMenu_add_item (menu, SSDATA (item_name), !NILP (def) ? (void *) (intptr_t) i : NULL, @@ -294,6 +303,27 @@ haiku_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) return selection; } +static void +haiku_menu_show_help (void *help, void *data) +{ + Lisp_Object *id = (Lisp_Object *) help; + + if (help) + show_help_echo (id[MENU_ITEMS_ITEM_HELP], + Qnil, Qnil, Qnil); + else + show_help_echo (Qnil, Qnil, Qnil, Qnil); +} + +static void +haiku_process_pending_signals_for_menu (void) +{ + process_pending_signals (); + + input_pending = false; + detect_input_pending_run_timers (true); +} + Lisp_Object haiku_menu_show (struct frame *f, int x, int y, int menuflags, Lisp_Object title, const char **error_name) @@ -327,9 +357,14 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags, } digest_menu_items (menu, 0, menu_items_used, 0); BView_convert_to_screen (view, &x, &y); - menu_item_selection = BMenu_run (menu, x, y); unblock_input (); + popup_activated_p++; + menu_item_selection = BMenu_run (menu, x, y, haiku_menu_show_help, + block_input, unblock_input, + haiku_process_pending_signals_for_menu, NULL); + popup_activated_p--; + FRAME_DISPLAY_INFO (f)->grabbed = 0; if (menu_item_selection) diff --git a/src/haikuterm.c b/src/haikuterm.c index b9eb1d2fc5..6a84e61add 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -2559,7 +2559,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) if (!buf) buf = xmalloc (200); - haiku_read_size (&b_size); + haiku_read_size (&b_size, false); while (b_size >= 0) { enum haiku_event_type type; @@ -2831,6 +2831,8 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) || !NILP (previous_help_echo_string)) do_help = 1; } + + need_flush = FRAME_DIRTY_P (f); break; } case BUTTON_UP: @@ -3260,7 +3262,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) break; } - haiku_read_size (&b_size); + haiku_read_size (&b_size, false); if (inev.kind != NO_EVENT) { @@ -3285,7 +3287,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) for (struct unhandled_event *ev = unhandled_events; ev;) { - haiku_write_without_signal (ev->type, &ev->buffer); + haiku_write_without_signal (ev->type, &ev->buffer, false); struct unhandled_event *old = ev; ev = old->next; xfree (old); commit 70fc32f6ddef871dd2ae15a3333974f6d8231d6a Author: Stefan Monnier Date: Fri Jan 28 23:39:31 2022 -0500 * src/data.c (Ffset, defalias): Complete last change Somehow part of the autoload history handling was left behind in `Ffset` when the rest was moved to `defalias`. Finish the job. * src/data.c (Ffset): Don't set the `autoload` property here... (defalias): ... set it here instead. diff --git a/src/data.c b/src/data.c index dd6ec4c41a..039e6c3113 100644 --- a/src/data.c +++ b/src/data.c @@ -846,9 +846,6 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0, function = XSYMBOL (symbol)->u.s.function; - if (AUTOLOADP (function)) - Fput (symbol, Qautoload, XCDR (function)); - eassert (valid_lisp_object_p (definition)); #ifdef HAVE_NATIVE_COMP @@ -880,6 +877,9 @@ defalias (Lisp_Object symbol, Lisp_Object definition) if (!NILP (Vautoload_queue) && !NILP (function)) Vautoload_queue = Fcons (Fcons (symbol, function), Vautoload_queue); + + if (AUTOLOADP (function)) + Fput (symbol, Qautoload, XCDR (function)); } } commit 7531bf096eb3f1b0b6612e94eb5211405e049fee Author: Stefan Monnier Date: Fri Jan 28 13:19:11 2022 -0500 Reduce code duplication in parts of (auto)load&defalias * src/data.c (defalias): New function, extracted from `Fdefalias`. (Fdefalias): Use it. (Ffset): Don't handle `Vautoload_queue` here, handle it in `defalias` instead. * src/comp.c (comp--register-subr): Use `defalias` instead of duplicating its code. * src/eval.c (load_with_autoload_queue): New function, extracted from `Fautoload_do_load`. (Fautoload_do_load): Use it. (un_autoload): Mark it as static. * src/fns.c (Frequire): Use it as well. * src/lisp.h (defalias, load_with_autoload_queue): New declarations. (un_autoload): Remove declaration. diff --git a/lisp/emacs-lisp/cl-preloaded.el b/lisp/emacs-lisp/cl-preloaded.el index ef60b266f9..6aa45526d8 100644 --- a/lisp/emacs-lisp/cl-preloaded.el +++ b/lisp/emacs-lisp/cl-preloaded.el @@ -1,6 +1,6 @@ ;;; cl-preloaded.el --- Preloaded part of the CL library -*- lexical-binding: t; -*- -;; Copyright (C) 2015-2021 Free Software Foundation, Inc +;; Copyright (C) 2015-2022 Free Software Foundation, Inc ;; Author: Stefan Monnier ;; Package: emacs diff --git a/src/comp.c b/src/comp.c index 56e583eb5c..9342712a38 100644 --- a/src/comp.c +++ b/src/comp.c @@ -5500,19 +5500,7 @@ This gets called by top_level_run during the load phase. */) make_subr (SYMBOL_NAME (name), minarg, maxarg, c_name, type, doc_idx, intspec, comp_u); - if (AUTOLOADP (XSYMBOL (name)->u.s.function)) - /* Remember that the function was already an autoload. */ - LOADHIST_ATTACH (Fcons (Qt, name)); - LOADHIST_ATTACH (Fcons (Qdefun, name)); - - { /* Handle automatic advice activation (bug#42038). - See `defalias'. */ - Lisp_Object hook = Fget (name, Qdefalias_fset_function); - if (!NILP (hook)) - call2 (hook, name, tem); - else - Ffset (name, tem); - } + defalias (name, tem); return tem; } diff --git a/src/data.c b/src/data.c index 7422348e39..dd6ec4c41a 100644 --- a/src/data.c +++ b/src/data.c @@ -846,9 +846,6 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0, function = XSYMBOL (symbol)->u.s.function; - if (!NILP (Vautoload_queue) && !NILP (function)) - Vautoload_queue = Fcons (Fcons (symbol, function), Vautoload_queue); - if (AUTOLOADP (function)) Fput (symbol, Qautoload, XCDR (function)); @@ -866,35 +863,23 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0, return definition; } -DEFUN ("defalias", Fdefalias, Sdefalias, 2, 3, 0, - doc: /* Set SYMBOL's function definition to DEFINITION. -Associates the function with the current load file, if any. -The optional third argument DOCSTRING specifies the documentation string -for SYMBOL; if it is omitted or nil, SYMBOL uses the documentation string -determined by DEFINITION. - -Internally, this normally uses `fset', but if SYMBOL has a -`defalias-fset-function' property, the associated value is used instead. - -The return value is undefined. */) - (register Lisp_Object symbol, Lisp_Object definition, Lisp_Object docstring) +void +defalias (Lisp_Object symbol, Lisp_Object definition) { - CHECK_SYMBOL (symbol); - if (!NILP (Vpurify_flag) - /* If `definition' is a keymap, immutable (and copying) is wrong. */ - && !KEYMAPP (definition)) - definition = Fpurecopy (definition); - { bool autoload = AUTOLOADP (definition); if (!will_dump_p () || !autoload) { /* Only add autoload entries after dumping, because the ones before are not useful and else we get loads of them from the loaddefs.el. */ + Lisp_Object function = XSYMBOL (symbol)->u.s.function; - if (AUTOLOADP (XSYMBOL (symbol)->u.s.function)) + if (AUTOLOADP (function)) /* Remember that the function was already an autoload. */ LOADHIST_ATTACH (Fcons (Qt, symbol)); LOADHIST_ATTACH (Fcons (autoload ? Qautoload : Qdefun, symbol)); + + if (!NILP (Vautoload_queue) && !NILP (function)) + Vautoload_queue = Fcons (Fcons (symbol, function), Vautoload_queue); } } @@ -905,6 +890,28 @@ The return value is undefined. */) else Ffset (symbol, definition); } +} + +DEFUN ("defalias", Fdefalias, Sdefalias, 2, 3, 0, + doc: /* Set SYMBOL's function definition to DEFINITION. +Associates the function with the current load file, if any. +The optional third argument DOCSTRING specifies the documentation string +for SYMBOL; if it is omitted or nil, SYMBOL uses the documentation string +determined by DEFINITION. + +Internally, this normally uses `fset', but if SYMBOL has a +`defalias-fset-function' property, the associated value is used instead. + +The return value is undefined. */) + (register Lisp_Object symbol, Lisp_Object definition, Lisp_Object docstring) +{ + CHECK_SYMBOL (symbol); + if (!NILP (Vpurify_flag) + /* If `definition' is a keymap, immutable (and copying) is wrong. */ + && !KEYMAPP (definition)) + definition = Fpurecopy (definition); + + defalias (symbol, definition); maybe_defer_native_compilation (symbol, definition); diff --git a/src/eval.c b/src/eval.c index 205a0b0db2..b083a00a79 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2247,7 +2247,7 @@ this does nothing and returns nil. */) Qnil); } -void +static void un_autoload (Lisp_Object oldqueue) { Lisp_Object queue, first, second; @@ -2269,6 +2269,32 @@ un_autoload (Lisp_Object oldqueue) } } +Lisp_Object +load_with_autoload_queue + (Lisp_Object file, Lisp_Object noerror, Lisp_Object nomessage, + Lisp_Object nosuffix, Lisp_Object must_suffix) +{ + ptrdiff_t count = SPECPDL_INDEX (); + + /* If autoloading gets an error (which includes the error of failing + to define the function being called), we use Vautoload_queue + to undo function definitions and `provide' calls made by + the function. We do this in the specific case of autoloading + because autoloading is not an explicit request "load this file", + but rather a request to "call this function". + + The value saved here is to be restored into Vautoload_queue. */ + record_unwind_protect (un_autoload, Vautoload_queue); + Vautoload_queue = Qt; + Lisp_Object tem + = save_match_data_load (file, noerror, nomessage, nosuffix, must_suffix); + + /* Once loading finishes, don't undo it. */ + Vautoload_queue = Qt; + unbind_to (count, Qnil); + return tem; +} + /* Load an autoloaded function. FUNNAME is the symbol which is the function's name. FUNDEF is the autoload definition (a list). */ @@ -2281,8 +2307,6 @@ If equal to `macro', MACRO-ONLY specifies that FUNDEF should only be loaded if it defines a macro. */) (Lisp_Object fundef, Lisp_Object funname, Lisp_Object macro_only) { - ptrdiff_t count = SPECPDL_INDEX (); - if (!CONSP (fundef) || !EQ (Qautoload, XCAR (fundef))) return fundef; @@ -2299,26 +2323,12 @@ it defines a macro. */) CHECK_SYMBOL (funname); - /* If autoloading gets an error (which includes the error of failing - to define the function being called), we use Vautoload_queue - to undo function definitions and `provide' calls made by - the function. We do this in the specific case of autoloading - because autoloading is not an explicit request "load this file", - but rather a request to "call this function". - - The value saved here is to be restored into Vautoload_queue. */ - record_unwind_protect (un_autoload, Vautoload_queue); - Vautoload_queue = Qt; /* If `macro_only' is set and fundef isn't a macro, assume this autoload to be a "best-effort" (e.g. to try and find a compiler macro), so don't signal an error if autoloading fails. */ Lisp_Object ignore_errors = (EQ (kind, Qt) || EQ (kind, Qmacro)) ? Qnil : macro_only; - save_match_data_load (Fcar (Fcdr (fundef)), ignore_errors, Qt, Qnil, Qt); - - /* Once loading finishes, don't undo it. */ - Vautoload_queue = Qt; - unbind_to (count, Qnil); + load_with_autoload_queue (Fcar (Fcdr (fundef)), ignore_errors, Qt, Qnil, Qt); if (NILP (funname) || !NILP (ignore_errors)) return Qnil; diff --git a/src/fns.c b/src/fns.c index 16f1ebe439..c67871da74 100644 --- a/src/fns.c +++ b/src/fns.c @@ -3249,12 +3249,8 @@ FILENAME are suppressed. */) record_unwind_protect (require_unwind, require_nesting_list); require_nesting_list = Fcons (feature, require_nesting_list); - /* Value saved here is to be restored into Vautoload_queue */ - record_unwind_protect (un_autoload, Vautoload_queue); - Vautoload_queue = Qt; - /* Load the file. */ - tem = save_match_data_load + tem = load_with_autoload_queue (NILP (filename) ? Fsymbol_name (feature) : filename, noerror, Qt, Qnil, (NILP (filename) ? Qt : Qnil)); @@ -3276,8 +3272,6 @@ FILENAME are suppressed. */) SDATA (tem3), tem2); } - /* Once loading finishes, don't undo it. */ - Vautoload_queue = Qt; feature = unbind_to (count, feature); } diff --git a/src/lisp.h b/src/lisp.h index 8c55ad72a9..10f45057d5 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -620,6 +620,7 @@ extern bool symbols_with_pos_enabled; extern AVOID args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object); extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object); extern Lisp_Object default_value (Lisp_Object symbol); +extern void defalias (Lisp_Object symbol, Lisp_Object definition); /* Defined in emacs.c. */ @@ -4366,7 +4367,9 @@ extern AVOID verror (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0); extern Lisp_Object vformat_string (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0); -extern void un_autoload (Lisp_Object); +extern Lisp_Object load_with_autoload_queue + (Lisp_Object file, Lisp_Object noerror, Lisp_Object nomessage, + Lisp_Object nosuffix, Lisp_Object must_suffix); extern Lisp_Object call_debugger (Lisp_Object arg); extern void init_eval_once (void); extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...); diff --git a/test/lisp/emacs-lisp/range-tests.el b/test/lisp/emacs-lisp/range-tests.el index d3abbf9da3..660110aa1f 100644 --- a/test/lisp/emacs-lisp/range-tests.el +++ b/test/lisp/emacs-lisp/range-tests.el @@ -1,6 +1,6 @@ ;;; range-tests.el --- Tests for range.el -*- lexical-binding: t; -*- -;; Copyright (C) 2021 Free Software Foundation, Inc. +;; Copyright (C) 2021-2022 Free Software Foundation, Inc. ;; This file is part of GNU Emacs. commit 1f5fa1de7fc2f23ebd7e68db219da4faee916a6f Author: Sebastian Urban Date: Fri Jan 28 17:27:28 2022 +0100 Make where-is correctly identify aliases * lisp/help.el (where-is): Make aliases correctly say which function is an alias for what (bug#37325). diff --git a/lisp/help.el b/lisp/help.el index 983f39479c..eb024373e4 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -650,15 +650,21 @@ If INSERT (the prefix arg) is non-nil, insert the message in the buffer." (if insert (if (> (length keys) 0) (if remapped - (format "%s (%s) (remapped from %s)" - keys remapped symbol) - (format "%s (%s)" keys symbol)) + (format "%s, remapped to %s (%s)" + symbol remapped keys) + (format "%s (%s)" symbol keys)) (format "M-x %s RET" symbol)) (if (> (length keys) 0) (if remapped - (format "%s is remapped to %s which is on %s" - symbol remapped keys) - (format "%s is on %s" symbol keys)) + (if (eq symbol (symbol-function definition)) + (format + "%s, which is remapped to %s, which is on %s" + symbol remapped keys) + (format "%s is remapped to %s, which is on %s" + symbol remapped keys)) + (if (eq symbol (symbol-function definition)) + (format "%s, which is on %s" symbol keys) + (format "%s is on %s" symbol keys))) ;; If this is the command the user asked about, ;; and it is not on any key, say so. ;; For other symbols, its aliases, say nothing @@ -667,7 +673,9 @@ If INSERT (the prefix arg) is non-nil, insert the message in the buffer." (format "%s is not on any key" symbol))))) (when string (unless (eq symbol definition) - (princ ";\n its alias ")) + (if (eq definition (symbol-function symbol)) + (princ ";\n its alias ") + (princ ";\n it's an alias for "))) (princ string))))) nil) commit 96867f9d0897319adda9d7b8ec84c1fb9e451225 Author: Sebastian Urban Date: Fri Jan 28 17:12:35 2022 +0100 Fix manual points about tex-latex-block/latex-insert-block * doc/emacs/text.texi (LaTeX Editing): (LaTeX Editing): Update documentation of tex-latex-block/latex-insert-block to what they really point to (bug#37325). Copyright-paperwork-exempt: yes diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi index c5b54777a8..9f152f1cc1 100644 --- a/doc/emacs/text.texi +++ b/doc/emacs/text.texi @@ -1702,17 +1702,17 @@ to work with them. @table @kbd @item C-c C-o Insert @samp{\begin} and @samp{\end} for @LaTeX{} block and position -point on a line between them (@code{tex-latex-block}). +point on a line between them (@code{latex-insert-block}). @item C-c C-e Close the innermost @LaTeX{} block not yet closed -(@code{tex-close-latex-block}). +(@code{latex-close-block}). @end table -@findex tex-latex-block +@findex latex-insert-block @kindex C-c C-o @r{(@LaTeX{} mode)} In @LaTeX{} input, @samp{\begin} and @samp{\end} tags are used to group blocks of text. To insert a block, type @kbd{C-c C-o} -(@code{tex-latex-block}). This prompts for a block type, and inserts +(@code{latex-insert-block}). This prompts for a block type, and inserts the appropriate matching @samp{\begin} and @samp{\end} tags, leaving a blank line between the two and moving point there. @@ -1723,11 +1723,11 @@ completion list contains the standard @LaTeX{} block types. If you want additional block types for completion, customize the list variable @code{latex-block-names}. -@findex tex-close-latex-block +@findex latex-close-block @kindex C-c C-e @r{(@LaTeX{} mode)} @findex latex-electric-env-pair-mode In @LaTeX{} input, @samp{\begin} and @samp{\end} tags must balance. -You can use @kbd{C-c C-e} (@code{tex-close-latex-block}) to insert an +You can use @kbd{C-c C-e} (@code{latex-close-block}) to insert an @samp{\end} tag which matches the last unmatched @samp{\begin}. It also indents the @samp{\end} to match the corresponding @samp{\begin}, and inserts a newline after the @samp{\end} tag if point is at the commit fdc72729802a60c64e44251b5a69824393ccd170 Author: Lars Ingebrigtsen Date: Fri Jan 28 17:03:14 2022 +0100 Improve the read-file-name doc string slightly * lisp/minibuffer.el (read-file-name): Note that the semantics of INITIAL are odd (bug#37883). diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 917879fb69..c9f5823940 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -3066,7 +3066,10 @@ Fourth arg MUSTMATCH can take the following values: - anything else behaves like t except that typing RET does not exit if it does non-null completion. -Fifth arg INITIAL specifies text to start with. +Fifth arg INITIAL specifies text to start with. It will be +interpreted as the trailing part of DEFAULT-FILENAME, so using a +full file name for INITIAL will usually lead to surprising +results. Sixth arg PREDICATE, if non-nil, should be a function of one argument; then a file name is considered an acceptable completion commit 87c23670111b03768dc722208dfe11183cebc5d5 Author: Michael Albinus Date: Fri Jan 28 16:32:15 2022 +0100 Clarify where the shell-command output goes * lisp/simple.el (shell-command): * doc/emacs/misc.texi (Single Shell): Clarify where the output goes if the specified buffer isn't the current one (bug#40896). diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index 365c079e89..4710c05b62 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -856,6 +856,9 @@ Restores the position of point as it was before inserting the shell-command output. @end table +In case the output buffer is not the current buffer, shell command +output is appended at the end of this buffer. + @node Interactive Shell @subsection Interactive Subshell diff --git a/lisp/simple.el b/lisp/simple.el index 801a3c992c..00669ac634 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -4092,6 +4092,10 @@ interactively when the prefix argument is given), insert the output in current buffer after point leaving mark after it. This cannot be done asynchronously. +If OUTPUT-BUFFER is a buffer or buffer name different from the +current buffer, instead of outputting at point in that buffer, +the output will be appended at the end of that buffer. + The user option `shell-command-dont-erase-buffer', which see, controls whether the output buffer is erased and where to put point after the shell command. commit 12d3c4831aa39974814604a3d13b8033d75441e6 Author: Lars Ingebrigtsen Date: Fri Jan 28 15:56:05 2022 +0100 Allow using dired-hide-details-mode in wdired buffers * lisp/dired.el (dired-hide-details-mode): Also work in wdired-mode buffers (bug#45127). * lisp/wdired.el (wdired-mode-map): Add a key binding. diff --git a/lisp/dired.el b/lisp/dired.el index 9813fca435..5f1bfef12c 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -2756,7 +2756,7 @@ permissions are hidden from view. See options: `dired-hide-details-hide-symlink-targets' and `dired-hide-details-hide-information-lines'." :group 'dired - (unless (derived-mode-p 'dired-mode) + (unless (derived-mode-p 'dired-mode 'wdired-mode) (error "Not a Dired buffer")) (dired-hide-details-update-invisibility-spec) (if dired-hide-details-mode diff --git a/lisp/wdired.el b/lisp/wdired.el index 1c02562721..ab3b91bbe5 100644 --- a/lisp/wdired.el +++ b/lisp/wdired.el @@ -169,6 +169,7 @@ nonexistent directory will fail." "C-p" #'wdired-previous-line "" #'wdired-next-line "C-n" #'wdired-next-line + "C-(" #'dired-hide-details-mode " " #'wdired-upcase-word " " #'wdired-capitalize-word " " #'wdired-downcase-word commit bf695b937e17068a1bc278c018235317fff787d8 Author: Lars Ingebrigtsen Date: Fri Jan 28 15:26:39 2022 +0100 Move native-comp-eln-load-path setting earlier again * lisp/startup.el (normal-top-level): Move `native-comp-eln-load-path' earlier because hooks called may need the setting (bug#53596). diff --git a/lisp/startup.el b/lisp/startup.el index 60aaa76002..66dd726ae9 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -693,6 +693,47 @@ It is the default value of the variable `top-level'." (let ((old-face-font-rescale-alist face-font-rescale-alist)) (unwind-protect (command-line) + + ;; Do this after `command-line', since it may alter + ;; `user-emacs-directory'. + (when (featurep 'native-compile) + ;; Form `native-comp-eln-load-path'. + (let ((path-env (getenv "EMACSNATIVELOADPATH"))) + (when path-env + (dolist (path (split-string path-env path-separator)) + (unless (string= "" path) + (push path native-comp-eln-load-path))))) + (push (expand-file-name "eln-cache/" user-emacs-directory) + native-comp-eln-load-path) + ;; When $HOME is set to '/nonexistent' means we are running the + ;; testsuite, add a temporary folder in front to produce there + ;; new compilations. + (when (and (equal (getenv "HOME") "/nonexistent") + ;; We may be running in a chroot environment where we + ;; can't write anything. + (file-writable-p (expand-file-name + (or temporary-file-directory "")))) + (let ((tmp-dir (make-temp-file "emacs-testsuite-" t))) + (add-hook 'kill-emacs-hook + (lambda () + (delete-directory tmp-dir t))) + (push tmp-dir native-comp-eln-load-path))) + (when locale-coding-system + (let ((coding (if (eq system-type 'windows-nt) + ;; MS-Windows build converts all file names to + ;; UTF-8 during startup. + 'utf-8 + locale-coding-system)) + (npath (symbol-value 'native-comp-eln-load-path))) + (set 'native-comp-eln-load-path + (mapcar (lambda (dir) + ;; Call expand-file-name to remove all the + ;; pesky ".." from the directyory names in + ;; native-comp-eln-load-path. + (expand-file-name + (decode-coding-string dir coding t))) + npath))))) + ;; Do this again, in case .emacs defined more abbreviations. (if default-directory (setq default-directory (abbreviate-file-name default-directory))) @@ -760,44 +801,6 @@ It is the default value of the variable `top-level'." (unless inhibit-startup-hooks (run-hooks 'window-setup-hook)))) - ;; Do this after `command-line', since it may alter - ;; `user-emacs-directory'. - (when (featurep 'native-compile) - ;; Form `native-comp-eln-load-path'. - (let ((path-env (getenv "EMACSNATIVELOADPATH"))) - (when path-env - (dolist (path (split-string path-env path-separator)) - (unless (string= "" path) - (push path native-comp-eln-load-path))))) - (push (expand-file-name "eln-cache/" user-emacs-directory) - native-comp-eln-load-path) - ;; When $HOME is set to '/nonexistent' means we are running the - ;; testsuite, add a temporary folder in front to produce there - ;; new compilations. - (when (and (equal (getenv "HOME") "/nonexistent") - ;; We may be running in a chroot environment where we - ;; can't write anything. - (file-writable-p (expand-file-name - (or temporary-file-directory "")))) - (let ((tmp-dir (make-temp-file "emacs-testsuite-" t))) - (add-hook 'kill-emacs-hook (lambda () (delete-directory tmp-dir t))) - (push tmp-dir native-comp-eln-load-path))) - (when locale-coding-system - (let ((coding (if (eq system-type 'windows-nt) - ;; MS-Windows build converts all file names to - ;; UTF-8 during startup. - 'utf-8 - locale-coding-system)) - (npath (symbol-value 'native-comp-eln-load-path))) - (set 'native-comp-eln-load-path - (mapcar (lambda (dir) - ;; Call expand-file-name to remove all the - ;; pesky ".." from the directyory names in - ;; native-comp-eln-load-path. - (expand-file-name - (decode-coding-string dir coding t))) - npath))))) - ;; Subprocesses of Emacs do not have direct access to the terminal, so ;; unless told otherwise they should only assume a dumb terminal. ;; We are careful to do it late (after term-setup-hook), although the commit 70c3437ae1f20c050ecb96a642c9a568fd656105 Author: Lele Gaifax Date: Fri Jan 28 08:41:51 2022 +0100 Fix copyright-fix-years, use a dash to separate years in a range Commit 7a46fa9c751f7c3147cd9b27fe84c1ce25419d3b, allowing en-dash as years separator, changed the way the years range is composed taking the separator from the `sep' variable instead of always using an hardwired hyphen. Since the code explicitly avoid to touch (that is, extend) existing ranges, that `sep' variable is almost always a space, or whatever character precedes the last parsed year, thus generating a range like "2020 2022" instead of "2020-2022". * lisp/emacs-lisp/copyright.el (copyright-fix-years): Always use an dash to separate years in a range. * test/lisp/emacs-lisp/copyright-tests.el (with-copyright-fix-years-test): (copyright-fix-years-tests--data): (text-copyright-fix-years): New test cases (bug#53597). diff --git a/lisp/emacs-lisp/copyright.el b/lisp/emacs-lisp/copyright.el index 6b60097782..e5087672ae 100644 --- a/lisp/emacs-lisp/copyright.el +++ b/lisp/emacs-lisp/copyright.el @@ -313,7 +313,7 @@ independently replaces consecutive years with a range." (> prev-year first-year)) (goto-char range-end) (delete-region range-start range-end) - (insert (format "%c%d" sep prev-year)) + (insert (format "-%d" prev-year)) (goto-char p)) (setq first-year year range-start (point))))) diff --git a/test/lisp/emacs-lisp/copyright-tests.el b/test/lisp/emacs-lisp/copyright-tests.el index abb0913a0d..b00d697aa6 100644 --- a/test/lisp/emacs-lisp/copyright-tests.el +++ b/test/lisp/emacs-lisp/copyright-tests.el @@ -72,5 +72,25 @@ (buffer-string)) "Copyright 2021 FSF\nCopyright 2021, 2022 FSF\n"))) +(defmacro with-copyright-fix-years-test (orig result) + `(let ((copyright-year-ranges t)) + (with-temp-buffer + (insert ,orig) + (copyright-fix-years) + (should (equal (buffer-string) ,result))))) + +(defvar copyright-fix-years-tests--data + '((";; Copyright (C) 2008, 2010, 2012" + . ";; Copyright (C) 2008, 2010, 2012") + (";; Copyright (C) 2008, 2009, 2010, 2013, 2014, 2015, 2016, 2018" + . ";; Copyright (C) 2008-2010, 2013-2016, 2018") + (";; Copyright (C) 2008-2010, 2011, 2015, 2016, 2017" + . ";; Copyright (C) 2008-2010, 2011, 2015-2017"))) + +(ert-deftest text-copyright-fix-years () + "Test basics of \\[copyright-fix-years]." + (dolist (test copyright-fix-years-tests--data) + (with-copyright-fix-years-test (car test) (cdr test)))) + (provide 'copyright-tests) ;;; copyright-tests.el ends here commit 7ba197a163ddf4002253d7b9a26fb28076e1cef7 Author: Lars Ingebrigtsen Date: Fri Jan 28 14:47:15 2022 +0100 Fix merge error in doc-view-pdf/ps->png * lisp/doc-view.el (doc-view-pdf/ps->png): Fix merge error from previous epub patch. diff --git a/lisp/doc-view.el b/lisp/doc-view.el index b222096ac6..4979a2c0e2 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -1217,7 +1217,8 @@ is named like ODF with the extension turned to pdf." "Convert PDF-PS to PNG asynchronously." (funcall (pcase doc-view-doc-type - ((or 'pdf 'odf) doc-view-pdf->png-converter-function) + ((or 'pdf 'odf 'epub 'cbz 'fb2 'xps 'oxps) + doc-view-pdf->png-converter-function) ('djvu #'doc-view-djvu->tiff-converter-ddjvu) (_ #'doc-view-ps->png-converter-ghostscript)) pdf-ps png nil commit 11add52bec02497900fb0256ec13df9cd838ad39 Author: Po Lu Date: Fri Jan 28 17:49:38 2022 +0800 Prevent duplicate grab setting with xwidgets * src/xwidget.c (xwidget_show_view): Don't set passive grab if already set. diff --git a/src/xwidget.c b/src/xwidget.c index 5ac8ed4e19..85535a35b1 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1178,7 +1178,7 @@ xwidget_button_1 (struct xwidget_view *view, if (!target) target = model->widget_osr; - if (down_p) + if (down_p && !view->passive_grab) { view->passive_grab = target; view->passive_grab_destruction_signal commit 15f8c6b11e6423a1fbdcee98617882b34f6958f5 Author: Po Lu Date: Fri Jan 28 16:38:02 2022 +0800 Use the real cursor beneath the pointer on xwidgets * src/xwidget.c (define_cursors): Make manual cursor definition code PGTK-only. (xw_update_cursor_for_view): (xw_last_crossing_cursor_cb): New functions. (xw_maybe_synthesize_crossing): Attach and disconnect cursor signal handler where appropriate. (xwidget_init_view): Set the default cursor to the nontext cursor. (Fxwidget_delete_view): Disconnect last crossing signal if appropriate. * src/xwidget.h (struct xwidget_view): New field `last_crossing_cursor_signal'. diff --git a/src/xwidget.c b/src/xwidget.c index 6f731adced..5ac8ed4e19 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -123,11 +123,12 @@ struct widget_search_data }; static void find_widget (GtkWidget *t, struct widget_search_data *); -static void mouse_target_changed (WebKitWebView *, WebKitHitTestResult *, guint, - gpointer); #endif #ifdef HAVE_PGTK +static void mouse_target_changed (WebKitWebView *, WebKitHitTestResult *, guint, + gpointer); + static int xw_forward_event_translate (GdkEvent *event, struct xwidget_view *xv, struct xwidget *xw) @@ -420,11 +421,12 @@ fails. */) G_CALLBACK (webkit_decide_policy_cb), xw); - +#ifdef HAVE_PGTK g_signal_connect (G_OBJECT (xw->widget_osr), "mouse-target-changed", G_CALLBACK (mouse_target_changed), xw); +#endif g_signal_connect (G_OBJECT (xw->widget_osr), "create", G_CALLBACK (webkit_create_cb), @@ -1014,6 +1016,7 @@ find_widget_at_pos (GtkWidget *w, int x, int y, return NULL; } +#ifdef HAVE_PGTK static Emacs_Cursor cursor_for_hit (guint result, struct frame *frame) { @@ -1037,9 +1040,7 @@ static void define_cursors (struct xwidget *xw, WebKitHitTestResult *res) { struct xwidget_view *xvw; -#ifdef HAVE_PGTK GdkWindow *wdesc; -#endif xw->hit_result = webkit_hit_test_result_get_context (res); @@ -1053,16 +1054,12 @@ define_cursors (struct xwidget *xw, WebKitHitTestResult *res) if (XXWIDGET (xvw->model) == xw) { xvw->cursor = cursor_for_hit (xw->hit_result, xvw->frame); -#ifdef HAVE_X_WINDOWS - if (xvw->wdesc != None) - XDefineCursor (xvw->dpy, xvw->wdesc, xvw->cursor); -#else + if (gtk_widget_get_realized (xvw->widget)) { wdesc = gtk_widget_get_window (xvw->widget); gdk_window_set_cursor (wdesc, xvw->cursor); } -#endif } } } @@ -1075,6 +1072,7 @@ mouse_target_changed (WebKitWebView *webview, { define_cursors (xw, hitresult); } +#endif static gboolean run_file_chooser_cb (WebKitWebView *webview, @@ -1682,6 +1680,37 @@ xw_notify_virtual_downwards_until (struct xwidget_view *xv, g_list_free (path); } +static void +xw_update_cursor_for_view (struct xwidget_view *xv, + GdkWindow *crossing_window) +{ + GdkCursor *xg_cursor; + Cursor cursor; + + xg_cursor = gdk_window_get_cursor (crossing_window); + + if (xg_cursor) + { + cursor = gdk_x11_cursor_get_xcursor (xg_cursor); + + if (gdk_x11_cursor_get_xdisplay (xg_cursor) == xv->dpy) + xv->cursor = cursor; + } + else + xv->cursor = FRAME_OUTPUT_DATA (xv->frame)->nontext_cursor; + + if (xv->wdesc != None) + XDefineCursor (xv->dpy, xv->wdesc, xv->cursor); +} + +static void +xw_last_crossing_cursor_cb (GdkWindow *window, + GParamSpec *spec, + gpointer user_data) +{ + xw_update_cursor_for_view (user_data, window); +} + static bool xw_maybe_synthesize_crossing (struct xwidget_view *view, GdkWindow *current_window, @@ -1708,8 +1737,12 @@ xw_maybe_synthesize_crossing (struct xwidget_view *view, if (view->last_crossing_window && (gdk_window_is_destroyed (view->last_crossing_window) || crossing == XW_CROSSING_LEFT)) - g_clear_pointer (&view->last_crossing_window, - g_object_unref); + { + g_signal_handler_disconnect (view->last_crossing_window, + view->last_crossing_cursor_signal); + g_clear_pointer (&view->last_crossing_window, + g_object_unref); + } last_crossing = view->last_crossing_window; if (!last_crossing) @@ -1717,6 +1750,10 @@ xw_maybe_synthesize_crossing (struct xwidget_view *view, if (current_window) { view->last_crossing_window = g_object_ref (current_window); + xw_update_cursor_for_view (view, current_window); + view->last_crossing_cursor_signal + = g_signal_connect (G_OBJECT (current_window), "notify::cursor", + G_CALLBACK (xw_last_crossing_cursor_cb), view); xw_notify_virtual_downwards_until (view, current_window, toplevel, toplevel, @@ -1730,6 +1767,12 @@ xw_maybe_synthesize_crossing (struct xwidget_view *view, if (last_crossing != current_window) { view->last_crossing_window = g_object_ref (current_window); + g_signal_handler_disconnect (last_crossing, view->last_crossing_cursor_signal); + + xw_update_cursor_for_view (view, current_window); + view->last_crossing_cursor_signal + = g_signal_connect (G_OBJECT (current_window), "notify::cursor", + G_CALLBACK (xw_last_crossing_cursor_cb), view); ancestor = xw_find_common_ancestor (last_crossing, current_window, toplevel); @@ -2594,7 +2637,7 @@ xwidget_init_view (struct xwidget *xww, xv->wdesc = None; xv->frame = s->f; - xv->cursor = cursor_for_hit (xww->hit_result, s->f); + xv->cursor = FRAME_OUTPUT_DATA (s->f)->nontext_cursor; xv->just_resized = false; xv->last_crossing_window = NULL; xv->passive_grab = NULL; @@ -3224,6 +3267,9 @@ DEFUN ("delete-xwidget-view", Fremhash (make_fixnum (xv->wdesc), x_window_to_xwv_map); } + if (xv->last_crossing_window) + g_signal_handler_disconnect (xv->last_crossing_window, + xv->last_crossing_cursor_signal); g_clear_pointer (&xv->last_crossing_window, g_object_unref); diff --git a/src/xwidget.h b/src/xwidget.h index 8b47a0b904..be1460ede5 100644 --- a/src/xwidget.h +++ b/src/xwidget.h @@ -120,6 +120,7 @@ struct xwidget_view Window wdesc; GdkWindow *last_crossing_window; + guint last_crossing_cursor_signal; GtkWidget *passive_grab; guint passive_grab_destruction_signal; guint passive_grab_drag_signal; commit bad16c6f566c909dec3e330e5755a66441162209 Author: Po Lu Date: Fri Jan 28 16:08:10 2022 +0800 Fix xwidget build on PGTK * src/xwidget.c (xw_forward_event_translate): Adjust calls to `find_widget_at_pos' for recent changes. diff --git a/src/xwidget.c b/src/xwidget.c index 75e909f0e6..6f731adced 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -144,7 +144,7 @@ xw_forward_event_translate (GdkEvent *event, struct xwidget_view *xv, widget = find_widget_at_pos (xw->widgetwindow_osr, lrint (event->button.x - xv->clip_left), lrint (event->button.y - xv->clip_top), - &new_x, &new_y); + &new_x, &new_y, false, NULL); if (widget) { event->any.window = gtk_widget_get_window (widget); @@ -157,7 +157,7 @@ xw_forward_event_translate (GdkEvent *event, struct xwidget_view *xv, widget = find_widget_at_pos (xw->widgetwindow_osr, lrint (event->scroll.x - xv->clip_left), lrint (event->scroll.y - xv->clip_top), - &new_x, &new_y); + &new_x, &new_y, false, NULL); if (widget) { event->any.window = gtk_widget_get_window (widget); @@ -170,7 +170,7 @@ xw_forward_event_translate (GdkEvent *event, struct xwidget_view *xv, widget = find_widget_at_pos (xw->widgetwindow_osr, lrint (event->motion.x - xv->clip_left), lrint (event->motion.y - xv->clip_top), - &new_x, &new_y); + &new_x, &new_y, false, NULL); if (widget) { event->any.window = gtk_widget_get_window (widget); @@ -184,7 +184,7 @@ xw_forward_event_translate (GdkEvent *event, struct xwidget_view *xv, widget = find_widget_at_pos (xw->widgetwindow_osr, lrint (event->crossing.x - xv->clip_left), lrint (event->crossing.y - xv->clip_top), - &new_x, &new_y); + &new_x, &new_y, false, NULL); if (widget) { event->any.window = gtk_widget_get_window (widget);