unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Latest master broken on Cocoa/NS
@ 2016-07-12 21:47 João Távora
  2016-07-12 22:05 ` John Wiegley
  2016-07-12 22:06 ` João Távora
  0 siblings, 2 replies; 25+ messages in thread
From: João Távora @ 2016-07-12 21:47 UTC (permalink / raw)
  To: emacs-devel, dmantipov

Hi Dmitry,

This commit seems to be the culprit:

  commit 20038f8ab75dd1551412a43cd58520c483c22921
  Author: Dmitry Antipov <dmantipov@yandex.ru>
  Date:   Tue Jul 12 09:16:26 2016 +0300

You add a frame argument to Fx_hide_tip and a corresponding call, but
apparently forgot to take care of nsfns.m, which also declares it for
use in the NS build:

   menu.c:1407:20: error: too many arguments to function call, expected 0, have 1
         Fx_hide_tip (frame);
         ~~~~~~~~~~~  ^~~~~
   ./globals.h:4300:1: note: 'Fx_hide_tip' declared here
   EXFUN (Fx_hide_tip, 0);
   ^
   ./../lwlib/../src/lisp.h:691:3: note: expanded from macro 'EXFUN'
     extern Lisp_Object fnname DEFUN_ARGS_ ## maxargs
     ^
   1 error generated.

The patch after my sig apparently fixes it...

João

diff --git a/src/nsfns.m b/src/nsfns.m
index a017be5..c5ff9e5 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -2800,7 +2800,7 @@ with offset DY added (default is -10).
   if (ns_tooltip == nil)
     ns_tooltip = [[EmacsTooltip alloc] init];
   else
-    Fx_hide_tip ();
+    Fx_hide_tip (frame);
 
   [ns_tooltip setText: str];
   size = [ns_tooltip frame].size;
@@ -2817,7 +2817,7 @@ with offset DY added (default is -10).
 }
 
 
-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.
 Value is t if tooltip was open, nil otherwise.  */)
      (void)










^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-12 21:47 Latest master broken on Cocoa/NS João Távora
@ 2016-07-12 22:05 ` John Wiegley
  2016-07-12 22:06 ` João Távora
  1 sibling, 0 replies; 25+ messages in thread
From: John Wiegley @ 2016-07-12 22:05 UTC (permalink / raw)
  To: João Távora; +Cc: dmantipov, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 722 bytes --]

>>>>> "JT" == João Távora <joaotavora@gmail.com> writes:

JT> This commit seems to be the culprit:

JT>   commit 20038f8ab75dd1551412a43cd58520c483c22921
JT>   Author: Dmitry Antipov <dmantipov@yandex.ru>
JT>   Date:   Tue Jul 12 09:16:26 2016 +0300

Dmitry,

This rather large change appeared in master today without any prior discussion
or review on this list. Can you please explain the motivations for this
change? The fact that it has already broken one port makes me think it should
be reverted until there has been more discussion and testing.

-- 
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 629 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-12 21:47 Latest master broken on Cocoa/NS João Távora
  2016-07-12 22:05 ` John Wiegley
@ 2016-07-12 22:06 ` João Távora
  2016-07-12 22:26   ` John Wiegley
  1 sibling, 1 reply; 25+ messages in thread
From: João Távora @ 2016-07-12 22:06 UTC (permalink / raw)
  To: emacs-devel, dmantipov

[-- Attachment #1: Type: text/plain, Size: 1900 bytes --]

Disregard the patch attached (and the diagnostic). My fix doesn't work for
some reason I have yet to investigate.

The problem is still there, though.

João




On Tue, Jul 12, 2016 at 10:47 PM, João Távora <joaotavora@gmail.com> wrote:

> Hi Dmitry,
>
> This commit seems to be the culprit:
>
>   commit 20038f8ab75dd1551412a43cd58520c483c22921
>   Author: Dmitry Antipov <dmantipov@yandex.ru>
>   Date:   Tue Jul 12 09:16:26 2016 +0300
>
> You add a frame argument to Fx_hide_tip and a corresponding call, but
> apparently forgot to take care of nsfns.m, which also declares it for
> use in the NS build:
>
>    menu.c:1407:20: error: too many arguments to function call, expected 0,
> have 1
>          Fx_hide_tip (frame);
>          ~~~~~~~~~~~  ^~~~~
>    ./globals.h:4300:1: note: 'Fx_hide_tip' declared here
>    EXFUN (Fx_hide_tip, 0);
>    ^
>    ./../lwlib/../src/lisp.h:691:3: note: expanded from macro 'EXFUN'
>      extern Lisp_Object fnname DEFUN_ARGS_ ## maxargs
>      ^
>    1 error generated.
>
> The patch after my sig apparently fixes it...
>
> João
>
> diff --git a/src/nsfns.m b/src/nsfns.m
> index a017be5..c5ff9e5 100644
> --- a/src/nsfns.m
> +++ b/src/nsfns.m
> @@ -2800,7 +2800,7 @@ with offset DY added (default is -10).
>    if (ns_tooltip == nil)
>      ns_tooltip = [[EmacsTooltip alloc] init];
>    else
> -    Fx_hide_tip ();
> +    Fx_hide_tip (frame);
>
>    [ns_tooltip setText: str];
>    size = [ns_tooltip frame].size;
> @@ -2817,7 +2817,7 @@ with offset DY added (default is -10).
>  }
>
>
> -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.
>  Value is t if tooltip was open, nil otherwise.  */)
>       (void)
>
>
>
>
>
>
>
>


-- 
João Távora

[-- Attachment #2: Type: text/html, Size: 2647 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-12 22:06 ` João Távora
@ 2016-07-12 22:26   ` John Wiegley
  2016-07-14  5:41     ` Dmitry Antipov
  0 siblings, 1 reply; 25+ messages in thread
From: John Wiegley @ 2016-07-12 22:26 UTC (permalink / raw)
  To: João Távora; +Cc: dmantipov, emacs-devel

>>>>> "JT" == João Távora <joaotavora@gmail.com> writes:

JT> Disregard the patch attached (and the diagnostic). My fix doesn't work for
JT> some reason I have yet to investigate.

JT> The problem is still there, though.

OK, I am going to revert until we've considered the patch in more detail here.

-- 
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-12 22:26   ` John Wiegley
@ 2016-07-14  5:41     ` Dmitry Antipov
  2016-07-14  6:26       ` John Wiegley
  0 siblings, 1 reply; 25+ messages in thread
From: Dmitry Antipov @ 2016-07-14  5:41 UTC (permalink / raw)
  To: emacs-devel; +Cc: John Wiegley, João Távora

[-- Attachment #1: Type: text/plain, Size: 163 bytes --]

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Cleanup-tooltips.patch --]
[-- Type: text/x-diff; name="0001-Cleanup-tooltips.patch", Size: 46788 bytes --]

From 78f46996b084ecb604bd6e284084a3342e11ce41 Mon Sep 17 00:00:00 2001
From: Dmitry Antipov <dmantipov@yandex.ru>
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 ports.
* 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'.
---
 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);
 
-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;
 }
 
 \f
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..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));
 }
 
-
-/* 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 == nil)
     ns_tooltip = [[EmacsTooltip alloc] init];
   else
-    Fx_hide_tip ();
+    Fx_hide_tip (frame);
 
   [ns_tooltip setText: str];
   size = [ns_tooltip frame].size;
@@ -2821,10 +2817,11 @@ with offset DY added (default is -10).
 }
 
 
-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 == 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)
 
 \f
 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 *);
 
@@ -5068,6 +5067,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);
@@ -5215,9 +5215,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)
@@ -5991,7 +5990,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),
@@ -6078,7 +6077,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);
@@ -6481,39 +6480,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.
 
@@ -6558,7 +6524,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
@@ -6570,6 +6536,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 =
@@ -6678,11 +6645,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.
@@ -6710,6 +6673,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++;
@@ -6828,46 +6794,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;
 }
 
 
@@ -6901,7 +6860,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;
@@ -6912,7 +6872,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);
@@ -6934,14 +6894,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)
@@ -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 = 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),
@@ -7026,17 +6990,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.  */
@@ -7056,11 +7025,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 ();
@@ -7164,20 +7130,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;
 }
 \f
 /***********************************************************************
@@ -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 = 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;
 }
 
 \f
@@ -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 */
-- 
2.9.0


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-14  5:41     ` Dmitry Antipov
@ 2016-07-14  6:26       ` John Wiegley
  2016-07-15  6:41         ` Dmitry Antipov
  0 siblings, 1 reply; 25+ messages in thread
From: John Wiegley @ 2016-07-14  6:26 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: João Távora, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 371 bytes --]

>>>>> Dmitry Antipov <dmantipov@yandex.ru> writes:

> Hm...then please try this.

Before trying it, can you please offer some motivation for why we want this
change?  That would help us in reading it.

Thanks,
-- 
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 629 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-14  6:26       ` John Wiegley
@ 2016-07-15  6:41         ` Dmitry Antipov
  2016-07-15  6:46           ` John Wiegley
                             ` (3 more replies)
  0 siblings, 4 replies; 25+ messages in thread
From: Dmitry Antipov @ 2016-07-15  6:41 UTC (permalink / raw)
  To: John Wiegley; +Cc: João Távora, emacs-devel

On 07/14/2016 09:26 AM, John Wiegley wrote:

> Before trying it, can you please offer some motivation for why we want this
> change?  That would help us in reading it.

For NS, this is a no-op.

For others, this addresses the cases where tooltips are 'first-class'
frames in Emacs terms (--with-x-toolkit={no,lucid,motif}, MS Windows,
GTK[23] builds when 'x-gtk-use-system-tooltips' is nil). The goal was
to avoid tricky global variables and (hopefully) to reduce overall
complexity of the relevant code.

Dmitry




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15  6:41         ` Dmitry Antipov
@ 2016-07-15  6:46           ` John Wiegley
  2016-07-15  7:25           ` Eli Zaretskii
                             ` (2 subsequent siblings)
  3 siblings, 0 replies; 25+ messages in thread
