From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Dmitry Antipov Newsgroups: gmane.emacs.devel Subject: Re: Latest master broken on Cocoa/NS Date: Thu, 14 Jul 2016 08:41:46 +0300 Message-ID: <6094b884-c675-cc67-cdc8-c6810b26f97d@yandex.ru> References: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------CDDDBA944ADD3B6DB33D7B72" X-Trace: ger.gmane.org 1468474982 17031 80.91.229.3 (14 Jul 2016 05:43:02 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 14 Jul 2016 05:43:02 +0000 (UTC) Cc: John Wiegley , =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= To: emacs-devel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Jul 14 07:42:54 2016 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1bNZQC-0006V0-Uq for ged-emacs-devel@m.gmane.org; Thu, 14 Jul 2016 07:42:53 +0200 Original-Received: from localhost ([::1]:51588 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bNZQ9-0001E5-47 for ged-emacs-devel@m.gmane.org; Thu, 14 Jul 2016 01:42:49 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:41434) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bNZPQ-0001Do-LN for emacs-devel@gnu.org; Thu, 14 Jul 2016 01:42:09 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bNZPL-0000BL-2K for emacs-devel@gnu.org; Thu, 14 Jul 2016 01:42:03 -0400 Original-Received: from forward4o.cmail.yandex.net ([37.9.109.248]:43975) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bNZPJ-0000Ar-6Q for emacs-devel@gnu.org; Thu, 14 Jul 2016 01:41:58 -0400 Original-Received: from smtp1o.mail.yandex.net (smtp1o.mail.yandex.net [IPv6:2a02:6b8:0:1a2d::25]) by forward4o.cmail.yandex.net (Yandex) with ESMTP id 8A61120FE1; Thu, 14 Jul 2016 08:41:47 +0300 (MSK) Original-Received: from smtp1o.mail.yandex.net (localhost [127.0.0.1]) by smtp1o.mail.yandex.net (Yandex) with ESMTP id 892AEDE377C; Thu, 14 Jul 2016 08:41:47 +0300 (MSK) Original-Received: by smtp1o.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id ABe3ixrCJw-fkI0pB4w; Thu, 14 Jul 2016 08:41:46 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client certificate not present) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1468474906; bh=mIvFycCObrfx1fictCUIzR9Lcv2E7233p2q5Ysb0i0I=; h=Subject:To:References:Cc:From:Message-ID:Date:In-Reply-To; b=nNjVvfw1H3huq9FJgze+kXiebO5gaWS63Ahr8KPNpvsgVkvRnObHSEY4VV/F8B2Tq kcv5TXWS4rqeIHA6vODFA/MdhD+zw0rxtXVamK9WV9tuI9/eG+jVm0qXv6HZS6LWcj hoZlh1zzqZ+daZPRkJXvfIdFuoEOy2vEtKnoXOLE= Authentication-Results: smtp1o.mail.yandex.net; dkim=pass header.i=@yandex.ru X-Yandex-Suid-Status: 1 0,1 0,1 0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 In-Reply-To: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 37.9.109.248 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:205668 Archived-At: This is a multi-part message in MIME format. --------------CDDDBA944ADD3B6DB33D7B72 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit On 07/13/2016 01:26 AM, John Wiegley wrote: > OK, I am going to revert until we've considered the patch in more detail here. Hm...then please try this. Dmitry --------------CDDDBA944ADD3B6DB33D7B72 Content-Type: text/x-diff; name="0001-Cleanup-tooltips.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0001-Cleanup-tooltips.patch" =46rom 78f46996b084ecb604bd6e284084a3342e11ce41 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Thu, 14 Jul 2016 08:34:02 +0300 Subject: [PATCH] Cleanup tooltips This is a minor rework of 20038f8ab75dd1551412a43cd58520c483c22921 tested on OS X 10.11 as well. * 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.m (toplevel): Remove 'tip_frame' leftover. (Fx_hide_tip): Add frame arg for the sake of compatibility with other por= ts. * 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'= =2E * 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'. --- src/dispextern.h | 2 - src/frame.c | 19 ++-- src/frame.h | 9 ++ src/gtkutil.c | 29 +++++- src/gtkutil.h | 1 + src/menu.c | 7 +- src/nsfns.m | 11 +-- src/w32fns.c | 213 ++++++++++++++++++++---------------------- src/w32term.c | 15 +-- src/w32term.h | 3 + src/xdisp.c | 21 +---- src/xfns.c | 277 ++++++++++++++++++++++++++++---------------------= ------ src/xterm.c | 19 ++-- src/xterm.h | 4 + 14 files changed, 323 insertions(+), 307 deletions(-) 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); =20 -extern Lisp_Object tip_frame; -extern Window tip_window; extern frame_parm_handler x_frame_parm_handlers[]; =20 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 =3D vertical_scroll_bar_none; f->horizontal_scroll_bars =3D false; f->want_fullscreen =3D FULLSCREEN_NONE; + f->tooltip =3D false; #if ! defined (USE_GTK) && ! defined (HAVE_NS) f->last_tool_bar_item =3D -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 =3D Fcopy_sequence (Vframe_list); #ifdef HAVE_WINDOW_SYSTEM - if (FRAMEP (tip_frame)) - frames =3D Fdelq (tip_frame, frames); + Lisp_Object list =3D Qnil, tail, frame; + + FOR_EACH_FRAME (tail, frame) + if (!FRAME_TOOLTIP_P (XFRAME (frame))) + list =3D Fcons (frame, list); + return list; +#else /* !HAVE_WINDOW_SYSTEM */ + return Fcopy_sequence (Vframe_list); #endif - return frames; } =20 /* 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)= } } =20 - is_tooltip_frame =3D !NILP (Fframe_parameter (frame, Qtooltip)); + is_tooltip_frame =3D FRAME_TOOLTIP_P (f); =20 /* 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"); =20 { 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; =20 #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; =20 @@ -861,6 +864,9 @@ default_pixels_per_inch_y (void) #define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) \ ((f)->vertical_scroll_bar_type =3D=3D vertical_scroll_bar_right) =20 +/* Whether F is a tooltip frame. */ +#define FRAME_TOOLTIP_P(f) ((f)->tooltip) + #else /* not HAVE_WINDOW_SYSTEM */ =20 /* 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) =20 +/* If there is no window system, there are no tooltips. */ +#define FRAME_TOOLTIP_P(f) ((void) f, 0) + #endif /* HAVE_WINDOW_SYSTEM */ =20 /* 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 r= oot_y) bool xg_hide_tooltip (struct frame *f) { - bool ret =3D 0; #ifdef USE_GTK_TOOLTIP - if (f->output_data.x->ttip_window) + struct x_output *x =3D FRAME_X_OUTPUT (f); + + if (x->ttip_window) { GtkWindow *win =3D f->output_data.x->ttip_window; + block_input (); gtk_widget_hide (GTK_WIDGET (win)); =20 + /* Cancel call to xg_hide_tip. */ + if (x->ttip_timeout !=3D 0) + { + g_source_remove (x->ttip_timeout); + x->ttip_timeout =3D 0; + } + if (g_object_get_data (G_OBJECT (win), "restore-tt")) { GdkWindow *gwin =3D 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 =3D 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; } =20 =0C 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); =20 #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 =20 #ifdef HAVE_NTGUI /* FIXME: Is it really w32-specific? --Stef */ diff --git a/src/nsfns.m b/src/nsfns.m index 051e509..43ab29a 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)); } =20 - -/* Unused dummy def needed for compatibility. */ -Lisp_Object tip_frame; - /* TODO: move to xdisp or similar */ static void compute_tip_xy (struct frame *f, @@ -2804,7 +2800,7 @@ with offset DY added (default is -10). if (ns_tooltip =3D=3D nil) ns_tooltip =3D [[EmacsTooltip alloc] init]; else - Fx_hide_tip (); + Fx_hide_tip (frame); =20 [ns_tooltip setText: str]; size =3D [ns_tooltip frame].size; @@ -2821,10 +2817,11 @@ with offset DY added (default is -10). } =20 =20 -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) { if (ns_tooltip =3D=3D nil || ![ns_tooltip isActive]) return Qnil; diff --git a/src/w32fns.c b/src/w32fns.c index d6b54d1..f5e5b33 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -343,7 +343,6 @@ x_window_to_frame (struct w32_display_info *dpyinfo, = HWND wdesc) =20 =0C 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 *); =20 @@ -5068,6 +5067,7 @@ static void my_create_tip_window (struct frame *f) { RECT rect; + Window tip_window; =20 rect.left =3D rect.top =3D 0; rect.right =3D FRAME_PIXEL_WIDTH (f); @@ -5215,9 +5215,8 @@ x_make_gc (struct frame *f) } =20 =20 -/* 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. */ =20 static Lisp_Object unwind_create_frame (Lisp_Object frame) @@ -5991,7 +5990,7 @@ w32_display_monitor_attributes_list (void) { struct frame *f =3D XFRAME (frame); =20 - if (FRAME_W32_P (f) && !EQ (frame, tip_frame)) + if (FRAME_W32_P (f) && !FRAME_TOOLTIP_P (f)) { HMONITOR monitor =3D monitor_from_window_fn (FRAME_W32_WINDOW (f), @@ -6078,7 +6077,7 @@ w32_display_monitor_attributes_list_fallback (struc= t w32_display_info *dpyinfo) { struct frame *f =3D XFRAME (frame); =20 - if (FRAME_W32_P (f) && !EQ (frame, tip_frame)) + if (FRAME_W32_P (f) && FRAME_TOOLTIP_P (f)) frames =3D Fcons (frame, frames); } attributes =3D Fcons (Fcons (Qframes, frames), attributes); @@ -6481,39 +6480,6 @@ no value of TYPE (always string in the MS Windows = case). */) Tool tips ***********************************************************************= / =20 -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 =3D unwind_create_frame (frame); - if (EQ (deleted, Qt)) - { - tip_window =3D NULL; - tip_frame =3D Qnil; - } -} - - /* Create a frame for a tooltip on the display described by DPYINFO. PARMS is a list of frame parameters. Value is the frame. =20 @@ -6558,7 +6524,7 @@ x_create_tip_frame (struct w32_display_info *dpyinf= o, Lisp_Object parms) f->wants_modeline =3D false; XSETFRAME (frame, f); =20 - record_unwind_protect (unwind_create_tip_frame, frame); + record_unwind_protect (do_unwind_create_frame, frame); =20 /* By setting the output method, we're essentially saying that the frame is live, as per FRAME_LIVE_P. If we get a signal @@ -6570,6 +6536,7 @@ x_create_tip_frame (struct w32_display_info *dpyinf= o, Lisp_Object parms) =20 FRAME_FONTSET (f) =3D -1; fset_icon_name (f, Qnil); + f->tooltip =3D true; =20 #ifdef GLYPH_DEBUG image_cache_refcount =3D @@ -6678,11 +6645,7 @@ x_create_tip_frame (struct w32_display_info *dpyin= fo, Lisp_Object parms) height =3D 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); =20 /* Set up faces after all frame parameters are known. This call also merges in face attributes specified for new frames. @@ -6710,6 +6673,9 @@ x_create_tip_frame (struct w32_display_info *dpyinf= o, Lisp_Object parms) =20 f->no_split =3D true; =20 + /* Now this is an official tooltip frame on this display. */ + dpyinfo->w32_tooltip_frame =3D f; + /* Now that the frame is official, it counts as a reference to its display. */ FRAME_DISPLAY_INFO (f)->reference_count++; @@ -6828,46 +6794,39 @@ compute_tip_xy (struct frame *f, *root_x =3D min_x; } =20 -/* 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 =3D Qnil; - } + Lisp_Object frame, timer; =20 - if (NILP (tip_frame) - || (!delete && FRAMEP (tip_frame) - && !FRAME_VISIBLE_P (XFRAME (tip_frame)))) - return Qnil; - else - { - ptrdiff_t count; - Lisp_Object was_open =3D Qnil; + XSETFRAME (frame, f); + timer =3D Fframe_parameter (frame, Qtooltip_timer); =20 - count =3D SPECPDL_INDEX (); - specbind (Qinhibit_redisplay, Qt); - specbind (Qinhibit_quit, Qt); + if (!NILP (timer)) + call1 (Qcancel_timer, timer); =20 - if (FRAMEP (tip_frame)) + if (!delete && !FRAME_VISIBLE_P (f)) + return Qnil; + else { + ptrdiff_t count =3D SPECPDL_INDEX (); + + specbind (Qinhibit_redisplay, Qt); + specbind (Qinhibit_quit, Qt); + if (delete) - { - delete_frame (tip_frame, Qnil); - tip_frame =3D Qnil; - } + delete_frame (frame, Qnil); else - x_make_frame_invisible (XFRAME (tip_frame)); + x_make_frame_invisible (f); =20 - was_open =3D Qt; + return unbind_to (count, Qt); } - else - tip_frame =3D Qnil; - - return unbind_to (count, was_open); } + return Qnil; } =20 =20 @@ -6901,7 +6860,8 @@ with offset DY added (default is -10). =20 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; @@ -6912,7 +6872,7 @@ Text larger than the specified size is clipped. */= ) int old_windows_or_buffers_changed =3D windows_or_buffers_changed; ptrdiff_t count =3D SPECPDL_INDEX (); ptrdiff_t count_1; - Lisp_Object window, size; + Lisp_Object window, size, tip_frame, parameters; AUTO_STRING (tip, " *tip*"); =20 specbind (Qinhibit_redisplay, Qt); @@ -6934,14 +6894,22 @@ Text larger than the specified size is clipped. = */) else CHECK_NUMBER (dy); =20 - if (NILP (last_show_tip_args)) - last_show_tip_args =3D Fmake_vector (make_number (3), Qnil); + parameters =3D Fframe_parameter (frame, Qtooltip_parameters); + if (NILP (parameters)) + parameters =3D Fmake_vector (make_number (3), Qnil); =20 - if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) + /* Look at current tooltip frame, if any. */ + tip_f =3D FRAME_DISPLAY_INFO (XFRAME (frame))->w32_tooltip_frame; + if (tip_f) + XSETFRAME (tip_frame, tip_f); + else + tip_frame =3D Qnil; + + if (tip_f && FRAME_LIVE_P (tip_f)) { - Lisp_Object last_string =3D AREF (last_show_tip_args, 0); - Lisp_Object last_frame =3D AREF (last_show_tip_args, 1); - Lisp_Object last_parms =3D AREF (last_show_tip_args, 2); + Lisp_Object last_string =3D AREF (parameters, 0); + Lisp_Object last_frame =3D AREF (parameters, 1); + Lisp_Object last_parms =3D AREF (parameters, 2); =20 if (FRAME_VISIBLE_P (XFRAME (tip_frame)) && EQ (frame, last_frame) @@ -6949,14 +6917,10 @@ Text larger than the specified size is clipped. = */) && !NILP (Fequal (last_parms, parms))) { /* Only DX and DY have changed. */ - tip_f =3D XFRAME (tip_frame); - if (!NILP (tip_timer)) - { - Lisp_Object timer =3D tip_timer; + Lisp_Object timer =3D Fframe_parameter (tip_frame, Qtooltip_timer); =20 - tip_timer =3D Qnil; - call1 (Qcancel_timer, timer); - } + if (!NILP (timer)) + call1 (Qcancel_timer, timer); =20 block_input (); compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f), @@ -7026,17 +6990,22 @@ Text larger than the specified size is clipped. = */) } } =20 - 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); =20 - 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); + } =20 /* Block input until the tip has been fully drawn, to avoid crashes when drawing tips in menus. */ @@ -7056,11 +7025,8 @@ Text larger than the specified size is clipped. *= /) if (NILP (Fassq (Qbackground_color, parms))) parms =3D 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 =3D x_create_tip_frame (FRAME_DISPLAY_INFO (f)= , parms))) + if (NILP (tip_frame + =3D x_create_tip_frame (FRAME_DISPLAY_INFO (XFRAME (frame)), parms))) { /* Creating the tip frame failed. */ unblock_input (); @@ -7164,20 +7130,47 @@ Text larger than the specified size is clipped. = */) windows_or_buffers_changed =3D old_windows_or_buffers_changed; =20 start_timer: - /* Let the tip disappear after timeout seconds. */ - tip_timer =3D 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); } =20 =20 -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 =3D Qnil; + + if (NILP (frame)) + { + struct w32_display_info *dpyinfo; + + for (dpyinfo =3D x_display_list; dpyinfo; dpyinfo =3D dpyinfo->nex= t) + if (dpyinfo->w32_tooltip_frame) + if (!NILP (x_hide_tip (dpyinfo->w32_tooltip_frame, + !tooltip_reuse_hidden_frame))) + obj =3D Qt; + } + else + { + struct frame *f; + + CHECK_FRAME (frame); + f =3D XFRAME (frame); + if (FRAME_DISPLAY_INFO (f) + && FRAME_DISPLAY_INFO (f)->w32_tooltip_frame) + obj =3D x_hide_tip (FRAME_DISPLAY_INFO (f)->w32_tooltip_frame, + !tooltip_reuse_hidden_frame); + } + return obj; } =0C /***********************************************************************= @@ -9780,7 +9773,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 @@ -10166,13 +10158,6 @@ tip frame. */); defsubr (&Sset_message_beep); defsubr (&Sx_show_tip); defsubr (&Sx_hide_tip); - tip_timer =3D Qnil; - staticpro (&tip_timer); - tip_frame =3D Qnil; - staticpro (&tip_frame); - - last_show_tip_args =3D Qnil; - staticpro (&last_show_tip_args); =20 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 =3D=3D tip_window) - { - tip_window =3D NULL; - x_redo_mouse_highlight (dpyinfo); - } + if (!msg.msg.wParam + && dpyinfo->w32_tooltip_frame + && FRAME_W32_WINDOW (dpyinfo->w32_tooltip_frame) =3D=3D msg.msg.h= wnd) + x_redo_mouse_highlight (dpyinfo); =20 /* 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 =3D 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; =20 /* Check "visible" frames and mark each as obscured or not. @@ -5871,7 +5870,7 @@ x_new_font (struct frame *f, Lisp_Object font_objec= t, 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) !=3D 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 =3D 0; if (f =3D=3D dpyinfo->x_highlight_frame) dpyinfo->x_highlight_frame =3D 0; + if (f =3D=3D dpyinfo->w32_tooltip_frame) + dpyinfo->w32_tooltip_frame =3D 0; if (f =3D=3D hlinfo->mouse_face_mouse_frame) reset_mouse_highlight (hlinfo); =20 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; =20 + /* 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; =20 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 =3D=3D XFRAME (tip_frame))) -#endif + if (!FRAME_TOOLTIP_P (it->f)) { if (it->line_wrap =3D=3D 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 !=3D f && FRAME_KBOARD (tf) =3D=3D 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 =3D windows_or_buffers_changed || update_mode_lines; bool some_windows =3D REDISPLAY_SOME_P (); - Lisp_Object tooltip_frame; - -#ifdef HAVE_WINDOW_SYSTEM - tooltip_frame =3D tip_frame; -#else - tooltip_frame =3D Qnil; -#endif =20 if (FUNCTIONP (Vpre_redisplay_function)) { @@ -11840,7 +11829,7 @@ prepare_menu_bars (void) && !XBUFFER (w->contents)->text->redisplay) continue; =20 - if (!EQ (frame, tooltip_frame) + if (!FRAME_TOOLTIP_P (f) && (FRAME_ICONIFIED_P (f) || FRAME_VISIBLE_P (f) =3D=3D 1 /* Exclude TTY frames that are obscured because they @@ -11877,7 +11866,7 @@ prepare_menu_bars (void) struct window *w =3D XWINDOW (FRAME_SELECTED_WINDOW (f)); =20 /* Ignore tooltip frame. */ - if (EQ (frame, tooltip_frame)) + if (FRAME_TOOLTIP_P (f)) continue; =20 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 =3D XFRAME (frame); =20 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) =3D=3D dpyinfo - && !EQ (frame, tip_frame)) + && !FRAME_TOOLTIP_P (f)) { int i =3D 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 =3D XFRAME (frame); =20 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) =3D=3D dpyinfo - && !EQ (frame, tip_frame)) + && !FRAME_TOOLTIP_P (f)) { GdkWindow *gwin =3D gtk_widget_get_window (FRAME_GTK_WIDGET (f)); =20 @@ -5312,39 +5312,6 @@ no value of TYPE (always string in the MS Windows = case). */) Tool tips ***********************************************************************= / =20 -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 =3D unwind_create_frame (frame); - if (EQ (deleted, Qt)) - { - tip_window =3D None; - tip_frame =3D 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 =3D make_frame (false); f->wants_modeline =3D false; XSETFRAME (frame, f); - record_unwind_protect (unwind_create_tip_frame, frame); + record_unwind_protect (do_unwind_create_frame, frame); =20 f->terminal =3D dpyinfo->terminal; =20 @@ -5402,6 +5369,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,= Lisp_Object parms) f->output_data.x->white_relief.pixel =3D -1; f->output_data.x->black_relief.pixel =3D -1; =20 + f->tooltip =3D true; fset_icon_name (f, Qnil); FRAME_DISPLAY_INFO (f) =3D dpyinfo; f->output_data.x->parent_desc =3D FRAME_DISPLAY_INFO (f)->root_window;= @@ -5545,8 +5513,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,= Lisp_Object parms) =3D f->output_data.x->text_cursor; /* Arrange for getting MapNotify and UnmapNotify events. */ attrs.event_mask =3D StructureNotifyMask; - tip_window - =3D FRAME_X_WINDOW (f) + FRAME_X_WINDOW (f) =3D 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); =20 - /* 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= */ =20 @@ -5633,6 +5593,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo,= Lisp_Object parms) =20 f->no_split =3D true; =20 + /* Now this is an official tooltip frame on this display. */ + dpyinfo->x_tooltip_frame =3D 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. */ =20 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 parm= s, Lisp_Object dx, Lisp_Object *root_x =3D min_x; } =20 +/* Hide tooltip frame F and delete it if DELETE is true. */ =20 -/* 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 =3D Qnil; - } + Lisp_Object frame, timer; =20 + XSETFRAME (frame, f); + timer =3D Fframe_parameter (frame, Qtooltip_timer); =20 - if (NILP (tip_frame) - || (!delete && FRAMEP (tip_frame) - && !FRAME_VISIBLE_P (XFRAME (tip_frame)))) - return Qnil; - else - { - ptrdiff_t count; - Lisp_Object was_open =3D Qnil; + if (!NILP (timer)) + call1 (Qcancel_timer, timer); =20 - count =3D SPECPDL_INDEX (); - specbind (Qinhibit_redisplay, Qt); - specbind (Qinhibit_quit, Qt); + if (!delete && !FRAME_VISIBLE_P (f)) + return Qnil; + else + { + ptrdiff_t count =3D SPECPDL_INDEX (); =20 -#ifdef USE_GTK - { - /* When using system tooltip, tip_frame is the Emacs frame on - which the tip is shown. */ - struct frame *f =3D XFRAME (tip_frame); + specbind (Qinhibit_redisplay, Qt); + specbind (Qinhibit_quit, Qt); =20 - if (FRAME_LIVE_P (f) && xg_hide_tooltip (f)) - { - tip_frame =3D Qnil; - was_open =3D 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 =3D Qnil; - } + delete_frame (frame, Qnil); else - x_make_frame_invisible (XFRAME (tip_frame)); - - was_open =3D Qt; + x_make_frame_invisible (f); =20 #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 =3D SELECTED_FRAME (); - if (FRAME_X_P (f) && FRAME_LIVE_P (f)) + struct frame *sf =3D SELECTED_FRAME (); + if (FRAME_X_P (sf) && FRAME_LIVE_P (sf)) { - w =3D f->output_data.x->menubar_widget; + w =3D sf->output_data.x->menubar_widget; =20 - if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen) + if (!DoesSaveUnders (FRAME_DISPLAY_INFO (sf)->screen) && w !=3D NULL) { block_input (); @@ -5831,12 +5779,10 @@ x_hide_tip (bool delete) } } #endif /* USE_LUCID */ + return unbind_to (count, Qt); } - else - tip_frame =3D Qnil; - - return unbind_to (count, was_open); } + return Qnil; } =20 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, @@ -5869,7 +5815,8 @@ with offset DY added (default is -10). =20 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 =3D windows_or_buffers_changed; ptrdiff_t count =3D SPECPDL_INDEX (); ptrdiff_t count_1; - Lisp_Object window, size; + Lisp_Object window, size, tip_frame, parameters; AUTO_STRING (tip, " *tip*"); =20 specbind (Qinhibit_redisplay, Qt); @@ -5910,8 +5857,8 @@ Text larger than the specified size is clipped. */= ) { bool ok; =20 - /* Hide a previous tip, if any. */ - Fx_hide_tip (); + /* Hide a previous tip on this frame, if any. */ + xg_hide_tooltip (f); =20 block_input (); ok =3D 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 + =3D g_timeout_add_seconds (XINT (timeout), xg_hide_tip, (gpointer) f)= ; + else + /* FIXME: what if not ok? */ + FRAME_X_OUTPUT (f)->ttip_timeout =3D 0; + return unbind_to (count, Qnil); } #endif /* USE_GTK */ =20 - if (NILP (last_show_tip_args)) - last_show_tip_args =3D Fmake_vector (make_number (3), Qnil); + parameters =3D Fframe_parameter (frame, Qtooltip_parameters); + if (NILP (parameters)) + parameters =3D Fmake_vector (make_number (3), Qnil); =20 - if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) + /* Look at current tooltip frame, if any. */ + tip_f =3D FRAME_DISPLAY_INFO (f)->x_tooltip_frame; + if (tip_f) + XSETFRAME (tip_frame, tip_f); + else + tip_frame =3D Qnil; + + if (tip_f && FRAME_LIVE_P (tip_f)) { - Lisp_Object last_string =3D AREF (last_show_tip_args, 0); - Lisp_Object last_frame =3D AREF (last_show_tip_args, 1); - Lisp_Object last_parms =3D AREF (last_show_tip_args, 2); + Lisp_Object last_string =3D AREF (parameters, 0); + Lisp_Object last_frame =3D AREF (parameters, 1); + Lisp_Object last_parms =3D AREF (parameters, 2); =20 - 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 =3D XFRAME (tip_frame); - if (!NILP (tip_timer)) - { - Lisp_Object timer =3D tip_timer; + Lisp_Object timer =3D Fframe_parameter (tip_frame, Qtooltip_timer); =20 - tip_timer =3D Qnil; - call1 (Qcancel_timer, timer); - } + if (!NILP (timer)) + call1 (Qcancel_timer, timer); =20 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. = */) } } =20 - 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); =20 - 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); + } =20 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 =3D 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 =3D 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 =3D old_windows_or_buffers_changed; =20 start_timer: - /* Let the tip disappear after timeout seconds. */ - tip_timer =3D 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); } =20 - -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 =3D 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 =3D Qt; + } + else + { + CHECK_FRAME (frame); + if (FRAME_X_P (XFRAME (frame))) + if (xg_hide_tooltip (XFRAME (frame))) + obj =3D Qt; + } + return obj; + } +#endif /* USE_GTK */ + + if (NILP (frame)) + { + struct x_display_info *dpyinfo; + + for (dpyinfo =3D x_display_list; dpyinfo; dpyinfo =3D dpyinfo->nex= t) + if (dpyinfo->x_tooltip_frame) + if (!NILP (x_hide_tip (dpyinfo->x_tooltip_frame, + !tooltip_reuse_hidden_frame))) + obj =3D Qt; + } + else + { + struct frame *f; + + CHECK_FRAME (frame); + f =3D XFRAME (frame); + if (FRAME_DISPLAY_INFO (f) + && FRAME_DISPLAY_INFO (f)->x_tooltip_frame) + obj =3D x_hide_tip (FRAME_DISPLAY_INFO (f)->x_tooltip_frame, + !tooltip_reuse_hidden_frame); + } + return obj; } =20 =0C @@ -6997,13 +7005,6 @@ When using Gtk+ tooltips, the tooltip face is not = used. */); =20 defsubr (&Sx_show_tip); defsubr (&Sx_hide_tip); - tip_timer =3D Qnil; - staticpro (&tip_timer); - tip_frame =3D Qnil; - staticpro (&tip_frame); - - last_show_tip_args =3D Qnil; - staticpro (&last_show_tip_args); =20 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) =3D=3D f - && ! FRAME_VISIBLE_P (f)) + if (FRAME_TOOLTIP_P (f) && ! FRAME_VISIBLE_P (f)) return; =20 if (! FRAME_CR_SURFACE (f)) @@ -7839,11 +7838,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,= =20 case UnmapNotify: /* Redo the mouse-highlight after the tooltip has gone. */ - if (event->xunmap.window =3D=3D tip_window) - { - tip_window =3D 0; - x_redo_mouse_highlight (dpyinfo); - } + if (dpyinfo->x_tooltip_frame + && FRAME_X_WINDOW (dpyinfo->x_tooltip_frame) =3D=3D event->xunmap.win= dow) + x_redo_mouse_highlight (dpyinfo); =20 f =3D 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, =20 #ifdef USE_X_TOOLKIT /* Tip frames are pure X window, set size for them. */ - if (! NILP (tip_frame) && XFRAME (tip_frame) =3D=3D f) + if (FRAME_TOOLTIP_P (f)) { if (FRAME_PIXEL_HEIGHT (f) !=3D configureEvent.xconfigure.= height || FRAME_PIXEL_WIDTH (f) !=3D configureEvent.xconfigur= e.width) @@ -9614,7 +9611,7 @@ x_new_font (struct frame *f, Lisp_Object font_objec= t, 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) !=3D 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_g= ravity, /* The following breaks our calculations. If it's really needed, think of something else. */ #if false - if (NILP (tip_frame) || XFRAME (tip_frame) !=3D f) + if (!FRAME_TOOLTIP_P (f)) { int text_width, text_height; =20 @@ -11340,6 +11337,8 @@ x_free_frame_resources (struct frame *f) dpyinfo->x_focus_event_frame =3D 0; if (f =3D=3D dpyinfo->x_highlight_frame) dpyinfo->x_highlight_frame =3D 0; + if (f =3D=3D dpyinfo->x_tooltip_frame) + dpyinfo->x_tooltip_frame =3D 0; if (f =3D=3D hlinfo->mouse_face_mouse_frame) reset_mouse_highlight (hlinfo); =20 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; =20 + /* Tooltip frame on this display. */ + struct frame *x_tooltip_frame; + /* The frame where the mouse was last time we reported a ButtonPress e= vent. */ struct frame *last_mouse_frame; =20 @@ -575,6 +578,7 @@ struct x_output GtkTooltip *ttip_widget; GtkWidget *ttip_lbl; GtkWindow *ttip_window; + guint ttip_timeout; #endif /* USE_GTK_TOOLTIP */ =20 #endif /* USE_GTK */ --=20 2.9.0 --------------CDDDBA944ADD3B6DB33D7B72--