commit a36ed9b5e95afea5716256bac24d883263aefbaf (HEAD, refs/remotes/origin/master) Author: Paul Eggert Date: Wed Jul 13 10:15:42 2016 +0200 Omit unnecessary #includes from xwidget.c * src/xwidget.c: Remove #include directives that are not needed. Also, don’t conditionalize #includes on HAVE_X_WINDOWS, since this file is compiled only if the X interface is available. diff --git a/src/xwidget.c b/src/xwidget.c index 9c50510..f5f4da0 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -21,87 +21,13 @@ along with GNU Emacs. If not, see . */ #include "xwidget.h" -#include - -#include -#include -#ifdef HAVE_X_WINDOWS - #include "lisp.h" #include "blockinput.h" -#include "syssignal.h" - -#include "xterm.h" -#include - -#ifndef makedev -# include -#endif - -#ifdef BSD_SYSTEM -# include -#endif - -#include "systime.h" - -#ifndef INCLUDED_FCNTL -# include -#endif -#include -#include -#include -#include - -#include "charset.h" -#include "character.h" -#include "coding.h" -#include "ccl.h" #include "frame.h" -#include "dispextern.h" -#include "fontset.h" -#include "termhooks.h" -#include "termopts.h" -#include "termchar.h" -#include "disptab.h" -#include "buffer.h" -#include "window.h" #include "keyboard.h" -#include "intervals.h" -#include "process.h" -#include "atimer.h" -#include "keymap.h" - - -#ifdef USE_X_TOOLKIT -#include -#endif -#include -#include -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif - #include "gtkutil.h" -#include "font.h" -#endif /* HAVE_X_WINDOWS */ - -#include -#include - -#include - -#include "emacsgtkfixed.h" - -#include #include -#include -#include -#include #include #include #include commit 66da81e577a7177c0595dbbc6b2e974740a19a42 Author: Paul Eggert Date: Wed Jul 13 09:56:50 2016 +0200 Port xwidget.c to GCC 6 with --enable-gcc-warnings * src/xwidget.c (x_draw_xwidget_glyph_string, xwidget_end_redisplay): Adjust to pacify GCC. Add a couple of FIXME comments, suggesting possible bugs found by GCC. diff --git a/src/xwidget.c b/src/xwidget.c index 82449f7..9c50510 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -565,12 +565,16 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) xwidget on screen. Moving and clipping is done here. Also view initialization. */ struct xwidget *xww = s->xwidget; - struct xwidget_view *xv = xwidget_view_lookup (xww, s->w); + struct xwidget_view *xv; int clip_right; int clip_bottom; int clip_top; int clip_left; + /* FIXME: The result of this call is discarded. + What if the lookup fails? */ + xwidget_view_lookup (xww, s->w); + int x = s->x; int y = s->y + (s->height / 2) - (xww->height / 2); @@ -1145,7 +1149,13 @@ xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix) { /* The only call to xwidget_end_redisplay is in dispnew. xwidget_end_redisplay (w->current_matrix); */ - xwidget_touch (xwidget_view_lookup (glyph->u.xwidget, w)); + struct xwidget_view *xv + = xwidget_view_lookup (glyph->u.xwidget, w); + /* FIXME: Is it safe to assume xwidget_view_lookup + always succeeds here? If so, this comment can be removed. + If not, the code probably needs fixing. */ + eassume (xv); + xwidget_touch (xv); } } } commit cff2f4606dfbc83f8e38a6b7a48eedcc47009a3b Author: Tino Calancha Date: Wed Jul 13 13:27:33 2016 +0900 Escape meta chars in commands processed by shell * lisp/progmodes/grep.el (grep-compute-defaults): Quote braces in all commands to be passed to a shell (Bug#23959). diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index 2b44b58..f7f097b 100644 --- a/lisp/progmodes/grep.el +++ b/lisp/progmodes/grep.el @@ -543,7 +543,9 @@ This function is called from `compilation-filter-hook'." (let* ((host-id (intern (or (file-remote-p default-directory) "localhost"))) (host-defaults (assq host-id grep-host-defaults-alist)) - (defaults (assq nil grep-host-defaults-alist))) + (defaults (assq nil grep-host-defaults-alist)) + (quot-braces (shell-quote-argument "{}")) + (quot-scolon (shell-quote-argument ";"))) ;; There are different defaults on different hosts. They must be ;; computed for every host once. (dolist (setting '(grep-command grep-template @@ -637,9 +639,8 @@ This function is called from `compilation-filter-hook'." ""))) (cons (if (eq grep-find-use-xargs 'exec-plus) - (format "%s %s{} +" cmd0 null) - (format "%s {} %s%s" cmd0 null - (shell-quote-argument ";"))) + (format "%s %s%s +" cmd0 null quot-braces) + (format "%s %s %s%s" cmd0 quot-braces null quot-scolon)) (1+ (length cmd0))))) (t (format "%s . -type f -print | \"%s\" %s" @@ -655,12 +656,11 @@ This function is called from `compilation-filter-hook'." (format "%s -type f -print0 | \"%s\" -0 %s" find-program xargs-program gcmd)) ((eq grep-find-use-xargs 'exec) - (format "%s -type f -exec %s {} %s%s" - find-program gcmd null - (shell-quote-argument ";"))) + (format "%s -type f -exec %s %s %s%s" + find-program gcmd quot-braces null quot-scolon)) ((eq grep-find-use-xargs 'exec-plus) - (format "%s -type f -exec %s %s{} +" - find-program gcmd null)) + (format "%s -type f -exec %s %s%s +" + find-program gcmd null quot-braces)) (t (format "%s -type f -print | \"%s\" %s" find-program xargs-program gcmd)))))))) commit 54b7eb0dee2397f1430e81b7356f8efb19946ba0 Author: John Wiegley Date: Tue Jul 12 15:27:25 2016 -0700 Revert "Cleanup tooltips" This reverts commit 20038f8ab75dd1551412a43cd58520c483c22921. I am reverting this change because it was applied without prior discussion on emacs-devel, and has been found to break the NS port. It needs more testing and review before it should be applied here. diff --git a/src/dispextern.h b/src/dispextern.h index c2fcca5..1325ff9 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3461,6 +3461,8 @@ void gamma_correct (struct frame *, COLORREF *); void x_implicitly_set_name (struct frame *, Lisp_Object, Lisp_Object); void x_change_tool_bar_height (struct frame *f, int); +extern Lisp_Object tip_frame; +extern Window tip_window; extern frame_parm_handler x_frame_parm_handlers[]; extern void start_hourglass (void); diff --git a/src/frame.c b/src/frame.c index 80e181f..22143ab 100644 --- a/src/frame.c +++ b/src/frame.c @@ -642,7 +642,6 @@ make_frame (bool mini_p) f->vertical_scroll_bar_type = vertical_scroll_bar_none; f->horizontal_scroll_bars = false; f->want_fullscreen = FULLSCREEN_NONE; - f->tooltip = false; #if ! defined (USE_GTK) && ! defined (HAVE_NS) f->last_tool_bar_item = -1; #endif @@ -1261,16 +1260,13 @@ DEFUN ("frame-list", Fframe_list, Sframe_list, doc: /* Return a list of all live frames. */) (void) { + Lisp_Object frames; + frames = Fcopy_sequence (Vframe_list); #ifdef HAVE_WINDOW_SYSTEM - Lisp_Object list = Qnil, tail, frame; - - FOR_EACH_FRAME (tail, frame) - if (!FRAME_TOOLTIP_P (XFRAME (frame))) - list = Fcons (frame, list); - return list; -#else /* !HAVE_WINDOW_SYSTEM */ - return Fcopy_sequence (Vframe_list); + if (FRAMEP (tip_frame)) + frames = Fdelq (tip_frame, frames); #endif + return frames; } /* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the @@ -1561,7 +1557,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) } } - is_tooltip_frame = FRAME_TOOLTIP_P (f); + is_tooltip_frame = !NILP (Fframe_parameter (frame, Qtooltip)); /* Run `delete-frame-functions' unless FORCE is `noelisp' or frame is a tooltip. FORCE is set to `noelisp' when handling @@ -4904,6 +4900,7 @@ syms_of_frame (void) DEFSYM (Qgeometry, "geometry"); DEFSYM (Qicon_left, "icon-left"); DEFSYM (Qicon_top, "icon-top"); + DEFSYM (Qtooltip, "tooltip"); DEFSYM (Quser_position, "user-position"); DEFSYM (Quser_size, "user-size"); DEFSYM (Qwindow_id, "window-id"); @@ -5025,8 +5022,6 @@ syms_of_frame (void) DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars"); DEFSYM (Qvisibility, "visibility"); DEFSYM (Qwait_for_wm, "wait-for-wm"); - DEFSYM (Qtooltip_timer, "tooltip-timer"); - DEFSYM (Qtooltip_parameters, "tooltip-parameters"); { int i; diff --git a/src/frame.h b/src/frame.h index 635a5ed..5e3ee68 100644 --- a/src/frame.h +++ b/src/frame.h @@ -309,9 +309,6 @@ struct frame ENUM_BF (output_method) output_method : 3; #ifdef HAVE_WINDOW_SYSTEM - /* True if this frame is a tooltip frame. */ - bool_bf tooltip : 1; - /* See FULLSCREEN_ enum on top. */ ENUM_BF (fullscreen_type) want_fullscreen : 4; @@ -864,9 +861,6 @@ default_pixels_per_inch_y (void) #define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) \ ((f)->vertical_scroll_bar_type == vertical_scroll_bar_right) -/* Whether F is a tooltip frame. */ -#define FRAME_TOOLTIP_P(f) ((f)->tooltip) - #else /* not HAVE_WINDOW_SYSTEM */ /* If there is no window system, there are no scroll bars. */ @@ -875,9 +869,6 @@ default_pixels_per_inch_y (void) #define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT(f) ((void) f, 0) #define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) f, 0) -/* If there is no window system, there are no tooltips. */ -#define FRAME_TOOLTIP_P(f) ((void) f, 0) - #endif /* HAVE_WINDOW_SYSTEM */ /* Whether horizontal scroll bars are currently enabled for frame F. */ diff --git a/src/gtkutil.c b/src/gtkutil.c index e08a4b5..88e6d30 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -731,23 +731,14 @@ xg_show_tooltip (struct frame *f, int root_x, int root_y) bool xg_hide_tooltip (struct frame *f) { + bool ret = 0; #ifdef USE_GTK_TOOLTIP - struct x_output *x = FRAME_X_OUTPUT (f); - - if (x->ttip_window) + if (f->output_data.x->ttip_window) { GtkWindow *win = f->output_data.x->ttip_window; - block_input (); gtk_widget_hide (GTK_WIDGET (win)); - /* Cancel call to xg_hide_tip. */ - if (x->ttip_timeout != 0) - { - g_source_remove (x->ttip_timeout); - x->ttip_timeout = 0; - } - if (g_object_get_data (G_OBJECT (win), "restore-tt")) { GdkWindow *gwin = gtk_widget_get_window (GTK_WIDGET (win)); @@ -756,21 +747,11 @@ xg_hide_tooltip (struct frame *f) g_object_set (settings, "gtk-enable-tooltips", TRUE, NULL); } unblock_input (); - return 1; - } -#endif - return 0; -} -/* One-shot timeout handler attached to GTK event loop in Fx_show_tip. */ - -gboolean -xg_hide_tip (gpointer data) -{ -#ifdef USE_GTK_TOOLTIP - xg_hide_tooltip ((struct frame *) data); + ret = 1; + } #endif - return FALSE; + return ret; } diff --git a/src/gtkutil.h b/src/gtkutil.h index d4dc295..8840fe7 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -178,7 +178,6 @@ extern bool xg_prepare_tooltip (struct frame *f, int *height); extern void xg_show_tooltip (struct frame *f, int root_x, int root_y); extern bool xg_hide_tooltip (struct frame *f); -extern gboolean xg_hide_tip (gpointer data); #ifdef USE_CAIRO extern void xg_page_setup_dialog (void); diff --git a/src/menu.c b/src/menu.c index 675caff..90bb19a 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1400,12 +1400,7 @@ no quit occurs and `x-popup-menu' returns nil. */) #ifdef HAVE_WINDOW_SYSTEM /* Hide a previous tip, if any. */ if (!FRAME_TERMCAP_P (f)) - { - Lisp_Object frame; - - XSETFRAME (frame, f); - Fx_hide_tip (frame); - } + Fx_hide_tip (); #endif #ifdef HAVE_NTGUI /* FIXME: Is it really w32-specific? --Stef */ diff --git a/src/nsfns.m b/src/nsfns.m index a017be5..051e509 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -2658,6 +2658,10 @@ and GNUstep implementations ("distributor-specific release return make_number (1 << min (dpyinfo->n_planes, 24)); } + +/* Unused dummy def needed for compatibility. */ +Lisp_Object tip_frame; + /* TODO: move to xdisp or similar */ static void compute_tip_xy (struct frame *f, diff --git a/src/w32fns.c b/src/w32fns.c index f5e5b33..d6b54d1 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -343,6 +343,7 @@ x_window_to_frame (struct w32_display_info *dpyinfo, HWND wdesc) static Lisp_Object unwind_create_frame (Lisp_Object); +static void unwind_create_tip_frame (Lisp_Object); static void my_create_window (struct frame *); static void my_create_tip_window (struct frame *); @@ -5067,7 +5068,6 @@ static void my_create_tip_window (struct frame *f) { RECT rect; - Window tip_window; rect.left = rect.top = 0; rect.right = FRAME_PIXEL_WIDTH (f); @@ -5215,8 +5215,9 @@ x_make_gc (struct frame *f) } -/* Handler for signals raised during x_create_frame. - FRAME is the frame which is partially constructed. */ +/* Handler for signals raised during x_create_frame and + x_create_tip_frame. FRAME is the frame which is partially + constructed. */ static Lisp_Object unwind_create_frame (Lisp_Object frame) @@ -5990,7 +5991,7 @@ w32_display_monitor_attributes_list (void) { struct frame *f = XFRAME (frame); - if (FRAME_W32_P (f) && !FRAME_TOOLTIP_P (f)) + if (FRAME_W32_P (f) && !EQ (frame, tip_frame)) { HMONITOR monitor = monitor_from_window_fn (FRAME_W32_WINDOW (f), @@ -6077,7 +6078,7 @@ w32_display_monitor_attributes_list_fallback (struct w32_display_info *dpyinfo) { struct frame *f = XFRAME (frame); - if (FRAME_W32_P (f) && FRAME_TOOLTIP_P (f)) + if (FRAME_W32_P (f) && !EQ (frame, tip_frame)) frames = Fcons (frame, frames); } attributes = Fcons (Fcons (Qframes, frames), attributes); @@ -6480,6 +6481,39 @@ no value of TYPE (always string in the MS Windows case). */) Tool tips ***********************************************************************/ +static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, + Lisp_Object, int, int, int *, int *); + +/* The frame of a currently visible tooltip. */ + +Lisp_Object tip_frame; + +/* If non-nil, a timer started that hides the last tooltip when it + fires. */ + +Lisp_Object tip_timer; +Window tip_window; + +/* If non-nil, a vector of 3 elements containing the last args + with which x-show-tip was called. See there. */ + +Lisp_Object last_show_tip_args; + + +static void +unwind_create_tip_frame (Lisp_Object frame) +{ + Lisp_Object deleted; + + deleted = unwind_create_frame (frame); + if (EQ (deleted, Qt)) + { + tip_window = NULL; + tip_frame = Qnil; + } +} + + /* Create a frame for a tooltip on the display described by DPYINFO. PARMS is a list of frame parameters. Value is the frame. @@ -6524,7 +6558,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) f->wants_modeline = false; XSETFRAME (frame, f); - record_unwind_protect (do_unwind_create_frame, frame); + record_unwind_protect (unwind_create_tip_frame, frame); /* By setting the output method, we're essentially saying that the frame is live, as per FRAME_LIVE_P. If we get a signal @@ -6536,7 +6570,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) FRAME_FONTSET (f) = -1; fset_icon_name (f, Qnil); - f->tooltip = true; #ifdef GLYPH_DEBUG image_cache_refcount = @@ -6645,7 +6678,11 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) height = FRAME_LINES (f); SET_FRAME_COLS (f, 0); SET_FRAME_LINES (f, 0); - change_frame_size (f, width, height, true, false, false, false); + adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f), + height * FRAME_LINE_HEIGHT (f), 0, true, Qtip_frame); + /* Add `tooltip' frame parameter's default value. */ + if (NILP (Fframe_parameter (frame, Qtooltip))) + Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil)); /* Set up faces after all frame parameters are known. This call also merges in face attributes specified for new frames. @@ -6673,9 +6710,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) f->no_split = true; - /* Now this is an official tooltip frame on this display. */ - dpyinfo->w32_tooltip_frame = f; - /* Now that the frame is official, it counts as a reference to its display. */ FRAME_DISPLAY_INFO (f)->reference_count++; @@ -6794,39 +6828,46 @@ compute_tip_xy (struct frame *f, *root_x = min_x; } -/* Hide tooltip frame F and delete it if DELETE is true. */ - +/* Hide tooltip. Delete its frame if DELETE is true. */ static Lisp_Object -x_hide_tip (struct frame *f, bool delete) +x_hide_tip (bool delete) { - if (f) + if (!NILP (tip_timer)) { - Lisp_Object frame, timer; + call1 (Qcancel_timer, tip_timer); + tip_timer = Qnil; + } - XSETFRAME (frame, f); - timer = Fframe_parameter (frame, Qtooltip_timer); + if (NILP (tip_frame) + || (!delete && FRAMEP (tip_frame) + && !FRAME_VISIBLE_P (XFRAME (tip_frame)))) + return Qnil; + else + { + ptrdiff_t count; + Lisp_Object was_open = Qnil; - if (!NILP (timer)) - call1 (Qcancel_timer, timer); + count = SPECPDL_INDEX (); + specbind (Qinhibit_redisplay, Qt); + specbind (Qinhibit_quit, Qt); - if (!delete && !FRAME_VISIBLE_P (f)) - return Qnil; - else + if (FRAMEP (tip_frame)) { - ptrdiff_t count = SPECPDL_INDEX (); - - specbind (Qinhibit_redisplay, Qt); - specbind (Qinhibit_quit, Qt); - if (delete) - delete_frame (frame, Qnil); + { + delete_frame (tip_frame, Qnil); + tip_frame = Qnil; + } else - x_make_frame_invisible (f); + x_make_frame_invisible (XFRAME (tip_frame)); - return unbind_to (count, Qt); + was_open = Qt; } + else + tip_frame = Qnil; + + return unbind_to (count, was_open); } - return Qnil; } @@ -6860,8 +6901,7 @@ with offset DY added (default is -10). A tooltip's maximum size is specified by `x-max-tooltip-size'. Text larger than the specified size is clipped. */) - (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, - Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) + (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) { struct frame *tip_f; struct window *w; @@ -6872,7 +6912,7 @@ Text larger than the specified size is clipped. */) int old_windows_or_buffers_changed = windows_or_buffers_changed; ptrdiff_t count = SPECPDL_INDEX (); ptrdiff_t count_1; - Lisp_Object window, size, tip_frame, parameters; + Lisp_Object window, size; AUTO_STRING (tip, " *tip*"); specbind (Qinhibit_redisplay, Qt); @@ -6894,22 +6934,14 @@ Text larger than the specified size is clipped. */) else CHECK_NUMBER (dy); - parameters = Fframe_parameter (frame, Qtooltip_parameters); - if (NILP (parameters)) - parameters = Fmake_vector (make_number (3), Qnil); + if (NILP (last_show_tip_args)) + last_show_tip_args = Fmake_vector (make_number (3), Qnil); - /* Look at current tooltip frame, if any. */ - tip_f = FRAME_DISPLAY_INFO (XFRAME (frame))->w32_tooltip_frame; - if (tip_f) - XSETFRAME (tip_frame, tip_f); - else - tip_frame = Qnil; - - if (tip_f && FRAME_LIVE_P (tip_f)) + if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) { - Lisp_Object last_string = AREF (parameters, 0); - Lisp_Object last_frame = AREF (parameters, 1); - Lisp_Object last_parms = AREF (parameters, 2); + Lisp_Object last_string = AREF (last_show_tip_args, 0); + Lisp_Object last_frame = AREF (last_show_tip_args, 1); + Lisp_Object last_parms = AREF (last_show_tip_args, 2); if (FRAME_VISIBLE_P (XFRAME (tip_frame)) && EQ (frame, last_frame) @@ -6917,10 +6949,14 @@ Text larger than the specified size is clipped. */) && !NILP (Fequal (last_parms, parms))) { /* Only DX and DY have changed. */ - Lisp_Object timer = Fframe_parameter (tip_frame, Qtooltip_timer); + tip_f = XFRAME (tip_frame); + if (!NILP (tip_timer)) + { + Lisp_Object timer = tip_timer; - if (!NILP (timer)) - call1 (Qcancel_timer, timer); + tip_timer = Qnil; + call1 (Qcancel_timer, timer); + } block_input (); compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f), @@ -6990,22 +7026,17 @@ Text larger than the specified size is clipped. */) } } - x_hide_tip (tip_f, delete); + x_hide_tip (delete); } else - x_hide_tip (tip_f, true); + x_hide_tip (true); } else - x_hide_tip (tip_f, true); + x_hide_tip (true); - /* Update tooltip parameters. */ - { - AUTO_FRAME_ARG (arg, Qtooltip_parameters, parameters); - ASET (parameters, 0, string); - ASET (parameters, 1, frame); - ASET (parameters, 2, parms); - Fmodify_frame_parameters (frame, arg); - } + ASET (last_show_tip_args, 0, string); + ASET (last_show_tip_args, 1, frame); + ASET (last_show_tip_args, 2, parms); /* Block input until the tip has been fully drawn, to avoid crashes when drawing tips in menus. */ @@ -7025,8 +7056,11 @@ Text larger than the specified size is clipped. */) if (NILP (Fassq (Qbackground_color, parms))) parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), parms); - if (NILP (tip_frame - = x_create_tip_frame (FRAME_DISPLAY_INFO (XFRAME (frame)), parms))) + + /* Create a frame for the tooltip, and record it in the global + variable tip_frame. */ + struct frame *f; /* The value is unused. */ + if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms))) { /* Creating the tip frame failed. */ unblock_input (); @@ -7130,47 +7164,20 @@ Text larger than the specified size is clipped. */) windows_or_buffers_changed = old_windows_or_buffers_changed; start_timer: - { - /* Let the tip disappear after timeout seconds. */ - AUTO_FRAME_ARG (arg, Qtooltip_timer, - call3 (intern ("run-at-time"), timeout, - Qnil, intern ("x-hide-tip"))); - Fmodify_frame_parameters (tip_frame, arg); - } + /* Let the tip disappear after timeout seconds. */ + tip_timer = call3 (intern ("run-at-time"), timeout, Qnil, + intern ("x-hide-tip")); + return unbind_to (count, Qnil); } -DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 1, 0, +DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0, doc: /* Hide the current tooltip window, if there is any. -Optional FRAME is the frame to hide tooltip on. Value is t if tooltip was open, nil otherwise. */) - (Lisp_Object frame) + (void) { - Lisp_Object obj = Qnil; - - if (NILP (frame)) - { - struct w32_display_info *dpyinfo; - - for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) - if (dpyinfo->w32_tooltip_frame) - if (!NILP (x_hide_tip (dpyinfo->w32_tooltip_frame, - !tooltip_reuse_hidden_frame))) - obj = Qt; - } - else - { - struct frame *f; - - CHECK_FRAME (frame); - f = XFRAME (frame); - if (FRAME_DISPLAY_INFO (f) - && FRAME_DISPLAY_INFO (f)->w32_tooltip_frame) - obj = x_hide_tip (FRAME_DISPLAY_INFO (f)->w32_tooltip_frame, - !tooltip_reuse_hidden_frame); - } - return obj; + return x_hide_tip (!tooltip_reuse_hidden_frame); } /*********************************************************************** @@ -9773,6 +9780,7 @@ syms_of_w32fns (void) DEFSYM (Qworkarea, "workarea"); DEFSYM (Qmm_size, "mm-size"); DEFSYM (Qframes, "frames"); + DEFSYM (Qtip_frame, "tip-frame"); DEFSYM (Qassq_delete_all, "assq-delete-all"); DEFSYM (Qunicode_sip, "unicode-sip"); #if defined WINDOWSNT && !defined HAVE_DBUS @@ -10158,6 +10166,13 @@ tip frame. */); defsubr (&Sset_message_beep); defsubr (&Sx_show_tip); defsubr (&Sx_hide_tip); + tip_timer = Qnil; + staticpro (&tip_timer); + tip_frame = Qnil; + staticpro (&tip_frame); + + last_show_tip_args = Qnil; + staticpro (&last_show_tip_args); defsubr (&Sx_file_dialog); #ifdef WINDOWSNT diff --git a/src/w32term.c b/src/w32term.c index 8c2fdaf..5a11e2a 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -5024,10 +5024,11 @@ w32_read_socket (struct terminal *terminal, /* wParam non-zero means Window is about to be shown, 0 means about to be hidden. */ /* Redo the mouse-highlight after the tooltip has gone. */ - if (!msg.msg.wParam - && dpyinfo->w32_tooltip_frame - && FRAME_W32_WINDOW (dpyinfo->w32_tooltip_frame) == msg.msg.hwnd) - x_redo_mouse_highlight (dpyinfo); + if (!msg.msg.wParam && msg.msg.hwnd == tip_window) + { + tip_window = NULL; + x_redo_mouse_highlight (dpyinfo); + } /* If window has been obscured or exposed by another window being maximized or minimized/restored, then recheck @@ -5393,7 +5394,7 @@ w32_read_socket (struct terminal *terminal, struct frame *f = XFRAME (frame); /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED below. */ - if (FRAME_TOOLTIP_P (f)) + if (EQ (frame, tip_frame)) continue; /* Check "visible" frames and mark each as obscured or not. @@ -5870,7 +5871,7 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) /* Don't change the size of a tip frame; there's no point in doing it because it's done in Fx_show_tip, and it leads to problems because the tip frame has no widget. */ - if (!FRAME_TOOLTIP_P (f)) + if (NILP (tip_frame) || XFRAME (tip_frame) != f) adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, false, Qfont); @@ -6568,8 +6569,6 @@ x_free_frame_resources (struct frame *f) dpyinfo->w32_focus_event_frame = 0; if (f == dpyinfo->x_highlight_frame) dpyinfo->x_highlight_frame = 0; - if (f == dpyinfo->w32_tooltip_frame) - dpyinfo->w32_tooltip_frame = 0; if (f == hlinfo->mouse_face_mouse_frame) reset_mouse_highlight (hlinfo); diff --git a/src/w32term.h b/src/w32term.h index 3934e85..3204770 100644 --- a/src/w32term.h +++ b/src/w32term.h @@ -186,9 +186,6 @@ struct w32_display_info /* The frame waiting to be auto-raised in w32_read_socket. */ struct frame *w32_pending_autoraise_frame; - /* Tooltip frame on this display. */ - struct frame *w32_tooltip_frame; - /* The frame where the mouse was last time we reported a mouse event. */ struct frame *last_mouse_frame; diff --git a/src/xdisp.c b/src/xdisp.c index b8dcdce..14d6f8f 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2841,7 +2841,11 @@ init_iterator (struct it *it, struct window *w, frames when the fringes are turned off. But leave the dimensions zero for tooltip frames, as these glyphs look ugly there and also sabotage calculations of tooltip dimensions in x-show-tip. */ - if (!FRAME_TOOLTIP_P (it->f)) +#ifdef HAVE_WINDOW_SYSTEM + if (!(FRAME_WINDOW_P (it->f) + && FRAMEP (tip_frame) + && it->f == XFRAME (tip_frame))) +#endif { if (it->line_wrap == TRUNCATE) { @@ -11709,7 +11713,7 @@ x_consider_frame_title (Lisp_Object frame) if ((FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name) - && !FRAME_TOOLTIP_P (f)) + && NILP (Fframe_parameter (frame, Qtooltip))) { /* Do we have more than one visible frame on this X display? */ Lisp_Object tail, other_frame, fmt; @@ -11726,7 +11730,7 @@ x_consider_frame_title (Lisp_Object frame) if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f) && !FRAME_MINIBUF_ONLY_P (tf) - && !FRAME_TOOLTIP_P (tf) + && !EQ (other_frame, tip_frame) && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf))) break; } @@ -11789,6 +11793,13 @@ prepare_menu_bars (void) { bool all_windows = windows_or_buffers_changed || update_mode_lines; bool some_windows = REDISPLAY_SOME_P (); + Lisp_Object tooltip_frame; + +#ifdef HAVE_WINDOW_SYSTEM + tooltip_frame = tip_frame; +#else + tooltip_frame = Qnil; +#endif if (FUNCTIONP (Vpre_redisplay_function)) { @@ -11829,7 +11840,7 @@ prepare_menu_bars (void) && !XBUFFER (w->contents)->text->redisplay) continue; - if (!FRAME_TOOLTIP_P (f) + if (!EQ (frame, tooltip_frame) && (FRAME_ICONIFIED_P (f) || FRAME_VISIBLE_P (f) == 1 /* Exclude TTY frames that are obscured because they @@ -11866,7 +11877,7 @@ prepare_menu_bars (void) struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); /* Ignore tooltip frame. */ - if (FRAME_TOOLTIP_P (f)) + if (EQ (frame, tooltip_frame)) continue; if (some_windows diff --git a/src/xfns.c b/src/xfns.c index 16dbcfd..798dc49 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -4151,7 +4151,7 @@ x_make_monitor_attribute_list (struct MonitorInfo *monitors, struct frame *f = XFRAME (frame); if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo - && !FRAME_TOOLTIP_P (f)) + && !EQ (frame, tip_frame)) { int i = x_get_monitor_for_frame (f, monitors, n_monitors); ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i))); @@ -4447,7 +4447,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */) struct frame *f = XFRAME (frame); if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo - && !FRAME_TOOLTIP_P (f)) + && !EQ (frame, tip_frame)) { GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); @@ -5312,6 +5312,39 @@ no value of TYPE (always string in the MS Windows case). */) Tool tips ***********************************************************************/ +static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, + Lisp_Object, int, int, int *, int *); + +/* The frame of a currently visible tooltip. */ + +Lisp_Object tip_frame; + +/* If non-nil, a timer started that hides the last tooltip when it + fires. */ + +static Lisp_Object tip_timer; +Window tip_window; + +/* If non-nil, a vector of 3 elements containing the last args + with which x-show-tip was called. See there. */ + +static Lisp_Object last_show_tip_args; + + +static void +unwind_create_tip_frame (Lisp_Object frame) +{ + Lisp_Object deleted; + + deleted = unwind_create_frame (frame); + if (EQ (deleted, Qt)) + { + tip_window = None; + tip_frame = Qnil; + } +} + + /* Create a frame for a tooltip on the display described by DPYINFO. PARMS is a list of frame parameters. TEXT is the string to display in the tip frame. Value is the frame. @@ -5348,7 +5381,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) f = make_frame (false); f->wants_modeline = false; XSETFRAME (frame, f); - record_unwind_protect (do_unwind_create_frame, frame); + record_unwind_protect (unwind_create_tip_frame, frame); f->terminal = dpyinfo->terminal; @@ -5369,7 +5402,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) f->output_data.x->white_relief.pixel = -1; f->output_data.x->black_relief.pixel = -1; - f->tooltip = true; fset_icon_name (f, Qnil); FRAME_DISPLAY_INFO (f) = dpyinfo; f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; @@ -5513,7 +5545,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) = f->output_data.x->text_cursor; /* Arrange for getting MapNotify and UnmapNotify events. */ attrs.event_mask = StructureNotifyMask; - FRAME_X_WINDOW (f) + tip_window + = FRAME_X_WINDOW (f) = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window, /* x, y, width, height */ @@ -5522,7 +5555,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) f->border_width, CopyFromParent, InputOutput, CopyFromParent, mask, &attrs); - XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + XChangeProperty (FRAME_X_DISPLAY (f), tip_window, FRAME_DISPLAY_INFO (f)->Xatom_net_window_type, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type, 1); @@ -5549,6 +5582,13 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) SET_FRAME_LINES (f, 0); change_frame_size (f, width, height, true, false, false, false); + /* Add `tooltip' frame parameter's default value. */ + if (NILP (Fframe_parameter (frame, Qtooltip))) + { + AUTO_FRAME_ARG (arg, Qtooltip, Qt); + Fmodify_frame_parameters (frame, arg); + } + /* FIXME - can this be done in a similar way to normal frames? http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */ @@ -5593,9 +5633,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) f->no_split = true; - /* Now this is an official tooltip frame on this display. */ - dpyinfo->x_tooltip_frame = f; - /* Now that the frame will be official, it counts as a reference to its display and terminal. */ FRAME_DISPLAY_INFO (f)->reference_count++; @@ -5626,9 +5663,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) the display in *ROOT_X, and *ROOT_Y. */ static void -compute_tip_xy (struct frame *f, - Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, - int width, int height, int *root_x, int *root_y) +compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, int width, int height, int *root_x, int *root_y) { Lisp_Object left, top, right, bottom; int win_x, win_y; @@ -5724,39 +5759,56 @@ compute_tip_xy (struct frame *f, *root_x = min_x; } -/* Hide tooltip frame F and delete it if DELETE is true. */ +/* Hide tooltip. Delete its frame if DELETE is true. */ static Lisp_Object -x_hide_tip (struct frame *f, bool delete) +x_hide_tip (bool delete) { - if (f) + if (!NILP (tip_timer)) { - Lisp_Object frame, timer; - - XSETFRAME (frame, f); - timer = Fframe_parameter (frame, Qtooltip_timer); + call1 (Qcancel_timer, tip_timer); + tip_timer = Qnil; + } - if (!NILP (timer)) - call1 (Qcancel_timer, timer); - if (!delete && !FRAME_VISIBLE_P (f)) - return Qnil; - else - { - ptrdiff_t count = SPECPDL_INDEX (); + if (NILP (tip_frame) + || (!delete && FRAMEP (tip_frame) + && !FRAME_VISIBLE_P (XFRAME (tip_frame)))) + return Qnil; + else + { + ptrdiff_t count; + Lisp_Object was_open = Qnil; - specbind (Qinhibit_redisplay, Qt); - specbind (Qinhibit_quit, Qt); + count = SPECPDL_INDEX (); + specbind (Qinhibit_redisplay, Qt); + specbind (Qinhibit_quit, Qt); #ifdef USE_GTK - if (x_gtk_use_system_tooltips) - /* Should be handled by xg_hide_tooltip. */ - emacs_abort (); + { + /* When using system tooltip, tip_frame is the Emacs frame on + which the tip is shown. */ + struct frame *f = XFRAME (tip_frame); + + if (FRAME_LIVE_P (f) && xg_hide_tooltip (f)) + { + tip_frame = Qnil; + was_open = Qt; + } + } #endif + + if (FRAMEP (tip_frame)) + { if (delete) - delete_frame (frame, Qnil); + { + delete_frame (tip_frame, Qnil); + tip_frame = Qnil; + } else - x_make_frame_invisible (f); + x_make_frame_invisible (XFRAME (tip_frame)); + + was_open = Qt; #ifdef USE_LUCID /* Bloodcurdling hack alert: The Lucid menu bar widget's @@ -5764,12 +5816,12 @@ x_hide_tip (struct frame *f, bool delete) menu items is unmapped. Redisplay the menu manually... */ { Widget w; - struct frame *sf = SELECTED_FRAME (); - if (FRAME_X_P (sf) && FRAME_LIVE_P (sf)) + struct frame *f = SELECTED_FRAME (); + if (FRAME_X_P (f) && FRAME_LIVE_P (f)) { - w = sf->output_data.x->menubar_widget; + w = f->output_data.x->menubar_widget; - if (!DoesSaveUnders (FRAME_DISPLAY_INFO (sf)->screen) + if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen) && w != NULL) { block_input (); @@ -5779,10 +5831,12 @@ x_hide_tip (struct frame *f, bool delete) } } #endif /* USE_LUCID */ - return unbind_to (count, Qt); } + else + tip_frame = Qnil; + + return unbind_to (count, was_open); } - return Qnil; } DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, @@ -5815,8 +5869,7 @@ with offset DY added (default is -10). A tooltip's maximum size is specified by `x-max-tooltip-size'. Text larger than the specified size is clipped. */) - (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, - Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) + (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) { struct frame *f, *tip_f; struct window *w; @@ -5827,7 +5880,7 @@ Text larger than the specified size is clipped. */) int old_windows_or_buffers_changed = windows_or_buffers_changed; ptrdiff_t count = SPECPDL_INDEX (); ptrdiff_t count_1; - Lisp_Object window, size, tip_frame, parameters; + Lisp_Object window, size; AUTO_STRING (tip, " *tip*"); specbind (Qinhibit_redisplay, Qt); @@ -5857,8 +5910,8 @@ Text larger than the specified size is clipped. */) { bool ok; - /* Hide a previous tip on this frame, if any. */ - xg_hide_tooltip (f); + /* Hide a previous tip, if any. */ + Fx_hide_tip (); block_input (); ok = xg_prepare_tooltip (f, string, &width, &height); @@ -5866,47 +5919,37 @@ Text larger than the specified size is clipped. */) { compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y); xg_show_tooltip (f, root_x, root_y); + /* This is used in Fx_hide_tip. */ + XSETFRAME (tip_frame, f); } unblock_input (); - if (ok) - /* Schedule call to xg_hide_tip from GTK event loop - to allow the tip disappear after timeout seconds. */ - FRAME_X_OUTPUT (f)->ttip_timeout - = g_timeout_add_seconds (XINT (timeout), xg_hide_tip, (gpointer) f); - else - /* FIXME: what if not ok? */ - FRAME_X_OUTPUT (f)->ttip_timeout = 0; - return unbind_to (count, Qnil); + if (ok) goto start_timer; } #endif /* USE_GTK */ - parameters = Fframe_parameter (frame, Qtooltip_parameters); - if (NILP (parameters)) - parameters = Fmake_vector (make_number (3), Qnil); + if (NILP (last_show_tip_args)) + last_show_tip_args = Fmake_vector (make_number (3), Qnil); - /* Look at current tooltip frame, if any. */ - tip_f = FRAME_DISPLAY_INFO (f)->x_tooltip_frame; - if (tip_f) - XSETFRAME (tip_frame, tip_f); - else - tip_frame = Qnil; - - if (tip_f && FRAME_LIVE_P (tip_f)) + if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) { - Lisp_Object last_string = AREF (parameters, 0); - Lisp_Object last_frame = AREF (parameters, 1); - Lisp_Object last_parms = AREF (parameters, 2); + Lisp_Object last_string = AREF (last_show_tip_args, 0); + Lisp_Object last_frame = AREF (last_show_tip_args, 1); + Lisp_Object last_parms = AREF (last_show_tip_args, 2); - if (FRAME_VISIBLE_P (tip_f) + if (FRAME_VISIBLE_P (XFRAME (tip_frame)) && EQ (frame, last_frame) && !NILP (Fequal_including_properties (last_string, string)) && !NILP (Fequal (last_parms, parms))) { /* Only DX and DY have changed. */ - Lisp_Object timer = Fframe_parameter (tip_frame, Qtooltip_timer); + tip_f = XFRAME (tip_frame); + if (!NILP (tip_timer)) + { + Lisp_Object timer = tip_timer; - if (!NILP (timer)) - call1 (Qcancel_timer, timer); + tip_timer = Qnil; + call1 (Qcancel_timer, timer); + } block_input (); compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f), @@ -5966,22 +6009,17 @@ Text larger than the specified size is clipped. */) } } - x_hide_tip (tip_f, delete); + x_hide_tip (delete); } else - x_hide_tip (tip_f, true); + x_hide_tip (true); } else - x_hide_tip (tip_f, true); + x_hide_tip (true); - /* Update tooltip parameters. */ - { - AUTO_FRAME_ARG (arg, Qtooltip_parameters, parameters); - ASET (parameters, 0, string); - ASET (parameters, 1, frame); - ASET (parameters, 2, parms); - Fmodify_frame_parameters (frame, arg); - } + ASET (last_show_tip_args, 0, string); + ASET (last_show_tip_args, 1, frame); + ASET (last_show_tip_args, 2, parms); if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame))) { @@ -5997,6 +6035,9 @@ Text larger than the specified size is clipped. */) if (NILP (Fassq (Qbackground_color, parms))) parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), parms); + + /* Create a frame for the tooltip, and record it in the global + variable tip_frame. */ if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms))) /* Creating the tip frame failed. */ return unbind_to (count, Qnil); @@ -6074,69 +6115,20 @@ Text larger than the specified size is clipped. */) windows_or_buffers_changed = old_windows_or_buffers_changed; start_timer: - { - /* Let the tip disappear after timeout seconds. */ - AUTO_FRAME_ARG (arg, Qtooltip_timer, - call3 (intern ("run-at-time"), timeout, - Qnil, intern ("x-hide-tip"))); - Fmodify_frame_parameters (tip_frame, arg); - } + /* Let the tip disappear after timeout seconds. */ + tip_timer = call3 (intern ("run-at-time"), timeout, Qnil, + intern ("x-hide-tip")); + return unbind_to (count, Qnil); } -DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 1, 0, + +DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0, doc: /* Hide the current tooltip window, if there is any. -Optional FRAME is the frame to hide tooltip on. Value is t if tooltip was open, nil otherwise. */) - (Lisp_Object frame) + (void) { - Lisp_Object obj = Qnil; - -#ifdef USE_GTK - if (x_gtk_use_system_tooltips) - { - if (NILP (frame)) - { - Lisp_Object tail, frame; - - FOR_EACH_FRAME (tail, frame) - if (FRAME_X_P (XFRAME (frame))) - if (xg_hide_tooltip (XFRAME (frame))) - obj = Qt; - } - else - { - CHECK_FRAME (frame); - if (FRAME_X_P (XFRAME (frame))) - if (xg_hide_tooltip (XFRAME (frame))) - obj = Qt; - } - return obj; - } -#endif /* USE_GTK */ - - if (NILP (frame)) - { - struct x_display_info *dpyinfo; - - for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) - if (dpyinfo->x_tooltip_frame) - if (!NILP (x_hide_tip (dpyinfo->x_tooltip_frame, - !tooltip_reuse_hidden_frame))) - obj = Qt; - } - else - { - struct frame *f; - - CHECK_FRAME (frame); - f = XFRAME (frame); - if (FRAME_DISPLAY_INFO (f) - && FRAME_DISPLAY_INFO (f)->x_tooltip_frame) - obj = x_hide_tip (FRAME_DISPLAY_INFO (f)->x_tooltip_frame, - !tooltip_reuse_hidden_frame); - } - return obj; + return x_hide_tip (!tooltip_reuse_hidden_frame); } @@ -7005,6 +6997,13 @@ When using Gtk+ tooltips, the tooltip face is not used. */); defsubr (&Sx_show_tip); defsubr (&Sx_hide_tip); + tip_timer = Qnil; + staticpro (&tip_timer); + tip_frame = Qnil; + staticpro (&tip_frame); + + last_show_tip_args = Qnil; + staticpro (&last_show_tip_args); defsubr (&Sx_uses_old_gtk_dialog); #if defined (USE_MOTIF) || defined (USE_GTK) diff --git a/src/xterm.c b/src/xterm.c index ada1160..cd1d712 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -987,7 +987,8 @@ static void x_update_begin (struct frame *f) { #ifdef USE_CAIRO - if (FRAME_TOOLTIP_P (f) && ! FRAME_VISIBLE_P (f)) + if (! NILP (tip_frame) && XFRAME (tip_frame) == f + && ! FRAME_VISIBLE_P (f)) return; if (! FRAME_CR_SURFACE (f)) @@ -7838,9 +7839,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, case UnmapNotify: /* Redo the mouse-highlight after the tooltip has gone. */ - if (dpyinfo->x_tooltip_frame - && FRAME_X_WINDOW (dpyinfo->x_tooltip_frame) == event->xunmap.window) - x_redo_mouse_highlight (dpyinfo); + if (event->xunmap.window == tip_window) + { + tip_window = 0; + x_redo_mouse_highlight (dpyinfo); + } f = x_top_window_to_frame (dpyinfo, event->xunmap.window); if (f) /* F may no longer exist if @@ -8430,7 +8433,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #ifdef USE_X_TOOLKIT /* Tip frames are pure X window, set size for them. */ - if (FRAME_TOOLTIP_P (f)) + if (! NILP (tip_frame) && XFRAME (tip_frame) == f) { if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width) @@ -9611,7 +9614,7 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) /* Don't change the size of a tip frame; there's no point in doing it because it's done in Fx_show_tip, and it leads to problems because the tip frame has no widget. */ - if (!FRAME_TOOLTIP_P (f)) + if (NILP (tip_frame) || XFRAME (tip_frame) != f) { adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, @@ -10686,7 +10689,7 @@ x_set_window_size (struct frame *f, bool change_gravity, /* The following breaks our calculations. If it's really needed, think of something else. */ #if false - if (!FRAME_TOOLTIP_P (f)) + if (NILP (tip_frame) || XFRAME (tip_frame) != f) { int text_width, text_height; @@ -11337,8 +11340,6 @@ x_free_frame_resources (struct frame *f) dpyinfo->x_focus_event_frame = 0; if (f == dpyinfo->x_highlight_frame) dpyinfo->x_highlight_frame = 0; - if (f == dpyinfo->x_tooltip_frame) - dpyinfo->x_tooltip_frame = 0; if (f == hlinfo->mouse_face_mouse_frame) reset_mouse_highlight (hlinfo); diff --git a/src/xterm.h b/src/xterm.h index 1eb3e30..675a484 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -362,9 +362,6 @@ struct x_display_info /* The frame waiting to be auto-raised in XTread_socket. */ struct frame *x_pending_autoraise_frame; - /* Tooltip frame on this display. */ - struct frame *x_tooltip_frame; - /* The frame where the mouse was last time we reported a ButtonPress event. */ struct frame *last_mouse_frame; @@ -578,7 +575,6 @@ struct x_output GtkTooltip *ttip_widget; GtkWidget *ttip_lbl; GtkWindow *ttip_window; - guint ttip_timeout; #endif /* USE_GTK_TOOLTIP */ #endif /* USE_GTK */ commit 9c8c3a5478db6ff4b245e9128cbf24bd722ab1d6 Author: Stefan Monnier Date: Tue Jul 12 12:05:01 2016 -0400 * lisp/emacs-lisp/cl-macs.el (cl--prog): New function (cl-prog, cl-prog*): New macros. diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index d2c90c2..56170e6 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -1808,6 +1808,27 @@ Labels have lexical scope and dynamic extent." `(throw ',catch-tag ',label)))) ,@macroexpand-all-environment))))) +(defun cl--prog (binder bindings body) + (let (decls) + (while (eq 'declare (car-safe (car body))) + (push (pop body) decls)) + `(cl-block nil + (,binder ,bindings + ,@(nreverse decls) + (cl-tagbody . ,body))))) + +;;;###autoload +(defmacro cl-prog (bindings &rest body) + "Run BODY like a `cl-tagbody' after setting up the BINDINGS. +Shorthand for (cl-block nil (let BINDINGS (cl-tagbody BODY)))" + (cl--prog 'let bindings body)) + +;;;###autoload +(defmacro cl-prog* (bindings &rest body) + "Run BODY like a `cl-tagbody' after setting up the BINDINGS. +Shorthand for (cl-block nil (let* BINDINGS (cl-tagbody BODY)))" + (cl--prog 'let* bindings body)) + ;;;###autoload (defmacro cl-do-symbols (spec &rest body) "Loop over all symbols. commit 3698c4e475fb59730626af5d001599785ef5ef9e Author: Stefan Monnier Date: Tue Jul 12 12:04:01 2016 -0400 * cl-generic.el (cl-defmethod): Make docstring dynamic * lisp/emacs-lisp/cl-generic.el (cl-defmethod): Make docstring dynamic. (cl--generic-make-defmethod-docstring): New function for that. (cl-defmethod, cl-generic-generalizers): Tweak docstrings accordingly. (cl-generic-define-method, cl--generic-describe): Change `load-history' format of cl-defmethods, so as not to confused methods with equal specializers but different qualifiers. * lisp/emacs-lisp/eieio-core.el (cl-generic-generalizers): Provide docstrings. diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 0144daf..b7c8395 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -353,6 +353,26 @@ the specializer used will be the one returned by BODY." ,nbody)))))) (f (error "Unexpected macroexpansion result: %S" f)))))) +(put 'cl-defmethod 'function-documentation + '(cl--generic-make-defmethod-docstring)) + +(defun cl--generic-make-defmethod-docstring () + ;; FIXME: Copy&paste from pcase--make-docstring. + (let* ((main (documentation (symbol-function 'cl-defmethod) 'raw)) + (ud (help-split-fundoc main 'cl-defmethod))) + ;; So that eg emacs -Q -l cl-lib --eval "(documentation 'pcase)" works, + ;; where cl-lib is anything using pcase-defmacro. + (require 'help-fns) + (with-temp-buffer + (insert (or (cdr ud) main)) + (insert "\n\n\tCurrently supported forms for TYPE:\n\n") + (dolist (method (reverse (cl--generic-method-table + (cl--generic 'cl-generic-generalizers)))) + (let* ((info (cl--generic-method-info method))) + (when (nth 2 info) + (insert (nth 2 info) "\n\n")))) + (let ((combined-doc (buffer-string))) + (if ud (help-add-fundoc-usage combined-doc (car ud)) combined-doc))))) ;;;###autoload (defmacro cl-defmethod (name args &rest body) @@ -370,15 +390,17 @@ modifies how the method is combined with other methods, including: :after - Method will be called after the primary :around - Method will be called around everything else The absence of QUALIFIER means this is a \"primary\" method. +The set of acceptable qualifiers and their meaning is defined +\(and can be extended) by the methods of `cl-generic-combine-methods'. -TYPE can be one of the basic types (see the full list and their -hierarchy in `cl--generic-typeof-types'), CL struct type, or an -EIEIO class. +ARGS can also include so-called context specializers, introduced by +`&context' (which should appear right after the mandatory arguments, +before any &optional or &rest). They have the form (EXPR TYPE) where +EXPR is an Elisp expression whose value should match TYPE for the +method to be applicable. -Other than that, TYPE can also be of the form `(eql VAL)' in -which case this method will be invoked when the argument is `eql' -to VAL, or `(head VAL)', in which case the argument is required -to be a cons with VAL as its head. +The set of acceptable TYPEs (also called \"specializers\") is defined +\(and can be extended) by the various methods of `cl-generic-generalizers'. \(fn NAME [QUALIFIER] ARGS &rest [DOCSTRING] BODY)" (declare (doc-string 3) (indent 2) @@ -464,7 +486,8 @@ to be a cons with VAL as its head. (cons method mt) ;; Keep the ordering; important for methods with :extra qualifiers. (mapcar (lambda (x) (if (eq x (car me)) method x)) mt))) - (cl-pushnew `(cl-defmethod . (,(cl--generic-name generic) . ,specializers)) + (cl-pushnew `(cl-defmethod . (,(cl--generic-name generic) + ,qualifiers . ,specializers)) current-load-list :test #'equal) ;; FIXME: Try to avoid re-constructing a new function if the old one ;; is still valid (e.g. still empty method cache)? @@ -737,7 +760,7 @@ methods.") (fset 'cl-generic-combine-methods #'cl--generic-standard-method-combination)) (cl-defmethod cl-generic-generalizers (specializer) - "Support for the catch-all t specializer." + "Support for the catch-all t specializer which always matches." (if (eq specializer t) (list cl--generic-t-generalizer) (error "Unknown specializer %S" specializer))) @@ -909,8 +932,9 @@ MET-NAME is a cons (SYMBOL . SPECIALIZERS)." (let* ((info (cl--generic-method-info method))) ;; FIXME: Add hyperlinks for the types as well. (insert (format "%s%S" (nth 0 info) (nth 1 info))) - (let* ((met-name (cons function - (cl--generic-method-specializers method))) + (let* ((met-name `(,function + ,(cl--generic-method-qualifiers method) + . ,(cl--generic-method-specializers method))) (file (find-lisp-object-file-name met-name 'cl-defmethod))) (when file (insert (substitute-command-keys " in `")) @@ -994,7 +1018,8 @@ The value returned is a list of elements of the form (lambda (tag &rest _) (if (eq (car-safe tag) 'head) (list tag)))) (cl-defmethod cl-generic-generalizers :extra "head" (specializer) - "Support for the `(head VAL)' specializers." + "Support for (head VAL) specializers. +These match if the argument is a cons cell whose car is `eql' to VAL." ;; We have to implement `head' here using the :extra qualifier, ;; since we can't use the `head' specializer to implement itself. (if (not (eq (car-safe specializer) 'head)) @@ -1014,7 +1039,8 @@ The value returned is a list of elements of the form (lambda (tag &rest _) (if (eq (car-safe tag) 'eql) (list tag)))) (cl-defmethod cl-generic-generalizers ((specializer (head eql))) - "Support for the `(eql VAL)' specializers." + "Support for (eql VAL) specializers. +These match if the argument is `eql' to VAL." (puthash (cadr specializer) specializer cl--generic-eql-used) (list cl--generic-eql-generalizer)) @@ -1069,7 +1095,7 @@ The value returned is a list of elements of the form #'cl--generic-struct-specializers) (cl-defmethod cl-generic-generalizers :extra "cl-struct" (type) - "Support for dispatch on cl-struct types." + "Support for dispatch on types defined by `cl-defstruct'." (or (when (symbolp type) ;; Use the "cl--struct-class*" (inlinable) functions/macros rather than @@ -1113,7 +1139,8 @@ The value returned is a list of elements of the form (and (symbolp tag) (assq tag cl--generic-typeof-types)))) (cl-defmethod cl-generic-generalizers :extra "typeof" (type) - "Support for dispatch on builtin types." + "Support for dispatch on builtin types. +See the full list and their hierarchy in `cl--generic-typeof-types'." ;; FIXME: Add support for other types accepted by `cl-typep' such ;; as `character', `atom', `face', `function', ... (or @@ -1151,7 +1178,8 @@ The value returned is a list of elements of the form #'cl--generic-derived-specializers) (cl-defmethod cl-generic-generalizers ((_specializer (head derived-mode))) - "Support for the `(derived-mode MODE)' specializers." + "Support for (derived-mode MODE) specializers. +Used internally for the (major-mode MODE) context specializers." (list cl--generic-derived-generalizer)) (cl-generic-define-context-rewriter major-mode (mode &rest modes) diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el index fd8ae2a..0567c87 100644 --- a/lisp/emacs-lisp/eieio-core.el +++ b/lisp/emacs-lisp/eieio-core.el @@ -1065,6 +1065,7 @@ method invocation orders of the involved classes." (eieio--class-precedence-list (symbol-value tag)))))) (cl-defmethod cl-generic-generalizers :extra "class" (specializer) + "Support for dispatch on types defined by EIEIO's `defclass'." ;; CLHS says: ;; A class must be defined before it can be used as a parameter ;; specializer in a defmethod form. @@ -1093,6 +1094,8 @@ method invocation orders of the involved classes." #'eieio--generic-subclass-specializers) (cl-defmethod cl-generic-generalizers ((_specializer (head subclass))) + "Support for (subclass CLASS) specializers. +These match if the argument is the name of a subclass of CLASS." (list eieio--generic-subclass-generalizer)) (provide 'eieio-core) commit 5155144bd4cece3bab200a0eb613ffcdef523202 Merge: 1048151 a1db933 Author: Eli Zaretskii Date: Tue Jul 12 16:19:18 2016 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit 1048151cc4bec79f7310f4f2ede309889822a6bb Author: Eli Zaretskii Date: Tue Jul 12 16:18:06 2016 +0300 Don't install keyboard hook when debugged on MS-Windows * src/w32fns.c (setup_w32_kbdhook): Don't install the keyboard hook if we are being debugged. This avoids hosing the debugger, because the hook is global, and is called in the context of the thread which installed it, and that thread is stopped when GDB has control. Reported by Fabrice Popineau . diff --git a/src/w32fns.c b/src/w32fns.c index 0eb720e..f5e5b33 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -276,6 +276,8 @@ static struct } kbdhook; typedef HWND (WINAPI *GetConsoleWindow_Proc) (void); +typedef BOOL (WINAPI *IsDebuggerPresent_Proc) (void); + /* stdin, from w32console.c */ extern HANDLE keyboard_handle; @@ -2303,6 +2305,19 @@ setup_w32_kbdhook (void) { kbdhook.hook_count++; + /* This hook gets in the way of debugging, since when Emacs stops, + its input thread stops, and there's nothing to process keyboard + events, whereas this hook is global, and is invoked in the + context of the thread that installed it. So we don't install the + hook if the process is being debugged. */ + if (w32_kbdhook_active) + { + IsDebuggerPresent_Proc is_debugger_present = (IsDebuggerPresent_Proc) + GetProcAddress (GetModuleHandle ("kernel32.dll"), "IsDebuggerPresent"); + if (is_debugger_present && is_debugger_present ()) + return; + } + /* Hooking is only available on NT architecture systems, as indicated by the w32_kbdhook_active variable. */ if (kbdhook.hook_count == 1 && w32_kbdhook_active) commit a1db933c5b68165879ada5ddf3c2585d1e7e893d Author: Alan Mackenzie Date: Tue Jul 12 13:16:02 2016 +0000 Amend CC Mode to handle big C++ raw strings correctly. Problems were caused by such a string spanning jit-lock chunks, and by a flaw in the +-500 bytes boundaries imposed for macros. * lisp/progmodes/cc-mode.el (c-extend-region-for-CPP): Check the +-500 byte macro boundaries here. (c-extend-font-lock-region-for-macros): Remove the check on the +-500 byte lower boundary. Fix the check on the upper boundary. * lisp/progmodes/cc-fonts.el (c-font-lock-raw-strings): Handle the starting point already being within a raw string. * lisp/progmodes/cc-engine.el (c-raw-string-pos) (c-depropertize-raw-strings-in-region, c-after-change-re-mark-raw-strings): Modify regexp element "\\{,16\\}" to "\\{0,16\\}" for greater compatibility with other Emacsen. diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 48b9e5e..8648bec 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -6039,7 +6039,7 @@ comment at the start of cc-engine.el for more info." (search-backward "\"" (max (- (point) 17) (point-min)) t)) (not (bobp))))) (eq (char-before) ?R) - (looking-at "\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(")) + (looking-at "\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(")) (setq open-quote-pos (point) open-paren-pos (match-end 1) id (match-string-no-properties 1)) @@ -6121,7 +6121,7 @@ comment at the start of cc-engine.el for more info." (concat "\\(" ; 1 c-anchored-cpp-prefix ; 2 "\\)\\|\\(" ; 3 - "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(" ; 4 + "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" ; 4 "\\)") finish t)) (when (save-excursion @@ -6140,7 +6140,7 @@ comment at the start of cc-engine.el for more info." (goto-char (match-end 2)) ; after the "#". (while (and (< (point) eom) (c-syntactic-re-search-forward - "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(" eom t)) + "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" eom t)) (c-depropertize-raw-string (match-string-no-properties 1) ; id (1+ (match-beginning 0)) ; open quote @@ -6275,7 +6275,7 @@ comment at the start of cc-engine.el for more info." (concat "\\(" ; 1 c-anchored-cpp-prefix ; 2 "\\)\\|\\(" ; 3 - "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(" ; 4 + "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" ; 4 "\\)") c-new-END t)) (when (save-excursion @@ -6294,7 +6294,7 @@ comment at the start of cc-engine.el for more info." (goto-char (match-end 2)) ; after the "#". (while (and (< (point) eom) (c-syntactic-re-search-forward - "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(" eom t)) + "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" eom t)) (c-propertize-raw-string-opener (match-string-no-properties 1) ; id (1+ (match-beginning 0)) ; open quote diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index dfc2c06..b45686c 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -1542,33 +1542,45 @@ casts and declarations are fontified. Used on level 2 and higher." ;; font-lock-keyword-face. It always returns NIL to inhibit this and ;; prevent a repeat invocation. See elisp/lispref page "Search-based ;; Fontification". - (while (search-forward-regexp - "R\\(\"\\)\\([^ ()\\\n\r\t]\\{,16\\}\\)(" limit t) - (when - (or (and (eobp) - (eq (c-get-char-property (1- (point)) 'face) - 'font-lock-warning-face)) - (eq (c-get-char-property (point) 'face) 'font-lock-string-face) - (and (equal (c-get-char-property (match-end 2) 'syntax-table) '(1)) - (equal (c-get-char-property (match-beginning 1) 'syntax-table) - '(1)))) - (let ((paren-prop (c-get-char-property (1- (point)) 'syntax-table))) - (if paren-prop - (progn - (c-put-font-lock-face (match-beginning 0) (match-end 0) - 'font-lock-warning-face) - (when - (and - (equal paren-prop '(15)) - (not (c-search-forward-char-property 'syntax-table '(15) limit))) - (goto-char limit))) - (c-put-font-lock-face (match-beginning 1) (match-end 2) 'default) - (when (search-forward-regexp - (concat ")\\(" (regexp-quote (match-string-no-properties 2)) - "\\)\"") - limit t) - (c-put-font-lock-face (match-beginning 1) (point) - 'default)))))) + (let* ((state (c-state-semi-pp-to-literal (point))) + (string-start (and (eq (cadr state) 'string) + (car (cddr state)))) + (raw-id (and string-start + (save-excursion + (goto-char string-start) + (and (eq (char-before) ?R) + (looking-at "\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(") + (match-string-no-properties 1)))))) + (while (< (point) limit) + (if raw-id + (progn + (if (search-forward-regexp (concat ")\\(" (regexp-quote raw-id) "\\)\"") + limit 'limit) + (c-put-font-lock-face (match-beginning 1) (point) 'default)) + (setq raw-id nil)) + + (when (search-forward-regexp + "R\\(\"\\)\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" limit 'limit) + (when + (or (and (eobp) + (eq (c-get-char-property (1- (point)) 'face) + 'font-lock-warning-face)) + (eq (c-get-char-property (point) 'face) 'font-lock-string-face) + (and (equal (c-get-char-property (match-end 2) 'syntax-table) '(1)) + (equal (c-get-char-property (match-beginning 1) 'syntax-table) + '(1)))) + (let ((paren-prop (c-get-char-property (1- (point)) 'syntax-table))) + (if paren-prop + (progn + (c-put-font-lock-face (match-beginning 0) (match-end 0) + 'font-lock-warning-face) + (when + (and + (equal paren-prop '(15)) + (not (c-search-forward-char-property 'syntax-table '(15) limit))) + (goto-char limit))) + (c-put-font-lock-face (match-beginning 1) (match-end 2) 'default) + (setq raw-id (match-string-no-properties 2))))))))) nil) (c-lang-defconst c-simple-decl-matchers diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 6711a02..04d2ed6 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -924,14 +924,16 @@ Note that the style variables are always made local to the buffer." ;; before change function. (goto-char c-new-BEG) (c-beginning-of-macro) - (setq c-new-BEG (point)) + (when (< (point) c-new-BEG) + (setq c-new-BEG (max (point) (c-determine-limit 500 c-new-BEG)))) (goto-char c-new-END) (when (c-beginning-of-macro) (c-end-of-macro) (or (eobp) (forward-char))) ; Over the terminating NL which may be marked ; with a c-cpp-delimiter category property - (setq c-new-END (point))) + (when (> (point) c-new-END) + (setq c-new-END (min (point) (c-determine-+ve-limit 500 c-new-END))))) (defun c-depropertize-new-text (beg end old-len) ;; Remove from the new text in (BEG END) any and all text properties which @@ -959,15 +961,17 @@ Note that the style variables are always made local to the buffer." ;; Point is undefined on both entry and exit to this function. The buffer ;; will have been widened on entry. ;; + ;; c-new-BEG has already been extended in `c-extend-region-for-CPP' so we + ;; don't need to repeat the exercise here. + ;; ;; This function is in the C/C++/ObjC value of `c-before-font-lock-functions'. (goto-char endd) - (if (c-beginning-of-macro) - (c-end-of-macro)) - (setq c-new-END (max endd c-new-END (point))) - ;; Determine the region, (c-new-BEG c-new-END), which will get font - ;; locked. This restricts the region should there be long macros. - (setq c-new-BEG (max c-new-BEG (c-determine-limit 500 begg)) - c-new-END (min c-new-END (c-determine-+ve-limit 500 endd)))) + (when (c-beginning-of-macro) + (c-end-of-macro) + ;; Determine the region, (c-new-BEG c-new-END), which will get font + ;; locked. This restricts the region should there be long macros. + (setq c-new-END (min (max c-new-END (point)) + (c-determine-+ve-limit 500 c-new-END))))) (defun c-neutralize-CPP-line (beg end) ;; BEG and END bound a region, typically a preprocessor line. Put a commit 2f67f8a145af8f185f644b1d094a03895a124ef1 Author: Stephen Berman Date: Tue Jul 12 10:43:24 2016 +0200 * lisp/mouse.el (mouse-select-region-move-to-beginning): Add :group. diff --git a/lisp/mouse.el b/lisp/mouse.el index 4446238..f595326 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -542,9 +542,10 @@ must be one of the symbols `header', `mode', or `vertical'." "Effect of selecting a region extending backward from double click. Nil means keep point at the position clicked (region end); non-nil means move point to beginning of region." - :version "25.2" :type '(choice (const :tag "Don't move point" nil) - (const :tag "Move point to beginning of region" t))) + (const :tag "Move point to beginning of region" t)) + :group 'mouse + :version "25.2") (defun mouse-set-point (event &optional promote-to-region) "Move point to the position clicked on with the mouse. commit 20038f8ab75dd1551412a43cd58520c483c22921 Author: Dmitry Antipov Date: Tue Jul 12 09:16:26 2016 +0300 Cleanup tooltips * src/dispextern.h (toplevel): Remove 'tip_frame' and 'tip_window' decls. * src/frame.h (struct frame): New bitfield to indicate tooltip frame. (FRAME_TOOLTIP_P): New macro. * src/frame.c (make_frame): Mark new frame as regular frame by default. (Fframe_list, delete_frame): Redesign to use FRAME_TOOLTIP_P. (syms_of_frame): Don't DEFSYM 'Qtooltip' but use 'Qtooltip_timer' and 'Qtooltip_parameters' instead. * src/gtkutil.h (toplevel): Add 'xg_hide_tip' decl. * src/gtkutil.c (xg_hide_tip): New function. (xg_hide_tooltip): Adjust to cancel GTK event loop timeout if needed. * src/menu.c (Fx_popup_menu): Adjust call to Fx_hide_tip. * src/nsfns.c (toplevel): Remove 'tip_frame' leftover. * src/w32fns.c (unwind_create_tip_frame): Remove. (w32_display_monitor_attributes_list) (w32_display_monitor_attributes_list_fallback): Use FRAME_TOOLTIP_P. (toplevel): Remove 'tip_frame', 'tip_window' and 'last_show_tip_args'. (x_create_tip_frame): Use do_unwind_create_frame. Mark new frame as a tooltip frame and record it using appropriate display info. (x_hide_tooltip): Add frame arg. (Fx_show_tip): Adjust to avoid globals, store tooltip parameters among base frame parameters, store tooltip hide timer among tooltip frame parameters. (Fx_hide_tip): Add frame arg, hide tooltips on all displays by default. (syms_of_w32fns): Don't DEFSYM 'Qtip_frame', don't initialize and GC-protect 'tip_timer', 'tip_frame' and 'last_show_tip_args'. * src/w32term.c (w32_read_socket): Extract tooltip window id from per-display data. Use FRAME_TOOLTIP_P where appropriate. (x_new_font): Use FRAME_TOOLTIP_P. (x_free_frame_resources): Reset pointer to tooltip frame. * src/w32term.h (struct w32_display_info): New member 'w32_tooltip_frame'. * src/xdisp.c (init_iterator, x_consider_frame_title, prepare_menu_bars): Use FRAME_TOOLTIP_P. * src/xfns.c (x_make_monitor_attribute_list) (Fx_display_monitor_attributes_list): Likewise. (unwind_create_tip_frame): Remove. (toplevel): Remove 'tip_frame', 'tip_window' and 'last_show_tip_args'. (x_create_tip_frame): Use do_unwind_create_frame. Mark new frame as a tooltip frame and record it using appropriate display info. (x_hide_tooltip): Add frame arg. (Fx_show_tip): Adjust to avoid globals, store tooltip parameters among base frame parameters, store tooltip hide timer among tooltip frame parameters. To hide GTK system tooltip, use timeout hooked into GTK event loop. (Fx_hide_tip): Add frame arg, hide tooltips on all displays by default. (syms_of_xfns): Don't DEFSYM 'Qtip_frame', don't initialize and GC-protect 'tip_timer', 'tip_frame' and 'last_show_tip_args'. * src/xterm.c (handle_one_xevent): Extract tooltip window id from per-display data. Use FRAME_TOOLTIP_P where appropriate. (x_new_font, x_set_window_size): Use FRAME_TOOLTIP_P. (x_free_frame_resources): Reset pointer to tooltip frame. * src/xterm.h (struct x_display_info): New member 'x_tooltip_frame'. (struct x_output) [USE_GTK_TOOLTIP]: New member 'ttip_timeout'. diff --git a/src/dispextern.h b/src/dispextern.h index 1325ff9..c2fcca5 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3461,8 +3461,6 @@ void gamma_correct (struct frame *, COLORREF *); void x_implicitly_set_name (struct frame *, Lisp_Object, Lisp_Object); void x_change_tool_bar_height (struct frame *f, int); -extern Lisp_Object tip_frame; -extern Window tip_window; extern frame_parm_handler x_frame_parm_handlers[]; extern void start_hourglass (void); diff --git a/src/frame.c b/src/frame.c index 22143ab..80e181f 100644 --- a/src/frame.c +++ b/src/frame.c @@ -642,6 +642,7 @@ make_frame (bool mini_p) f->vertical_scroll_bar_type = vertical_scroll_bar_none; f->horizontal_scroll_bars = false; f->want_fullscreen = FULLSCREEN_NONE; + f->tooltip = false; #if ! defined (USE_GTK) && ! defined (HAVE_NS) f->last_tool_bar_item = -1; #endif @@ -1260,13 +1261,16 @@ DEFUN ("frame-list", Fframe_list, Sframe_list, doc: /* Return a list of all live frames. */) (void) { - Lisp_Object frames; - frames = Fcopy_sequence (Vframe_list); #ifdef HAVE_WINDOW_SYSTEM - if (FRAMEP (tip_frame)) - frames = Fdelq (tip_frame, frames); + Lisp_Object list = Qnil, tail, frame; + + FOR_EACH_FRAME (tail, frame) + if (!FRAME_TOOLTIP_P (XFRAME (frame))) + list = Fcons (frame, list); + return list; +#else /* !HAVE_WINDOW_SYSTEM */ + return Fcopy_sequence (Vframe_list); #endif - return frames; } /* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the @@ -1557,7 +1561,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) } } - is_tooltip_frame = !NILP (Fframe_parameter (frame, Qtooltip)); + is_tooltip_frame = FRAME_TOOLTIP_P (f); /* Run `delete-frame-functions' unless FORCE is `noelisp' or frame is a tooltip. FORCE is set to `noelisp' when handling @@ -4900,7 +4904,6 @@ syms_of_frame (void) DEFSYM (Qgeometry, "geometry"); DEFSYM (Qicon_left, "icon-left"); DEFSYM (Qicon_top, "icon-top"); - DEFSYM (Qtooltip, "tooltip"); DEFSYM (Quser_position, "user-position"); DEFSYM (Quser_size, "user-size"); DEFSYM (Qwindow_id, "window-id"); @@ -5022,6 +5025,8 @@ syms_of_frame (void) DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars"); DEFSYM (Qvisibility, "visibility"); DEFSYM (Qwait_for_wm, "wait-for-wm"); + DEFSYM (Qtooltip_timer, "tooltip-timer"); + DEFSYM (Qtooltip_parameters, "tooltip-parameters"); { int i; diff --git a/src/frame.h b/src/frame.h index 5e3ee68..635a5ed 100644 --- a/src/frame.h +++ b/src/frame.h @@ -309,6 +309,9 @@ struct frame ENUM_BF (output_method) output_method : 3; #ifdef HAVE_WINDOW_SYSTEM + /* True if this frame is a tooltip frame. */ + bool_bf tooltip : 1; + /* See FULLSCREEN_ enum on top. */ ENUM_BF (fullscreen_type) want_fullscreen : 4; @@ -861,6 +864,9 @@ default_pixels_per_inch_y (void) #define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) \ ((f)->vertical_scroll_bar_type == vertical_scroll_bar_right) +/* Whether F is a tooltip frame. */ +#define FRAME_TOOLTIP_P(f) ((f)->tooltip) + #else /* not HAVE_WINDOW_SYSTEM */ /* If there is no window system, there are no scroll bars. */ @@ -869,6 +875,9 @@ default_pixels_per_inch_y (void) #define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT(f) ((void) f, 0) #define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) f, 0) +/* If there is no window system, there are no tooltips. */ +#define FRAME_TOOLTIP_P(f) ((void) f, 0) + #endif /* HAVE_WINDOW_SYSTEM */ /* Whether horizontal scroll bars are currently enabled for frame F. */ diff --git a/src/gtkutil.c b/src/gtkutil.c index 88e6d30..e08a4b5 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -731,14 +731,23 @@ xg_show_tooltip (struct frame *f, int root_x, int root_y) bool xg_hide_tooltip (struct frame *f) { - bool ret = 0; #ifdef USE_GTK_TOOLTIP - if (f->output_data.x->ttip_window) + struct x_output *x = FRAME_X_OUTPUT (f); + + if (x->ttip_window) { GtkWindow *win = f->output_data.x->ttip_window; + block_input (); gtk_widget_hide (GTK_WIDGET (win)); + /* Cancel call to xg_hide_tip. */ + if (x->ttip_timeout != 0) + { + g_source_remove (x->ttip_timeout); + x->ttip_timeout = 0; + } + if (g_object_get_data (G_OBJECT (win), "restore-tt")) { GdkWindow *gwin = gtk_widget_get_window (GTK_WIDGET (win)); @@ -747,11 +756,21 @@ xg_hide_tooltip (struct frame *f) g_object_set (settings, "gtk-enable-tooltips", TRUE, NULL); } unblock_input (); - - ret = 1; + return 1; } #endif - return ret; + return 0; +} + +/* One-shot timeout handler attached to GTK event loop in Fx_show_tip. */ + +gboolean +xg_hide_tip (gpointer data) +{ +#ifdef USE_GTK_TOOLTIP + xg_hide_tooltip ((struct frame *) data); +#endif + return FALSE; } diff --git a/src/gtkutil.h b/src/gtkutil.h index 8840fe7..d4dc295 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -178,6 +178,7 @@ extern bool xg_prepare_tooltip (struct frame *f, int *height); extern void xg_show_tooltip (struct frame *f, int root_x, int root_y); extern bool xg_hide_tooltip (struct frame *f); +extern gboolean xg_hide_tip (gpointer data); #ifdef USE_CAIRO extern void xg_page_setup_dialog (void); diff --git a/src/menu.c b/src/menu.c index 90bb19a..675caff 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1400,7 +1400,12 @@ no quit occurs and `x-popup-menu' returns nil. */) #ifdef HAVE_WINDOW_SYSTEM /* Hide a previous tip, if any. */ if (!FRAME_TERMCAP_P (f)) - Fx_hide_tip (); + { + Lisp_Object frame; + + XSETFRAME (frame, f); + Fx_hide_tip (frame); + } #endif #ifdef HAVE_NTGUI /* FIXME: Is it really w32-specific? --Stef */ diff --git a/src/nsfns.m b/src/nsfns.m index 051e509..a017be5 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -2658,10 +2658,6 @@ and GNUstep implementations ("distributor-specific release return make_number (1 << min (dpyinfo->n_planes, 24)); } - -/* Unused dummy def needed for compatibility. */ -Lisp_Object tip_frame; - /* TODO: move to xdisp or similar */ static void compute_tip_xy (struct frame *f, diff --git a/src/w32fns.c b/src/w32fns.c index 20e09d8..0eb720e 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -341,7 +341,6 @@ x_window_to_frame (struct w32_display_info *dpyinfo, HWND wdesc) static Lisp_Object unwind_create_frame (Lisp_Object); -static void unwind_create_tip_frame (Lisp_Object); static void my_create_window (struct frame *); static void my_create_tip_window (struct frame *); @@ -5053,6 +5052,7 @@ static void my_create_tip_window (struct frame *f) { RECT rect; + Window tip_window; rect.left = rect.top = 0; rect.right = FRAME_PIXEL_WIDTH (f); @@ -5200,9 +5200,8 @@ x_make_gc (struct frame *f) } -/* Handler for signals raised during x_create_frame and - x_create_tip_frame. FRAME is the frame which is partially - constructed. */ +/* Handler for signals raised during x_create_frame. + FRAME is the frame which is partially constructed. */ static Lisp_Object unwind_create_frame (Lisp_Object frame) @@ -5976,7 +5975,7 @@ w32_display_monitor_attributes_list (void) { struct frame *f = XFRAME (frame); - if (FRAME_W32_P (f) && !EQ (frame, tip_frame)) + if (FRAME_W32_P (f) && !FRAME_TOOLTIP_P (f)) { HMONITOR monitor = monitor_from_window_fn (FRAME_W32_WINDOW (f), @@ -6063,7 +6062,7 @@ w32_display_monitor_attributes_list_fallback (struct w32_display_info *dpyinfo) { struct frame *f = XFRAME (frame); - if (FRAME_W32_P (f) && !EQ (frame, tip_frame)) + if (FRAME_W32_P (f) && FRAME_TOOLTIP_P (f)) frames = Fcons (frame, frames); } attributes = Fcons (Fcons (Qframes, frames), attributes); @@ -6466,39 +6465,6 @@ no value of TYPE (always string in the MS Windows case). */) Tool tips ***********************************************************************/ -static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, - Lisp_Object, int, int, int *, int *); - -/* The frame of a currently visible tooltip. */ - -Lisp_Object tip_frame; - -/* If non-nil, a timer started that hides the last tooltip when it - fires. */ - -Lisp_Object tip_timer; -Window tip_window; - -/* If non-nil, a vector of 3 elements containing the last args - with which x-show-tip was called. See there. */ - -Lisp_Object last_show_tip_args; - - -static void -unwind_create_tip_frame (Lisp_Object frame) -{ - Lisp_Object deleted; - - deleted = unwind_create_frame (frame); - if (EQ (deleted, Qt)) - { - tip_window = NULL; - tip_frame = Qnil; - } -} - - /* Create a frame for a tooltip on the display described by DPYINFO. PARMS is a list of frame parameters. Value is the frame. @@ -6543,7 +6509,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) f->wants_modeline = false; XSETFRAME (frame, f); - record_unwind_protect (unwind_create_tip_frame, frame); + record_unwind_protect (do_unwind_create_frame, frame); /* By setting the output method, we're essentially saying that the frame is live, as per FRAME_LIVE_P. If we get a signal @@ -6555,6 +6521,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) FRAME_FONTSET (f) = -1; fset_icon_name (f, Qnil); + f->tooltip = true; #ifdef GLYPH_DEBUG image_cache_refcount = @@ -6663,11 +6630,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) height = FRAME_LINES (f); SET_FRAME_COLS (f, 0); SET_FRAME_LINES (f, 0); - adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f), - height * FRAME_LINE_HEIGHT (f), 0, true, Qtip_frame); - /* Add `tooltip' frame parameter's default value. */ - if (NILP (Fframe_parameter (frame, Qtooltip))) - Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil)); + change_frame_size (f, width, height, true, false, false, false); /* Set up faces after all frame parameters are known. This call also merges in face attributes specified for new frames. @@ -6695,6 +6658,9 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) f->no_split = true; + /* Now this is an official tooltip frame on this display. */ + dpyinfo->w32_tooltip_frame = f; + /* Now that the frame is official, it counts as a reference to its display. */ FRAME_DISPLAY_INFO (f)->reference_count++; @@ -6813,46 +6779,39 @@ compute_tip_xy (struct frame *f, *root_x = min_x; } -/* Hide tooltip. Delete its frame if DELETE is true. */ +/* Hide tooltip frame F and delete it if DELETE is true. */ + static Lisp_Object -x_hide_tip (bool delete) +x_hide_tip (struct frame *f, bool delete) { - if (!NILP (tip_timer)) + if (f) { - call1 (Qcancel_timer, tip_timer); - tip_timer = Qnil; - } + Lisp_Object frame, timer; - if (NILP (tip_frame) - || (!delete && FRAMEP (tip_frame) - && !FRAME_VISIBLE_P (XFRAME (tip_frame)))) - return Qnil; - else - { - ptrdiff_t count; - Lisp_Object was_open = Qnil; + XSETFRAME (frame, f); + timer = Fframe_parameter (frame, Qtooltip_timer); - count = SPECPDL_INDEX (); - specbind (Qinhibit_redisplay, Qt); - specbind (Qinhibit_quit, Qt); + if (!NILP (timer)) + call1 (Qcancel_timer, timer); - if (FRAMEP (tip_frame)) + if (!delete && !FRAME_VISIBLE_P (f)) + return Qnil; + else { + ptrdiff_t count = SPECPDL_INDEX (); + + specbind (Qinhibit_redisplay, Qt); + specbind (Qinhibit_quit, Qt); + if (delete) - { - delete_frame (tip_frame, Qnil); - tip_frame = Qnil; - } + delete_frame (frame, Qnil); else - x_make_frame_invisible (XFRAME (tip_frame)); + x_make_frame_invisible (f); - was_open = Qt; + return unbind_to (count, Qt); } - else - tip_frame = Qnil; - - return unbind_to (count, was_open); } + return Qnil; } @@ -6886,7 +6845,8 @@ with offset DY added (default is -10). A tooltip's maximum size is specified by `x-max-tooltip-size'. Text larger than the specified size is clipped. */) - (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) + (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, + Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) { struct frame *tip_f; struct window *w; @@ -6897,7 +6857,7 @@ Text larger than the specified size is clipped. */) int old_windows_or_buffers_changed = windows_or_buffers_changed; ptrdiff_t count = SPECPDL_INDEX (); ptrdiff_t count_1; - Lisp_Object window, size; + Lisp_Object window, size, tip_frame, parameters; AUTO_STRING (tip, " *tip*"); specbind (Qinhibit_redisplay, Qt); @@ -6919,14 +6879,22 @@ Text larger than the specified size is clipped. */) else CHECK_NUMBER (dy); - if (NILP (last_show_tip_args)) - last_show_tip_args = Fmake_vector (make_number (3), Qnil); + parameters = Fframe_parameter (frame, Qtooltip_parameters); + if (NILP (parameters)) + parameters = Fmake_vector (make_number (3), Qnil); - if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) + /* Look at current tooltip frame, if any. */ + tip_f = FRAME_DISPLAY_INFO (XFRAME (frame))->w32_tooltip_frame; + if (tip_f) + XSETFRAME (tip_frame, tip_f); + else + tip_frame = Qnil; + + if (tip_f && FRAME_LIVE_P (tip_f)) { - Lisp_Object last_string = AREF (last_show_tip_args, 0); - Lisp_Object last_frame = AREF (last_show_tip_args, 1); - Lisp_Object last_parms = AREF (last_show_tip_args, 2); + Lisp_Object last_string = AREF (parameters, 0); + Lisp_Object last_frame = AREF (parameters, 1); + Lisp_Object last_parms = AREF (parameters, 2); if (FRAME_VISIBLE_P (XFRAME (tip_frame)) && EQ (frame, last_frame) @@ -6934,14 +6902,10 @@ Text larger than the specified size is clipped. */) && !NILP (Fequal (last_parms, parms))) { /* Only DX and DY have changed. */ - tip_f = XFRAME (tip_frame); - if (!NILP (tip_timer)) - { - Lisp_Object timer = tip_timer; + Lisp_Object timer = Fframe_parameter (tip_frame, Qtooltip_timer); - tip_timer = Qnil; - call1 (Qcancel_timer, timer); - } + if (!NILP (timer)) + call1 (Qcancel_timer, timer); block_input (); compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f), @@ -7011,17 +6975,22 @@ Text larger than the specified size is clipped. */) } } - x_hide_tip (delete); + x_hide_tip (tip_f, delete); } else - x_hide_tip (true); + x_hide_tip (tip_f, true); } else - x_hide_tip (true); + x_hide_tip (tip_f, true); - ASET (last_show_tip_args, 0, string); - ASET (last_show_tip_args, 1, frame); - ASET (last_show_tip_args, 2, parms); + /* Update tooltip parameters. */ + { + AUTO_FRAME_ARG (arg, Qtooltip_parameters, parameters); + ASET (parameters, 0, string); + ASET (parameters, 1, frame); + ASET (parameters, 2, parms); + Fmodify_frame_parameters (frame, arg); + } /* Block input until the tip has been fully drawn, to avoid crashes when drawing tips in menus. */ @@ -7041,11 +7010,8 @@ Text larger than the specified size is clipped. */) if (NILP (Fassq (Qbackground_color, parms))) parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), parms); - - /* Create a frame for the tooltip, and record it in the global - variable tip_frame. */ - struct frame *f; /* The value is unused. */ - if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms))) + if (NILP (tip_frame + = x_create_tip_frame (FRAME_DISPLAY_INFO (XFRAME (frame)), parms))) { /* Creating the tip frame failed. */ unblock_input (); @@ -7149,20 +7115,47 @@ Text larger than the specified size is clipped. */) windows_or_buffers_changed = old_windows_or_buffers_changed; start_timer: - /* Let the tip disappear after timeout seconds. */ - tip_timer = call3 (intern ("run-at-time"), timeout, Qnil, - intern ("x-hide-tip")); - + { + /* Let the tip disappear after timeout seconds. */ + AUTO_FRAME_ARG (arg, Qtooltip_timer, + call3 (intern ("run-at-time"), timeout, + Qnil, intern ("x-hide-tip"))); + Fmodify_frame_parameters (tip_frame, arg); + } return unbind_to (count, Qnil); } -DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0, +DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 1, 0, doc: /* Hide the current tooltip window, if there is any. +Optional FRAME is the frame to hide tooltip on. Value is t if tooltip was open, nil otherwise. */) - (void) + (Lisp_Object frame) { - return x_hide_tip (!tooltip_reuse_hidden_frame); + Lisp_Object obj = Qnil; + + if (NILP (frame)) + { + struct w32_display_info *dpyinfo; + + for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) + if (dpyinfo->w32_tooltip_frame) + if (!NILP (x_hide_tip (dpyinfo->w32_tooltip_frame, + !tooltip_reuse_hidden_frame))) + obj = Qt; + } + else + { + struct frame *f; + + CHECK_FRAME (frame); + f = XFRAME (frame); + if (FRAME_DISPLAY_INFO (f) + && FRAME_DISPLAY_INFO (f)->w32_tooltip_frame) + obj = x_hide_tip (FRAME_DISPLAY_INFO (f)->w32_tooltip_frame, + !tooltip_reuse_hidden_frame); + } + return obj; } /*********************************************************************** @@ -9765,7 +9758,6 @@ syms_of_w32fns (void) DEFSYM (Qworkarea, "workarea"); DEFSYM (Qmm_size, "mm-size"); DEFSYM (Qframes, "frames"); - DEFSYM (Qtip_frame, "tip-frame"); DEFSYM (Qassq_delete_all, "assq-delete-all"); DEFSYM (Qunicode_sip, "unicode-sip"); #if defined WINDOWSNT && !defined HAVE_DBUS @@ -10151,13 +10143,6 @@ tip frame. */); defsubr (&Sset_message_beep); defsubr (&Sx_show_tip); defsubr (&Sx_hide_tip); - tip_timer = Qnil; - staticpro (&tip_timer); - tip_frame = Qnil; - staticpro (&tip_frame); - - last_show_tip_args = Qnil; - staticpro (&last_show_tip_args); defsubr (&Sx_file_dialog); #ifdef WINDOWSNT diff --git a/src/w32term.c b/src/w32term.c index 5a11e2a..8c2fdaf 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -5024,11 +5024,10 @@ w32_read_socket (struct terminal *terminal, /* wParam non-zero means Window is about to be shown, 0 means about to be hidden. */ /* Redo the mouse-highlight after the tooltip has gone. */ - if (!msg.msg.wParam && msg.msg.hwnd == tip_window) - { - tip_window = NULL; - x_redo_mouse_highlight (dpyinfo); - } + if (!msg.msg.wParam + && dpyinfo->w32_tooltip_frame + && FRAME_W32_WINDOW (dpyinfo->w32_tooltip_frame) == msg.msg.hwnd) + x_redo_mouse_highlight (dpyinfo); /* If window has been obscured or exposed by another window being maximized or minimized/restored, then recheck @@ -5394,7 +5393,7 @@ w32_read_socket (struct terminal *terminal, struct frame *f = XFRAME (frame); /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED below. */ - if (EQ (frame, tip_frame)) + if (FRAME_TOOLTIP_P (f)) continue; /* Check "visible" frames and mark each as obscured or not. @@ -5871,7 +5870,7 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) /* Don't change the size of a tip frame; there's no point in doing it because it's done in Fx_show_tip, and it leads to problems because the tip frame has no widget. */ - if (NILP (tip_frame) || XFRAME (tip_frame) != f) + if (!FRAME_TOOLTIP_P (f)) adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, false, Qfont); @@ -6569,6 +6568,8 @@ x_free_frame_resources (struct frame *f) dpyinfo->w32_focus_event_frame = 0; if (f == dpyinfo->x_highlight_frame) dpyinfo->x_highlight_frame = 0; + if (f == dpyinfo->w32_tooltip_frame) + dpyinfo->w32_tooltip_frame = 0; if (f == hlinfo->mouse_face_mouse_frame) reset_mouse_highlight (hlinfo); diff --git a/src/w32term.h b/src/w32term.h index 3204770..3934e85 100644 --- a/src/w32term.h +++ b/src/w32term.h @@ -186,6 +186,9 @@ struct w32_display_info /* The frame waiting to be auto-raised in w32_read_socket. */ struct frame *w32_pending_autoraise_frame; + /* Tooltip frame on this display. */ + struct frame *w32_tooltip_frame; + /* The frame where the mouse was last time we reported a mouse event. */ struct frame *last_mouse_frame; diff --git a/src/xdisp.c b/src/xdisp.c index 14d6f8f..b8dcdce 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2841,11 +2841,7 @@ init_iterator (struct it *it, struct window *w, frames when the fringes are turned off. But leave the dimensions zero for tooltip frames, as these glyphs look ugly there and also sabotage calculations of tooltip dimensions in x-show-tip. */ -#ifdef HAVE_WINDOW_SYSTEM - if (!(FRAME_WINDOW_P (it->f) - && FRAMEP (tip_frame) - && it->f == XFRAME (tip_frame))) -#endif + if (!FRAME_TOOLTIP_P (it->f)) { if (it->line_wrap == TRUNCATE) { @@ -11713,7 +11709,7 @@ x_consider_frame_title (Lisp_Object frame) if ((FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name) - && NILP (Fframe_parameter (frame, Qtooltip))) + && !FRAME_TOOLTIP_P (f)) { /* Do we have more than one visible frame on this X display? */ Lisp_Object tail, other_frame, fmt; @@ -11730,7 +11726,7 @@ x_consider_frame_title (Lisp_Object frame) if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f) && !FRAME_MINIBUF_ONLY_P (tf) - && !EQ (other_frame, tip_frame) + && !FRAME_TOOLTIP_P (tf) && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf))) break; } @@ -11793,13 +11789,6 @@ prepare_menu_bars (void) { bool all_windows = windows_or_buffers_changed || update_mode_lines; bool some_windows = REDISPLAY_SOME_P (); - Lisp_Object tooltip_frame; - -#ifdef HAVE_WINDOW_SYSTEM - tooltip_frame = tip_frame; -#else - tooltip_frame = Qnil; -#endif if (FUNCTIONP (Vpre_redisplay_function)) { @@ -11840,7 +11829,7 @@ prepare_menu_bars (void) && !XBUFFER (w->contents)->text->redisplay) continue; - if (!EQ (frame, tooltip_frame) + if (!FRAME_TOOLTIP_P (f) && (FRAME_ICONIFIED_P (f) || FRAME_VISIBLE_P (f) == 1 /* Exclude TTY frames that are obscured because they @@ -11877,7 +11866,7 @@ prepare_menu_bars (void) struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); /* Ignore tooltip frame. */ - if (EQ (frame, tooltip_frame)) + if (FRAME_TOOLTIP_P (f)) continue; if (some_windows diff --git a/src/xfns.c b/src/xfns.c index 798dc49..16dbcfd 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -4151,7 +4151,7 @@ x_make_monitor_attribute_list (struct MonitorInfo *monitors, struct frame *f = XFRAME (frame); if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo - && !EQ (frame, tip_frame)) + && !FRAME_TOOLTIP_P (f)) { int i = x_get_monitor_for_frame (f, monitors, n_monitors); ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i))); @@ -4447,7 +4447,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */) struct frame *f = XFRAME (frame); if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo - && !EQ (frame, tip_frame)) + && !FRAME_TOOLTIP_P (f)) { GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); @@ -5312,39 +5312,6 @@ no value of TYPE (always string in the MS Windows case). */) Tool tips ***********************************************************************/ -static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, - Lisp_Object, int, int, int *, int *); - -/* The frame of a currently visible tooltip. */ - -Lisp_Object tip_frame; - -/* If non-nil, a timer started that hides the last tooltip when it - fires. */ - -static Lisp_Object tip_timer; -Window tip_window; - -/* If non-nil, a vector of 3 elements containing the last args - with which x-show-tip was called. See there. */ - -static Lisp_Object last_show_tip_args; - - -static void -unwind_create_tip_frame (Lisp_Object frame) -{ - Lisp_Object deleted; - - deleted = unwind_create_frame (frame); - if (EQ (deleted, Qt)) - { - tip_window = None; - tip_frame = Qnil; - } -} - - /* Create a frame for a tooltip on the display described by DPYINFO. PARMS is a list of frame parameters. TEXT is the string to display in the tip frame. Value is the frame. @@ -5381,7 +5348,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) f = make_frame (false); f->wants_modeline = false; XSETFRAME (frame, f); - record_unwind_protect (unwind_create_tip_frame, frame); + record_unwind_protect (do_unwind_create_frame, frame); f->terminal = dpyinfo->terminal; @@ -5402,6 +5369,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) f->output_data.x->white_relief.pixel = -1; f->output_data.x->black_relief.pixel = -1; + f->tooltip = true; fset_icon_name (f, Qnil); FRAME_DISPLAY_INFO (f) = dpyinfo; f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; @@ -5545,8 +5513,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) = f->output_data.x->text_cursor; /* Arrange for getting MapNotify and UnmapNotify events. */ attrs.event_mask = StructureNotifyMask; - tip_window - = FRAME_X_WINDOW (f) + FRAME_X_WINDOW (f) = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window, /* x, y, width, height */ @@ -5555,7 +5522,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) f->border_width, CopyFromParent, InputOutput, CopyFromParent, mask, &attrs); - XChangeProperty (FRAME_X_DISPLAY (f), tip_window, + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_net_window_type, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type, 1); @@ -5582,13 +5549,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) SET_FRAME_LINES (f, 0); change_frame_size (f, width, height, true, false, false, false); - /* Add `tooltip' frame parameter's default value. */ - if (NILP (Fframe_parameter (frame, Qtooltip))) - { - AUTO_FRAME_ARG (arg, Qtooltip, Qt); - Fmodify_frame_parameters (frame, arg); - } - /* FIXME - can this be done in a similar way to normal frames? http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */ @@ -5633,6 +5593,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) f->no_split = true; + /* Now this is an official tooltip frame on this display. */ + dpyinfo->x_tooltip_frame = f; + /* Now that the frame will be official, it counts as a reference to its display and terminal. */ FRAME_DISPLAY_INFO (f)->reference_count++; @@ -5663,7 +5626,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) the display in *ROOT_X, and *ROOT_Y. */ static void -compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, int width, int height, int *root_x, int *root_y) +compute_tip_xy (struct frame *f, + Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, + int width, int height, int *root_x, int *root_y) { Lisp_Object left, top, right, bottom; int win_x, win_y; @@ -5759,56 +5724,39 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object *root_x = min_x; } +/* Hide tooltip frame F and delete it if DELETE is true. */ -/* Hide tooltip. Delete its frame if DELETE is true. */ static Lisp_Object -x_hide_tip (bool delete) +x_hide_tip (struct frame *f, bool delete) { - if (!NILP (tip_timer)) + if (f) { - call1 (Qcancel_timer, tip_timer); - tip_timer = Qnil; - } + Lisp_Object frame, timer; + XSETFRAME (frame, f); + timer = Fframe_parameter (frame, Qtooltip_timer); - if (NILP (tip_frame) - || (!delete && FRAMEP (tip_frame) - && !FRAME_VISIBLE_P (XFRAME (tip_frame)))) - return Qnil; - else - { - ptrdiff_t count; - Lisp_Object was_open = Qnil; + if (!NILP (timer)) + call1 (Qcancel_timer, timer); - count = SPECPDL_INDEX (); - specbind (Qinhibit_redisplay, Qt); - specbind (Qinhibit_quit, Qt); + if (!delete && !FRAME_VISIBLE_P (f)) + return Qnil; + else + { + ptrdiff_t count = SPECPDL_INDEX (); -#ifdef USE_GTK - { - /* When using system tooltip, tip_frame is the Emacs frame on - which the tip is shown. */ - struct frame *f = XFRAME (tip_frame); + specbind (Qinhibit_redisplay, Qt); + specbind (Qinhibit_quit, Qt); - if (FRAME_LIVE_P (f) && xg_hide_tooltip (f)) - { - tip_frame = Qnil; - was_open = Qt; - } - } +#ifdef USE_GTK + if (x_gtk_use_system_tooltips) + /* Should be handled by xg_hide_tooltip. */ + emacs_abort (); #endif - - if (FRAMEP (tip_frame)) - { if (delete) - { - delete_frame (tip_frame, Qnil); - tip_frame = Qnil; - } + delete_frame (frame, Qnil); else - x_make_frame_invisible (XFRAME (tip_frame)); - - was_open = Qt; + x_make_frame_invisible (f); #ifdef USE_LUCID /* Bloodcurdling hack alert: The Lucid menu bar widget's @@ -5816,12 +5764,12 @@ x_hide_tip (bool delete) menu items is unmapped. Redisplay the menu manually... */ { Widget w; - struct frame *f = SELECTED_FRAME (); - if (FRAME_X_P (f) && FRAME_LIVE_P (f)) + struct frame *sf = SELECTED_FRAME (); + if (FRAME_X_P (sf) && FRAME_LIVE_P (sf)) { - w = f->output_data.x->menubar_widget; + w = sf->output_data.x->menubar_widget; - if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen) + if (!DoesSaveUnders (FRAME_DISPLAY_INFO (sf)->screen) && w != NULL) { block_input (); @@ -5831,12 +5779,10 @@ x_hide_tip (bool delete) } } #endif /* USE_LUCID */ + return unbind_to (count, Qt); } - else - tip_frame = Qnil; - - return unbind_to (count, was_open); } + return Qnil; } DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, @@ -5869,7 +5815,8 @@ with offset DY added (default is -10). A tooltip's maximum size is specified by `x-max-tooltip-size'. Text larger than the specified size is clipped. */) - (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) + (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, + Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) { struct frame *f, *tip_f; struct window *w; @@ -5880,7 +5827,7 @@ Text larger than the specified size is clipped. */) int old_windows_or_buffers_changed = windows_or_buffers_changed; ptrdiff_t count = SPECPDL_INDEX (); ptrdiff_t count_1; - Lisp_Object window, size; + Lisp_Object window, size, tip_frame, parameters; AUTO_STRING (tip, " *tip*"); specbind (Qinhibit_redisplay, Qt); @@ -5910,8 +5857,8 @@ Text larger than the specified size is clipped. */) { bool ok; - /* Hide a previous tip, if any. */ - Fx_hide_tip (); + /* Hide a previous tip on this frame, if any. */ + xg_hide_tooltip (f); block_input (); ok = xg_prepare_tooltip (f, string, &width, &height); @@ -5919,37 +5866,47 @@ Text larger than the specified size is clipped. */) { compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y); xg_show_tooltip (f, root_x, root_y); - /* This is used in Fx_hide_tip. */ - XSETFRAME (tip_frame, f); } unblock_input (); - if (ok) goto start_timer; + if (ok) + /* Schedule call to xg_hide_tip from GTK event loop + to allow the tip disappear after timeout seconds. */ + FRAME_X_OUTPUT (f)->ttip_timeout + = g_timeout_add_seconds (XINT (timeout), xg_hide_tip, (gpointer) f); + else + /* FIXME: what if not ok? */ + FRAME_X_OUTPUT (f)->ttip_timeout = 0; + return unbind_to (count, Qnil); } #endif /* USE_GTK */ - if (NILP (last_show_tip_args)) - last_show_tip_args = Fmake_vector (make_number (3), Qnil); + parameters = Fframe_parameter (frame, Qtooltip_parameters); + if (NILP (parameters)) + parameters = Fmake_vector (make_number (3), Qnil); - if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) + /* Look at current tooltip frame, if any. */ + tip_f = FRAME_DISPLAY_INFO (f)->x_tooltip_frame; + if (tip_f) + XSETFRAME (tip_frame, tip_f); + else + tip_frame = Qnil; + + if (tip_f && FRAME_LIVE_P (tip_f)) { - Lisp_Object last_string = AREF (last_show_tip_args, 0); - Lisp_Object last_frame = AREF (last_show_tip_args, 1); - Lisp_Object last_parms = AREF (last_show_tip_args, 2); + Lisp_Object last_string = AREF (parameters, 0); + Lisp_Object last_frame = AREF (parameters, 1); + Lisp_Object last_parms = AREF (parameters, 2); - if (FRAME_VISIBLE_P (XFRAME (tip_frame)) + if (FRAME_VISIBLE_P (tip_f) && EQ (frame, last_frame) && !NILP (Fequal_including_properties (last_string, string)) && !NILP (Fequal (last_parms, parms))) { /* Only DX and DY have changed. */ - tip_f = XFRAME (tip_frame); - if (!NILP (tip_timer)) - { - Lisp_Object timer = tip_timer; + Lisp_Object timer = Fframe_parameter (tip_frame, Qtooltip_timer); - tip_timer = Qnil; - call1 (Qcancel_timer, timer); - } + if (!NILP (timer)) + call1 (Qcancel_timer, timer); block_input (); compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f), @@ -6009,17 +5966,22 @@ Text larger than the specified size is clipped. */) } } - x_hide_tip (delete); + x_hide_tip (tip_f, delete); } else - x_hide_tip (true); + x_hide_tip (tip_f, true); } else - x_hide_tip (true); + x_hide_tip (tip_f, true); - ASET (last_show_tip_args, 0, string); - ASET (last_show_tip_args, 1, frame); - ASET (last_show_tip_args, 2, parms); + /* Update tooltip parameters. */ + { + AUTO_FRAME_ARG (arg, Qtooltip_parameters, parameters); + ASET (parameters, 0, string); + ASET (parameters, 1, frame); + ASET (parameters, 2, parms); + Fmodify_frame_parameters (frame, arg); + } if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame))) { @@ -6035,9 +5997,6 @@ Text larger than the specified size is clipped. */) if (NILP (Fassq (Qbackground_color, parms))) parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), parms); - - /* Create a frame for the tooltip, and record it in the global - variable tip_frame. */ if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms))) /* Creating the tip frame failed. */ return unbind_to (count, Qnil); @@ -6115,20 +6074,69 @@ Text larger than the specified size is clipped. */) windows_or_buffers_changed = old_windows_or_buffers_changed; start_timer: - /* Let the tip disappear after timeout seconds. */ - tip_timer = call3 (intern ("run-at-time"), timeout, Qnil, - intern ("x-hide-tip")); - + { + /* Let the tip disappear after timeout seconds. */ + AUTO_FRAME_ARG (arg, Qtooltip_timer, + call3 (intern ("run-at-time"), timeout, + Qnil, intern ("x-hide-tip"))); + Fmodify_frame_parameters (tip_frame, arg); + } return unbind_to (count, Qnil); } - -DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0, +DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 1, 0, doc: /* Hide the current tooltip window, if there is any. +Optional FRAME is the frame to hide tooltip on. Value is t if tooltip was open, nil otherwise. */) - (void) + (Lisp_Object frame) { - return x_hide_tip (!tooltip_reuse_hidden_frame); + Lisp_Object obj = Qnil; + +#ifdef USE_GTK + if (x_gtk_use_system_tooltips) + { + if (NILP (frame)) + { + Lisp_Object tail, frame; + + FOR_EACH_FRAME (tail, frame) + if (FRAME_X_P (XFRAME (frame))) + if (xg_hide_tooltip (XFRAME (frame))) + obj = Qt; + } + else + { + CHECK_FRAME (frame); + if (FRAME_X_P (XFRAME (frame))) + if (xg_hide_tooltip (XFRAME (frame))) + obj = Qt; + } + return obj; + } +#endif /* USE_GTK */ + + if (NILP (frame)) + { + struct x_display_info *dpyinfo; + + for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) + if (dpyinfo->x_tooltip_frame) + if (!NILP (x_hide_tip (dpyinfo->x_tooltip_frame, + !tooltip_reuse_hidden_frame))) + obj = Qt; + } + else + { + struct frame *f; + + CHECK_FRAME (frame); + f = XFRAME (frame); + if (FRAME_DISPLAY_INFO (f) + && FRAME_DISPLAY_INFO (f)->x_tooltip_frame) + obj = x_hide_tip (FRAME_DISPLAY_INFO (f)->x_tooltip_frame, + !tooltip_reuse_hidden_frame); + } + return obj; } @@ -6997,13 +7005,6 @@ When using Gtk+ tooltips, the tooltip face is not used. */); defsubr (&Sx_show_tip); defsubr (&Sx_hide_tip); - tip_timer = Qnil; - staticpro (&tip_timer); - tip_frame = Qnil; - staticpro (&tip_frame); - - last_show_tip_args = Qnil; - staticpro (&last_show_tip_args); defsubr (&Sx_uses_old_gtk_dialog); #if defined (USE_MOTIF) || defined (USE_GTK) diff --git a/src/xterm.c b/src/xterm.c index cd1d712..ada1160 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -987,8 +987,7 @@ static void x_update_begin (struct frame *f) { #ifdef USE_CAIRO - if (! NILP (tip_frame) && XFRAME (tip_frame) == f - && ! FRAME_VISIBLE_P (f)) + if (FRAME_TOOLTIP_P (f) && ! FRAME_VISIBLE_P (f)) return; if (! FRAME_CR_SURFACE (f)) @@ -7839,11 +7838,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, case UnmapNotify: /* Redo the mouse-highlight after the tooltip has gone. */ - if (event->xunmap.window == tip_window) - { - tip_window = 0; - x_redo_mouse_highlight (dpyinfo); - } + if (dpyinfo->x_tooltip_frame + && FRAME_X_WINDOW (dpyinfo->x_tooltip_frame) == event->xunmap.window) + x_redo_mouse_highlight (dpyinfo); f = x_top_window_to_frame (dpyinfo, event->xunmap.window); if (f) /* F may no longer exist if @@ -8433,7 +8430,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #ifdef USE_X_TOOLKIT /* Tip frames are pure X window, set size for them. */ - if (! NILP (tip_frame) && XFRAME (tip_frame) == f) + if (FRAME_TOOLTIP_P (f)) { if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width) @@ -9614,7 +9611,7 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) /* Don't change the size of a tip frame; there's no point in doing it because it's done in Fx_show_tip, and it leads to problems because the tip frame has no widget. */ - if (NILP (tip_frame) || XFRAME (tip_frame) != f) + if (!FRAME_TOOLTIP_P (f)) { adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, @@ -10689,7 +10686,7 @@ x_set_window_size (struct frame *f, bool change_gravity, /* The following breaks our calculations. If it's really needed, think of something else. */ #if false - if (NILP (tip_frame) || XFRAME (tip_frame) != f) + if (!FRAME_TOOLTIP_P (f)) { int text_width, text_height; @@ -11340,6 +11337,8 @@ x_free_frame_resources (struct frame *f) dpyinfo->x_focus_event_frame = 0; if (f == dpyinfo->x_highlight_frame) dpyinfo->x_highlight_frame = 0; + if (f == dpyinfo->x_tooltip_frame) + dpyinfo->x_tooltip_frame = 0; if (f == hlinfo->mouse_face_mouse_frame) reset_mouse_highlight (hlinfo); diff --git a/src/xterm.h b/src/xterm.h index 675a484..1eb3e30 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -362,6 +362,9 @@ struct x_display_info /* The frame waiting to be auto-raised in XTread_socket. */ struct frame *x_pending_autoraise_frame; + /* Tooltip frame on this display. */ + struct frame *x_tooltip_frame; + /* The frame where the mouse was last time we reported a ButtonPress event. */ struct frame *last_mouse_frame; @@ -575,6 +578,7 @@ struct x_output GtkTooltip *ttip_widget; GtkWidget *ttip_lbl; GtkWindow *ttip_window; + guint ttip_timeout; #endif /* USE_GTK_TOOLTIP */ #endif /* USE_GTK */ commit 8ea599254784e3e6da37ec7ea73f1f6ec6a92ff1 Author: Stefan Monnier Date: Mon Jul 11 21:33:43 2016 -0400 * src/fns.c (syms_of_fns): Leave `features' lexically scoped diff --git a/src/fns.c b/src/fns.c index 270dfb4..c318608 100644 --- a/src/fns.c +++ b/src/fns.c @@ -5147,6 +5147,9 @@ syms_of_fns (void) doc: /* A list of symbols which are the features of the executing Emacs. Used by `featurep' and `require', and altered by `provide'. */); Vfeatures = list1 (Qemacs); + DEFSYM (Qfeatures, "features"); + /* Let people use lexically scoped vars named `features'. */ + Fmake_var_non_special (Qfeatures); DEFSYM (Qsubfeatures, "subfeatures"); DEFSYM (Qfuncall, "funcall"); commit 846761e426ec4056b7d662adbe3ec4c80a7e8307 Author: Mario Lang Date: Mon Jul 11 21:43:48 2016 +0200 Test mapcan * test/src/fns-tests.el (fns-tests-mapcan): New test. diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index 8485896..c533bad 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el @@ -235,3 +235,13 @@ (backward-delete-char 1) (buffer-hash)) (sha1 "foo")))) + +(ert-deftest fns-tests-mapcan () + (should-error (mapcan)) + (should-error (mapcan #'identity)) + (should-error (mapcan #'identity (make-char-table 'foo))) + (should (equal (mapcan #'list '(1 2 3)) '(1 2 3))) + ;; `mapcan' is destructive + (let ((data '((foo) (bar)))) + (should (equal (mapcan #'identity data) '(foo bar))) + (should (equal data '((foo bar) (bar)))))) commit 69b79bdff07bff2174d782dc4c69cf2dadc8225b Author: Mark Oteiza Date: Mon Jul 11 14:37:54 2016 -0400 ; Remove parens from sentence in docstring. diff --git a/lisp/simple.el b/lisp/simple.el index 4d35d7c..6d7f00f 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -3239,7 +3239,7 @@ If OUTPUT-BUFFER is a buffer or buffer name, erase that buffer and insert the output there. If OUTPUT-BUFFER is not a buffer and not nil, insert the output in current buffer after point leaving mark after it. -(This cannot be done asynchronously). +This cannot be done asynchronously. If the command terminates without error, but generates output, and you did not specify \"insert it in the current buffer\", commit 7af6c87b5047c5362cb57c6173d27fe877597c04 Author: Stefan Monnier Date: Tue Jul 12 00:55:04 2016 +0900 Prevent to apply funcall on t * lisp/vc/ediff-util.el (ediff-really-quit): Ignore the global part of 'ediff-after-quit-hook-internal' hook (Bug#23933). diff --git a/lisp/vc/ediff-util.el b/lisp/vc/ediff-util.el index a6b88d5..99672fc 100644 --- a/lisp/vc/ediff-util.el +++ b/lisp/vc/ediff-util.el @@ -2439,7 +2439,9 @@ temporarily reverses the meaning of this variable." ;; restore buffer mode line id's in buffer-A/B/C (let ((control-buffer ediff-control-buffer) (meta-buffer ediff-meta-buffer) - (after-quit-hook-internal ediff-after-quit-hook-internal) + ;; FIXME: Here we ignore the global part of the + ;; ediff-after-quit-hook-internal hook. + (after-quit-hook-internal (remq t ediff-after-quit-hook-internal)) (session-number ediff-meta-session-number) ;; suitable working frame (warp-frame (if (and (ediff-window-display-p) (eq ediff-grab-mouse t)) commit 713e922243fb60d850f7b0ff83f3e2a3682f1832 Author: Tino Calancha Date: Tue Jul 12 00:38:14 2016 +0900 Ignore angle mode while simplifying units * lisp/calc/calc-forms.el (math-to-hms, math-from-hms): Ignore value of 'calc-angle-mode' when 'math-simplifying-units' is non-nil (Bug#23889). * lisp/calc/calc-math.el (math-to-radians, math-from-radians) (math-from-radians-2, math-to-radians-2): Idem. diff --git a/lisp/calc/calc-forms.el b/lisp/calc/calc-forms.el index c94b89d..153b904 100644 --- a/lisp/calc/calc-forms.el +++ b/lisp/calc/calc-forms.el @@ -317,7 +317,9 @@ (list 'calcFunc-hms a)) ((math-negp a) (math-neg (math-to-hms (math-neg a) ang))) - ((eq (or ang calc-angle-mode) 'rad) + ((eq (or ang + (and (not math-simplifying-units) calc-angle-mode)) + 'rad) (math-to-hms (math-div a (math-pi-over-180)) 'deg)) ((memq (car-safe a) '(cplx polar)) a) (t @@ -354,12 +356,16 @@ (if (eq (car-safe a) 'sdev) (math-make-sdev (math-from-hms (nth 1 a) ang) (math-from-hms (nth 2 a) ang)) - (if (eq (or ang calc-angle-mode) 'rad) + (if (eq (or ang + (and (not math-simplifying-units) calc-angle-mode)) + 'rad) (list 'calcFunc-rad a) (list 'calcFunc-deg a))))) ((math-negp a) (math-neg (math-from-hms (math-neg a) ang))) - ((eq (or ang calc-angle-mode) 'rad) + ((eq (or ang + (and (not math-simplifying-units) calc-angle-mode)) + 'rad) (math-mul (math-from-hms a 'deg) (math-pi-over-180))) (t (math-add (math-div (math-add (math-div (nth 3 a) diff --git a/lisp/calc/calc-math.el b/lisp/calc/calc-math.el index 699ef6f..567635e 100644 --- a/lisp/calc/calc-math.el +++ b/lisp/calc/calc-math.el @@ -763,12 +763,14 @@ If this can't be done, return NIL." (defun math-to-radians (a) ; [N N] (cond ((eq (car-safe a) 'hms) (math-from-hms a 'rad)) - ((memq calc-angle-mode '(deg hms)) + ((and (not math-simplifying-units) + (memq calc-angle-mode '(deg hms))) (math-mul a (math-pi-over-180))) (t a))) (defun math-from-radians (a) ; [N N] - (cond ((eq calc-angle-mode 'deg) + (cond ((and (not math-simplifying-units) + (eq calc-angle-mode 'deg)) (if (math-constp a) (math-div a (math-pi-over-180)) (list 'calcFunc-deg a))) @@ -779,14 +781,16 @@ If this can't be done, return NIL." (defun math-to-radians-2 (a &optional force-symbolic) ; [N N] (cond ((eq (car-safe a) 'hms) (math-from-hms a 'rad)) - ((memq calc-angle-mode '(deg hms)) + ((and (not math-simplifying-units) + (memq calc-angle-mode '(deg hms))) (if (or calc-symbolic-mode force-symbolic) (math-div (math-mul a '(var pi var-pi)) 180) (math-mul a (math-pi-over-180)))) (t a))) (defun math-from-radians-2 (a &optional force-symbolic) ; [N N] - (cond ((memq calc-angle-mode '(deg hms)) + (cond ((and (not math-simplifying-units) + (memq calc-angle-mode '(deg hms))) (if (or calc-symbolic-mode force-symbolic) (math-div (math-mul 180 a) '(var pi var-pi)) (math-div a (math-pi-over-180)))) commit 188fb3b58a17d566c2b0feabf8ec26c1eaa42c61 Merge: 10cfb73 4ba2946 Author: Eli Zaretskii Date: Mon Jul 11 17:19:40 2016 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit 10cfb736e2d32bd2604dc93a979ce136473b5944 Author: Eli Zaretskii Date: Mon Jul 11 17:18:11 2016 +0300 Fix display of composed characters * src/xdisp.c (x_produce_glyphs): Fix off-by-one error in iteration through composition glyphs. (Bug#23938) diff --git a/src/xdisp.c b/src/xdisp.c index d5ffb25..14d6f8f 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -27369,8 +27369,8 @@ x_produce_glyphs (struct it *it) eassume (0 < glyph_len); /* See Bug#8512. */ do - c = COMPOSITION_GLYPH (cmp, --glyph_len); - while (c == '\t' && 0 < glyph_len); + c = COMPOSITION_GLYPH (cmp, glyph_len - 1); + while (c == '\t' && 0 < --glyph_len); bool right_padded = glyph_len < cmp->glyph_len; for (i = 0; i < glyph_len; i++) commit 4ba2946369cb19dfeb258839add0658c742c12a1 Author: Paul Eggert Date: Mon Jul 11 16:14:33 2016 +0200 Fix composition bug caused by off-by-1 typo * src/xdisp.c (x_produce_glyphs): Fix off-by-one typo when computing composition glyph (Bug#23938). diff --git a/src/xdisp.c b/src/xdisp.c index d5ffb25..14d6f8f 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -27369,8 +27369,8 @@ x_produce_glyphs (struct it *it) eassume (0 < glyph_len); /* See Bug#8512. */ do - c = COMPOSITION_GLYPH (cmp, --glyph_len); - while (c == '\t' && 0 < glyph_len); + c = COMPOSITION_GLYPH (cmp, glyph_len - 1); + while (c == '\t' && 0 < --glyph_len); bool right_padded = glyph_len < cmp->glyph_len; for (i = 0; i < glyph_len; i++)