From: John Wiegley @ 2016-07-15  6:46 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: João Távora, emacs-devel

>>>>> Dmitry Antipov <dmantipov@yandex.ru> writes:

DA> For NS, this is a no-op.

At least one user has reported that it breaks the NS build...

-- 
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15  6:41         ` Dmitry Antipov
  2016-07-15  6:46           ` John Wiegley
@ 2016-07-15  7:25           ` Eli Zaretskii
  2016-07-15  7:28           ` martin rudalics
  2016-07-15 13:35           ` Stefan Monnier
  3 siblings, 0 replies; 25+ messages in thread
From: Eli Zaretskii @ 2016-07-15  7:25 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: jwiegley, joaotavora, emacs-devel

> From: Dmitry Antipov <dmantipov@yandex.ru>
> Date: Fri, 15 Jul 2016 09:41:32 +0300
> Cc: João Távora <joaotavora@gmail.com>,
> 	emacs-devel <emacs-devel@gnu.org>
> 
> For others, this addresses the cases where tooltips are 'first-class'
> frames in Emacs terms (--with-x-toolkit={no,lucid,motif}, MS Windows,
> GTK[23] builds when 'x-gtk-use-system-tooltips' is nil). The goal was
> to avoid tricky global variables and (hopefully) to reduce overall
> complexity of the relevant code.

What are the advantages of making tooltip frame "first-class" frames?
IOW, what can't we currently do with tooltip frames that we will be
able to do after your changes?



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15  6:41         ` Dmitry Antipov
  2016-07-15  6:46           ` John Wiegley
  2016-07-15  7:25           ` Eli Zaretskii
@ 2016-07-15  7:28           ` martin rudalics
  2016-07-15  8:02             ` Eli Zaretskii
  2016-07-15 13:35           ` Stefan Monnier
  3 siblings, 1 reply; 25+ messages in thread
From: martin rudalics @ 2016-07-15  7:28 UTC (permalink / raw)
  To: Dmitry Antipov, John Wiegley; +Cc: João Távora, emacs-devel

 > For others, this addresses the cases where tooltips are 'first-class'
 > frames in Emacs terms (--with-x-toolkit={no,lucid,motif}, MS Windows,
 > GTK[23] builds when 'x-gtk-use-system-tooltips' is nil). The goal was
 > to avoid tricky global variables and (hopefully) to reduce overall
 > complexity of the relevant code.

Why do we need frame parameters when there can be only one tooltip per
display?  Why not put the tooltip timer and the last_show_tip_args into
the display info too just like you did with tip_frame?

martin



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15  7:28           ` martin rudalics
@ 2016-07-15  8:02             ` Eli Zaretskii
  2016-07-15  9:10               ` martin rudalics
  0 siblings, 1 reply; 25+ messages in thread
From: Eli Zaretskii @ 2016-07-15  8:02 UTC (permalink / raw)
  To: martin rudalics; +Cc: jwiegley, dmantipov, joaotavora, emacs-devel

> Date: Fri, 15 Jul 2016 09:28:45 +0200
> From: martin rudalics <rudalics@gmx.at>
> Cc: João Távora <joaotavora@gmail.com>,
> 	emacs-devel <emacs-devel@gnu.org>
> 
> Why not put the tooltip timer and the last_show_tip_args into the
> display info too just like you did with tip_frame?

What will that buy us?



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15  8:02             ` Eli Zaretskii
@ 2016-07-15  9:10               ` martin rudalics
  0 siblings, 0 replies; 25+ messages in thread
From: martin rudalics @ 2016-07-15  9:10 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jwiegley, dmantipov, joaotavora, emacs-devel

 > What will that buy us?

Nothing probably.  I intuitively dislike the idea of having a timer
sit on a frame parameter.

martin






^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15  6:41         ` Dmitry Antipov
                             ` (2 preceding siblings ...)
  2016-07-15  7:28           ` martin rudalics
@ 2016-07-15 13:35           ` Stefan Monnier
  2016-07-15 13:51             ` Clément Pit--Claudel
  2016-07-15 14:08             ` Dmitry Gutov
  3 siblings, 2 replies; 25+ messages in thread
From: Stefan Monnier @ 2016-07-15 13:35 UTC (permalink / raw)
  To: emacs-devel

>> Before trying it, can you please offer some motivation for why we want this
>> change?  That would help us in reading it.
> For NS, this is a no-op.
> For others, this addresses the cases where tooltips are 'first-class'
> frames in Emacs terms (--with-x-toolkit={no,lucid,motif}, MS Windows,
> GTK[23] builds when 'x-gtk-use-system-tooltips' is nil). The goal was
> to avoid tricky global variables and (hopefully) to reduce overall
> complexity of the relevant code.

I'm completely unfamiliar with this code so can't say anything
intelligent about that change (and don't have any opinion whether it's
good or not).

But it does ring a bell here: for company-mode's popup menus, we'd want
to be able to create non-toolkit popup frames, even if Emacs was built
with support for toolkit popup frames.


        Stefan




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 13:35           ` Stefan Monnier
@ 2016-07-15 13:51             ` Clément Pit--Claudel
  2016-07-15 14:09               ` Eli Zaretskii
  2016-07-15 14:08             ` Dmitry Gutov
  1 sibling, 1 reply; 25+ messages in thread
From: Clément Pit--Claudel @ 2016-07-15 13:51 UTC (permalink / raw)
  To: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 1316 bytes --]

On 2016-07-15 15:35, Stefan Monnier wrote:
>>> Before trying it, can you please offer some motivation for why we want this
>>> change?  That would help us in reading it.
>> For NS, this is a no-op.
>> For others, this addresses the cases where tooltips are 'first-class'
>> frames in Emacs terms (--with-x-toolkit={no,lucid,motif}, MS Windows,
>> GTK[23] builds when 'x-gtk-use-system-tooltips' is nil). The goal was
>> to avoid tricky global variables and (hopefully) to reduce overall
>> complexity of the relevant code.
> 
> I'm completely unfamiliar with this code so can't say anything
> intelligent about that change (and don't have any opinion whether it's
> good or not).
> 
> But it does ring a bell here: for company-mode's popup menus, we'd want
> to be able to create non-toolkit popup frames, even if Emacs was built
> with support for toolkit popup frames.

I can't say anything about the patch either, but something confuses me a bit: why does displaying non-toolkit popups require so much C code? If we just extracted the ability to create chrome-less frames from that code, couldn't all the rest be written in Lisp?

I tried to do this and got things semi-working with Eli's help, but then got confused about what had to be done for it to work on Windows as well.

Clément.


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 13:35           ` Stefan Monnier
  2016-07-15 13:51             ` Clément Pit--Claudel
@ 2016-07-15 14:08             ` Dmitry Gutov
  2016-07-15 15:20               ` martin rudalics
  1 sibling, 1 reply; 25+ messages in thread
From: Dmitry Gutov @ 2016-07-15 14:08 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

On 07/15/2016 04:35 PM, Stefan Monnier wrote:

> I'm completely unfamiliar with this code so can't say anything
> intelligent about that change (and don't have any opinion whether it's
> good or not).

Same here, but...

> But it does ring a bell here: for company-mode's popup menus, we'd want
> to be able to create non-toolkit popup frames, even if Emacs was built
> with support for toolkit popup frames.

We also want to be able to show multiple popup frames simultaneously. 
Avoiding global variables seems like a good change in this regard.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 13:51             ` Clément Pit--Claudel
@ 2016-07-15 14:09               ` Eli Zaretskii
  2016-07-15 14:21                 ` Clément Pit--Claudel
  0 siblings, 1 reply; 25+ messages in thread
From: Eli Zaretskii @ 2016-07-15 14:09 UTC (permalink / raw)
  To: Clément Pit--Claudel; +Cc: emacs-devel

> From: Clément Pit--Claudel <clement.pit@gmail.com>
> Date: Fri, 15 Jul 2016 15:51:42 +0200
> 
> why does displaying non-toolkit popups require so much C code? If we just extracted the ability to create chrome-less frames from that code, couldn't all the rest be written in Lisp?

Frame-creation code is mostly in C.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 14:09               ` Eli Zaretskii
@ 2016-07-15 14:21                 ` Clément Pit--Claudel
  2016-07-15 14:25                   ` Eli Zaretskii
  0 siblings, 1 reply; 25+ messages in thread
From: Clément Pit--Claudel @ 2016-07-15 14:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 668 bytes --]

On 2016-07-15 16:09, Eli Zaretskii wrote:
>> From: Clément Pit--Claudel <clement.pit@gmail.com> Date: Fri, 15
>> Jul 2016 15:51:42 +0200
>> 
>> why does displaying non-toolkit popups require so much C code? If
>> we just extracted the ability to create chrome-less frames from
>> that code, couldn't all the rest be written in Lisp?
> 
> Frame-creation code is mostly in C.

Sure, but that code (the one that ‘make-frame’ calls) already exists independently of the code for popups, right? If that's correct, couldn't one imagine the non-toolkit pop-up code being entirely moved to lisp, with the exception of the part that makes a frame frame chromeless?


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 14:21                 ` Clément Pit--Claudel
@ 2016-07-15 14:25                   ` Eli Zaretskii
  2016-07-15 15:14                     ` Clément Pit--Claudel
  0 siblings, 1 reply; 25+ messages in thread
From: Eli Zaretskii @ 2016-07-15 14:25 UTC (permalink / raw)
  To: Clément Pit--Claudel; +Cc: emacs-devel

> Cc: emacs-devel@gnu.org
> From: Clément Pit--Claudel <clement.pit@gmail.com>
> Date: Fri, 15 Jul 2016 16:21:12 +0200
> 
> > Frame-creation code is mostly in C.
> 
> Sure, but that code (the one that ‘make-frame’ calls) already exists independently of the code for popups, right? If that's correct, couldn't one imagine the non-toolkit pop-up code being entirely moved to lisp, with the exception of the part that makes a frame frame chromeless?

Maybe I misunderstand what you have in mind, but there's almost
nothing to move to Lisp after that exception.  Take a look at
tooltip.el -- that's all that's left for Lisp to do about tooltips.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 14:25                   ` Eli Zaretskii
@ 2016-07-15 15:14                     ` Clément Pit--Claudel
  2016-07-15 16:04                       ` Eli Zaretskii
  0 siblings, 1 reply; 25+ messages in thread
