commit e1c6b40e9d3b9bb44a310dcac4f7f05b4e5bde4f (HEAD, refs/remotes/origin/master) Author: Po Lu Date: Wed Apr 13 15:03:50 2022 +0800 Fix input availability detection during visible-bell * src/xterm.c (XTflash): Exit pselect loop also if input becomes available on f's display connection. diff --git a/src/xterm.c b/src/xterm.c index c1c9ebde5c..0c1c70340d 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -8652,6 +8652,8 @@ XTflash (struct frame *f) { GC gc; XGCValues values; + fd_set fds; + int fd; block_input (); @@ -8702,6 +8704,7 @@ XTflash (struct frame *f) struct timespec delay = make_timespec (0, 150 * 1000 * 1000); struct timespec wakeup = timespec_add (current_timespec (), delay); + fd = ConnectionNumber (FRAME_X_DISPLAY (f)); /* Keep waiting until past the time wakeup or any input gets available. */ @@ -8717,8 +8720,17 @@ XTflash (struct frame *f) /* How long `select' should wait. */ timeout = make_timespec (0, 10 * 1000 * 1000); + /* Wait for some input to become available on the X + connection. */ + FD_ZERO (&fds); + FD_SET (fd, &fds); + /* Try to wait that long--but we might wake up sooner. */ - pselect (0, NULL, NULL, NULL, &timeout, NULL); + pselect (fd + 1, &fds, NULL, NULL, &timeout, NULL); + + /* Some input is available, exit the visible bell. */ + if (FD_ISSET (fd, &fds)) + break; } /* If window is tall, flash top and bottom line. */ commit eb85abf5b2d0ce02f934f2d334ecd60c57da907c Author: Po Lu Date: Wed Apr 13 06:46:45 2022 +0000 Minor cleanups to Haiku windowing * src/haikufns.c (haiku_create_frame, haiku_create_tip_frame): * src/haikuterm.h (struct haiku_output, struct scroll_bar) (XSCROLL_BAR): Remove used fields of various structs. * src/haikuterm.c (haiku_flash): Make input detection actually work. diff --git a/src/haikufns.c b/src/haikufns.c index 0662410289..b282cf292a 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -800,8 +800,6 @@ haiku_create_frame (Lisp_Object parms) initialize_frame_menubar (f); unblock_input (); - FRAME_OUTPUT_DATA (f)->window_desc = FRAME_OUTPUT_DATA (f)->window; - Vframe_list = Fcons (frame, Vframe_list); Lisp_Object parent_frame = gui_display_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL, @@ -1046,7 +1044,6 @@ haiku_create_tip_frame (Lisp_Object parms) if (!window) emacs_abort (); - FRAME_OUTPUT_DATA (f)->window_desc = window; BWindow_set_tooltip_decoration (window); unblock_input (); } diff --git a/src/haikuterm.c b/src/haikuterm.c index 667ed685c5..bc21276437 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -3723,10 +3723,13 @@ haiku_flash (struct frame *f) int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f); int width = flash_right - flash_left; void *view = FRAME_HAIKU_VIEW (f); - struct timespec delay, wakeup, current, timeout; + object_wait_info info; + bigtime_t wakeup; - delay = make_timespec (0, 150 * 1000 * 1000); - wakeup = timespec_add (current_timespec (), delay); + info.object = port_application_to_emacs; + info.type = B_OBJECT_TYPE_PORT; + info.events = B_EVENT_READ; + wakeup = system_time () + 150000; BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); @@ -3760,17 +3763,17 @@ haiku_flash (struct frame *f) available. */ while (!detect_input_pending ()) { - current = current_timespec (); - /* Break if result would not be positive. */ - if (timespec_cmp (wakeup, current) <= 0) + if (wakeup < system_time ()) break; - /* How long `select' should wait. */ - timeout = make_timespec (0, 10 * 1000 * 1000); - /* Try to wait that long--but we might wake up sooner. */ - pselect (0, NULL, NULL, NULL, &timeout, NULL); + wait_for_objects_etc (&info, 1, B_ABSOLUTE_TIMEOUT, wakeup); + + if (info.events & B_EVENT_READ) + break; + + info.events = B_EVENT_READ; } BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f), diff --git a/src/haikuterm.h b/src/haikuterm.h index 02bb1ddc6f..5f905ab400 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h @@ -36,8 +36,6 @@ along with GNU Emacs. If not, see . */ extern int popup_activated_p; -extern void be_app_quit (void); - struct haikufont_info { struct font font; @@ -128,6 +126,8 @@ struct haiku_display_info struct haiku_output { + struct haiku_display_info *display_info; + Emacs_Cursor text_cursor; Emacs_Cursor nontext_cursor; Emacs_Cursor modeline_cursor; @@ -144,20 +144,11 @@ struct haiku_output Emacs_Cursor bottom_edge_cursor; Emacs_Cursor bottom_left_corner_cursor; Emacs_Cursor no_cursor; - Emacs_Cursor current_cursor; - struct haiku_display_info *display_info; - - int baseline_offset; - int fontset; - Emacs_Color cursor_color; - Window window_desc, parent_desc; - - int titlebar_height; - int toolbar_height; + Window parent_desc; haiku window; haiku view; @@ -165,21 +156,26 @@ struct haiku_output int menu_up_to_date_p; int zoomed_p; - + int hourglass_p; int menu_bar_open_p; + int fontset; + int baseline_offset; - struct font *font; - - int hourglass_p; - uint32_t cursor_fg; + /* Whether or not there is data in a back buffer that hasn't been + displayed yet. */ bool dirty_p; + struct font *font; + /* The pending position we're waiting for. */ int pending_top, pending_left; /* Whether or not adjust_frame_size and haiku_set_offset have yet been called by haiku_create_frame. */ bool configury_done; + + /* The default cursor foreground color. */ + uint32_t cursor_fg; }; struct x_output @@ -230,23 +226,25 @@ struct scroll_bar /* True if the scroll bar is horizontal. */ bool horizontal; + /* The amount of units taken up by the thumb, which represents the + portion of the buffer currently on screen. */ int page_size; }; #define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec)) -#define FRAME_DIRTY_P(f) (FRAME_OUTPUT_DATA (f)->dirty_p) -#define MAKE_FRAME_DIRTY(f) (FRAME_DIRTY_P (f) = 1) -#define FRAME_OUTPUT_DATA(f) ((f)->output_data.haiku) -#define FRAME_HAIKU_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window) -#define FRAME_HAIKU_VIEW(f) ((MAKE_FRAME_DIRTY (f)), FRAME_OUTPUT_DATA (f)->view) -#define FRAME_HAIKU_MENU_BAR(f) (FRAME_OUTPUT_DATA (f)->menubar) -#define FRAME_DISPLAY_INFO(f) (FRAME_OUTPUT_DATA (f)->display_info) -#define FRAME_FONT(f) (FRAME_OUTPUT_DATA (f)->font) -#define FRAME_FONTSET(f) (FRAME_OUTPUT_DATA (f)->fontset) -#define FRAME_NATIVE_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window) -#define FRAME_BASELINE_OFFSET(f) (FRAME_OUTPUT_DATA (f)->baseline_offset) -#define FRAME_CURSOR_COLOR(f) (FRAME_OUTPUT_DATA (f)->cursor_color) +#define FRAME_DIRTY_P(f) (FRAME_OUTPUT_DATA (f)->dirty_p) +#define MAKE_FRAME_DIRTY(f) (FRAME_DIRTY_P (f) = 1) +#define FRAME_OUTPUT_DATA(f) ((f)->output_data.haiku) +#define FRAME_HAIKU_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window) +#define FRAME_HAIKU_VIEW(f) ((MAKE_FRAME_DIRTY (f)), FRAME_OUTPUT_DATA (f)->view) +#define FRAME_HAIKU_MENU_BAR(f) (FRAME_OUTPUT_DATA (f)->menubar) +#define FRAME_DISPLAY_INFO(f) (FRAME_OUTPUT_DATA (f)->display_info) +#define FRAME_FONT(f) (FRAME_OUTPUT_DATA (f)->font) +#define FRAME_FONTSET(f) (FRAME_OUTPUT_DATA (f)->fontset) +#define FRAME_NATIVE_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window) +#define FRAME_BASELINE_OFFSET(f) (FRAME_OUTPUT_DATA (f)->baseline_offset) +#define FRAME_CURSOR_COLOR(f) (FRAME_OUTPUT_DATA (f)->cursor_color) #ifdef USE_BE_CAIRO #define FRAME_CR_CONTEXT(f) \ @@ -262,57 +260,57 @@ extern void syms_of_haikufont (void); extern void syms_of_haikuselect (void); extern void init_haiku_select (void); +extern void be_app_quit (void); + extern void haiku_iconify_frame (struct frame *); extern void haiku_visualize_frame (struct frame *); extern void haiku_unvisualize_frame (struct frame *); extern void haiku_set_offset (struct frame *, int, int, int); extern void haiku_set_frame_visible_invisible (struct frame *, bool); -extern void haiku_free_frame_resources (struct frame *f); -extern void haiku_scroll_bar_remove (struct scroll_bar *bar); -extern void haiku_clear_under_internal_border (struct frame *f); -extern void haiku_set_name (struct frame *f, Lisp_Object name, bool explicit_p); +extern void haiku_free_frame_resources (struct frame *); +extern void haiku_scroll_bar_remove (struct scroll_bar *); +extern void haiku_clear_under_internal_border (struct frame *); +extern void haiku_set_name (struct frame *, Lisp_Object, bool); extern Lisp_Object haiku_message_to_lisp (void *); extern struct haiku_display_info *haiku_term_init (void); extern void mark_haiku_display (void); -extern int haiku_get_color (const char *name, Emacs_Color *color); -extern void haiku_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval); -extern void haiku_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval); -extern void haiku_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval); -extern void haiku_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval); -extern void haiku_change_tab_bar_height (struct frame *f, int height); -extern void haiku_change_tool_bar_height (struct frame *f, int height); +extern int haiku_get_color (const char *, Emacs_Color *); +extern void haiku_set_background_color (struct frame *, Lisp_Object, Lisp_Object); +extern void haiku_set_cursor_color (struct frame *, Lisp_Object, Lisp_Object); +extern void haiku_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object); +extern void haiku_set_internal_border_width (struct frame *, Lisp_Object, Lisp_Object); +extern void haiku_change_tab_bar_height (struct frame *, int); +extern void haiku_change_tool_bar_height (struct frame *, int); -extern void haiku_query_color (uint32_t col, Emacs_Color *color); +extern void haiku_query_color (uint32_t, Emacs_Color *); -extern unsigned long haiku_get_pixel (haiku bitmap, int x, int y); -extern void haiku_put_pixel (haiku bitmap, int x, int y, unsigned long pixel); +extern unsigned long haiku_get_pixel (haiku, int, int); +extern void haiku_put_pixel (haiku, int, int, unsigned long); -extern Lisp_Object haiku_menu_show (struct frame *f, int x, int y, int menu_flags, - Lisp_Object title, const char **error_name); -extern Lisp_Object haiku_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents); +extern Lisp_Object haiku_menu_show (struct frame *, int, int, int, + Lisp_Object, const char **); +extern Lisp_Object haiku_popup_dialog (struct frame *, Lisp_Object, Lisp_Object); extern void haiku_note_drag_motion (void); -extern void initialize_frame_menubar (struct frame *f); +extern void initialize_frame_menubar (struct frame *); -extern void run_menu_bar_help_event (struct frame *f, int mb_idx); -extern void put_xrm_resource (Lisp_Object name, Lisp_Object val); +extern void run_menu_bar_help_event (struct frame *, int); +extern void put_xrm_resource (Lisp_Object, Lisp_Object); #ifdef HAVE_NATIVE_IMAGE_API -extern bool haiku_can_use_native_image_api (Lisp_Object type); -extern int haiku_load_image (struct frame *f, struct image *img, - Lisp_Object spec_file, Lisp_Object spec_data); +extern bool haiku_can_use_native_image_api (Lisp_Object); +extern int haiku_load_image (struct frame *, struct image *, + Lisp_Object, Lisp_Object); extern void syms_of_haikuimage (void); #endif #ifdef USE_BE_CAIRO -extern cairo_t * -haiku_begin_cr_clip (struct frame *f, struct glyph_string *s); +extern cairo_t *haiku_begin_cr_clip (struct frame *, struct glyph_string *); -extern void -haiku_end_cr_clip (cairo_t *cr); +extern void haiku_end_cr_clip (cairo_t *); #endif extern void haiku_merge_cursor_foreground (struct glyph_string *, unsigned long *, commit 8e3d120b9f06bc1cc5e84d9a8a3773700494234f Author: Po Lu Date: Wed Apr 13 04:44:11 2022 +0000 Fix zoom rect computation for some deskbar positions on Haiku * src/haiku_support.cc (CalculateZoomRect): Fix computation for left top and right bottom. diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 826e1c2100..599ff305ae 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -477,8 +477,7 @@ class EmacsWindow : public BWindow screen_frame = frame = screen.Frame (); deskbar_frame = deskbar.Frame (); - if (!(modifiers () & B_SHIFT_KEY) - && !deskbar.IsAutoHide ()) + if (!(modifiers () & B_SHIFT_KEY) && !deskbar.IsAutoHide ()) { switch (deskbar.Location ()) { @@ -489,13 +488,14 @@ class EmacsWindow : public BWindow case B_DESKBAR_BOTTOM: case B_DESKBAR_LEFT_BOTTOM: case B_DESKBAR_RIGHT_BOTTOM: - frame.bottom = deskbar_frame.bottom - 2; + frame.bottom = deskbar_frame.top - 2; break; case B_DESKBAR_LEFT_TOP: - if (deskbar.IsExpanded ()) + if (!deskbar.IsExpanded ()) frame.top = deskbar_frame.bottom + 2; - else + else if (!deskbar.IsAlwaysOnTop () + && !deskbar.IsAutoRaise ()) frame.left = deskbar_frame.right + 2; break; @@ -525,7 +525,7 @@ class EmacsWindow : public BWindow frame.left = screen_frame.left + (window_frame.left - decorator_frame.left); frame.right = screen_frame.right - (decorator_frame.right - - window_frame.left); + - window_frame.right); } return frame; commit 199606499606c3f2fc75161da2f286a12cb608c2 Author: Po Lu Date: Wed Apr 13 11:17:34 2022 +0800 Fix last change in configure.ac * configure.ac: Test window system against "x11", not "x". diff --git a/configure.ac b/configure.ac index 1e66acf52f..721cf16684 100644 --- a/configure.ac +++ b/configure.ac @@ -2797,7 +2797,7 @@ gtk3_pkg_errors= if test "${opsys}" != "mingw32"; then if test "${with_gtk3}" = "yes" || test "${with_gtk}" = "yes" || test "$USE_X_TOOLKIT" = "maybe"; then GLIB_REQUIRED=2.37.5 - if test "${window_system}" = "x"; then + if test "${window_system}" = "x11"; then GTK_REQUIRED=3.10 else GTK_REQUIRED=3.20 commit e91cbdfaee57052e0cbfecd08f77d95915ea532a Author: Po Lu Date: Wed Apr 13 11:13:28 2022 +0800 Bump minimum GTK for PGTK builds * configure.ac: Require GTK 3.20 or later if building with PGTK. It has already been required for some time now, but the requirement was not reflected in the configure script. * src/pgtkterm.c (pgtk_any_window_to_frame): Remove version check. diff --git a/configure.ac b/configure.ac index 185e4d0862..1e66acf52f 100644 --- a/configure.ac +++ b/configure.ac @@ -2797,7 +2797,11 @@ gtk3_pkg_errors= if test "${opsys}" != "mingw32"; then if test "${with_gtk3}" = "yes" || test "${with_gtk}" = "yes" || test "$USE_X_TOOLKIT" = "maybe"; then GLIB_REQUIRED=2.37.5 - GTK_REQUIRED=3.10 + if test "${window_system}" = "x"; then + GTK_REQUIRED=3.10 + else + GTK_REQUIRED=3.20 + fi GTK_MODULES="gtk+-3.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED" dnl Checks for libraries. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 566fc1f03d..0bb41cb446 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5008,7 +5008,6 @@ pgtk_any_window_to_frame (GdkWindow * window) static gboolean pgtk_handle_event (GtkWidget *widget, GdkEvent *event, gpointer *data) { -#if GTK_CHECK_VERSION (3, 18, 0) struct frame *f; union buffered_input_event inev; GtkWidget *frame_widget; @@ -5045,7 +5044,6 @@ pgtk_handle_event (GtkWidget *widget, GdkEvent *event, gpointer *data) return TRUE; } -#endif return FALSE; } commit 88a04ea985180d1fd619c4a6540fb117a1d59d9e Author: Lars Ingebrigtsen Date: Wed Apr 13 05:07:30 2022 +0200 Tweak how `M-q' in emacs-lisp-mode works * lisp/emacs-lisp/lisp-mode.el (lisp-fill-paragraph): Only fill as strings inside strings (bug#31656). (lisp--fill-line-simple): New function to do simple sexp-based filling. diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 7df40e36f8..e7c3a4b64f 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -1436,29 +1436,49 @@ and initial semicolons." (derived-mode-p 'emacs-lisp-mode)) emacs-lisp-docstring-fill-column fill-column))) - (save-restriction + (let ((ppss (syntax-ppss)) + (start (point))) (save-excursion - (let ((ppss (syntax-ppss)) - (start (point))) - ;; If we're in a string, then narrow (roughly) to that - ;; string before filling. This avoids filling Lisp - ;; statements that follow the string. - (when (ppss-string-terminator ppss) - (goto-char (ppss-comment-or-string-start ppss)) - (beginning-of-line) - ;; The string may be unterminated -- in that case, don't - ;; narrow. - (when (ignore-errors - (progn - (forward-sexp 1) - t)) - (narrow-to-region (ppss-comment-or-string-start ppss) - (point)))) - ;; Move back to where we were. + (save-restriction + ;; If we're not inside a string, then do very basic + ;; filling. This avoids corrupting embedded strings in + ;; code. + (if (not (ppss-comment-or-string-start ppss)) + (lisp--fill-line-simple) + ;; If we're in a string, then narrow (roughly) to that + ;; string before filling. This avoids filling Lisp + ;; statements that follow the string. + (when (ppss-string-terminator ppss) + (goto-char (ppss-comment-or-string-start ppss)) + ;; The string may be unterminated -- in that case, don't + ;; narrow. + (when (ignore-errors + (progn + (forward-sexp 1) + t)) + (narrow-to-region (ppss-comment-or-string-start ppss) + (point)))) + ;; Move back to where we were. + (goto-char start) + (fill-paragraph justify))))))) + ;; Never return nil. + t) + +(defun lisp--fill-line-simple () + (narrow-to-region (line-beginning-position) (line-end-position)) + (goto-char (point-min)) + (while (and (not (eobp)) + (re-search-forward "\\_>" nil t)) + (when (> (current-column) fill-column) + (let ((start (point))) + (backward-sexp) + (if (looking-back "[[(]" (point-min)) (goto-char start) - (fill-paragraph justify))))) - ;; Never return nil. - t)) + (skip-chars-backward " \t") + (insert "\n") + (forward-sexp)))) + (unless (eobp) + (forward-char 1)))) (defun indent-code-rigidly (start end arg &optional nochange-regexp) "Indent all lines of code, starting in the region, sideways by ARG columns. commit 1c1ae6ba802cc5813fa6f8f90f21050aae6bb459 Author: Po Lu Date: Wed Apr 13 10:54:56 2022 +0800 Clean up PGTK code more * src/pgtkterm.c (STORE_KEYSYM_FOR_DEBUG): Delete macro. (x_find_modifier_meanings): Delete function. (get_modifier_values, pgtk_gtk_to_emacs_modifiers) (pgtk_emacs_to_gtk_modifiers): Use GDK's own modifier mask constants instead of detecting our own from the keymap. This does mean a specific "meta" key will no longer be detected on X Windows, but that interface doesn't exist on Wayland, and X users should use the X port anyway. (key_press_event): Avoid decoding input text. (pgtk_term_init): Stop computing modifiers. (syms_of_pgtkterm): Delete obsolete comment. * src/pgtkterm.h (struct pgtk_display_info): Delete modifier masks. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 8b60064c42..566fc1f03d 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -68,11 +68,9 @@ along with GNU Emacs. If not, see . */ #include #endif -#define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0) - -#define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context) +#define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context) #define FRAME_CR_ACTIVE_CONTEXT(f) ((f)->output_data.pgtk->cr_active) -#define FRAME_CR_SURFACE(f) (cairo_get_target (FRAME_CR_CONTEXT (f))) +#define FRAME_CR_SURFACE(f) (cairo_get_target (FRAME_CR_CONTEXT (f))) /* Non-zero means that a HELP_EVENT has been generated since Emacs start. */ @@ -5161,88 +5159,8 @@ size_allocate (GtkWidget * widget, GtkAllocation * alloc, } static void -x_find_modifier_meanings (struct pgtk_display_info *dpyinfo) -{ - GdkDisplay *gdpy = dpyinfo->gdpy; - GdkKeymap *keymap = gdk_keymap_get_for_display (gdpy); - GdkModifierType state = GDK_META_MASK; - gboolean r = gdk_keymap_map_virtual_modifiers (keymap, &state); - if (r) - { - /* Meta key exists. */ - if (state == GDK_META_MASK) - { - dpyinfo->meta_mod_mask = GDK_MOD1_MASK; /* maybe this is meta. */ - dpyinfo->alt_mod_mask = 0; - } - else - { - dpyinfo->meta_mod_mask = state & ~GDK_META_MASK; - if (dpyinfo->meta_mod_mask == GDK_MOD1_MASK) - dpyinfo->alt_mod_mask = 0; - else - dpyinfo->alt_mod_mask = GDK_MOD1_MASK; - } - } - else - { - dpyinfo->meta_mod_mask = GDK_MOD1_MASK; - dpyinfo->alt_mod_mask = 0; - } - - state = GDK_SUPER_MASK; - r = gdk_keymap_map_virtual_modifiers (keymap, &state); - if (r) - { - /* Super key exists. */ - if (state == GDK_SUPER_MASK) - { - dpyinfo->super_mod_mask = GDK_MOD4_MASK; /* maybe this is super. */ - } - else - { - dpyinfo->super_mod_mask = state & ~GDK_SUPER_MASK; - } - } - else - { - dpyinfo->super_mod_mask = GDK_MOD4_MASK; - } - - state = GDK_HYPER_MASK; - r = gdk_keymap_map_virtual_modifiers (keymap, &state); - if (r) - { - /* Hyper key exists. */ - if (state == GDK_HYPER_MASK) - { - dpyinfo->hyper_mod_mask = GDK_MOD3_MASK; /* maybe this is hyper. */ - } - else - { - dpyinfo->hyper_mod_mask = state & ~GDK_HYPER_MASK; - } - } - else - { - dpyinfo->hyper_mod_mask = GDK_MOD3_MASK; - } - - /* If xmodmap says: - * $ xmodmap | grep mod4 - * mod4 Super_L (0x85), Super_R (0x86), Super_L (0xce), Hyper_L (0xcf) - * then, when mod4 is pressed, both of super and hyper are recognized ON. - * Maybe many people have such configuration, and they don't like such behavior, - * so I disable hyper if such configuration is detected. - */ - if (dpyinfo->hyper_mod_mask == dpyinfo->super_mod_mask) - dpyinfo->hyper_mod_mask = 0; -} - -static void -get_modifier_values (int *mod_ctrl, - int *mod_meta, - int *mod_alt, int *mod_hyper, int *mod_super) +get_modifier_values (int *mod_ctrl, int *mod_meta, int *mod_alt, + int *mod_hyper, int *mod_super) { Lisp_Object tem; @@ -5287,14 +5205,13 @@ pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, int state) mod |= shift_modifier; if (state & GDK_CONTROL_MASK) mod |= mod_ctrl; - if (state & dpyinfo->meta_mod_mask) + if (state & GDK_META_MASK || state & GDK_MOD1_MASK) mod |= mod_meta; - if (state & dpyinfo->alt_mod_mask) - mod |= mod_alt; - if (state & dpyinfo->super_mod_mask) + if (state & GDK_SUPER_MASK) mod |= mod_super; - if (state & dpyinfo->hyper_mod_mask) + if (state & GDK_HYPER_MASK) mod |= mod_hyper; + return mod; } @@ -5312,18 +5229,16 @@ pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state) &mod_super); mask = 0; - if (state & mod_alt) - mask |= dpyinfo->alt_mod_mask; if (state & mod_super) - mask |= dpyinfo->super_mod_mask; + mask |= GDK_SUPER_MASK; if (state & mod_hyper) - mask |= dpyinfo->hyper_mod_mask; + mask |= GDK_HYPER_MASK; if (state & shift_modifier) mask |= GDK_SHIFT_MASK; if (state & mod_ctrl) mask |= GDK_CONTROL_MASK; if (state & mod_meta) - mask |= dpyinfo->meta_mod_mask; + mask |= GDK_MOD1_MASK; return mask; } @@ -5382,16 +5297,13 @@ pgtk_enqueue_preedit (struct frame *f, Lisp_Object preedit) static gboolean key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data) { - struct coding_system coding; union buffered_input_event inev; ptrdiff_t nbytes = 0; Mouse_HLInfo *hlinfo; + struct frame *f; - USE_SAFE_ALLOCA; - + f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); EVENT_INIT (inev.ie); - - struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); hlinfo = MOUSE_HL_INFO (f); /* If mouse-highlight is an integer, input clears out @@ -5402,20 +5314,6 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data) hlinfo->mouse_face_hidden = true; } - if (f != 0) - { - /* While super is pressed, gtk_im_context_filter_keypress() always process the - * key events ignoring super. - * As a work around, don't call it while super or hyper are pressed... - */ - struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - if (!(event->key.state & (dpyinfo->super_mod_mask | dpyinfo->hyper_mod_mask))) - { - if (pgtk_im_filter_keypress (f, &event->key)) - return TRUE; - } - } - if (f != 0) { guint keysym, orig_keysym; @@ -5434,9 +5332,19 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data) unsigned char *copy_bufptr = copy_buffer; int copy_bufsiz = sizeof (copy_buffer); int modifiers; - Lisp_Object coding_system = Qlatin_1; Lisp_Object c; - guint state = event->key.state; + guint state; + + state = event->key.state; + + /* While super is pressed, the input method will always always + resend the key events ignoring super. As a workaround, don't + filter key events with super or hyper pressed. */ + if (!(event->key.state & (GDK_SUPER_MASK | GDK_HYPER_MASK))) + { + if (pgtk_im_filter_keypress (f, &event->key)) + return TRUE; + } state |= pgtk_emacs_to_gtk_modifiers (FRAME_DISPLAY_INFO (f), @@ -5582,7 +5490,6 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data) #endif )) { - STORE_KEYSYM_FOR_DEBUG (keysym); /* make_lispy_event will convert this to a symbolic key. */ inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT; @@ -5593,62 +5500,11 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data) goto done; } - { /* Raw bytes, not keysym. */ - ptrdiff_t i; - int nchars, len; - - for (i = 0, nchars = 0; i < nbytes; i++) - { - if (ASCII_CHAR_P (copy_bufptr[i])) - nchars++; - STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); - } - - if (nchars < nbytes) - { - /* Decode the input data. */ - - /* The input should be decoded with locale `coding_system'. */ - if (!NILP (Vlocale_coding_system)) - coding_system = Vlocale_coding_system; - setup_coding_system (coding_system, &coding); - coding.src_multibyte = false; - coding.dst_multibyte = true; - /* The input is converted to events, thus we can't - handle composition. Anyway, there's no XIM that - gives us composition information. */ - coding.common_flags &= ~CODING_ANNOTATION_MASK; - - SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH, nbytes); - coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes; - coding.mode |= CODING_MODE_LAST_BLOCK; - decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil); - nbytes = coding.produced; - nchars = coding.produced_char; - copy_bufptr = coding.destination; - } - - /* Convert the input data to a sequence of - character events. */ - for (i = 0; i < nbytes; i += len) - { - int ch; - if (nchars == nbytes) - ch = copy_bufptr[i], len = 1; - else - ch = string_char_and_length (copy_bufptr + i, &len); - inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch) - ? ASCII_KEYSTROKE_EVENT - : MULTIBYTE_CHAR_KEYSTROKE_EVENT); - inev.ie.code = ch; - inev.ie.device - = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event); - evq_enqueue (&inev); - } - - /* count += nchars; */ - - inev.ie.kind = NO_EVENT; /* Already stored above. */ + { + inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes); + inev.ie.device + = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event); if (keysym == GDK_KEY_VoidSymbol) goto done; @@ -5660,11 +5516,8 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data) { XSETFRAME (inev.ie.frame_or_window, f); evq_enqueue (&inev); - /* count++; */ } - SAFE_FREE (); - return TRUE; } @@ -6793,9 +6646,6 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) *nametail++ = '@'; lispstpcpy (nametail, system_name); - /* Figure out which modifier bits mean what. */ - x_find_modifier_meanings (dpyinfo); - /* Get the scroll bar cursor. */ /* We must create a GTK cursor, it is required for GTK widgets. */ dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->gdpy); @@ -7044,7 +6894,6 @@ pgtk_clear_area (struct frame *f, int x, int y, int width, int height) void syms_of_pgtkterm (void) { - /* from 23+ we need to tell emacs what modifiers there are.. */ DEFSYM (Qmodifier_value, "modifier-value"); DEFSYM (Qalt, "alt"); DEFSYM (Qhyper, "hyper"); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 56c5d22e54..321c923db5 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -225,9 +225,6 @@ struct pgtk_display_info /* The frame where the mouse was last time we reported a mouse position. */ struct frame *last_mouse_glyph_frame; - /* Modifier masks in gdk */ - int meta_mod_mask, alt_mod_mask, super_mod_mask, hyper_mod_mask; - /* The last click event. */ GdkEvent *last_click_event; commit db56a69274f7690eea2c8d8a12a9c367bb93c4d1 Author: Po Lu Date: Wed Apr 13 02:37:54 2022 +0000 Remove unused flag on Haiku * src/haikufns.c (haiku_create_frame, haiku_create_tip_frame): * src/haikuterm.h (struct haiku_output): Delete mentions of `explicit_parent'. diff --git a/src/haikufns.c b/src/haikufns.c index ef95d42f0f..0662410289 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -648,9 +648,6 @@ haiku_create_frame (Lisp_Object parms) /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */ record_unwind_protect (unwind_create_frame, frame); - FRAME_OUTPUT_DATA (f)->parent_desc = NULL; - FRAME_OUTPUT_DATA (f)->explicit_parent = 0; - /* Set the name; the functions to which we pass f expect the name to be set. */ if (EQ (name, Qunbound) || NILP (name) || ! STRINGP (name)) @@ -860,22 +857,19 @@ haiku_create_frame (Lisp_Object parms) adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, true, Qx_create_frame_2); - if (!FRAME_OUTPUT_DATA (f)->explicit_parent) + Lisp_Object visibility; + + visibility = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0, + RES_TYPE_SYMBOL); + if (EQ (visibility, Qunbound)) + visibility = Qt; + if (EQ (visibility, Qicon)) + haiku_iconify_frame (f); + else if (!NILP (visibility)) + haiku_visualize_frame (f); + else /* Qnil */ { - Lisp_Object visibility; - - visibility = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0, - RES_TYPE_SYMBOL); - if (EQ (visibility, Qunbound)) - visibility = Qt; - if (EQ (visibility, Qicon)) - haiku_iconify_frame (f); - else if (!NILP (visibility)) - haiku_visualize_frame (f); - else /* Qnil */ - { - f->was_invisible = true; - } + f->was_invisible = true; } if (FRAME_HAS_MINIBUF_P (f) @@ -961,7 +955,6 @@ haiku_create_tip_frame (Lisp_Object parms) FRAME_DISPLAY_INFO (f) = dpyinfo; FRAME_OUTPUT_DATA (f)->parent_desc = NULL; - FRAME_OUTPUT_DATA (f)->explicit_parent = 0; /* Set the name; the functions to which we pass f expect the name to be set. */ diff --git a/src/haikuterm.h b/src/haikuterm.h index 586df28575..02bb1ddc6f 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h @@ -155,7 +155,6 @@ struct haiku_output Emacs_Color cursor_color; Window window_desc, parent_desc; - char explicit_parent; int titlebar_height; int toolbar_height; commit 4cf885a41a9e15a9668862747117e57f31b6146b Author: Po Lu Date: Wed Apr 13 10:07:00 2022 +0800 Fix bit rot in the XEmbed code * src/xterm.c (x_term_init): Delete unused atom. (handle_one_xevent): (x_make_frame_visible): Handle embedded frame visibility correctly. * src/xterm.h (struct x_display_info): Delete unused atom. diff --git a/src/xterm.c b/src/xterm.c index 2999480659..c1c9ebde5c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -14060,7 +14060,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, } f = x_top_window_to_frame (dpyinfo, event->xproperty.window); - if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state) + if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state + /* This should never happen with embedded windows. */ + && !FRAME_X_EMBEDDED_P (f)) { bool not_hidden = x_handle_net_wm_state (f, &event->xproperty); @@ -14417,7 +14419,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_set_z_group (f, Qbelow, Qnil); } - if (not_hidden) + /* Embedded frames might have NET_WM_STATE left over, but + are always visible once mapped. */ + if (not_hidden || FRAME_X_EMBEDDED_P (f)) { SET_FRAME_VISIBLE (f, 1); SET_FRAME_ICONIFIED (f, false); @@ -14436,7 +14440,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_update_opaque_region (f, NULL); - if (not_hidden && iconified) + if ((not_hidden || FRAME_X_EMBEDDED_P (f)) && iconified) { inev.ie.kind = DEICONIFY_EVENT; XSETFRAME (inev.ie.frame_or_window, f); @@ -15543,6 +15547,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, /* Even if the number of character rows and columns has not changed, the font size may have changed, so we need to check the pixel dimensions as well. */ + if (width != FRAME_PIXEL_WIDTH (f) || height != FRAME_PIXEL_HEIGHT (f) || (f->new_size_p @@ -21217,6 +21222,12 @@ x_make_frame_visible (struct frame *f) XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); #endif /* not USE_GTK */ #endif /* not USE_X_TOOLKIT */ + + if (FRAME_X_EMBEDDED_P (f)) + { + SET_FRAME_VISIBLE (f, true); + SET_FRAME_ICONIFIED (f, false); + } } XFlush (FRAME_X_DISPLAY (f)); @@ -22949,7 +22960,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) ATOM_REFS_INIT ("ATOM", Xatom_ATOM) ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR) ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER) - ATOM_REFS_INIT ("XATOM_COUNTER", Xatom_XEMBED_INFO) ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO) ATOM_REFS_INIT ("_MOTIF_WM_HINTS", Xatom_MOTIF_WM_HINTS) /* For properties of font. */ diff --git a/src/xterm.h b/src/xterm.h index 69313166db..7509408268 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -414,7 +414,7 @@ struct x_display_info Atom Xatom_CLIPBOARD, Xatom_TIMESTAMP, Xatom_TEXT, Xatom_DELETE, Xatom_COMPOUND_TEXT, Xatom_UTF8_STRING, Xatom_MULTIPLE, Xatom_INCR, Xatom_EMACS_TMP, Xatom_TARGETS, Xatom_NULL, - Xatom_ATOM, Xatom_ATOM_PAIR, Xatom_CLIPBOARD_MANAGER, Xatom_COUNTER, + Xatom_ATOM, Xatom_ATOM_PAIR, Xatom_CLIPBOARD_MANAGER, Xatom_EMACS_SERVER_TIME_PROP; /* More atoms for font properties. The last three are private commit fe98a67f34dc5d4884b6c52e0bdfd3cd59debb41 Author: Lars Ingebrigtsen Date: Wed Apr 13 03:52:15 2022 +0200 Add NEWS entry for `C-h m' change diff --git a/etc/NEWS b/etc/NEWS index c738126aaf..41e7f376ff 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -408,6 +408,11 @@ These will take you (respectively) to the next and previous "page". This will take you to the Emacs Lisp manual entry for the item displayed, if any. +--- +*** The 'C-h m' ('describe-mode') *Help* buffer has been reformatted. +It now only includes local minor modes at the start, and the global +minor modes are listed after the major mode. + ** Outline Mode +++ commit 3c059f269e0182bd19df37871585e0b0bf1d47e5 Author: Lars Ingebrigtsen Date: Wed Apr 13 03:50:06 2022 +0200 Redo `C-h m' output * lisp/help-fns.el (describe-mode--minor-modes): New function (bug#2473). (describe-mode): Rewritten to include local minor mode links first, then the major mode, and then global minor mode links, and then all the minor modes. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 38b11f1c99..5a38153aca 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -1878,111 +1878,96 @@ whose documentation describes the minor mode. If called from Lisp with a non-nil BUFFER argument, display documentation for the major and minor modes of that buffer." (interactive "@") - (let ((help-buffer-under-preparation t)) - (unless buffer (setq buffer (current-buffer))) + (unless buffer + (setq buffer (current-buffer))) + (let ((help-buffer-under-preparation t) + (local-minors (buffer-local-value 'local-minor-modes buffer))) (help-setup-xref (list #'describe-mode buffer) (called-interactively-p 'interactive)) ;; For the sake of help-do-xref and help-xref-go-back, ;; don't switch buffers before calling `help-buffer'. (with-help-window (help-buffer) - (with-current-buffer buffer - (let (minors) - ;; Older packages do not register in minor-mode-list but only in - ;; minor-mode-alist. - (dolist (x minor-mode-alist) - (setq x (car x)) - (unless (memq x minor-mode-list) - (push x minor-mode-list))) - ;; Find enabled minor mode we will want to mention. - (dolist (mode minor-mode-list) - ;; Document a minor mode if it is listed in minor-mode-alist, - ;; non-nil, and has a function definition. - (let ((fmode (or (get mode :minor-mode-function) mode))) - (and (boundp mode) (symbol-value mode) - (fboundp fmode) - (let ((pretty-minor-mode - (if (string-match "\\(\\(-minor\\)?-mode\\)?\\'" - (symbol-name fmode)) - (capitalize - (substring (symbol-name fmode) - 0 (match-beginning 0))) - fmode))) - (push (list fmode pretty-minor-mode - (format-mode-line (assq mode minor-mode-alist))) - minors))))) - ;; Narrowing is not a minor mode, but its indicator is part of - ;; mode-line-modes. - (when (buffer-narrowed-p) - (push '(narrow-to-region "Narrow" " Narrow") minors)) - (setq minors - (sort minors - (lambda (a b) (string-lessp (cadr a) (cadr b))))) - (when minors - (princ "Enabled minor modes:\n") - (make-local-variable 'help-button-cache) - (with-current-buffer standard-output - (dolist (mode minors) - (let ((mode-function (nth 0 mode)) - (pretty-minor-mode (nth 1 mode)) - (indicator (nth 2 mode))) - (save-excursion - (goto-char (point-max)) - (princ "\n\f\n") - (push (point-marker) help-button-cache) - ;; Document the minor modes fully. - (insert-text-button - pretty-minor-mode 'type 'help-function - 'help-args (list mode-function) - 'button '(t)) - (princ (format " minor mode (%s):\n" - (if (zerop (length indicator)) - "no indicator" - (format "indicator%s" - indicator)))) - (princ (help-split-fundoc (documentation mode-function) - nil 'doc))) - (insert-button pretty-minor-mode - 'action (car help-button-cache) - 'follow-link t - 'help-echo "mouse-2, RET: show full information") - (newline))) - (forward-line -1) - (fill-paragraph nil) - (forward-line 1)) - - (princ "\n(Information about these minor modes follows the major mode info.)\n\n")) - ;; Document the major mode. - (with-current-buffer standard-output - (insert (buttonize - (propertize (format-mode-line - (buffer-local-value 'mode-name buffer) - nil nil buffer) - 'face 'bold) - (lambda (_) - (describe-function - (buffer-local-value 'major-mode buffer)))))) - (princ " mode") - (let* ((mode major-mode) - (file-name (find-lisp-object-file-name mode nil))) - (if (not file-name) - (setq help-mode--current-data (list :symbol mode)) - (princ (format-message " defined in `%s'" - (help-fns-short-filename file-name))) - ;; Make a hyperlink to the library. - (with-current-buffer standard-output - (save-excursion - (re-search-backward (substitute-command-keys "`\\([^`']+\\)'") - nil t) - (setq help-mode--current-data (list :symbol mode - :file file-name)) - (help-xref-button 1 'help-function-def mode file-name))))) - (let ((fundoc (help-split-fundoc (documentation major-mode) nil 'doc))) - (with-current-buffer standard-output - (insert ":\n") - (insert fundoc) - (insert (help-fns--list-local-commands)))))))) - ;; For the sake of IELM and maybe others - nil) + (with-current-buffer (help-buffer) + ;; Add the local minor modes at the start. + (when local-minors + (insert (format "Minor mode%s enabled in this buffer:" + (if (length> local-minors 1) + "s" ""))) + (describe-mode--minor-modes local-minors)) + + ;; Document the major mode. + (let ((major (buffer-local-value 'major-mode buffer))) + (insert "The major mode is " + (buttonize + (propertize (format-mode-line + (buffer-local-value 'mode-name buffer) + nil nil buffer) + 'face 'bold) + (lambda (_) + (describe-function major)))) + (insert " mode") + (when-let ((file-name (find-lisp-object-file-name major nil))) + (insert (format " defined in %s:\n\n" + (buttonize + (help-fns-short-filename file-name) + (lambda (_) + (help-function-def--button-function + major file-name)))))) + (insert (help-split-fundoc (documentation major-mode) nil 'doc) + (with-current-buffer buffer + (help-fns--list-local-commands))) + (ensure-empty-lines 1) + + ;; Insert the global minor modes after the major mode. + (when global-minor-modes + (insert (format "Global minor mode%s enabled:" + (if (length> global-minor-modes 1) + "s" ""))) + (describe-mode--minor-modes global-minor-modes) + (when (re-search-forward "^\f") + (beginning-of-line) + (ensure-empty-lines 1))) + ;; For the sake of IELM and maybe others + nil))))) + +(defun describe-mode--minor-modes (modes) + (dolist (mode (seq-sort #'string< modes)) + (let ((pretty-minor-mode + (capitalize + (replace-regexp-in-string + "\\(\\(-minor\\)?-mode\\)?\\'" "" + (symbol-name mode))))) + (insert + " " + (buttonize + pretty-minor-mode + (lambda (mode) + (goto-char (point-min)) + (text-property-search-forward + 'help-minor-mode mode t) + (beginning-of-line)) + mode)) + (save-excursion + (goto-char (point-max)) + (insert "\n\n\f\n") + ;; Document the minor modes fully. + (insert (buttonize + (propertize pretty-minor-mode 'help-minor-mode mode) + (lambda (mode) + (describe-function mode)) + mode)) + (let ((indicator + (format-mode-line (assq mode minor-mode-alist)))) + (insert (format " minor mode (%s):\n" + (if (zerop (length indicator)) + "no indicator" + (format "indicator%s" + indicator))))) + (insert (help-split-fundoc (documentation mode) nil 'doc))))) + (forward-line -1) + (fill-paragraph nil) + (forward-line 1) + (ensure-empty-lines 1)) (defun help-fns--list-local-commands () (let ((functions nil)) commit 6b16092a8d6f12fa8c5e69dd6948f8f524212bb3 Author: Lars Ingebrigtsen Date: Wed Apr 13 02:51:03 2022 +0200 Make `describe-mode' include a link to the major mode function * lisp/help-fns.el (describe-mode): Add a link to the mode function so that the user can go to the manual more easily (bug#575). diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 80d7d5cb02..38b11f1c99 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -1952,12 +1952,16 @@ documentation for the major and minor modes of that buffer." (princ "\n(Information about these minor modes follows the major mode info.)\n\n")) ;; Document the major mode. - (let ((mode mode-name)) - (with-current-buffer standard-output - (let ((start (point))) - (insert (format-mode-line mode nil nil buffer)) - (add-text-properties start (point) '(face bold))))) - (princ " mode") + (with-current-buffer standard-output + (insert (buttonize + (propertize (format-mode-line + (buffer-local-value 'mode-name buffer) + nil nil buffer) + 'face 'bold) + (lambda (_) + (describe-function + (buffer-local-value 'major-mode buffer)))))) + (princ " mode") (let* ((mode major-mode) (file-name (find-lisp-object-file-name mode nil))) (if (not file-name) commit 2e0a2ecc294aa2273ffbef27f49706db2cf40062 Author: Po Lu Date: Wed Apr 13 00:47:00 2022 +0000 Fix freezes when trying to accelerate menu bar on Haiku * src/haiku_support.cc (class EmacsWindow): New field `menus_begun'. (MenusBeginning): Don't send menu bar open events when that is set, instead set it to true. (BMenuBar_start_tracking): Stop locking the menu bar here and send a special BE_MENU_BAR_OPEN event instead. * src/haiku_support.h (struct haiku_menu_bar_state_event): Delete field `no_lock'. * src/haikumenu.c (Fhaiku_menu_bar_open): * src/haikuterm.c (haiku_read_socket): Update accordingly. diff --git a/src/haiku_support.cc b/src/haiku_support.cc index cb38a572f7..826e1c2100 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -87,6 +87,8 @@ enum WAIT_FOR_RELEASE = 3001, RELEASE_NOW = 3002, CANCEL_DROP = 3003, + SHOW_MENU_BAR = 3004, + BE_MENU_BAR_OPEN = 3005, }; static color_space dpy_color_space = B_NO_COLOR_SPACE; @@ -423,6 +425,7 @@ class EmacsWindow : public BWindow pthread_cond_t menu_update_cv = PTHREAD_COND_INITIALIZER; bool menu_updated_p = false; int window_id; + bool *menus_begun = NULL; EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS) @@ -902,19 +905,14 @@ class EmacsWindow : public BWindow MenusBeginning () { struct haiku_menu_bar_state_event rq; - int lock_count = 0; - thread_id current_thread = find_thread (NULL); - thread_id window_thread = Thread (); - rq.window = this; - rq.no_lock = false; - - if (window_thread != current_thread) - rq.no_lock = true; + int lock_count; - haiku_write (MENU_BAR_OPEN, &rq); + rq.window = this; + lock_count = 0; - if (!rq.no_lock) + if (!menus_begun) { + haiku_write (MENU_BAR_OPEN, &rq); while (IsLocked ()) { ++lock_count; @@ -932,6 +930,9 @@ class EmacsWindow : public BWindow gui_abort ("Failed to lock after cv signal denoting menu update"); } } + else + *menus_begun = true; + menu_bar_active_p = true; } @@ -1244,6 +1245,37 @@ class EmacsMenuBar : public BMenuBar BMenuBar::MouseMoved (point, transit, msg); } + + void + MessageReceived (BMessage *msg) + { + BRect frame; + BPoint pt, l; + EmacsWindow *window; + bool menus_begun; + + if (msg->what == SHOW_MENU_BAR) + { + window = (EmacsWindow *) Window (); + frame = Frame (); + pt = frame.LeftTop (); + l = pt; + menus_begun = false; + Parent ()->ConvertToScreen (&pt); + + window->menus_begun = &menus_begun; + set_mouse_position (pt.x, pt.y); + MouseDown (l); + window->menus_begun = NULL; + + if (!menus_begun) + msg->SendReply (msg); + else + msg->SendReply (BE_MENU_BAR_OPEN); + } + else + BMenuBar::MessageReceived (msg); + } }; class EmacsView : public BView @@ -3748,20 +3780,18 @@ EmacsWindow_unzoom (void *window) w->UnZoom (); } -/* Move the pointer into MBAR and start tracking. */ -void +/* Move the pointer into MBAR and start tracking. Return whether the + menu bar was opened correctly. */ +bool BMenuBar_start_tracking (void *mbar) { EmacsMenuBar *mb = (EmacsMenuBar *) mbar; - if (!mb->LockLooper ()) - gui_abort ("Couldn't lock menubar"); - BRect frame = mb->Frame (); - BPoint pt = frame.LeftTop (); - BPoint l = pt; - mb->Parent ()->ConvertToScreen (&pt); - set_mouse_position (pt.x, pt.y); - mb->MouseDown (l); - mb->UnlockLooper (); + BMessenger messenger (mb); + BMessage reply; + + messenger.SendMessage (SHOW_MENU_BAR, &reply); + + return reply.what == BE_MENU_BAR_OPEN; } #ifdef HAVE_NATIVE_IMAGE_API diff --git a/src/haiku_support.h b/src/haiku_support.h index d0a78c693b..1de135c55b 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -328,7 +328,6 @@ struct haiku_menu_bar_resize_event struct haiku_menu_bar_state_event { void *window; - bool no_lock; }; #define HAIKU_THIN 0 @@ -869,7 +868,7 @@ extern "C" be_translate_bitmap_from_memory (const void *buf, size_t bytes); #endif - extern void + extern bool BMenuBar_start_tracking (void *mbar); extern size_t diff --git a/src/haikumenu.c b/src/haikumenu.c index 4cee69826d..22e9c4ecad 100644 --- a/src/haikumenu.c +++ b/src/haikumenu.c @@ -752,19 +752,24 @@ the position of the last non-menu event instead. */) (Lisp_Object frame) { struct frame *f = decode_window_system_frame (frame); + int rc; if (FRAME_EXTERNAL_MENU_BAR (f)) { block_input (); set_frame_menubar (f, 1); - BMenuBar_start_tracking (FRAME_HAIKU_MENU_BAR (f)); + rc = BMenuBar_start_tracking (FRAME_HAIKU_MENU_BAR (f)); unblock_input (); + + if (!rc) + return Qnil; + + FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1; + popup_activated_p += 1; } else - { - return call2 (Qpopup_menu, call0 (Qmouse_menu_bar_map), - last_nonmenu_event); - } + return call2 (Qpopup_menu, call0 (Qmouse_menu_bar_map), + last_nonmenu_event); return Qnil; } diff --git a/src/haikuterm.c b/src/haikuterm.c index f07e9e0b29..667ed685c5 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -3517,36 +3517,24 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) { struct haiku_menu_bar_state_event *b = buf; struct frame *f = haiku_window_to_frame (b->window); + int was_waiting_for_input_p; if (!f || !FRAME_EXTERNAL_MENU_BAR (f)) continue; if (type == MENU_BAR_OPEN) { - /* b->no_lock means that MenusBeginning was called - from the main thread, which means tracking was - started manually, and we have already updated the - menu bar. */ - if (!b->no_lock) - { - BView_draw_lock (FRAME_HAIKU_VIEW (f), false, 0, 0, 0, 0); - /* This shouldn't be here, but nsmenu does it, so - it should probably be safe. */ - int was_waiting_for_input_p = waiting_for_input; - if (waiting_for_input) - waiting_for_input = 0; - set_frame_menubar (f, 1); - waiting_for_input = was_waiting_for_input_p; - BView_draw_unlock (FRAME_HAIKU_VIEW (f)); - } + was_waiting_for_input_p = waiting_for_input; + if (waiting_for_input) + waiting_for_input = 0; + + set_frame_menubar (f, 1); + waiting_for_input = was_waiting_for_input_p; - /* But set the flag anyway, because the menu will end - from the window thread. */ FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1; popup_activated_p += 1; - if (!b->no_lock) - EmacsWindow_signal_menu_update_complete (b->window); + EmacsWindow_signal_menu_update_complete (b->window); } else { commit 33cc12498b0f9191437d1f273d0467d0f69d48f3 Author: Lars Ingebrigtsen Date: Wed Apr 13 02:29:27 2022 +0200 Provide a useful default to smime-CA-file * lisp/gnus/smime.el (smime-CA-file): Use `gnutls-trustfiles' to provide a default so that this will work automatically on many systems (bug#20960). diff --git a/lisp/gnus/smime.el b/lisp/gnus/smime.el index ac1e081041..87b5551d31 100644 --- a/lisp/gnus/smime.el +++ b/lisp/gnus/smime.el @@ -119,7 +119,7 @@ ;;; Code: (require 'dig) - +(require 'gnutls) (require 'password-cache) (eval-when-compile (require 'cl-lib)) @@ -149,10 +149,11 @@ certificate." :type '(choice (const :tag "none" nil) directory)) -(defcustom smime-CA-file nil - "Files containing certificates for CAs you trust. -File should contain certificates in PEM format." - :version "22.1" +(defcustom smime-CA-file (car (gnutls-trustfiles)) + "File containing certificates for CAs you trust. +The file should contain certificates in PEM format. By default, +this is initialized from the `gnutls-trusfiles' variable." + :version "29.1" :type '(choice (const :tag "none" nil) file)) commit 95c9079da0208e0b1506ed19bb6db811d4ea4d84 Author: Lars Ingebrigtsen Date: Wed Apr 13 01:38:10 2022 +0200 Make the SVG error message less verbose * src/image.c (svg_load_image): Don't include the spec in the error message, because this is commonly the entire SVG string, and this will fill up the *Messages* buffer quickly. diff --git a/src/image.c b/src/image.c index 45de7ae83d..e4b56e29cf 100644 --- a/src/image.c +++ b/src/image.c @@ -11316,7 +11316,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents, #endif /* FIXME: Use error->message so the user knows what is the actual problem with the image. */ - image_error ("Error parsing SVG image `%s'", img->spec); + image_error ("Error parsing SVG image"); g_clear_error (&err); return 0; } commit 1cdb8d4c99bf82579dd180187a11f2bcbeccd4c4 Author: Lars Ingebrigtsen Date: Tue Apr 12 21:29:10 2022 +0200 Mention animated WebP images diff --git a/etc/NEWS b/etc/NEWS index 79c27da549..c738126aaf 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -434,8 +434,9 @@ This is a list of pairs of open/close strings used to display buttons. +++ ** Support for the WebP image format. This support is built by default when the libwebp library is -available. To disable it, use the '--without-webp' configure flag. -Image specifiers can now use ':type webp'. +available. (This also includes support for animated WebP images.) To +disable WebP support, use the '--without-webp' configure flag. Image +specifiers can now use ':type webp'. ** Windows commit 451eeb512dbfb5ccd4e75eca696a5d4143fec646 Author: Sean Whitton Date: Tue Apr 12 17:59:22 2022 +0200 Fix eager macroexpansion cycle in cl-once-only * lisp/emacs-lisp/cl-macs.el (cl-once-only): Use different cl-loop syntax, with no functional change, but such that the loop does not expand into cl-psetq. diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index af8855516c..364b5120a0 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -2473,11 +2473,11 @@ See also `macroexp-let2'." ;; We require this explicit call to `list' rather than using ;; (,,@(cl-loop ...)) due to a limitation of Elisp's backquote. `(let ,(list - ,@(cl-loop for name in names and gensym in our-gensyms + ,@(cl-loop for name in names for gensym in our-gensyms for to-eval = (or (cadr name) (car name)) collect ``(,,gensym ,,to-eval))) ;; During macroexpansion, bind each NAME to its gensym. - ,(let ,(cl-loop for name in names and gensym in our-gensyms + ,(let ,(cl-loop for name in names for gensym in our-gensyms collect `(,(car name) ,gensym)) ,@body))))) commit a987e66e6ba014795ba4540c5fedeb9894bdd94e Author: Lars Ingebrigtsen Date: Tue Apr 12 16:22:27 2022 +0200 Improve DISPOSE_PREVIOUS in gif_load slightly * src/image.c (gif_load): Tweak how DISPOSE_PREVIOUS is handled. It's still not right, but it's less glaringly wrong. diff --git a/src/image.c b/src/image.c index 530819eab9..45de7ae83d 100644 --- a/src/image.c +++ b/src/image.c @@ -9115,6 +9115,14 @@ gif_load (struct frame *f, struct image *img) if (disposal == DISPOSAL_UNSPECIFIED) disposal = DISPOSE_DO_NOT; + /* This is not quite correct -- the specification is unclear, + but I think we're supposed to restore to the frame before the + previous frame? And we don't have that data at this point. + But DISPOSE_DO_NOT is less wrong than substituting the + background, so do that for now. */ + if (disposal == DISPOSE_PREVIOUS) + disposal = DISPOSE_DO_NOT; + gif_color_map = subimage->ImageDesc.ColorMap; if (!gif_color_map) gif_color_map = gif->SColorMap; commit 66189689ca2f22de47e1a83af1deb9b0bff29ab7 Author: Eli Zaretskii Date: Tue Apr 12 17:19:06 2022 +0300 Fix 'window-text-pixel-size' when starting from a display property * src/xdisp.c (Fwindow_text_pixel_size): Handle the case where there's a display property at START and 'move_it_to' overshoots. (Bug#54862) diff --git a/src/xdisp.c b/src/xdisp.c index bdefd2b042..6a0d0ea879 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -10957,6 +10957,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, same directionality. */ it.bidi_p = false; + int start_x; if (vertical_offset != 0) { int last_y; @@ -10990,6 +10991,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, + WINDOW_HEADER_LINE_HEIGHT (w)); start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV); start_y = it.current_y; + start_x = it.current_x; } else { @@ -10999,11 +11001,52 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, reseat_at_previous_visible_line_start (&it); it.current_x = it.hpos = 0; if (IT_CHARPOS (it) != start) - move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS); + { + void *it1data = NULL; + struct it it1; + + SAVE_IT (it1, it, it1data); + move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS); + /* We could have a display property at START, in which case + asking move_it_to to stop at START will overshoot and + stop at position after START. So we try again, stopping + before START, and account for the width of the last + buffer position manually. */ + if (IT_CHARPOS (it) > start && start > BEGV) + { + ptrdiff_t it1pos = IT_CHARPOS (it1); + int it1_x = it1.current_x; + + RESTORE_IT (&it, &it1, it1data); + /* If START - 1 is the beginning of screen line, + move_it_to will not move, so we need to use a + lower-level move_it_in_display_line subroutine, and + tell it to move just 1 pixel, so it stops at the next + display element. */ + if (start - 1 > it1pos) + move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS); + else + move_it_in_display_line (&it, start, it1_x + 1, + MOVE_TO_POS | MOVE_TO_X); + move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS); + start_x = it.current_x; + /* If we didn't change our buffer position, the pixel + width of what's here was not yet accounted for; do it + manually. */ + if (IT_CHARPOS (it) == start - 1) + start_x += it.pixel_width; + } + else + { + start_x = it.current_x; + bidi_unshelve_cache (it1data, true); + } + } + else + start_x = it.current_x; } /* Now move to TO. */ - int start_x = it.current_x; int move_op = MOVE_TO_POS | MOVE_TO_Y; int to_x = -1; it.current_y = start_y; commit 9b892eeb918a7416a62506f4c618a9de75e99165 Author: Lars Ingebrigtsen Date: Tue Apr 12 16:08:50 2022 +0200 Fix webp_load data lifetime issues * src/image.c (webp_load): Take care of lifetime issues of the image data we're iterating over for animated images. diff --git a/src/image.c b/src/image.c index 3afb832407..530819eab9 100644 --- a/src/image.c +++ b/src/image.c @@ -9525,7 +9525,19 @@ webp_load (struct frame *f, struct image *img) WebPAnimDecoderDelete (cache->handle); WebPData webp_data; - webp_data.bytes = contents; + if (NILP (specified_data)) + /* If we got the data from a file, then we don't need to + copy the data. */ + webp_data.bytes = cache->temp = contents; + else + /* We got the data from a string, so copy it over so that + it doesn't get garbage-collected. */ + { + webp_data.bytes = xmalloc (size); + memcpy ((void*) webp_data.bytes, contents, size); + } + /* In any case, we release the allocated memory when we + purge the anim cache. */ webp_data.size = size; /* Get the width/height of the total image. */ @@ -9662,7 +9674,7 @@ webp_load (struct frame *f, struct image *img) /* Clean up. */ if (!anim) WebPFree (decoded); - if (NILP (specified_data)) + if (NILP (specified_data) && !anim) xfree (contents); return true; commit c3c08b90b67ba42be06a260718c5b6e5939e0b25 Author: Po Lu Date: Tue Apr 12 21:29:02 2022 +0800 Fix keyboard event device attribution on GTK+ 2 * src/xfns.c (setup_xi_event_mask): Select for raw keypress events on GTK 2. * src/xterm.c (handle_one_xevent): Set pending keystroke time when a raw event is received. * src/xterm.h (struct x_display_info): New flag `pending_keystroke_time_special_p'. diff --git a/src/xfns.c b/src/xfns.c index 5cf3eb4199..2f90534c48 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -3688,6 +3688,15 @@ setup_xi_event_mask (struct frame *f) XISelectEvents (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &mask, 1); + +#if defined USE_GTK && !defined HAVE_GTK3 + memset (m, 0, l); + XISetMask (m, XI_RawKeyPress); + + XISelectEvents (FRAME_X_DISPLAY (f), + FRAME_DISPLAY_INFO (f)->root_window, + &mask, 1); +#endif unblock_input (); } #endif diff --git a/src/xterm.c b/src/xterm.c index e922ab8fbb..2999480659 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -14516,7 +14516,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, pending_keystroke_time = dpyinfo->pending_keystroke_time; if (event->xkey.time >= pending_keystroke_time) - dpyinfo->pending_keystroke_time = 0; + { +#if defined USE_GTK && !defined HAVE_GTK3 + if (!dpyinfo->pending_keystroke_time_special_p) +#endif + dpyinfo->pending_keystroke_time = 0; +#if defined USE_GTK && !defined HAVE_GTK3 + else + dpyinfo->pending_keystroke_time_special_p = false; +#endif + } #endif #ifdef USE_GTK @@ -17781,6 +17790,21 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto XI_OTHER; } +#if defined USE_GTK && !defined HAVE_GTK3 + case XI_RawKeyPress: + { + XIRawEvent *raw_event = (XIRawEvent *) xi_event; + + /* This is the only way to attribute core keyboard + events generated on GTK+ 2.x to the extension device + that generated them. */ + dpyinfo->pending_keystroke_time = raw_event->time; + dpyinfo->pending_keystroke_source = raw_event->sourceid; + dpyinfo->pending_keystroke_time_special_p = true; + goto XI_OTHER; + } +#endif + case XI_KeyRelease: #if defined HAVE_X_I18N || defined USE_GTK { diff --git a/src/xterm.h b/src/xterm.h index 85b773cf0b..69313166db 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -618,6 +618,14 @@ struct x_display_info Time pending_keystroke_time; int pending_keystroke_source; + +#if defined USE_GTK && !defined HAVE_GTK3 + /* This means the two variables above shouldn't be reset the first + time a KeyPress event arrives, since they were set from a raw key + press event that was sent before the first (real, not sent by an + input method) core key event. */ + bool pending_keystroke_time_special_p; +#endif #endif #ifdef HAVE_XKB commit 1b20c4eaa2e5befc4c500637332c3bc1b719cf47 Author: Po Lu Date: Tue Apr 12 21:15:05 2022 +0800 Fix detection of Meta key in some cases * src/xterm.c (x_find_modifier_meanings): Set found_meta_p correctly. diff --git a/src/xterm.c b/src/xterm.c index 12707fc9a2..e922ab8fbb 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -9883,6 +9883,7 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo) #ifdef HAVE_XKB int i; int found_meta_p = false; + uint vmodmask; #endif dpyinfo->meta_mod_mask = 0; @@ -9897,12 +9898,14 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo) { for (i = 0; i < XkbNumVirtualMods; i++) { - uint vmodmask = dpyinfo->xkb_desc->server->vmods[i]; + vmodmask = dpyinfo->xkb_desc->server->vmods[i]; if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Meta) { dpyinfo->meta_mod_mask |= vmodmask; - found_meta_p = vmodmask; + + if (vmodmask) + found_meta_p = true; } else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Alt) dpyinfo->alt_mod_mask |= vmodmask; commit 4a108df0ebb68e9ea1073d53c14d8f897e43f21c Author: Lars Ingebrigtsen Date: Tue Apr 12 15:11:09 2022 +0200 Fix check for whether frames fit into gif images * src/image.c (gif_load): Really check all frames that they fit. diff --git a/src/image.c b/src/image.c index b6edcf96a0..3afb832407 100644 --- a/src/image.c +++ b/src/image.c @@ -8937,16 +8937,19 @@ gif_load (struct frame *f, struct image *img) /* Check that the selected subimages fit. It's not clear whether the GIF spec requires this, but Emacs can crash if they don't fit. */ - for (j = 0; j <= idx; ++j) + for (j = 0; j < gif->ImageCount; ++j) { struct SavedImage *subimage = gif->SavedImages + j; int subimg_width = subimage->ImageDesc.Width; int subimg_height = subimage->ImageDesc.Height; int subimg_top = subimage->ImageDesc.Top; int subimg_left = subimage->ImageDesc.Left; - if (! (subimg_width >= 0 && subimg_height >= 0 - && 0 <= subimg_top && subimg_top <= height - subimg_height - && 0 <= subimg_left && subimg_left <= width - subimg_width)) + if (subimg_width < 0 + || subimg_height < 0 + || subimg_top < 0 + || subimg_left < 0 + || subimg_top + subimg_height > height + || subimg_left + subimg_width > width) { image_error ("Subimage does not fit in image"); goto gif_error; commit 00071c976f9a16b5684697d10b086fc1b0be7145 Author: Po Lu Date: Tue Apr 12 21:08:36 2022 +0800 Fix some confusing names in xterm.c * src/xterm.c (enum xm_targets_table_byte_order): Rename to `xm_byte_order'. All uses changed. diff --git a/src/xterm.c b/src/xterm.c index 1bc92c67c0..12707fc9a2 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1020,16 +1020,16 @@ static bool x_dnd_use_toplevels; /* Motif drag-and-drop protocol support. */ -typedef enum xm_targets_table_byte_order +typedef enum xm_byte_order { - XM_TARGETS_TABLE_LSB = 'l', - XM_TARGETS_TABLE_MSB = 'B', + XM_BYTE_ORDER_LSB_FIRST = 'l', + XM_BYTE_ORDER_MSB_FIRST = 'B', #ifndef WORDS_BIGENDIAN - XM_TARGETS_TABLE_CUR = 'l', + XM_BYTE_ORDER_CUR_FIRST = 'l', #else - XM_TARGETS_TABLE_CUR = 'B', + XM_BYTE_ORDER_CUR_FIRST = 'B', #endif - } xm_targets_table_byte_order; + } xm_byte_order; #define SWAPCARD32(l) \ { \ @@ -1204,7 +1204,7 @@ xm_side_effect_from_action (struct x_display_info *dpyinfo, Atom action) static int xm_read_targets_table_header (uint8_t *bytes, ptrdiff_t length, xm_targets_table_header *header_return, - xm_targets_table_byte_order *byteorder_return) + xm_byte_order *byteorder_return) { if (length < 8) return -1; @@ -1215,20 +1215,20 @@ xm_read_targets_table_header (uint8_t *bytes, ptrdiff_t length, header_return->target_list_count = *(uint16_t *) bytes; header_return->total_data_size = *(uint32_t *) (bytes + 2); - if (header_return->byte_order != XM_TARGETS_TABLE_CUR) + if (header_return->byte_order != XM_BYTE_ORDER_CUR_FIRST) { SWAPCARD16 (header_return->target_list_count); SWAPCARD32 (header_return->total_data_size); } - header_return->byte_order = XM_TARGETS_TABLE_CUR; + header_return->byte_order = XM_BYTE_ORDER_CUR_FIRST; return 8; } static xm_targets_table_rec * xm_read_targets_table_rec (uint8_t *bytes, ptrdiff_t length, - xm_targets_table_byte_order byteorder) + xm_byte_order byteorder) { uint16_t nitems, i; xm_targets_table_rec *rec; @@ -1241,7 +1241,7 @@ xm_read_targets_table_rec (uint8_t *bytes, ptrdiff_t length, if (length < 2 + nitems * 4) return NULL; - if (byteorder != XM_TARGETS_TABLE_CUR) + if (byteorder != XM_BYTE_ORDER_CUR_FIRST) SWAPCARD16 (nitems); rec = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec, @@ -1252,7 +1252,7 @@ xm_read_targets_table_rec (uint8_t *bytes, ptrdiff_t length, { rec->targets[i] = ((uint32_t *) (bytes + 2))[i]; - if (byteorder != XM_TARGETS_TABLE_CUR) + if (byteorder != XM_BYTE_ORDER_CUR_FIRST) SWAPCARD32 (rec->targets[i]); } @@ -1450,7 +1450,7 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, int rc, actual_format, idx; xm_targets_table_header header; xm_targets_table_rec **recs; - xm_targets_table_byte_order byteorder; + xm_byte_order byteorder; uint8_t *data; ptrdiff_t total_bytes, total_items, i; @@ -1536,7 +1536,7 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, if (!rc) { - header.byte_order = XM_TARGETS_TABLE_CUR; + header.byte_order = XM_BYTE_ORDER_CUR_FIRST; header.protocol = 0; header.target_list_count = 1; header.total_data_size = 8 + 2 + ntargets * 4; @@ -1604,7 +1604,7 @@ xm_setup_drag_info (struct x_display_info *dpyinfo, if (idx != -1) { - drag_initiator_info.byteorder = XM_TARGETS_TABLE_CUR; + drag_initiator_info.byteorder = XM_BYTE_ORDER_CUR_FIRST; drag_initiator_info.protocol = 0; drag_initiator_info.table_index = idx; drag_initiator_info.selection = dpyinfo->Xatom_XdndSelection; @@ -1719,7 +1719,7 @@ xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source, { mmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_DRAG_MOTION); - mmsg.byteorder = XM_TARGETS_TABLE_CUR; + mmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; mmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, x_dnd_wanted_action), XM_DROP_SITE_NONE, XM_DRAG_NOOP, @@ -1774,14 +1774,14 @@ xm_read_drop_start_reply (const XEvent *msg, xm_drop_start_reply *reply) reply->better_x = *(uint16_t *) (data + 2); reply->better_y = *(uint16_t *) (data + 4); - if (reply->byte_order != XM_TARGETS_TABLE_CUR) + if (reply->byte_order != XM_BYTE_ORDER_CUR_FIRST) { SWAPCARD16 (reply->side_effects); SWAPCARD16 (reply->better_x); SWAPCARD16 (reply->better_y); } - reply->byte_order = XM_TARGETS_TABLE_CUR; + reply->byte_order = XM_BYTE_ORDER_CUR_FIRST; return 0; } @@ -1823,14 +1823,14 @@ xm_read_drag_receiver_info (struct x_display_info *dpyinfo, rec->unspecified2 = *(uint32_t *) &data[8]; rec->unspecified3 = *(uint32_t *) &data[12]; - if (rec->byteorder != XM_TARGETS_TABLE_CUR) + if (rec->byteorder != XM_BYTE_ORDER_CUR_FIRST) { SWAPCARD32 (rec->unspecified1); SWAPCARD32 (rec->unspecified2); SWAPCARD32 (rec->unspecified3); } - rec->byteorder = XM_TARGETS_TABLE_CUR; + rec->byteorder = XM_BYTE_ORDER_CUR_FIRST; } if (tmp_data) @@ -1848,7 +1848,7 @@ x_dnd_send_xm_leave_for_drop (struct x_display_info *dpyinfo, lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_TOP_LEVEL_LEAVE); - lmsg.byteorder = XM_TARGETS_TABLE_CUR; + lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; lmsg.zero = 0; lmsg.timestamp = timestamp; lmsg.source_window = FRAME_X_WINDOW (f); @@ -3545,7 +3545,7 @@ x_dnd_cleanup_drag_and_drop (void *frame) { dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_DROP_START); - dmsg.byte_order = XM_TARGETS_TABLE_CUR; + dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time; dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), @@ -9613,7 +9613,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, { dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_DROP_START); - dmsg.byte_order = XM_TARGETS_TABLE_CUR; + dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; dmsg.timestamp = hold_quit.timestamp; dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), @@ -13346,7 +13346,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_TOP_LEVEL_LEAVE); - lmsg.byteorder = XM_TARGETS_TABLE_CUR; + lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; lmsg.zero = 0; lmsg.timestamp = timestamp; lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); @@ -13385,7 +13385,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_TOP_LEVEL_LEAVE); - lmsg.byteorder = XM_TARGETS_TABLE_CUR; + lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; lmsg.zero = 0; lmsg.timestamp = timestamp; lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); @@ -13410,7 +13410,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_TOP_LEVEL_ENTER); - emsg.byteorder = XM_TARGETS_TABLE_CUR; + emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; emsg.zero = 0; emsg.timestamp = timestamp; emsg.source_window = FRAME_X_WINDOW (x_dnd_frame); @@ -13435,7 +13435,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_DRAG_MOTION); - dmsg.byteorder = XM_TARGETS_TABLE_CUR; + dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, x_dnd_wanted_action), @@ -13468,7 +13468,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) { dsmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_DROP_START); - dmsg.byteorder = XM_TARGETS_TABLE_CUR; + dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; dsmsg.timestamp = timestamp; dsmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, @@ -15088,7 +15088,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_TOP_LEVEL_LEAVE); - lmsg.byteorder = XM_TARGETS_TABLE_CUR; + lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; lmsg.zero = 0; lmsg.timestamp = event->xmotion.time; lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); @@ -15133,7 +15133,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_DRAG_MOTION); - dmsg.byteorder = XM_TARGETS_TABLE_CUR; + dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, x_dnd_wanted_action), XM_DROP_SITE_NONE, XM_DRAG_NOOP, @@ -15144,7 +15144,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_TOP_LEVEL_LEAVE); - lmsg.byteorder = XM_TARGETS_TABLE_CUR; + lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; lmsg.zero = 0; lmsg.timestamp = event->xbutton.time; lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); @@ -15173,7 +15173,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_TOP_LEVEL_ENTER); - emsg.byteorder = XM_TARGETS_TABLE_CUR; + emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; emsg.zero = 0; emsg.timestamp = event->xbutton.time; emsg.source_window = FRAME_X_WINDOW (x_dnd_frame); @@ -15199,7 +15199,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_DRAG_MOTION); - dmsg.byteorder = XM_TARGETS_TABLE_CUR; + dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, x_dnd_wanted_action), XM_DROP_SITE_VALID, @@ -15677,7 +15677,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_DROP_START); - dmsg.byte_order = XM_TARGETS_TABLE_CUR; + dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, x_dnd_wanted_action), @@ -16615,7 +16615,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_TOP_LEVEL_LEAVE); - lmsg.byteorder = XM_TARGETS_TABLE_CUR; + lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; lmsg.zero = 0; lmsg.timestamp = event->xmotion.time; lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); @@ -16661,7 +16661,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_DRAG_MOTION); - dmsg.byteorder = XM_TARGETS_TABLE_CUR; + dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, x_dnd_wanted_action), @@ -16673,7 +16673,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_TOP_LEVEL_LEAVE); - lmsg.byteorder = XM_TARGETS_TABLE_CUR; + lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; lmsg.zero = 0; lmsg.timestamp = xev->time; lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); @@ -16702,7 +16702,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_TOP_LEVEL_ENTER); - emsg.byteorder = XM_TARGETS_TABLE_CUR; + emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; emsg.zero = 0; emsg.timestamp = xev->time; emsg.source_window = FRAME_X_WINDOW (x_dnd_frame); @@ -16727,7 +16727,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_DRAG_MOTION); - dmsg.byteorder = XM_TARGETS_TABLE_CUR; + dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, x_dnd_wanted_action), @@ -16893,7 +16893,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, XM_DRAG_REASON_DROP_START); - dmsg.byte_order = XM_TARGETS_TABLE_CUR; + dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, x_dnd_wanted_action), commit 7b67b9a5a2135d479dfe86f40109778ac5f99920 Author: Lars Ingebrigtsen Date: Tue Apr 12 14:45:13 2022 +0200 Store less data in the gif animation cache * src/image.c (gif_load): Only start a cache if we're have an :index entry (which means that we're trying to animate something). diff --git a/src/image.c b/src/image.c index f56d02bf19..b6edcf96a0 100644 --- a/src/image.c +++ b/src/image.c @@ -8814,14 +8814,12 @@ gif_load (struct frame *f, struct image *img) EMACS_INT idx = -1; int gif_err; struct anim_cache* cache = NULL; - /* Which sub-image are we to display? */ - { - Lisp_Object image_number = image_spec_value (img->spec, QCindex, NULL); - idx = FIXNUMP (image_number) ? XFIXNAT (image_number) : 0; - } + Lisp_Object image_number = image_spec_value (img->spec, QCindex, NULL); + + idx = FIXNUMP (image_number) ? XFIXNAT (image_number) : 0; - if (idx != -1) + if (!NILP (image_number)) { /* If this is an animated image, create a cache for it. */ cache = anim_get_animation_cache (img->spec); commit 9561d45de16b1dece79410c126ff741c09d91e22 Author: Po Lu Date: Tue Apr 12 19:21:21 2022 +0800 Fix clicking on files in Dired when drag is enabled * lisp/dired.el (dired-mouse-drag): Don't drag if the mouse didn't move far enough. diff --git a/lisp/dired.el b/lisp/dired.el index d6e189cba3..5accad8efd 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -1726,37 +1726,50 @@ when Emacs exits or the user drags another file.") (with-selected-window (posn-window (event-end event)) (goto-char (posn-point (event-end event)))) (track-mouse - (let ((new-event (read-event))) - (if (not (eq (event-basic-type new-event) 'mouse-movement)) - (when (eq (event-basic-type new-event) 'mouse-1) - (push new-event unread-command-events)) - ;; We can get an error if there's by some chance no file - ;; name at point. - (condition-case nil - (let ((filename (with-selected-window (posn-window - (event-end event)) - (dired-file-name-at-point)))) - (when filename - ;; In theory x-dnd-username combined with a proper - ;; file URI containing the hostname of the remote - ;; server could be used here instead of creating a - ;; local copy of the remote file, but no program - ;; actually implements file DND according to the - ;; spec. - (when (file-remote-p filename) - (setq filename (file-local-copy filename)) - (setq dired-last-dragged-remote-file filename) - (add-hook 'kill-emacs-hook - #'dired-remove-last-dragged-local-file)) - (gui-backend-set-selection 'XdndSelection filename) - (x-begin-drag '("text/uri-list" "text/x-dnd-username" - "FILE_NAME" "FILE" "HOST_NAME") - (if (eq 'dired-mouse-drag-files 'link) - 'XdndActionLink - 'XdndActionCopy) - nil nil t))) - (error (when (eq (event-basic-type new-event) 'mouse-1) - (push new-event unread-command-events))))))))) + (let ((beginning-position (mouse-pixel-position)) + new-event) + (catch 'track-again + (setq new-event (read-event)) + (if (not (eq (event-basic-type new-event) 'mouse-movement)) + (when (eq (event-basic-type new-event) 'mouse-1) + (push new-event unread-command-events)) + (let ((current-position (mouse-pixel-position))) + ;; If the mouse didn't move far enough, don't + ;; inadvertently trigger a drag. + (when (and (eq (car current-position) (car beginning-position)) + (ignore-errors + (and (> 3 (abs (- (cadr beginning-position) + (cadr current-position)))) + (> 3 (abs (- (caddr beginning-position) + (caddr current-position))))))) + (throw 'track-again nil))) + ;; We can get an error if there's by some chance no file + ;; name at point. + (condition-case nil + (let ((filename (with-selected-window (posn-window + (event-end event)) + (dired-file-name-at-point)))) + (when filename + ;; In theory x-dnd-username combined with a proper + ;; file URI containing the hostname of the remote + ;; server could be used here instead of creating a + ;; local copy of the remote file, but no program + ;; actually implements file DND according to the + ;; spec. + (when (file-remote-p filename) + (setq filename (file-local-copy filename)) + (setq dired-last-dragged-remote-file filename) + (add-hook 'kill-emacs-hook + #'dired-remove-last-dragged-local-file)) + (gui-backend-set-selection 'XdndSelection filename) + (x-begin-drag '("text/uri-list" "text/x-dnd-username" + "FILE_NAME" "FILE" "HOST_NAME") + (if (eq 'dired-mouse-drag-files 'link) + 'XdndActionLink + 'XdndActionCopy) + nil nil t))) + (error (when (eq (event-basic-type new-event) 'mouse-1) + (push new-event unread-command-events)))))))))) (defvar dired-mouse-drag-files-map (let ((keymap (make-sparse-keymap))) (define-key keymap [down-mouse-1] #'dired-mouse-drag) commit 25a28ed4f7419154cd89b83a2ed907585db0de2b Author: Lars Ingebrigtsen Date: Tue Apr 12 13:17:14 2022 +0200 Release resources in gif_load on errors * src/image.c (webp_load): Clean up code slightly. (gif_load): Really release resources on GIF parsing errors. diff --git a/src/image.c b/src/image.c index 3b3d1fc080..f56d02bf19 100644 --- a/src/image.c +++ b/src/image.c @@ -9249,11 +9249,13 @@ gif_load (struct frame *f, struct image *img) return true; gif_error: - if (!cache) + if (pixmap) + xfree (pixmap); + gif_close (gif, NULL); + if (cache) { - if (pixmap) - xfree (pixmap); - gif_close (gif, NULL); + cache->handle = NULL; + cache->temp = NULL; } return false; } @@ -9501,9 +9503,6 @@ webp_load (struct frame *f, struct image *img) if (features.has_animation) { /* Animated image. */ - WebPData webp_data; - webp_data.bytes = contents; - webp_data.size = size; int timestamp; struct anim_cache* cache = anim_get_animation_cache (img->spec); @@ -9524,6 +9523,10 @@ webp_load (struct frame *f, struct image *img) if (cache->handle) WebPAnimDecoderDelete (cache->handle); + WebPData webp_data; + webp_data.bytes = contents; + webp_data.size = size; + /* Get the width/height of the total image. */ WebPDemuxer* demux = WebPDemux (&webp_data); cache->width = width = WebPDemuxGetI (demux, WEBP_FF_CANVAS_WIDTH); commit 3de2462da7306f3b342f6402dd0c0b185ac2741f Author: Lars Ingebrigtsen Date: Tue Apr 12 12:43:56 2022 +0200 Animate GIF images that don't have an explicit delay setting * src/image.c (gif_load): Use the default delay for GIF images that don't explicitly state a delay. diff --git a/src/image.c b/src/image.c index f6143f5b46..3b3d1fc080 100644 --- a/src/image.c +++ b/src/image.c @@ -9208,11 +9208,11 @@ gif_load (struct frame *f, struct image *img) } } img->lisp_data = list2 (Qextension_data, img->lisp_data); - if (delay) - img->lisp_data - = Fcons (Qdelay, - Fcons (make_float (delay / 100.0), - img->lisp_data)); + img->lisp_data + = Fcons (Qdelay, + /* Default GIF delay is 1/15th of a second. */ + Fcons (make_float (delay? delay / 100.0: 1.0 / 15), + img->lisp_data)); } if (gif->ImageCount > 1) commit 8c3d655fe76e1148adcaac0b2fe9550621ba7e54 Author: Olaf Trygve Berglihn Date: Tue Apr 12 12:21:19 2022 +0200 Add biblatex alias entry types for compability with bibtex * lisp/textmodes/bibtex.el (bibtex-biblatex-entry-alist): Add biblatex alias entry types for compability with bibtex (bug#54877). Copyright-paperwork-exempt: yes diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el index ab6a907c52..d02eca506a 100644 --- a/lisp/textmodes/bibtex.el +++ b/lisp/textmodes/bibtex.el @@ -764,6 +764,20 @@ for a new entry." ("eprint") ("eprintclass" nil nil 4) ("primaryclass" nil nil -4) ("eprinttype" nil nil 5) ("archiveprefix" nil nil -5) ("url") ("urldate"))) + ("Conference" "Article in Conference Proceedings" ; same as InProceedings + (("author") + ("title" "Title of the article in proceedings (BibTeX converts it to lowercase)")) + (("booktitle" "Name of the conference proceedings") + ("year")) + (("editor") + ("volume" "Volume of the conference proceedings in the series") + ("number" "Number of the conference proceedings in a small series (overwritten by volume)") + ("series" "Series in which the conference proceedings appeared") + ("pages" "Pages in the conference proceedings") + ("month") ("address") + ("organization" "Sponsoring organization of the conference") + ("publisher" "Publishing company, its location") + ("note"))) ("Reference" "Single-Volume Work of Reference" ; same as @collection (("editor") ("title") ("date" nil nil 1) ("year" nil nil -1)) nil @@ -848,6 +862,15 @@ for a new entry." (("type" "Type of the PhD thesis") ("address" "Address of the school (if not part of field \"school\") or country") ("month") ("note"))) + ("MastersThesis" "Master's Thesis" + (("author") + ("title" "Title of the master's thesis (BibTeX converts it to lowercase)") + ("school" "School where the master's thesis was written") + ("year")) + nil + (("type" "Type of the master's thesis (if other than \"Master's thesis\")") + ("address" "Address of the school (if not part of field \"school\") or country") + ("month") ("note"))) ("TechReport" "Technical Report" (("author") ("title" "Title of the technical report (BibTeX converts it to lowercase)") commit 8e1c0054b3545863e41d51c95b69ab7fdb0cc61d Author: Lars Ingebrigtsen Date: Tue Apr 12 12:12:24 2022 +0200 Fix thinko in the anim cache * src/image.c (gif_load): Fix resetting the cache when we're out of sync. (anim_create_cache): Start from zero, not 1. diff --git a/src/image.c b/src/image.c index 38c3f1496a..f6143f5b46 100644 --- a/src/image.c +++ b/src/image.c @@ -2847,7 +2847,7 @@ anim_create_cache (Lisp_Object spec) cache->handle = NULL; cache->temp = NULL; - cache->index = 0; + cache->index = -1; cache->next = NULL; cache->spec = spec; return cache; @@ -8825,15 +8825,14 @@ gif_load (struct frame *f, struct image *img) { /* If this is an animated image, create a cache for it. */ cache = anim_get_animation_cache (img->spec); + /* We have an old cache entry, so use it. */ if (cache->handle) { - /* We have an old cache entry, and it looks correct, so use - it. */ - if (cache->index == idx - 1) - { - gif = cache->handle; - pixmap = cache->temp; - } + gif = cache->handle; + pixmap = cache->temp; + /* We're out of sync, so start from the beginning. */ + if (cache->index != idx - 1) + cache->index = -1; } } commit 78784ccfadaee1c86207ecc360db7236285713f5 Author: Po Lu Date: Tue Apr 12 16:36:42 2022 +0800 Disallow drag and drop inside a menu-entry * src/xterm.c (x_dnd_cleanup_drag_and_drop): Always free DND targets even if waiting for finish. (x_dnd_begin_drag_and_drop): Free targets correctly when signalling error and prevent activating drag-and-drop inside a menu or popup. (It doesn't work.) diff --git a/src/xterm.c b/src/xterm.c index b1d9ca7361..1bc92c67c0 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3571,9 +3571,9 @@ x_dnd_cleanup_drag_and_drop (void *frame) x_dnd_last_seen_window = None; x_dnd_last_seen_toplevel = None; x_dnd_in_progress = false; - x_set_dnd_targets (NULL, 0); } + x_set_dnd_targets (NULL, 0); x_dnd_waiting_for_finish = false; if (x_dnd_use_toplevels) @@ -9373,20 +9373,35 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, Lisp_Object frame_object, x, y, frame, local_value; if (!FRAME_VISIBLE_P (f)) - error ("Frame is invisible"); + { + x_set_dnd_targets (NULL, 0); + error ("Frame is invisible"); + } XSETFRAME (frame, f); local_value = assq_no_quit (QXdndSelection, FRAME_TERMINAL (f)->Vselection_alist); if (x_dnd_in_progress || x_dnd_waiting_for_finish) - error ("A drag-and-drop session is already in progress"); + { + x_set_dnd_targets (NULL, 0); + error ("A drag-and-drop session is already in progress"); + } if (CONSP (local_value)) x_own_selection (QXdndSelection, Fnth (make_fixnum (1), local_value), frame); else - error ("No local value for XdndSelection"); + { + x_set_dnd_targets (NULL, 0); + error ("No local value for XdndSelection"); + } + + if (popup_activated ()) + { + x_set_dnd_targets (NULL, 0); + error ("Trying to drag-and-drop from within a menu-entry"); + } ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f), QXdndSelection); @@ -9624,9 +9639,9 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_dnd_last_seen_toplevel = None; x_dnd_in_progress = false; x_dnd_frame = NULL; - x_set_dnd_targets (NULL, 0); } + x_set_dnd_targets (NULL, 0); x_dnd_waiting_for_finish = false; if (x_dnd_use_toplevels) @@ -9647,6 +9662,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, quit (); } } + x_set_dnd_targets (NULL, 0); x_dnd_waiting_for_finish = false; commit 17f0900d7bd783375e07f642cf8740c3e1dbaa8f Author: Michael Albinus Date: Tue Apr 12 09:41:11 2022 +0200 Adapt macOS defaults in Tramp's process-attributes implementation * doc/misc/tramp.texi (Remote processes): Mention tramp-connection-local-darwin-ps-* constants. * lisp/net/tramp-integration.el (tramp-connection-local-darwin-ps-variables): Fix docstring. (top): Simplify setting local profiles. * test/lisp/net/tramp-tests.el (tramp-test31-list-system-processes) (tramp-test31-process-attributes): New tests. diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index e4a586f817..3cc312d2f5 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -4097,6 +4097,8 @@ The corresponding @code{tramp-process-attributes-ps-format} has the value @vindex tramp-connection-local-bsd-ps-variables @vindex tramp-connection-local-busybox-ps-profile @vindex tramp-connection-local-busybox-ps-variables +@vindex tramp-connection-local-darwin-ps-profile +@vindex tramp-connection-local-darwin-ps-variables The default values for @code{tramp-process-attributes-ps-args} and @code{tramp-process-attributes-ps-format} can be overwritten by connection-local variables. @@ -4107,14 +4109,11 @@ This is already done by @value{tramp} for the @option{adb} method, see @code{tramp-adb-connection-local-default-ps-profile} and @code{tramp-adb-connection-local-default-ps-variables}. -There are two further predefined sets of connection-local variables -for remote BSD systems, and for a remote @command{ps} command -implemented with @command{busybox}. These are called -@code{tramp-connection-local-bsd-ps-profile}, -@code{tramp-connection-local-bsd-ps-variables}, -@code{tramp-connection-local-busybox-ps-profile}, and -@code{tramp-connection-local-busybox-ps-variables}. Use them -like +There are three further predefined sets of connection-local variables +for remote BSD systems, for remote macOS systems, and for a remote +@command{ps} command implemented with @command{busybox}. These are +called @code{tramp-connection-local-*-ps-profile} and +@code{tramp-connection-local-*-ps-variables}. Use them like @lisp @group diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el index 901826bfc1..b7f82770c4 100644 --- a/lisp/net/tramp-integration.el +++ b/lisp/net/tramp-integration.el @@ -430,8 +430,7 @@ See `tramp-process-attributes-ps-format'.") 'tramp-connection-local-busybox-ps-profile tramp-connection-local-busybox-ps-variables) - -;; Darwin (macOS) +;; Darwin (macOS). (defconst tramp-darwin-process-attributes-ps-args `("-acxww" "-o" @@ -498,31 +497,25 @@ See `tramp-process-attributes-ps-format'.") . ,tramp-darwin-process-attributes-ps-args) (tramp-process-attributes-ps-format . ,tramp-darwin-process-attributes-ps-format)) - "Default connection-local ps variables for remote Darwin -connections.") + "Default connection-local ps variables for remote Darwin connections.") (connection-local-set-profile-variables 'tramp-connection-local-darwin-ps-profile tramp-connection-local-darwin-ps-variables) +;; Preset default "ps" profile for local hosts, based on system type. - -;; Preset default "ps" profile for the case of local sudo, based on -;; system type. - -(let ((local-sudo-profile - (cond ((eq system-type 'darwin) - 'tramp-connection-local-darwin-ps-profile) - ;; ...add other system types here - ))) - (when local-sudo-profile - (connection-local-set-profiles - `(:application tramp :protocol "sudo" :user "root" :machine ,(system-name)) - local-sudo-profile) - (connection-local-set-profiles - '(:application tramp :protocol "sudo" :user "root" :machine "localhost") - local-sudo-profile))) - +(when-let ((local-profile + (cond ((eq system-type 'darwin) + 'tramp-connection-local-darwin-ps-profile) + ;; ... Add other system types here. + ))) + (connection-local-set-profiles + `(:application tramp :machine ,(system-name)) + local-profile) + (connection-local-set-profiles + '(:application tramp :machine "localhost") + local-profile)) (add-hook 'tramp-unload-hook (lambda () (unload-feature 'tramp-integration 'force))) diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index c3b3f21d52..e9ea758956 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -5090,6 +5090,51 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." (ignore-errors (kill-process proc)) (ignore-errors (delete-process proc)))))) +(ert-deftest tramp-test31-list-system-processes () + "Check `list-system-processes'." + :tags '(:expensive-test) + (skip-unless (tramp--test-enabled)) + (skip-unless (tramp--test-supports-processes-p)) + ;; `list-system-processes' is supported since Emacs 29.1. + (skip-unless (tramp--test-emacs29-p)) + + (let ((default-directory tramp-test-temporary-file-directory)) + (skip-unless (consp (list-system-processes))) + (should (not (equal (list-system-processes) + (let ((default-directory temporary-file-directory)) + (list-system-processes))))))) + +(ert-deftest tramp-test31-process-attributes () + "Check `process-attributes'." + :tags '(:expensive-test :tramp-asynchronous-processes) + (skip-unless (tramp--test-enabled)) + (skip-unless (tramp--test-supports-processes-p)) + ;; `process-attributes' is supported since Emacs 29.1. + (skip-unless (tramp--test-emacs29-p)) + + ;; We must use `file-truename' for the temporary directory, in + ;; order to establish the connection prior running an asynchronous + ;; process. + (let ((default-directory (file-truename tramp-test-temporary-file-directory)) + (delete-exited-processes t) + kill-buffer-query-functions command proc) + (skip-unless (consp (list-system-processes))) + + (unwind-protect + (progn + (setq command '("sleep" "100") + proc (apply #'start-file-process "test" nil command)) + (while (accept-process-output proc 0)) + (when-let ((pid (process-get proc 'remote-pid)) + (attributes (process-attributes pid))) + ;; (tramp--test-message "%s" attributes) + (should (equal (cdr (assq 'comm attributes)) (car command))) + (should (equal (cdr (assq 'args attributes)) + (mapconcat #'identity command " "))))) + + ;; Cleanup. + (ignore-errors (delete-process proc))))) + (defun tramp--test-async-shell-command (command output-buffer &optional error-buffer input) "Like `async-shell-command', reading the output. commit e258e582768a6f974ab1da198e894408d9933cd1 Author: Filipp Gunbin Date: Tue Apr 12 09:12:29 2022 +0200 process-attributes-ps-args / process-attributes-ps-format for Darwin * lisp/net/tramp-integration.el (tramp-darwin-process-attributes-ps-args) (tramp-darwin-process-attributes-ps-format) (tramp-connection-local-darwin-ps-variables): New defconsts. Add them to connection-local variables. Preset default "ps" profile for Darwin. diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el index 81990c6a33..901826bfc1 100644 --- a/lisp/net/tramp-integration.el +++ b/lisp/net/tramp-integration.el @@ -430,6 +430,100 @@ See `tramp-process-attributes-ps-format'.") 'tramp-connection-local-busybox-ps-profile tramp-connection-local-busybox-ps-variables) + +;; Darwin (macOS) +(defconst tramp-darwin-process-attributes-ps-args + `("-acxww" + "-o" + ,(mapconcat + #'identity + '("pid" + "uid" + "user" + "gid" + "comm=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + ",") + "-o" "state=abcde" + "-o" + ,(mapconcat + #'identity + '("ppid" + "pgid" + "sess" + "tty" + "tpgid" + "minflt" + "majflt" + "time" + "pri" + "nice" + "vsz" + "rss" + "etime" + "pcpu" + "pmem" + "args") + ",")) + "List of arguments for \"ps\". +See `tramp-process-attributes-ps-args'.") + +(defconst tramp-darwin-process-attributes-ps-format + '((pid . number) + (euid . number) + (user . string) + (egid . number) + (comm . 52) + (state . 5) + (ppid . number) + (pgrp . number) + (sess . number) + (ttname . string) + (tpgid . number) + (minflt . number) + (majflt . number) + (time . tramp-ps-time) + (pri . number) + (nice . number) + (vsize . number) + (rss . number) + (etime . tramp-ps-time) + (pcpu . number) + (pmem . number) + (args . nil)) + "Alist of formats for \"ps\". +See `tramp-process-attributes-ps-format'.") + +(defconst tramp-connection-local-darwin-ps-variables + `((tramp-process-attributes-ps-args + . ,tramp-darwin-process-attributes-ps-args) + (tramp-process-attributes-ps-format + . ,tramp-darwin-process-attributes-ps-format)) + "Default connection-local ps variables for remote Darwin +connections.") + +(connection-local-set-profile-variables + 'tramp-connection-local-darwin-ps-profile + tramp-connection-local-darwin-ps-variables) + + + +;; Preset default "ps" profile for the case of local sudo, based on +;; system type. + +(let ((local-sudo-profile + (cond ((eq system-type 'darwin) + 'tramp-connection-local-darwin-ps-profile) + ;; ...add other system types here + ))) + (when local-sudo-profile + (connection-local-set-profiles + `(:application tramp :protocol "sudo" :user "root" :machine ,(system-name)) + local-sudo-profile) + (connection-local-set-profiles + '(:application tramp :protocol "sudo" :user "root" :machine "localhost") + local-sudo-profile))) + + (add-hook 'tramp-unload-hook (lambda () (unload-feature 'tramp-integration 'force)))