From: Clément Pit--Claudel @ 2016-07-15 15:14 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 1079 bytes --]

On 2016-07-15 16:25, Eli Zaretskii wrote:
>> Cc: emacs-devel@gnu.org
>> From: Clément Pit--Claudel <clement.pit@gmail.com>
>> Date: Fri, 15 Jul 2016 16:21:12 +0200
>>
>>> Frame-creation code is mostly in C.
>>
>> Sure, but that code (the one that ‘make-frame’ calls) already exists independently of the code for popups, right? If that's correct, couldn't one imagine the non-toolkit pop-up code being entirely moved to lisp, with the exception of the part that makes a frame frame chromeless?
> 
> Maybe I misunderstand what you have in mind, but there's almost
> nothing to move to Lisp after that exception.  Take a look at
> tooltip.el -- that's all that's left for Lisp to do about tooltips.

I think it's more likely that I'm misunderstanding the C code :) Looking in xfns.c, there seems to be about 1000 lines of code for tooltips, and significant overlap between x_create_frame and x_create_tip_frame. Most of the rest (about 700 lines) seems to be code that deals with creating timers, and showing and hiding tooltip frames. Isn't that right?

Clément.


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 14:08             ` Dmitry Gutov
@ 2016-07-15 15:20               ` martin rudalics
  2016-07-15 16:12                 ` Clément Pit--Claudel
  0 siblings, 1 reply; 25+ messages in thread
From: martin rudalics @ 2016-07-15 15:20 UTC (permalink / raw)
  To: Dmitry Gutov, Stefan Monnier, emacs-devel

 >> But it does ring a bell here: for company-mode's popup menus, we'd want
 >> to be able to create non-toolkit popup frames, even if Emacs was built
 >> with support for toolkit popup frames.
 >
 > We also want to be able to show multiple popup frames simultaneously. Avoiding global variables seems like a good change in this regard.

Tooltips can't be used for that purpose because there's inherently only
one tooltip for any instance of Emacs.  Dimitry relaxes this restriction
slightly by allowing one tooltip per display.  Neither of these
restrictions is really necessary.  We could allow an arbitrary number of
tooltips simultaneously with the minor drawback that one sometimes has
to scan the frame list for finding them.  No great deal.

One question is whether and what kind of input we want for such frames.
Or, as Eli would put it, whether they should become "first-class"
frames.  And obviously some support is needed like, for example, a
‘move-frame-functions’ hook to allow "non-child" popup frames move
together with their parent frame.

I have so called "mini frames" working here.  If anyone's interested I
can post the patch (obviously to be applied before Dimitry's changes).

martin




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 15:14                     ` Clément Pit--Claudel
@ 2016-07-15 16:04                       ` Eli Zaretskii
  2016-07-15 16:16                         ` Clément Pit--Claudel
  0 siblings, 1 reply; 25+ messages in thread
From: Eli Zaretskii @ 2016-07-15 16:04 UTC (permalink / raw)
  To: Clément Pit--Claudel; +Cc: emacs-devel

> Cc: emacs-devel@gnu.org
> From: Clément Pit--Claudel <clement.pit@gmail.com>
> Date: Fri, 15 Jul 2016 17:14:19 +0200
> 
> Looking in xfns.c, there seems to be about 1000 lines of code for tooltips, and significant overlap between x_create_frame and x_create_tip_frame. Most of the rest (about 700 lines) seems to be code that deals with creating timers, and showing and hiding tooltip frames. Isn't that right?

So which part(s) of that would you like to move to Lisp?



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 15:20               ` martin rudalics
@ 2016-07-15 16:12                 ` Clément Pit--Claudel
  2016-07-15 16:41                   ` martin rudalics
  0 siblings, 1 reply; 25+ messages in thread
From: Clément Pit--Claudel @ 2016-07-15 16:12 UTC (permalink / raw)
  To: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 274 bytes --]

On 2016-07-15 17:20, martin rudalics wrote:
> I have so called "mini frames" working here.  If anyone's interested I
> can post the patch (obviously to be applied before Dimitry's changes).

Yes yes yes! :)
company-mode would benefit tremendously from such a thing.


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 16:04                       ` Eli Zaretskii
@ 2016-07-15 16:16                         ` Clément Pit--Claudel
  2016-07-15 17:37                           ` Eli Zaretskii
  0 siblings, 1 reply; 25+ messages in thread
From: Clément Pit--Claudel @ 2016-07-15 16:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 769 bytes --]

On 2016-07-15 18:04, Eli Zaretskii wrote:
>> Cc: emacs-devel@gnu.org From: Clément Pit--Claudel
>> <clement.pit@gmail.com> Date: Fri, 15 Jul 2016 17:14:19 +0200
>> 
>> Looking in xfns.c, there seems to be about 1000 lines of code for
>> tooltips, and significant overlap between x_create_frame and
>> x_create_tip_frame. Most of the rest (about 700 lines) seems to be
>> code that deals with creating timers, and showing and hiding
>> tooltip frames. Isn't that right?
> 
> So which part(s) of that would you like to move to Lisp?

Everything except x_create_tip_frame :) And then x_create_frame could be refactored to allow x_create_tip_frame to just call it.

But this is far beyond my current understanding of Emacs' C, unfortunately :/

Clément.


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 16:12                 ` Clément Pit--Claudel
@ 2016-07-15 16:41                   ` martin rudalics
  0 siblings, 0 replies; 25+ messages in thread
From: martin rudalics @ 2016-07-15 16:41 UTC (permalink / raw)
  To: Clément Pit--Claudel, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 347 bytes --]

 > company-mode would benefit tremendously from such a thing.

Attached.  mini-frame.diff is against master from this morning and
contains unrelated stuff which should not bother you.  The entry point
is the function ‘make-mini-frame’.  mini-frame.el has some functions to
show how it can be used.  No NS support, obviously.

martin


[-- Attachment #2: mini-frame.diff --]
[-- Type: text/plain, Size: 49068 bytes --]

diff --git a/lisp/frame.el b/lisp/frame.el
index 09738d1..478cc2b 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -144,6 +144,13 @@ handle-focus-out
 This function runs the hook `focus-out-hook'."
   (interactive "e")
   (run-hooks 'focus-out-hook))
+
+(defun handle-move-frame (event)
+  "Handle a move-frame event.
+This function runs the abnormal hook `move-frame-functions'."
+  (interactive "e")
+  (let ((frame (posn-window (event-start event))))
+    (run-hook-with-args 'move-frame-functions frame)))
 \f
 ;;;; Arrangement of frames at startup

@@ -1483,6 +1490,90 @@ frame-monitor-attributes
 	   for frames = (cdr (assq 'frames attributes))
 	   if (memq frame frames) return attributes))

+(declare-function x-make-mini-frame "xfns.c" (&optional frame parameters))
+(declare-function w32-make-mini-frame "w32fns.c" (&optional frame parameters))
+
+(defun make-mini-frame (&optional frame parameters)
+  "Make a new mini-frame with FRAME as its parent.
+Optional argument FRAME must specify a live frame.  If omitted,
+FRAME defaults to the selected frame.  The mini-frame is made on
+the same display as FRAME.  Return the new mini-frame, nil if its
+creation failed.
+
+PARAMETERS is a list of frame parameters.  The 'child-window'
+parameter is special: If non-nil, the mini-frame becomes a
+\"child window\" of FRAME.  This usually means that the
+mini-frame is clipped at the boundaries of FRAME and is moved,
+raised, and iconified together with FRAME.  Usually, this also
+means that the position of the mini-frame in the Z-order
+\(stacking order) is always right above FRAME.
+
+'child-window' omitted or nil usually means that the application
+has to take full care of how to raise, move and iconify the
+mini-frame and how to maintain its place in the Z-order (stacking
+order) of frames on the display.  On some platforms, such a
+mini-frame invariably appears on top of all other frames so you
+usually would like to hide it whenever its parent frame is not on
+top of the Z-order or does not have focus.  On other platforms,
+such a mini-frame may appear right above FRAME as with a non-nil
+'child-window' parameter.
+
+The stacking order of mini-frames with the same parent is
+undefined regardless of whether a 'child-window' parameter has
+been specified or not.  On many platforms, the stacking order of
+mini-frames with a non-nil 'child-window' parameter may be also
+undefined wrt control elements (like a scroll bar) which may
+appear under or over the mini-frame, depending on which of them
+has been drawn later.
+
+By default, mini-frames are drawn without any external borders, a
+title bar or the buttons to minimize, maximize or delete the
+frame.  The 'border-width' parameter, which is usually not used
+on \"normal\" frames, can be used to draw a border around the
+mini-frame.  On Windows, specifying a positive number as border
+width produces a one pixel wide external border.  That border is
+also reported as \"external\" by `frame-geometry' which, on
+Windows, always returns value of zero for `border-width'.  On
+both, X and Windows, the border drawn due to this parameter's
+setting is not within the native edges of the mini-frame.
+
+Other aspects of mini-frames are platform-dependent as well.  For
+example, on Windows, the 'alpha' parameter may not work correctly
+when used together with a non-nil 'child-window' parameter.  On
+X, mini-frames with a non-nil 'child-window' parameter may have
+to be explicitly redrawn when their parent frame is deiconified.
+
+The hooks `move-frame-functions', `focus-in-hook',
+`focus-out-hook', `window-configuration-change-hook', and
+‘window-size-change-functions' can be used to control size,
+placing and visibilty of a mini-frame when size, position or
+contents of its parent frame change."
+  (let* ((frame (window-normalize-frame frame))
+	 (frame-type (framep-on-display frame)))
+    (cond
+     ((eq frame-type 'x)
+      (x-create-mini-frame frame parameters))
+     ((eq frame-type 'w32)
+      (w32-create-mini-frame frame parameters)))))
+
+(declare-function x-frame-list-z-order "xfns.c" (&optional display))
+(declare-function w32-frame-list-z-order "w32fns.c" (&optional display))
+
+(defun frame-list-z-order (&optional display)
+  "Return list of Emacs' frames, in Z (stacking) order.
+The optional argument DISPLAY specifies which display to poll.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.
+
+Frames are listed from bottommost (first) to topmost (last).
+Return nil if DISPLAY contains no Emacs frame.  Child frames are
+not listed by this function."
+  (let ((display (framep-on-display display)))
+    (cond
+     ((eq display 'x)
+      (x-frame-list-z-order display))
+     ((eq display 'w32)
+      (w32-frame-list-z-order display)))))
 \f
 ;;;; Frame/display capabilities.

@@ -1882,14 +1973,14 @@ delete-other-frames
   (interactive)
   (unless frame
     (setq frame (selected-frame)))
-  (let* ((mini-frame (window-frame (minibuffer-window frame)))
-	 (frames (delq mini-frame (delq frame (frame-list)))))
+  (let* ((minibuffer-frame (window-frame (minibuffer-window frame)))
+	 (frames (delq minibuffer-frame (delq frame (frame-list)))))
     ;; Only consider frames on the same terminal.
     (dolist (frame (prog1 frames (setq frames nil)))
       (if (eq (frame-terminal) (frame-terminal frame))
           (push frame frames)))
     ;; Delete mon-minibuffer-only frames first, because `delete-frame'
-    ;; signals an error when trying to delete a mini-frame that's
+    ;; signals an error when trying to delete a minibuffer-frame that's
     ;; still in use by another frame.
     (dolist (frame frames)
       (unless (eq (frame-parameter frame 'minibuffer) 'only)
diff --git a/src/frame.c b/src/frame.c
index 22143ab..9d86b07 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -81,11 +81,6 @@
 {
   f->buffer_predicate = val;
 }
-static void
-fset_minibuffer_window (struct frame *f, Lisp_Object val)
-{
-  f->minibuffer_window = val;
-}

 struct frame *
 decode_live_frame (register Lisp_Object frame)
@@ -418,9 +413,13 @@ struct frame *
      sizes and any "new" settings for scroll bars, dividers, fringes and
      margins (though the latter should have been processed already).  */
   min_windows_width
-    = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt);
+    = (f->mini_frame
+       ? unit_width
+       : frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt));
   min_windows_height
-    = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
+    = (f->mini_frame
+       ? unit_height
+       : frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt));

   if (inhibit >= 2 && inhibit <= 4)
     /* When INHIBIT is in [2..4] inhibit if the "old" window sizes stay
@@ -636,6 +635,7 @@ struct frame *
   f->inhibit_vertical_resize = false;
   f->tool_bar_redisplayed = false;
   f->tool_bar_resized = false;
+  f->mini_frame = false;
   f->column_width = 1;  /* !FRAME_WINDOW_P value.  */
   f->line_height = 1;  /* !FRAME_WINDOW_P value.  */
 #ifdef HAVE_WINDOW_SYSTEM
@@ -1381,18 +1381,18 @@ of them (the selected terminal frame) is actually displayed.
 It considers only frames on the same terminal as FRAME.
 By default, skip minibuffer-only frames.
 If omitted, FRAME defaults to the selected frame.
-If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
-If MINIFRAME is a window, include only its own frame
+If optional argument MINIBUF is nil, exclude minibuffer-only frames.
+If MINIBUF is a window, include only its own frame
 and any frame now using that window as the minibuffer.
-If MINIFRAME is `visible', include all visible frames.
-If MINIFRAME is 0, include all visible and iconified frames.
+If MINIBUF is `visible', include all visible frames.
+If MINIBUF is 0, include all visible and iconified frames.
 Otherwise, include all frames.  */)
-  (Lisp_Object frame, Lisp_Object miniframe)
+  (Lisp_Object frame, Lisp_Object minibuf)
 {
   if (NILP (frame))
     frame = selected_frame;
   CHECK_LIVE_FRAME (frame);
-  return next_frame (frame, miniframe);
+  return next_frame (frame, minibuf);
 }

 DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
@@ -1400,18 +1400,18 @@ of them (the selected terminal frame) is actually displayed.
 It considers only frames on the same terminal as FRAME.
 By default, skip minibuffer-only frames.
 If omitted, FRAME defaults to the selected frame.
-If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
-If MINIFRAME is a window, include only its own frame
+If optional argument MINIBUF is nil, exclude minibuffer-only frames.
+If MINIBUF is a window, include only its own frame
 and any frame now using that window as the minibuffer.
-If MINIFRAME is `visible', include all visible frames.
-If MINIFRAME is 0, include all visible and iconified frames.
+If MINIBUF is `visible', include all visible frames.
+If MINIBUF is 0, include all visible and iconified frames.
 Otherwise, include all frames.  */)
-  (Lisp_Object frame, Lisp_Object miniframe)
+  (Lisp_Object frame, Lisp_Object minibuf)
 {
   if (NILP (frame))
     frame = selected_frame;
   CHECK_LIVE_FRAME (frame);
-  return prev_frame (frame, miniframe);
+  return prev_frame (frame, minibuf);
 }

 DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
@@ -1515,7 +1515,7 @@ of them (the selected terminal frame) is actually displayed.
   struct frame *sf;
   struct kboard *kb;

-  int minibuffer_selected, is_tooltip_frame;
+  int minibuffer_selected, tip_or_mini_frame;

   if (! FRAME_LIVE_P (f))
     return Qnil;
@@ -1557,13 +1557,14 @@ of them (the selected terminal frame) is actually displayed.
 	}
     }

-  is_tooltip_frame = !NILP (Fframe_parameter (frame, Qtooltip));
+  tip_or_mini_frame
+    = (!NILP (Fframe_parameter (frame, Qtooltip))
+       || !NILP (Fframe_parameter (frame, Qmini_frame)));

-  /* Run `delete-frame-functions' unless FORCE is `noelisp' or
-     frame is a tooltip.  FORCE is set to `noelisp' when handling
-     a disconnect from the terminal, so we don't dare call Lisp
-     code.  */
-  if (NILP (Vrun_hooks) || is_tooltip_frame)
+  /* Run `delete-frame-functions' unless FORCE is `noelisp' or FRAME is
+     a tip or mini-frame.  FORCE is set to `noelisp' when handling a
+     disconnect from the terminal, so we don't dare call Lisp code.  */
+  if (NILP (Vrun_hooks) || tip_or_mini_frame)
     ;
   else if (EQ (force, Qnoelisp))
     pending_funcalls
@@ -1815,7 +1816,7 @@ of them (the selected terminal frame) is actually displayed.
     }

   /* Cause frame titles to update--necessary if we now have just one frame.  */
-  if (!is_tooltip_frame)
+  if (!tip_or_mini_frame)
     update_mode_lines = 15;

   return Qnil;
@@ -4901,6 +4902,7 @@ or a list (- N) meaning -N pixels relative to bottom/right corner.
   DEFSYM (Qicon_left, "icon-left");
   DEFSYM (Qicon_top, "icon-top");
   DEFSYM (Qtooltip, "tooltip");
+  DEFSYM (Qmini_frame, "mini-frame");
   DEFSYM (Quser_position, "user-position");
   DEFSYM (Quser_size, "user-size");
   DEFSYM (Qwindow_id, "window-id");
@@ -5138,6 +5140,11 @@ even if the end of the buffer is shown (i.e. overscrolling).
                doc: /* Normal hook run when a frame loses input focus.  */);
   Vfocus_out_hook = Qnil;

+  DEFVAR_LISP ("move-frame-functions", Vmove_frame_functions,
+               doc: /* Functions run after a frame was moved.
+The functions are run with one arg, the frame that moved.  */);
+  Vmove_frame_functions = Qnil;
+
   DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
 	       doc: /* Functions run before deleting a frame.
 The functions are run with one arg, the frame to be deleted.
diff --git a/src/frame.h b/src/frame.h
index 5e3ee68..16c5a92 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -342,6 +342,9 @@ struct frame
   /* Non-zero if this frame's faces need to be recomputed.  */
   bool_bf face_change : 1;

+  /* True means this a mini-frame.  */
+  bool_bf mini_frame : 1;
+
   /* Bitfield area ends here.  */

   /* Number of lines (rounded up) of tool bar.  REMOVE THIS  */
@@ -515,6 +518,12 @@ struct frame
 /* Most code should use these functions to set Lisp fields in struct frame.  */

 INLINE void
+fset_minibuffer_window (struct frame *f, Lisp_Object val)
+{
+  f->minibuffer_window = val;
+}
+
+INLINE void
 fset_buffer_list (struct frame *f, Lisp_Object val)
 {
   f->buffer_list = val;
diff --git a/src/keyboard.c b/src/keyboard.c
index 653f527..e4b4fcd 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4048,6 +4048,14 @@ static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, bool *used_mouse_menu,
 	  kbd_fetch_ptr = event + 1;
 	}
 #endif
+#if defined (HAVE_X11) || defined (HAVE_NTGUI)
+      else if (event->kind == MOVE_FRAME_EVENT)
+	{
+	  /* Make an event (move-frame (FRAME)).  */
+	  obj = list2 (Qmove_frame, list1 (event->ie.frame_or_window));
+	  kbd_fetch_ptr = event + 1;
+	}
+#endif
 #ifdef HAVE_XWIDGETS
       else if (event->kind == XWIDGET_EVENT)
 	{
@@ -10936,6 +10944,7 @@ struct event_head

   {SYMBOL_INDEX (Qfocus_in),            SYMBOL_INDEX (Qfocus_in)},
   {SYMBOL_INDEX (Qfocus_out),           SYMBOL_INDEX (Qfocus_out)},
+  {SYMBOL_INDEX (Qmove_frame),          SYMBOL_INDEX (Qmove_frame)},
   {SYMBOL_INDEX (Qdelete_frame),        SYMBOL_INDEX (Qdelete_frame)},
   {SYMBOL_INDEX (Qiconify_frame),       SYMBOL_INDEX (Qiconify_frame)},
   {SYMBOL_INDEX (Qmake_frame_visible),  SYMBOL_INDEX (Qmake_frame_visible)},
@@ -11108,6 +11117,7 @@ struct event_head
   DEFSYM (Qswitch_frame, "switch-frame");
   DEFSYM (Qfocus_in, "focus-in");
   DEFSYM (Qfocus_out, "focus-out");
+  DEFSYM (Qmove_frame, "move-frame");
   DEFSYM (Qdelete_frame, "delete-frame");
   DEFSYM (Qiconify_frame, "iconify-frame");
   DEFSYM (Qmake_frame_visible, "make-frame-visible");
@@ -11846,6 +11856,8 @@ shutdown when Emacs receives a fatal signal (e.g., a crash).
 			    "handle-focus-in");
   initial_define_lispy_key (Vspecial_event_map, "focus-out",
 			    "handle-focus-out");
+  initial_define_lispy_key (Vspecial_event_map, "move-frame",
+			    "handle-move-frame");
 }

 /* Mark the pointers in the kboard objects.
diff --git a/src/termhooks.h b/src/termhooks.h
index ff74d99..9829b50 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -202,6 +202,9 @@ enum event_kind

   FOCUS_OUT_EVENT,

+  /* Generated when a frame is moved.  */
+  MOVE_FRAME_EVENT,
+
   /* Generated when mouse moves over window not currently selected.  */
   SELECT_WINDOW_EVENT,

diff --git a/src/w32fns.c b/src/w32fns.c
index d6b54d1..70e0ab3 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -345,7 +345,7 @@ struct frame *
 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 *);
+static void my_create_tip_window (struct frame *, bool, Lisp_Object);

 /* TODO: Native Input Method support; see x_create_im.  */
 void x_set_foreground_color (struct frame *, Lisp_Object, Lisp_Object);
@@ -5065,42 +5065,39 @@ struct frame *
    messages for the tooltip.  Creating tooltips indirectly also creates
    deadlocks when tooltips are created for menu items.  */
 static void
-my_create_tip_window (struct frame *f)
+my_create_tip_window (struct frame *f, bool mini_frame, Lisp_Object owner)
 {
   RECT rect;
+  Window window;

   rect.left = rect.top = 0;
   rect.right = FRAME_PIXEL_WIDTH (f);
   rect.bottom = FRAME_PIXEL_HEIGHT (f);
-
   AdjustWindowRect (&rect, f->output_data.w32->dwStyle, false);

-  tip_window = FRAME_W32_WINDOW (f)
-    = CreateWindow (EMACS_CLASS,
-		    f->namebuf,
-		    f->output_data.w32->dwStyle,
-		    f->left_pos,
-		    f->top_pos,
-		    rect.right - rect.left,
-		    rect.bottom - rect.top,
-		    FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
-		    NULL,
-		    hinst,
-		    NULL);
-
-  if (tip_window)
+  if (window
+      = CreateWindow (EMACS_CLASS, f->namebuf, f->output_data.w32->dwStyle,
+		      f->left_pos, f->top_pos,
+		      rect.right - rect.left, rect.bottom - rect.top,
+		      (FRAME_W32_WINDOW /* owner */
+		       (mini_frame ? XFRAME (owner) : SELECTED_FRAME ())),
+		      NULL, hinst, NULL))
     {
-      SetWindowLong (tip_window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
-      SetWindowLong (tip_window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
-      SetWindowLong (tip_window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
-      SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
+      FRAME_W32_WINDOW (f) = window;
+      if (!mini_frame)
+	tip_window = FRAME_W32_WINDOW (f);
+
+      SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
+      SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
+      SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
+      SetWindowLong (window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));

       /* Tip frames have no scrollbars.  */
-      SetWindowLong (tip_window, WND_VSCROLLBAR_INDEX, 0);
-      SetWindowLong (tip_window, WND_HSCROLLBAR_INDEX, 0);
+      SetWindowLong (window, WND_VSCROLLBAR_INDEX, 0);
+      SetWindowLong (window, WND_HSCROLLBAR_INDEX, 0);

       /* Do this to discard the default setting specified by our parent. */
-      ShowWindow (tip_window, SW_HIDE);
+      ShowWindow (window, SW_HIDE);
     }
 }

@@ -6515,7 +6512,8 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,


 /* Create a frame for a tooltip on the display described by DPYINFO.
-   PARMS is a list of frame parameters.  Value is the frame.
+   PARMS is a list of frame parameters.  MINI_FRAME true means to create
+   a mini-frame.  Value is the frame.

    Note that functions called here, esp. x_default_parameter can
    signal errors, for instance when a specified color name is
@@ -6523,7 +6521,7 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
    when this happens.  */

 static Lisp_Object
-x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
+x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms, bool mini_frame, Lisp_Object owner)
 {
   struct frame *f;
   Lisp_Object frame;
@@ -6558,7 +6556,10 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
   f->wants_modeline = false;
   XSETFRAME (frame, f);

-  record_unwind_protect (unwind_create_tip_frame, frame);
+  if (mini_frame)
+    record_unwind_protect (do_unwind_create_frame, frame);
+  else
+    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
@@ -6606,7 +6607,8 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
      that are needed to determine window geometry.  */
   x_default_font_parameter (f, parms);

-  x_default_parameter (f, parms, Qborder_width, make_number (2),
+  x_default_parameter (f, parms, Qborder_width,
+		       make_number (mini_frame ? 0 : 2),
 		       "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
   /* This defaults to 2 in order to match xterm.  We recognize either
      internalBorderWidth or internalBorder (which is what xterm calls
@@ -6622,7 +6624,8 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
 		       parms);
     }

-  x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
+  x_default_parameter (f, parms, Qinternal_border_width,
+		       make_number (mini_frame ? 0 : 1),
 		       "internalBorderWidth", "internalBorderWidth",
 		       RES_TYPE_NUMBER);
   /* Also do the stuff which must be set before the window exists.  */
@@ -6642,7 +6645,29 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
      init_iterator with a null face cache, which should not happen.  */
   init_frame_faces (f);

-  f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
+  /* Handle `child-window' and `border-width' separately for
+     mini-frames.  */
+  if (mini_frame)
+    {
+      Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
+
+      f->output_data.w32->dwStyle =
+	(!NILP (Fassq (Qchild_window, parms))) ? WS_CHILD : WS_POPUP;
+
+      /* Always disable input.  */
+      f->output_data.w32->dwStyle =
+	f->output_data.w32->dwStyle | WS_DISABLED;
+
+      /* Have Windows draw a "thin-line border".  `border-width' is
+	 usually dismissed on Windows but for mini frames, if it's
+	 non-zero, draw a standard thin border around the frame. */
+      if (NUMBERP (border_width) && (XINT (border_width) > 0))
+	f->output_data.w32->dwStyle =
+	  f->output_data.w32->dwStyle | WS_BORDER;
+    }
+  else
+    f->output_data.w32->dwStyle = WS_DISABLED | WS_BORDER | WS_POPUP;
+
   f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;

   x_figure_window_size (f, parms, true, &x_width, &x_height);
@@ -6656,7 +6681,7 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
   f->bottom_divider_width = 0;

   block_input ();
-  my_create_tip_window (f);
+  my_create_tip_window (f, mini_frame, owner);
   unblock_input ();

   x_make_gc (f);
@@ -6680,8 +6705,10 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
   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)))
+  /* Add `mini-frame' or `tooltip' frame parameter's default value. */
+  if (mini_frame && NILP (Fframe_parameter (frame, Qmini_frame)))
+    Fmodify_frame_parameters (frame, Fcons (Fcons (Qmini_frame, Qt), Qnil));
+  if (!mini_frame && 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
@@ -7060,7 +7087,7 @@ with offset DY added (default is -10).
       /* 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 (f), parms, false, Qnil)))
 	{
 	  /* Creating the tip frame failed.  */
 	  unblock_input ();
@@ -7071,6 +7098,7 @@ with offset DY added (default is -10).
   tip_f = XFRAME (tip_frame);
   window = FRAME_ROOT_WINDOW (tip_f);
   set_window_buffer (window, Fget_buffer_create (tip), false, false);
+
   w = XWINDOW (window);
   w->pseudo_window_p = true;

@@ -7179,6 +7207,89 @@ with offset DY added (default is -10).
 {
   return x_hide_tip (!tooltip_reuse_hidden_frame);
 }
+
+
+DEFUN ("w32-create-mini-frame", Fw32_create_mini_frame, Sw32_create_mini_frame, 1, 2, 0,
+       doc: /* Create a mini-frame.
+FRAME is the frame where to attach this one to.  PARAMETERS is an alist of
+frame paramaters.
+
+The following parameters are special:
+
+- 'child-window" makes the new frame a child window of FRAME.  This has
+  a number of consequences.  On Windows 'alpha' does not necessarily
+  work if this is set.
+
+- 'external-border' enables external border.  */)
+     (Lisp_Object frame, Lisp_Object parameters)
+{
+  struct frame *f = decode_window_system_frame (frame);
+  Lisp_Object tip_frame;
+  ptrdiff_t count = SPECPDL_INDEX ();
+  long window_prompting = 0;
+
+  if (!FRAME_W32_P (f) || NILP (FRAME_MINIBUF_WINDOW(f)))
+    error ("Cannot create tip-like frame for non-GUI or minibuffer-less frame");
+
+  /* Make copy of frame parameters because the original is in pure
+     storage now. */
+  parameters = Fcopy_alist (parameters);
+
+  specbind (Qinhibit_redisplay, Qt);
+  block_input ();
+  if (!NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parameters, true, frame)))
+    {
+      struct frame *tip_f;
+      struct window *w;
+      int old_windows_or_buffers_changed = windows_or_buffers_changed;
+      Lisp_Object window, tem;
+      Lisp_Object visibility;
+      int x_width = 0, x_height = 0;
+
+      tip_f = XFRAME (tip_frame);
+      window = FRAME_ROOT_WINDOW (tip_f);
+      w = XWINDOW (window);
+      w->pseudo_window_p = true;
+
+      fset_minibuffer_window (tip_f, FRAME_MINIBUF_WINDOW (f));
+      FRAME_EXTERNAL_MENU_BAR (tip_f) = false;
+
+      window_prompting
+	= x_figure_window_size (tip_f, parameters, true, &x_width, &x_height);
+
+      tip_f->mini_frame = true;
+      /* Allow x_set_window_size, now.  */
+      tip_f->can_x_set_window_size = true;
+
+      if (x_width > 0)
+	SET_FRAME_WIDTH (tip_f, x_width);
+      if (x_height > 0)
+	SET_FRAME_HEIGHT (tip_f, x_height);
+
+      adjust_frame_size (tip_f, FRAME_TEXT_WIDTH (tip_f), FRAME_TEXT_HEIGHT (tip_f),
+			 0, true, Qx_create_frame_2); /* NEW SYMBOL NEEDED */
+
+      visibility = x_get_arg (FRAME_DISPLAY_INFO (f), parameters,
+			      Qvisibility, 0, 0, RES_TYPE_SYMBOL);
+      if (EQ (visibility, Qunbound) || !NILP (visibility))
+	SET_FRAME_VISIBLE (tip_f, 1);
+
+      ShowWindow (FRAME_W32_WINDOW (tip_f),
+		  (EQ (visibility, Qunbound) || !NILP (visibility))
+		  ? SW_SHOWNOACTIVATE : SW_HIDE);
+
+      w->must_be_updated_p = true;
+      update_single_window (w);
+      windows_or_buffers_changed = old_windows_or_buffers_changed;
+
+      for (tem = parameters; CONSP (tem); tem = XCDR (tem))
+	if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
+	  fset_param_alist (tip_f, Fcons (XCAR (tem), tip_f->param_alist));
+    }
+
+  unblock_input ();
+  return unbind_to (count, tip_frame);
+}
 \f
 /***********************************************************************
 			File selection dialog
@@ -8563,6 +8674,58 @@ value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
     }
 }

+static Lisp_Object
+w32_frame_list_z_order (struct w32_display_info *dpyinfo, HWND window, Lisp_Object frames)
+{
+  while (window)
+    {
+      HWND child;
+      struct frame *f = x_window_to_frame (dpyinfo, window);
+      Lisp_Object frame;
+
+      /* Process child windows first - they precede their parent in the
+	 z-order.  */
+      block_input ();
+      child = GetWindow (window, GW_CHILD);
+      unblock_input ();
+      if (child)
+	frames = w32_frame_list_z_order (dpyinfo, child, frames);
+
+      if (f)
+	{
+	  XSETFRAME (frame, f);
+	  frames = Fcons (frame, frames);
+	}
+
+      block_input ();
+      window = GetNextWindow (window, GW_HWNDNEXT);
+      unblock_input ();
+    }
+
+  return frames;
+}
+
+DEFUN ("w32-frame-list-z-order", Fw32_frame_list_z_order,
+       Sw32_frame_list_z_order, 0, 1, 0,
+       doc: /* Return list of Emacs' frames, in Z (stacking) order.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.
+
+Frames are listed from bottommost (first) to topmost (last).  Return
+nil if DISPLAY contains no Emacs frame.  */)
+  (Lisp_Object display)
+{
+  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  HWND window;
+
+  block_input ();
+  window = GetTopWindow (NULL);
+  unblock_input ();
+
+  return w32_frame_list_z_order (dpyinfo, window, Qnil);
+}
+
 DEFUN ("w32-mouse-absolute-pixel-position", Fw32_mouse_absolute_pixel_position,
        Sw32_mouse_absolute_pixel_position, 0, 0, 0,
        doc: /* Return absolute position of mouse cursor in pixels.
@@ -9709,6 +9872,41 @@ enum NI_Severity {

 #endif	/* WINDOWSNT && !HAVE_DBUS */

+/* XXXXXXXXXXXXXXXXXXXXX */
+#ifdef WINDOWSNT
+DEFUN ("w32-focus", Fw32_focus, Sw32_focus,
+       0, 0, 0,
+       doc: /* Return t if the selected frame has focus.  */)
+     (void)
+{
+  HWND focus_window;
+
+  block_input ();
+  focus_window = GetFocus ();
+  unblock_input ();
+
+  return focus_window == NULL ? Qnil : Qt;
+}
+
+DEFUN ("w32-foreground-window", Fw32_foreground_window, Sw32_foreground_window,
+       0, 0, 0,
+       doc: /* Return frame of current foreground window, if it's ours.  */)
+     (void)
+{
+  Lisp_Object frame;
+  struct frame *f;
+  struct w32_display_info *dpyinfo = &one_w32_display_info;
+
+  block_input ();
+  f = x_window_to_frame (dpyinfo, GetForegroundWindow ());
+  unblock_input ();
+  XSETFRAME (frame, f);
+
+  return frame;
+}
+
+#endif
+/* XXXXXXXXXXXXXXXXXXXXXXXX */
 \f
 /***********************************************************************
 			    Initialization
@@ -9781,6 +9979,7 @@ enum NI_Severity {
   DEFSYM (Qmm_size, "mm-size");
   DEFSYM (Qframes, "frames");
   DEFSYM (Qtip_frame, "tip-frame");
+  DEFSYM (Qchild_window, "child-window");
   DEFSYM (Qassq_delete_all, "assq-delete-all");
   DEFSYM (Qunicode_sip, "unicode-sip");
 #if defined WINDOWSNT && !defined HAVE_DBUS
@@ -10094,6 +10293,15 @@ successive mouse move (or scroll bar drag) events before they are
 This variable has effect only on Windows Vista and later.  */);
   w32_disable_new_uniscribe_apis = 0;

+  /* XXXXXXXXXXXXXX */
+  DEFVAR_BOOL ("w32-keyboard-hook-active",
+	       w32_keyboard_hook_active,
+	       doc: /* Non-nil means w32 hotkey registration is activated.
+Set this to nil to get the old behavior of hotkey handling; this should
+only be necessary if the default setting causes problems.  */);
+  w32_keyboard_hook_active = true;
+  /* XXXXXXXXXXXXXX */
+
   DEFVAR_LISP ("w32-tooltip-extra-pixels",
 	       Vw32_tooltip_extra_pixels,
 	       doc: /* Number of pixels added after tooltip text.
@@ -10134,6 +10342,7 @@ successive mouse move (or scroll bar drag) events before they are
   defsubr (&Sx_display_list);
   defsubr (&Sw32_frame_geometry);
   defsubr (&Sw32_frame_edges);
+  defsubr (&Sw32_frame_list_z_order);
   defsubr (&Sw32_mouse_absolute_pixel_position);
   defsubr (&Sw32_set_mouse_absolute_pixel_position);
   defsubr (&Sx_synchronize);
@@ -10159,6 +10368,10 @@ successive mouse move (or scroll bar drag) events before they are
 #endif

 #ifdef WINDOWSNT
+  /* XXXXXXXXXXXXXXX */
+  defsubr (&Sw32_focus);
+  defsubr (&Sw32_foreground_window);
+  /* XXXXXXXXXXXXXXX */
   defsubr (&Sfile_system_info);
   defsubr (&Sdefault_printer_name);
 #endif
@@ -10166,6 +10379,7 @@ successive mouse move (or scroll bar drag) events before they are
   defsubr (&Sset_message_beep);
   defsubr (&Sx_show_tip);
   defsubr (&Sx_hide_tip);
+  defsubr (&Sw32_create_mini_frame);
   tip_timer = Qnil;
   staticpro (&tip_timer);
   tip_frame = Qnil;
diff --git a/src/w32term.c b/src/w32term.c
index 5a11e2a..04c6178 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -5015,7 +5015,11 @@ static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object
 	  f = x_window_to_frame (dpyinfo, msg.msg.hwnd);

 	  if (f && !FRAME_ICONIFIED_P (f))
-	    x_real_positions (f, &f->left_pos, &f->top_pos);
+	    {
+	      x_real_positions (f, &f->left_pos, &f->top_pos);
+	      inev.kind = MOVE_FRAME_EVENT;
+	      XSETFRAME (inev.frame_or_window, f);
+	    }

 	  check_visibility = 1;
 	  break;
@@ -6444,9 +6448,11 @@ struct xim_inst_t
 	 frames that were truely hidden (using make-frame-invisible), so
 	 we need it to avoid Bug#5482.  It seems that iconified is only
 	 set for minimized windows that are still visible, so use that to
-	 determine the appropriate flag to pass ShowWindow.  */
+	 determine the appropriate flag to pass to ShowWindow.  */
       my_show_window (f, FRAME_W32_WINDOW (f),
-                      FRAME_ICONIFIED_P (f) ? SW_RESTORE : SW_SHOWNORMAL);
+		      f->mini_frame ? SW_SHOWNOACTIVATE
+                      : FRAME_ICONIFIED_P (f) ? SW_RESTORE
+		      : SW_SHOWNORMAL);
     }

   /* Synchronize to ensure Emacs knows the frame is visible
@@ -6531,7 +6537,8 @@ struct xim_inst_t
   x_set_bitmap_icon (f);

   /* Simulate the user minimizing the frame.  */
-  SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
+/**   SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0); **/
+  my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWMINNOACTIVE);

   SET_FRAME_VISIBLE (f, 0);
   SET_FRAME_ICONIFIED (f, true);
diff --git a/src/window.c b/src/window.c
index e123b89..2ff0dc5 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1896,6 +1896,115 @@ of the (first) text line, YPOS is negative.
   return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
 }

+DEFUN ("window-lines-pixel-dimensions", Fwindow_lines_pixel_dimensions, Swindow_lines_pixel_dimensions, 0, 6, 0,
+       doc: /* Return pixel dimensions of WINDOW's lines.
+The return value is a list of the x- and y-coordinates of the lower
+right corner of the last character of each line.  Return nil if the
+current glyph matrix of WINDOW is not up-to-date.
+
+Optional argument WINDOW specifies the window whose lines' dimensions
+shall be returned.  Nil or omitted means to return the dimensions for
+the selected window.
+
+FIRST, if non-nil, specifies the first line whose dimensions shall be
+returned.  If FIRST is nil and BODY is non-nil, start with the first
+text line of WINDOW.  Otherwise, start with the first line of WINDOW.
+
+LAST, if non-nil, specifies the last line whose dimensions shall be
+returned.  If LAST is nil and BODY is non-nil, the last line is the last
+line of the body (text area) of WINDOW.  Otherwise, last is the last
+line of WINDOW.
+
+INVERSE, if non-nil, means that the y-pixel value returned should
+specify the number of pixels from the left corner of the last glyph of
+each line to the right edge (body edge if BODY is non-nil) of WINDOW.
+INVERSE nil means to count from the left edge (body edge if BODY is
+non-nil) of WINDOW.
+
+LEFT non-nil means to return the x- and y-coordinates of the lower left
+corner of the leftmost character on each line.  This is the value that
+should be used for buffers that mostly display text from right to
+left.  */)
+  (Lisp_Object window, Lisp_Object first, Lisp_Object last, Lisp_Object body, Lisp_Object inverse, Lisp_Object left)
+{
+  struct window *w = decode_live_window (window);
+  struct buffer *b;
+  struct glyph_row *row, *end_row;
+  int max_y = NILP (body) ? WINDOW_PIXEL_HEIGHT (w) : window_text_bottom_y (w);
+  Lisp_Object rows = Qnil;
+  int window_width = NILP (body) ? w->pixel_width : window_body_width (w, true);
+  int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+  int subtract = NILP (body) ? 0 : header_line_height;
+  bool invert = !NILP (inverse);
+  bool left_flag = !NILP (left);
+
+  if (noninteractive || w->pseudo_window_p)
+    return Qnil;
+
+  CHECK_BUFFER (w->contents);
+  b = XBUFFER (w->contents);
+
+  /* Fail if current matrix is not up-to-date.  */
+  if (!w->window_end_valid
+      || windows_or_buffers_changed
+      || b->clip_changed
+      || b->prevent_redisplay_optimizations_p
+      || window_outdated (w))
+    return Qnil;
+
+  if (NILP (first))
+    row = MATRIX_ROW (w->current_matrix, 0);
+  else if (NUMBERP (first))
+    {
+      CHECK_RANGED_INTEGER (first, 0, w->current_matrix->nrows);
+      row = MATRIX_ROW (w->current_matrix, XINT (first));
+    }
+  else if (!NILP (body))
+    row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  else
+    error ("Invalid specification of first line");
+
+  if (NILP (last))
+    end_row = MATRIX_ROW (w->current_matrix, w->current_matrix->nrows);
+  else if (NUMBERP (first))
+    {
+      CHECK_RANGED_INTEGER (first, 0, w->current_matrix->nrows);
+      end_row = MATRIX_ROW (w->current_matrix, XINT (last));
+    }
+  else if (!NILP (body))
+    end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
+  else
+    error ("Invalid specification of last line");
+
+  while (row <= end_row && row->enabled_p
+	 && row->y + row->height < max_y)
+    {
+
+      if (left_flag)
+	{
+	  struct glyph *glyph = row->glyphs[TEXT_AREA];
+
+	  rows = Fcons (Fcons (make_number
+			       (invert
+				? glyph->pixel_width
+				: window_width - glyph->pixel_width),
+			       make_number (row->y + row->height - subtract)),
+			rows);
+	}
+      else
+	rows = Fcons (Fcons (make_number
+			     (invert
+			      ? window_width - row->pixel_width
+			      : row->pixel_width), /* maybe add left
+						      margin here */
+			     make_number (row->y + row->height - subtract)),
+		      rows);
+      row++;
+    }
+
+  return Fnreverse (rows);
+}
+
 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
        0, 1, 0,
        doc: /* Return non-nil when WINDOW is dedicated to its buffer.
@@ -7571,6 +7680,7 @@ this value for parameters without read syntax (like windows or frames).
   defsubr (&Sset_window_point);
   defsubr (&Sset_window_start);
   defsubr (&Swindow_dedicated_p);
+  defsubr (&Swindow_lines_pixel_dimensions);
   defsubr (&Sset_window_dedicated_p);
   defsubr (&Swindow_display_table);
   defsubr (&Sset_window_display_table);
diff --git a/src/xdisp.c b/src/xdisp.c
index 14d6f8f..b31e77d 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -11367,10 +11367,15 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
   struct frame *sf = SELECTED_FRAME ();

   mini_window = FRAME_MINIBUF_WINDOW (sf);
+
+  /* Don't redisplay if the selected frame has no mini_window.  This may
+     be the case for tooltip frames.  */
+  if (NILP (mini_window))
+    return;
   w = XWINDOW (mini_window);
   f = XFRAME (WINDOW_FRAME (w));

-  /* Don't display if frame is invisible or not yet initialized.  */
+  /* Don't redisplay if frame is invisible or not yet initialized.  */
   if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
     return;

@@ -11713,7 +11718,8 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
   if ((FRAME_WINDOW_P (f)
        || FRAME_MINIBUF_ONLY_P (f)
        || f->explicit_name)
-      && NILP (Fframe_parameter (frame, Qtooltip)))
+      && NILP (Fframe_parameter (frame, Qtooltip))
+      && NILP (Fframe_parameter (frame, Qmini_frame)))
     {
       /* Do we have more than one visible frame on this X display?  */
       Lisp_Object tail, other_frame, fmt;
diff --git a/src/xfns.c b/src/xfns.c
index 798dc49..2643f11 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4738,6 +4738,60 @@ value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
 				 : Qnative_edges));
 }

+static Lisp_Object
+x_frame_list_z_order (Display* dpy, struct x_display_info *dpyinfo,  Window window, Lisp_Object frames)
+{
+  Window root, parent, *children;
+  unsigned int nchildren;
+  int i;
+
+  block_input ();
+  if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
+    {
+      unblock_input ();
+      for (i = nchildren - 1; i >= 0; i--)
+	{
+	  struct frame *f = x_window_to_frame (dpyinfo, children[i]);
+
+	  /* Process child windows first - they precede their paarent
+	     in the z-order.  */
+	  frames = x_frame_list_z_order (dpy, dpyinfo, children[i], frames);
+
+	  if (f)
+	    {
+	      Lisp_Object frame;
+
+	      XSETFRAME (frame, f);
+	      frames = Fcons (frame, frames);
+	    }
+	}
+
+      if (children) XFree ((char *)children);
+    }
+  else
+    unblock_input ();
+
+  return frames;
+}
+
+
+DEFUN ("x-frame-list-z-order", Fx_frame_list_z_order,
+       Sx_frame_list_z_order, 0, 1, 0,
+       doc: /* Return list of Emacs' frames, in Z (stacking) order.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.
+
+Frames are listed from bottommost (first) to topmost (last).  Return
+nil if DISPLAY contains no Emacs frame.  */)
+  (Lisp_Object display)
+{
+  struct x_display_info *dpyinfo = check_x_display_info (display);
+  Display *dpy = dpyinfo->display;
+
+  return x_frame_list_z_order (dpy, dpyinfo, dpyinfo->root_window, Qnil);
+}
+
 DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
        Sx_mouse_absolute_pixel_position, 0, 0, 0,
        doc: /* Return absolute position of mouse cursor in pixels.
@@ -5355,7 +5409,7 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
    when this happens.  */

 static Lisp_Object
-x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
+x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms,  bool mini_frame, Lisp_Object owner)
 {
   struct frame *f;
   Lisp_Object frame;
@@ -5381,7 +5435,10 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
   f = make_frame (false);
   f->wants_modeline = false;
   XSETFRAME (frame, f);
-  record_unwind_protect (unwind_create_tip_frame, frame);
+  if (mini_frame)
+    record_unwind_protect (do_unwind_create_frame, frame);
+  else
+    record_unwind_protect (unwind_create_tip_frame, frame);

   f->terminal = dpyinfo->terminal;

@@ -5495,7 +5552,8 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
 		       parms);
     }

-  x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
+  x_default_parameter (f, parms, Qinternal_border_width,
+		       make_number (mini_frame ? 0 : 1),
 		       "internalBorderWidth", "internalBorderWidth",
 		       RES_TYPE_NUMBER);
   x_default_parameter (f, parms, Qright_divider_width, make_number (0),
@@ -5545,17 +5603,30 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
       = f->output_data.x->text_cursor;
     /* Arrange for getting MapNotify and UnmapNotify events.  */
     attrs.event_mask = StructureNotifyMask;
-    tip_window
-      = FRAME_X_WINDOW (f)
-      = XCreateWindow (FRAME_X_DISPLAY (f),
-		       FRAME_DISPLAY_INFO (f)->root_window,
-		       /* x, y, width, height */
-		       0, 0, 1, 1,
-		       /* Border.  */
-		       f->border_width,
-		       CopyFromParent, InputOutput, CopyFromParent,
-		       mask, &attrs);
-    XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
+    if (mini_frame && !NILP (Fassq (Qchild_window, parms)))
+      FRAME_X_WINDOW (f)
+	= (XCreateSimpleWindow
+	   (FRAME_X_DISPLAY (f),
+	    FRAME_X_WINDOW (XFRAME (owner)),
+	    /* x, y, width, height */
+	    f->left_pos, f->top_pos, 1, 1,
+	    f->border_width,
+	    CopyFromParent, CopyFromParent));
+    else
+      FRAME_X_WINDOW (f)
+	= (XCreateWindow
+	   (FRAME_X_DISPLAY (f),
+	    FRAME_DISPLAY_INFO (f)->root_window,
+	    /* x, y, width, height */
+	    f->left_pos, f->top_pos, 1, 1,
+	    /* Border.  */
+	    f->border_width,
+	    CopyFromParent, InputOutput, CopyFromParent,
+	    mask, &attrs));
+
+    if (!mini_frame) tip_window = FRAME_X_WINDOW (f);
+
+    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);
@@ -6038,7 +6109,7 @@ with offset DY added (default is -10).

       /* 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)))
+      if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, false, Qnil)))
 	/* Creating the tip frame failed.  */
 	return unbind_to (count, Qnil);
     }
@@ -6131,6 +6202,90 @@ with offset DY added (default is -10).
   return x_hide_tip (!tooltip_reuse_hidden_frame);
 }

+DEFUN ("x-create-mini-frame", Fx_create_mini_frame, Sx_create_mini_frame, 1, 2, 0,
+       doc:  /* Create a mini-frame.
+FRAME is the frame where to attach this one to.  PARAMETERS is an alist of
+frame paramaters.
+
+The following parameters are special:
+
+- 'child-window" makes the new frame a child window of FRAME.  This has
+  a number of consequences.  On Windows 'alpha' does not necessarily
+  work if this is set.
+
+- 'external-border' enables external border.  */)
+     (Lisp_Object frame, Lisp_Object parameters)
+{
+  struct frame *f = decode_window_system_frame (frame);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+  Lisp_Object tip_frame;
+  ptrdiff_t count = SPECPDL_INDEX ();
+
+  if (!dpyinfo->terminal->name)
+    error ("Terminal is not live, can't create new frames on it");
+
+  if (NILP (FRAME_MINIBUF_WINDOW(f)))
+    error ("Cannot create tip-like frame for minibuffer-less frame");
+
+  /* Make copy of frame parameters because the original is in pure
+     storage now. */
+  parameters = Fcopy_alist (parameters);
+
+  specbind (Qinhibit_redisplay, Qt);
+  block_input ();
+  if (!NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parameters, true, frame)))
+    {
+      struct frame *tip_f;
+      struct window *w;
+      int old_windows_or_buffers_changed = windows_or_buffers_changed;
+      Lisp_Object window, tem;
+      Lisp_Object visibility;
+      int x_width = 0, x_height = 0;
+
+      tip_f = XFRAME (tip_frame);
+      window = FRAME_ROOT_WINDOW (tip_f);
+      w = XWINDOW (window);
+      w->pseudo_window_p = true;
+
+      fset_minibuffer_window (tip_f, FRAME_MINIBUF_WINDOW (f));
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+      FRAME_EXTERNAL_MENU_BAR (tip_f) = false;
+#endif /* not USE_X_TOOLKIT && not USE_GTK */
+
+      x_figure_window_size (tip_f, parameters, true, &x_width, &x_height);
+
+      tip_f->mini_frame = true;
+      /* Allow x_set_window_size, now.  */
+      tip_f->can_x_set_window_size = true;
+
+      if (x_width > 0)
+	SET_FRAME_WIDTH (tip_f, x_width);
+      if (x_height > 0)
+	SET_FRAME_HEIGHT (tip_f, x_height);
+
+      adjust_frame_size (tip_f, FRAME_TEXT_WIDTH (tip_f), FRAME_TEXT_HEIGHT (tip_f),
+			 0, true, Qx_create_frame_2); /* NEW SYMBOL NEEDED */
+
+      visibility = x_get_arg (FRAME_DISPLAY_INFO (f), parameters,
+			      Qvisibility, 0, 0, RES_TYPE_SYMBOL);
+      if (EQ (visibility, Qunbound) || !NILP (visibility))
+	SET_FRAME_VISIBLE (tip_f, 1);
+
+      /* Map tip-like frame.  */
+      XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f));
+
+      w->must_be_updated_p = true;
+      update_single_window (w);
+      windows_or_buffers_changed = old_windows_or_buffers_changed;
+
+      for (tem = parameters; CONSP (tem); tem = XCDR (tem))
+	if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
+	  fset_param_alist (tip_f, Fcons (XCAR (tem), tip_f->param_alist));
+    }
+
+  unblock_input ();
+  return unbind_to (count, tip_frame);
+}
 \f
 /***********************************************************************
 			File selection dialog
@@ -6792,6 +6947,7 @@ FRAMES should be nil (the selected frame), a frame, or a list of
   DEFSYM (Qcancel_timer, "cancel-timer");
   DEFSYM (Qfont_parameter, "font-parameter");
   DEFSYM (Qmono, "mono");
+  DEFSYM (Qchild_window, "child-window");
   DEFSYM (Qassq_delete_all, "assq-delete-all");

 #ifdef USE_CAIRO
@@ -6985,6 +7141,7 @@ FRAMES should be nil (the selected frame), a frame, or a list of
   defsubr (&Sx_display_monitor_attributes_list);
   defsubr (&Sx_frame_geometry);
   defsubr (&Sx_frame_edges);
+  defsubr (&Sx_frame_list_z_order);
   defsubr (&Sx_mouse_absolute_pixel_position);
   defsubr (&Sx_set_mouse_absolute_pixel_position);
   defsubr (&Sx_wm_set_size_hint);
@@ -6997,6 +7154,7 @@ FRAMES should be nil (the selected frame), a frame, or a list of

   defsubr (&Sx_show_tip);
   defsubr (&Sx_hide_tip);
+  defsubr (&Sx_create_mini_frame);
   tip_timer = Qnil;
   staticpro (&tip_timer);
   tip_frame = Qnil;
diff --git a/src/xterm.c b/src/xterm.c
index cd1d712..03d53c6 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -4252,7 +4252,7 @@ Status x_parse_color (struct frame *f, const char *color_name,
 /* Return the Emacs frame-object corresponding to an X window.
    It could be the frame's main window or an icon window.  */

-static struct frame *
+struct frame *
 x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
 {
   Lisp_Object tail, frame;
@@ -8476,7 +8476,20 @@ static void xembed_send_message (struct frame *f, Time,
           if (FRAME_GTK_OUTER_WIDGET (f)
               && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
 #endif
-	    x_real_positions (f, &f->left_pos, &f->top_pos);
+
+
+	    {
+	      int old_left = f->left_pos;
+	      int old_top = f->top_pos;
+
+	      x_real_positions (f, &f->left_pos, &f->top_pos);
+
+	      if (old_left != f->left_pos || old_top != f->top_pos)
+		{
+		  inev.ie.kind = MOVE_FRAME_EVENT;
+		  XSETFRAME (inev.ie.frame_or_window, f);
+		}
+	    }

 #ifdef HAVE_X_I18N
           if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
diff --git a/src/xterm.h b/src/xterm.h
index 675a484..c61a339 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1086,6 +1086,7 @@ extern bool x_alloc_lighter_color_for_widget (Widget, Display *, Colormap,
 extern void x_cr_draw_frame (cairo_t *, struct frame *);
 extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t);
 #endif
+extern struct frame *x_window_to_frame (struct x_display_info *, int);

 INLINE int
 x_display_pixel_height (struct x_display_info *dpyinfo)


[-- Attachment #3: mini-frame.el --]
[-- Type: application/emacs-lisp, Size: 13768 bytes --]

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: Latest master broken on Cocoa/NS
  2016-07-15 16:16                         ` Clément Pit--Claudel
@ 2016-07-15 17:37                           ` Eli Zaretskii
  0 siblings, 0 replies; 25+ messages in thread
From: Eli Zaretskii @ 2016-07-15 17:37 UTC (permalink / raw)
  To: Clément Pit--Claudel; +Cc: emacs-devel

> Cc: emacs-devel@gnu.org
> From: Clément Pit--Claudel <clement.pit@gmail.com>
> Date: Fri, 15 Jul 2016 18:16:44 +0200
> 
> > So which part(s) of that would you like to move to Lisp?
> 
> Everything except x_create_tip_frame :)

How do you write compute_tip_xy, x_hide_tip, and most of x-show-tip in
Lisp?



^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2016-07-15 17:37 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-12 21:47 Latest master broken on Cocoa/NS João Távora
2016-07-12 22:05 ` John Wiegley
2016-07-12 22:06 ` João Távora
2016-07-12 22:26   ` John Wiegley
2016-07-14  5:41     ` Dmitry Antipov
2016-07-14  6:26       ` John Wiegley
2016-07-15  6:41         ` Dmitry Antipov
2016-07-15  6:46           ` John Wiegley
2016-07-15  7:25           ` Eli Zaretskii
2016-07-15  7:28           ` martin rudalics
2016-07-15  8:02             ` Eli Zaretskii
2016-07-15  9:10               ` martin rudalics
2016-07-15 13:35           ` Stefan Monnier
2016-07-15 13:51             ` Clément Pit--Claudel
2016-07-15 14:09               ` Eli Zaretskii
2016-07-15 14:21                 ` Clément Pit--Claudel
2016-07-15 14:25                   ` Eli Zaretskii
2016-07-15 15:14                     ` Clément Pit--Claudel
2016-07-15 16:04                       ` Eli Zaretskii
2016-07-15 16:16                         ` Clément Pit--Claudel
2016-07-15 17:37                           ` Eli Zaretskii
2016-07-15 14:08             ` Dmitry Gutov
2016-07-15 15:20               ` martin rudalics
2016-07-15 16:12                 ` Clément Pit--Claudel
2016-07-15 16:41                   ` martin rudalics

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).