]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve tooltip implementation on Haiku
authorPo Lu <luangruo@yahoo.com>
Tue, 18 Jan 2022 08:15:08 +0000 (08:15 +0000)
committerPo Lu <luangruo@yahoo.com>
Tue, 18 Jan 2022 08:21:42 +0000 (08:21 +0000)
This fixes several issues: tooltips having no right internal
border, reusing tooltips occasionally freezing Emacs, and
inconsistent behaviour when compared to X.

* src/haiku_support.cc (BWindow_resize): Revert a recent change.
(BView_move_frame):
(BWindow_set_avoid_focus): Stop sync'ing when locked.  This
tends to cause lockups for an unknown reason.
* src/haikufns.c (initial_setup_back_buffer): New function.
(haiku_create_frame): Remove tooltip related code.
(haiku_set_internal_border_width): Handle cases where the face
cache is NULL and/or the window has not been created.
(haiku_set_inhibit_double_buffering): Likewise.
(haiku_create_tip_frame): New function.
(Fx_create_frame): Remove tooltip specific code.
(Fx_show_tip): Synchronize code with X.

* src/haikuterm.c (haiku_new_font): Don't adjust size on tooltip
frames.
(haiku_read_socket): Draw internal border on tooltip frames
during resize.
(haiku_clear_under_internal_border): Handle cases where the face
cache is NULL.

src/haiku_support.cc
src/haikufns.c
src/haikuterm.c

index 2d6fd0381fc4a470f0ea00a8bbb8c063030b07af..53716ff1612171a78242ec00b7599971129c7714 100644 (file)
@@ -1862,7 +1862,7 @@ BWindow_retitle (void *window, const char *title)
 void
 BWindow_resize (void *window, int width, int height)
 {
-  ((BWindow *) window)->ResizeTo (width - 1, height - 1);
+  ((BWindow *) window)->ResizeTo (width, height);
 }
 
 /* Activate WINDOW, making it the subject of keyboard focus and
@@ -1998,8 +1998,6 @@ BView_move_frame (void *view, int x, int y, int x1, int y1)
     gui_abort ("Failed to lock view moving frame");
   vw->MoveTo (x, y);
   vw->ResizeTo (x1 - x, y1 - y);
-  vw->Flush ();
-  vw->Sync ();
   vw->UnlockLooper ();
 }
 
@@ -2248,7 +2246,6 @@ BWindow_set_avoid_focus (void *window, int avoid_focus_p)
     w->SetFlags (w->Flags () & ~B_AVOID_FOCUS);
   else
     w->SetFlags (w->Flags () | B_AVOID_FOCUS);
-  w->Sync ();
   w->UnlockLooper ();
 }
 
index bf2201770811f67dbf12d6cde8ff65ed5e74dbce..13d7a9d20430c41ac9b43189b228bd2c16621134 100644 (file)
@@ -451,6 +451,15 @@ haiku_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object o
   unblock_input ();
 }
 
+static void
+initial_setup_back_buffer (struct frame *f)
+{
+  block_input ();
+  if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist))))
+    EmacsView_set_up_double_buffering (FRAME_HAIKU_VIEW (f));
+  unblock_input ();
+}
+
 static void
 unwind_create_frame (Lisp_Object frame)
 {
@@ -547,13 +556,12 @@ unwind_popup (void)
 }
 
 static Lisp_Object
-haiku_create_frame (Lisp_Object parms, int ttip_p)
+haiku_create_frame (Lisp_Object parms)
 {
   struct frame *f;
   Lisp_Object frame, tem;
   Lisp_Object name;
   bool minibuffer_only = false;
-  bool face_change_before = face_change;
   long window_prompting = 0;
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object display;
@@ -593,10 +601,8 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
   tem = gui_display_get_arg (dpyinfo, parms, Qminibuffer,
                              "minibuffer", "Minibuffer",
                              RES_TYPE_SYMBOL);
-  if (ttip_p)
-    f = make_frame (0);
-  else if (EQ (tem, Qnone) || NILP (tem))
-      f = make_frame_without_minibuffer (Qnil, kb, display);
+  if (EQ (tem, Qnone) || NILP (tem))
+    f = make_frame_without_minibuffer (Qnil, kb, display);
   else if (EQ (tem, Qonly))
     {
       f = make_minibuffer_frame ();
@@ -618,22 +624,16 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
   f->output_data.haiku->pending_zoom_width = INT_MIN;
   f->output_data.haiku->pending_zoom_height = INT_MIN;
 
-  if (ttip_p)
-    f->wants_modeline = false;
-
   fset_icon_name (f, gui_display_get_arg (dpyinfo, parms, Qicon_name,
                                           "iconName", "Title",
                                           RES_TYPE_STRING));
-  if (! STRINGP (f->icon_name) || ttip_p)
+  if (! STRINGP (f->icon_name))
     fset_icon_name (f, Qnil);
 
   FRAME_DISPLAY_INFO (f) = dpyinfo;
 
   /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
-  if (!ttip_p)
-    record_unwind_protect (unwind_create_frame, frame);
-  else
-    record_unwind_protect (unwind_create_tip_frame, frame);
+  record_unwind_protect (unwind_create_frame, frame);
 
   FRAME_OUTPUT_DATA (f)->parent_desc = NULL;
   FRAME_OUTPUT_DATA (f)->explicit_parent = 0;
@@ -660,8 +660,6 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
 #endif
   register_font_driver (&haikufont_driver, f);
 
-  f->tooltip = ttip_p;
-
   image_cache_refcount =
     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
 
@@ -674,7 +672,7 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
 
   gui_default_parameter (f, parms, Qborder_width, make_fixnum (0),
                          "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
-  gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (ttip_p ? 1 : 2),
+  gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (2),
                          "internalBorderWidth", "InternalBorderWidth",
                          RES_TYPE_NUMBER);
   gui_default_parameter (f, parms, Qchild_frame_border_width, Qnil,
@@ -684,7 +682,7 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
                       NULL, NULL, RES_TYPE_NUMBER);
   gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
                       NULL, NULL, RES_TYPE_NUMBER);
-  gui_default_parameter (f, parms, Qvertical_scroll_bars, !ttip_p ? Qt : Qnil,
+  gui_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
                         "verticalScrollBars", "VerticalScrollBars",
                         RES_TYPE_SYMBOL);
   gui_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
@@ -700,7 +698,7 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
                          "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
   gui_default_parameter (f, parms, Qright_fringe, Qnil,
                          "rightFringe", "RightFringe", RES_TYPE_NUMBER);
-  gui_default_parameter (f, parms, Qno_special_glyphs, ttip_p ? Qnil : Qt,
+  gui_default_parameter (f, parms, Qno_special_glyphs, Qt,
                          NULL, NULL, RES_TYPE_BOOLEAN);
 
   init_frame_faces (f);
@@ -718,57 +716,39 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
                     FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1,
                     Qx_create_frame_1);
 
-  if (!ttip_p)
-    {
-      gui_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL);
-      gui_default_parameter (f, parms, Qno_focus_on_map, Qnil,
-                            NULL, NULL, RES_TYPE_BOOLEAN);
-      gui_default_parameter (f, parms, Qno_accept_focus, Qnil,
-                            NULL, NULL, RES_TYPE_BOOLEAN);
-
-      /* The resources controlling the menu-bar, tool-bar, and tab-bar are
-        processed specially at startup, and reflected in the mode
-        variables; ignore them here.  */
-      gui_default_parameter (f, parms, Qmenu_bar_lines,
-                            NILP (Vmenu_bar_mode)
-                            ? make_fixnum (0) : make_fixnum (1),
-                            NULL, NULL, RES_TYPE_NUMBER);
-      gui_default_parameter (f, parms, Qtab_bar_lines,
-                            NILP (Vtab_bar_mode)
-                            ? make_fixnum (0) : make_fixnum (1),
-                            NULL, NULL, RES_TYPE_NUMBER);
-      gui_default_parameter (f, parms, Qtool_bar_lines,
-                            NILP (Vtool_bar_mode)
-                            ? make_fixnum (0) : make_fixnum (1),
-                            NULL, NULL, RES_TYPE_NUMBER);
-      gui_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
-                            "BufferPredicate", RES_TYPE_SYMBOL);
-      gui_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
-                            RES_TYPE_STRING);
-    }
+  gui_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL);
+  gui_default_parameter (f, parms, Qno_focus_on_map, Qnil,
+                        NULL, NULL, RES_TYPE_BOOLEAN);
+  gui_default_parameter (f, parms, Qno_accept_focus, Qnil,
+                        NULL, NULL, RES_TYPE_BOOLEAN);
+
+  /* The resources controlling the menu-bar, tool-bar, and tab-bar are
+     processed specially at startup, and reflected in the mode
+     variables; ignore them here.  */
+  gui_default_parameter (f, parms, Qmenu_bar_lines,
+                        NILP (Vmenu_bar_mode)
+                        ? make_fixnum (0) : make_fixnum (1),
+                        NULL, NULL, RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qtab_bar_lines,
+                        NILP (Vtab_bar_mode)
+                        ? make_fixnum (0) : make_fixnum (1),
+                        NULL, NULL, RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qtool_bar_lines,
+                        NILP (Vtool_bar_mode)
+                        ? make_fixnum (0) : make_fixnum (1),
+                        NULL, NULL, RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
+                        "BufferPredicate", RES_TYPE_SYMBOL);
+  gui_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
+                        RES_TYPE_STRING);
 
   parms = get_geometry_from_preferences (dpyinfo, parms);
   window_prompting = gui_figure_window_size (f, parms, false, true);
 
-  if (ttip_p)
-    {
-       /* No fringes on tip frame.  */
-      f->fringe_cols = 0;
-      f->left_fringe_width = 0;
-      f->right_fringe_width = 0;
-      /* No dividers on tip frame.  */
-      f->right_divider_width = 0;
-      f->bottom_divider_width = 0;
-    }
-
   tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0,
                              RES_TYPE_BOOLEAN);
   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !NILP (tem));
 
-  /* Add `tooltip' frame parameter's default value.  */
-  if (NILP (Fframe_parameter (frame, Qtooltip)) && ttip_p)
-    Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));
-
 #define ASSIGN_CURSOR(cursor, be_cursor) \
   (FRAME_OUTPUT_DATA (f)->cursor = be_cursor)
 
@@ -803,16 +783,13 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
   ASSIGN_CURSOR (current_cursor, FRAME_OUTPUT_DATA (f)->text_cursor);
 #undef ASSIGN_CURSOR
 
-
-  if (ttip_p)
-    f->no_split = true;
   f->terminal->reference_count++;
 
   FRAME_OUTPUT_DATA (f)->window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view);
   if (!FRAME_OUTPUT_DATA (f)->window)
     xsignal1 (Qerror, build_unibyte_string ("Could not create window"));
 
-  if (!minibuffer_only && !ttip_p && FRAME_EXTERNAL_MENU_BAR (f))
+  if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
     initialize_frame_menubar (f);
 
   FRAME_OUTPUT_DATA (f)->window_desc = FRAME_OUTPUT_DATA (f)->window;
@@ -839,58 +816,33 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
 
   gui_default_parameter (f, parms, Qicon_type, Qnil,
                          "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
-  if (ttip_p)
-    {
-      gui_default_parameter (f, parms, Qundecorated, Qt, NULL, NULL, RES_TYPE_BOOLEAN);
-      gui_default_parameter (f, parms, Qno_accept_focus, Qt, NULL, NULL,
-                            RES_TYPE_BOOLEAN);
-    }
-  else
-    {
-      gui_default_parameter (f, parms, Qauto_raise, Qnil,
-                            "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
-      gui_default_parameter (f, parms, Qauto_lower, Qnil,
-                            "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
-      gui_default_parameter (f, parms, Qcursor_type, Qbox,
-                            "cursorType", "CursorType", RES_TYPE_SYMBOL);
-      gui_default_parameter (f, parms, Qscroll_bar_width, Qnil,
-                            "scrollBarWidth", "ScrollBarWidth",
-                            RES_TYPE_NUMBER);
-      gui_default_parameter (f, parms, Qscroll_bar_height, Qnil,
-                            "scrollBarHeight", "ScrollBarHeight",
-                            RES_TYPE_NUMBER);
-      gui_default_parameter (f, parms, Qalpha, Qnil,
-                            "alpha", "Alpha", RES_TYPE_NUMBER);
-      gui_default_parameter (f, parms, Qfullscreen, Qnil,
-                            "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
-    }
+  gui_default_parameter (f, parms, Qauto_raise, Qnil,
+                        "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+  gui_default_parameter (f, parms, Qauto_lower, Qnil,
+                        "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
+  gui_default_parameter (f, parms, Qcursor_type, Qbox,
+                        "cursorType", "CursorType", RES_TYPE_SYMBOL);
+  gui_default_parameter (f, parms, Qscroll_bar_width, Qnil,
+                        "scrollBarWidth", "ScrollBarWidth",
+                        RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qscroll_bar_height, Qnil,
+                        "scrollBarHeight", "ScrollBarHeight",
+                        RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qalpha, Qnil,
+                        "alpha", "Alpha", RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qfullscreen, Qnil,
+                        "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
 
   gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
                         "inhibitDoubleBuffering", "InhibitDoubleBuffering",
                         RES_TYPE_BOOLEAN);
 
-  if (ttip_p)
-    {
-      Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
-
-      call2 (Qface_set_after_frame_default, frame, Qnil);
-
-      if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
-       {
-         AUTO_FRAME_ARG (arg, Qbackground_color, bg);
-         Fmodify_frame_parameters (frame, arg);
-       }
-    }
-
-  if (ttip_p)
-    face_change = face_change_before;
-
   f->can_set_window_size = true;
 
   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
-                    0, true, ttip_p ? Qtip_frame : Qx_create_frame_2);
+                    0, true, Qx_create_frame_2);
 
-  if (!FRAME_OUTPUT_DATA (f)->explicit_parent && !ttip_p)
+  if (!FRAME_OUTPUT_DATA (f)->explicit_parent)
     {
       Lisp_Object visibility;
 
@@ -908,13 +860,10 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
        }
     }
 
-  if (!ttip_p)
-    {
-      if (FRAME_HAS_MINIBUF_P (f)
-         && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
-             || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
-       kset_default_minibuffer_frame (kb, frame);
-    }
+  if (FRAME_HAS_MINIBUF_P (f)
+      && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
+         || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
+    kset_default_minibuffer_frame (kb, frame);
 
   for (tem = parms; CONSP (tem); tem = XCDR (tem))
     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
@@ -929,13 +878,230 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
      and similar functions.  */
   Vwindow_list = Qnil;
 
-  if (ttip_p)
-    adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
-                      0, true, Qtip_frame);
+  return unbind_to (count, frame);
+}
+
+/* Create a frame for a tooltip.  PARMS is a list of frame parameters.
+   TEXT is the string to display in the tip frame.  Value is the
+   frame.
+
+   Note that functions called here, esp. gui_default_parameter can
+   signal errors, for instance when a specified color name is
+   undefined.  We have to make sure that we're in a consistent state
+   when this happens.  */
 
+static Lisp_Object
+haiku_create_tip_frame (Lisp_Object parms)
+{
+  struct frame *f;
+  Lisp_Object frame;
+  Lisp_Object name;
+  ptrdiff_t count = SPECPDL_INDEX ();
+  bool face_change_before = face_change;
+  struct haiku_display_info *dpyinfo = x_display_list;
+
+  if (!dpyinfo->terminal->name)
+    error ("Terminal is not live, can't create new frames on it");
+
+  parms = Fcopy_alist (parms);
+
+  /* Get the name of the frame to use for resource lookup.  */
+  name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
+                              RES_TYPE_STRING);
+  if (!STRINGP (name)
+      && !EQ (name, Qunbound)
+      && !NILP (name))
+    error ("Invalid frame name--not a string or nil");
+
+  frame = Qnil;
+  f = make_frame (false);
+  f->wants_modeline = false;
+  XSETFRAME (frame, f);
+  record_unwind_protect (unwind_create_tip_frame, frame);
+
+  f->terminal = dpyinfo->terminal;
+
+  /* By setting the output method, we're essentially saying that
+     the frame is live, as per FRAME_LIVE_P.  If we get a signal
+     from this point on, x_destroy_window might screw up reference
+     counts etc.  */
+  f->output_method = output_haiku;
+  f->output_data.haiku = xzalloc (sizeof *f->output_data.haiku);
+
+  f->output_data.haiku->pending_zoom_x = INT_MIN;
+  f->output_data.haiku->pending_zoom_y = INT_MIN;
+  f->output_data.haiku->pending_zoom_width = INT_MIN;
+  f->output_data.haiku->pending_zoom_height = INT_MIN;
+
+  f->tooltip = true;
+  fset_icon_name (f, Qnil);
+  FRAME_DISPLAY_INFO (f) = dpyinfo;
+
+  FRAME_OUTPUT_DATA (f)->parent_desc = NULL;
+  FRAME_OUTPUT_DATA (f)->explicit_parent = 0;
+
+  /* Set the name; the functions to which we pass f expect the name to
+     be set.  */
+  if (EQ (name, Qunbound) || NILP (name))
+    f->explicit_name = false;
+  else
+    {
+      fset_name (f, name);
+      f->explicit_name = true;
+      /* use the frame's title when getting resources for this frame.  */
+      specbind (Qx_resource_name, name);
+    }
+
+#ifdef USE_BE_CAIRO
+  register_font_driver (&ftcrfont_driver, f);
+#ifdef HAVE_HARFBUZZ
+  register_font_driver (&ftcrhbfont_driver, f);
+#endif
+#endif
+  register_font_driver (&haikufont_driver, f);
+
+  image_cache_refcount =
+    FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
+
+  gui_default_parameter (f, parms, Qfont_backend, Qnil,
+                         "fontBackend", "FontBackend", RES_TYPE_STRING);
+
+  /* Extract the window parameters from the supplied values that are
+     needed to determine window geometry.  */
+  FRAME_RIF (f)->default_font_parameter (f, parms);
+
+  /* This defaults to 1 in order to match xterm.  We recognize either
+     internalBorderWidth or internalBorder (which is what xterm calls
+     it).  */
+  if (NILP (Fassq (Qinternal_border_width, parms)))
+    {
+      Lisp_Object value;
+
+      value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
+                                   "internalBorder", "internalBorder",
+                                   RES_TYPE_NUMBER);
+      if (! EQ (value, Qunbound))
+       parms = Fcons (Fcons (Qinternal_border_width, value),
+                      parms);
+    }
+
+  gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (1),
+                         "internalBorderWidth", "internalBorderWidth",
+                         RES_TYPE_NUMBER);
+
+  gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
+                         NULL, NULL, RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
+                         NULL, NULL, RES_TYPE_NUMBER);
+
+  /* Also do the stuff which must be set before the window exists.  */
+  gui_default_parameter (f, parms, Qforeground_color, build_string ("black"),
+                         "foreground", "Foreground", RES_TYPE_STRING);
+
+  gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
+                         "background", "Background", RES_TYPE_STRING);
+  gui_default_parameter (f, parms, Qmouse_color, build_string ("black"),
+                         "pointerColor", "Foreground", RES_TYPE_STRING);
+  gui_default_parameter (f, parms, Qcursor_color, build_string ("black"),
+                         "cursorColor", "Foreground", RES_TYPE_STRING);
+  gui_default_parameter (f, parms, Qborder_color, build_string ("black"),
+                         "borderColor", "BorderColor", RES_TYPE_STRING);
+  gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
+                         NULL, NULL, RES_TYPE_BOOLEAN);
+
+  /* Init faces before gui_default_parameter is called for the
+     scroll-bar-width parameter because otherwise we end up in
+     init_iterator with a null face cache, which should not happen.  */
+  init_frame_faces (f);
+
+  gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
+                         "inhibitDoubleBuffering", "InhibitDoubleBuffering",
+                         RES_TYPE_BOOLEAN);
+
+  gui_figure_window_size (f, parms, false, false);
+
+  {
+    void *window;
+
+    block_input ();
+    window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view);
+
+    FRAME_OUTPUT_DATA (f)->window = window;
+    if (!window)
+      emacs_abort ();
+
+    FRAME_OUTPUT_DATA (f)->window_desc = window;
+    BWindow_set_tooltip_decoration (window);
+    unblock_input ();
+  }
+
+  gui_default_parameter (f, parms, Qauto_raise, Qnil,
+                         "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+  gui_default_parameter (f, parms, Qauto_lower, Qnil,
+                         "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+  gui_default_parameter (f, parms, Qcursor_type, Qbox,
+                         "cursorType", "CursorType", RES_TYPE_SYMBOL);
+  gui_default_parameter (f, parms, Qalpha, Qnil,
+                         "alpha", "Alpha", RES_TYPE_NUMBER);
+
+  initial_setup_back_buffer (f);
+
+  /* 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?
+     https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */
+
+  /* Set up faces after all frame parameters are known.  This call
+     also merges in face attributes specified for new frames.
+
+     Frame parameters may be changed if .Xdefaults contains
+     specifications for the default font.  For example, if there is an
+     `Emacs.default.attributeBackground: pink', the `background-color'
+     attribute of the frame gets set, which let's the internal border
+     of the tooltip frame appear in pink.  Prevent this.  */
+  {
+    Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
+
+    call2 (Qface_set_after_frame_default, frame, Qnil);
+
+    if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
+      {
+       AUTO_FRAME_ARG (arg, Qbackground_color, bg);
+       Fmodify_frame_parameters (frame, arg);
+      }
+  }
+
+  f->no_split = true;
+
+  /* Now that the frame will be official, it counts as a reference to
+     its display and terminal.  */
+  f->terminal->reference_count++;
+
+  /* It is now ok to make the frame official even if we get an error
+     below.  And the frame needs to be on Vframe_list or making it
+     visible won't work.  */
+  Vframe_list = Fcons (frame, Vframe_list);
+  f->can_set_window_size = true;
+  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
+                    0, true, Qtip_frame);
+
+  /* Setting attributes of faces of the tooltip frame from resources
+     and similar will set face_change, which leads to the clearing of
+     all current matrices.  Since this isn't necessary here, avoid it
+     by resetting face_change to the value it had before we created
+     the tip frame.  */
+  face_change = face_change_before;
+
+  /* Discard the unwind_protect.  */
   return unbind_to (count, frame);
 }
 
+
 static void
 compute_tip_xy (struct frame *f,
                Lisp_Object parms, Lisp_Object dx, Lisp_Object dy,
@@ -1440,6 +1606,7 @@ haiku_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object o
 
   if (new_width == old_width)
     return;
+
   f->internal_border_width = new_width;
 
   if (FRAME_HAIKU_WINDOW (f))
@@ -1527,9 +1694,9 @@ haiku_set_inhibit_double_buffering (struct frame *f,
                                    Lisp_Object old_value)
 {
   block_input ();
-#ifndef USE_BE_CAIRO
   if (FRAME_HAIKU_WINDOW (f))
     {
+#ifndef USE_BE_CAIRO
       if (NILP (new_value))
        {
 #endif
@@ -1543,8 +1710,8 @@ haiku_set_inhibit_double_buffering (struct frame *f,
        }
       else
        EmacsView_disable_double_buffering (FRAME_HAIKU_VIEW (f));
-    }
 #endif
+    }
   unblock_input ();
 }
 
@@ -1717,7 +1884,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
        doc: /* SKIP: real doc in xfns.c.  */)
      (Lisp_Object parms)
 {
-  return haiku_create_frame (parms, 0);
+  return haiku_create_frame (parms);
 }
 
 DEFUN ("x-display-visual-class", Fx_display_visual_class,
@@ -1752,20 +1919,17 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
   ptrdiff_t count = SPECPDL_INDEX ();
   ptrdiff_t count_1;
   Lisp_Object window, size, tip_buf;
-
   AUTO_STRING (tip, " *tip*");
 
   specbind (Qinhibit_redisplay, Qt);
-  /* FIXME: Why don't re-used tooltip frames update correctly when a
-     menu is active? */
-  if (popup_activated_p)
-    specbind (Qtooltip_reuse_hidden_frame, Qnil);
 
   CHECK_STRING (string);
+  if (SCHARS (string) == 0)
+    string = make_unibyte_string (" ", 1);
 
   if (NILP (frame))
     frame = selected_frame;
-  decode_window_system_frame (frame);
+  check_window_system (frame);
 
   if (NILP (timeout))
     timeout = make_fixnum (5);
@@ -1825,24 +1989,21 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
     {
       if (FRAME_VISIBLE_P (XFRAME (tip_frame))
          && EQ (frame, tip_last_frame)
-         && !NILP (Fequal_including_properties (string, tip_last_string))
-         && !NILP (Fequal (parms, tip_last_parms)))
+         && !NILP (Fequal_including_properties (tip_last_string, string))
+         && !NILP (Fequal (tip_last_parms, parms)))
        {
          /* Only DX and DY have changed.  */
          tip_f = XFRAME (tip_frame);
          if (!NILP (tip_timer))
            {
-             Lisp_Object timer = tip_timer;
-
+             call1 (Qcancel_timer, tip_timer);
              tip_timer = Qnil;
-             call1 (Qcancel_timer, timer);
            }
 
          block_input ();
          compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
                          FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
-         haiku_set_offset (tip_f, root_x, root_y, 1);
-         haiku_visualize_frame (tip_f);
+         BWindow_set_offset (FRAME_HAIKU_WINDOW (tip_f), root_x, root_y);
          unblock_input ();
 
          goto start_timer;
@@ -1853,8 +2014,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
          Lisp_Object tail, elt, parm, last;
 
          /* Check if every parameter in PARMS has the same value in
-            tip_last_parms.  This may destruct tip_last_parms
-            which, however, will be recreated below.  */
+            tip_last_parms.  This may destruct tip_last_parms which,
+            however, will be recreated below.  */
          for (tail = parms; CONSP (tail); tail = XCDR (tail))
            {
              elt = XCAR (tail);
@@ -1880,8 +2041,9 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
                  call2 (Qassq_delete_all, parm, tip_last_parms);
            }
 
-         /* Now check if there's a parameter left in tip_last_parms with a
-            non-nil value.  */
+         /* Now check if every parameter in what is left of
+            tip_last_parms with a non-nil value has an association in
+            PARMS.  */
          for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
            {
              elt = XCAR (tail);
@@ -1917,21 +2079,16 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
       if (NILP (Fassq (Qborder_width, parms)))
        parms = Fcons (Fcons (Qborder_width, make_fixnum (1)), parms);
       if (NILP (Fassq (Qborder_color, parms)))
-       parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")),
-                      parms);
+       parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
       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
+      /* Create a frame for the tooltip, and record it in the global
         variable tip_frame.  */
-
-      if (NILP (tip_frame = haiku_create_frame (parms, 1)))
-       {
-         /* Creating the tip frame failed.  */
-         unblock_input ();
-         return unbind_to (count, Qnil);
-       }
+      if (NILP (tip_frame = haiku_create_tip_frame (parms)))
+       /* Creating the tip frame failed.  */
+       return unbind_to (count, Qnil);
     }
 
   tip_f = XFRAME (tip_frame);
@@ -1971,11 +2128,11 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
 
   w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
   w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
-  FRAME_TOTAL_COLS (tip_f) = WINDOW_TOTAL_COLS (w);
+  FRAME_TOTAL_COLS (tip_f) = w->total_cols;
   adjust_frame_glyphs (tip_f);
 
-  /* Insert STRING into the root window's buffer and fit the frame to
-     the buffer.  */
+  /* Insert STRING into root window's buffer and fit the frame to the
+     buffer.  */
   count_1 = SPECPDL_INDEX ();
   old_buffer = current_buffer;
   set_buffer_internal_1 (XBUFFER (w->contents));
@@ -1996,26 +2153,26 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
   /* Add the frame's internal border to calculated size.  */
   width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
   height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
+
   /* Calculate position of tooltip frame.  */
   compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
 
+  /* Show tooltip frame.  */
   block_input ();
-  BWindow_set_offset (FRAME_HAIKU_WINDOW (tip_f),
-                     root_x, root_y);
-  BWindow_resize (FRAME_HAIKU_WINDOW (tip_f), width, height);
+  void *wnd = FRAME_HAIKU_WINDOW (tip_f);
+  BWindow_resize (wnd, width, height);
   BView_resize_to (FRAME_HAIKU_VIEW (tip_f), width, height);
-  tip_f->pixel_width = width;
-  tip_f->pixel_height = height;
-  BWindow_set_tooltip_decoration (FRAME_HAIKU_WINDOW (tip_f));
-  BWindow_set_visible (FRAME_HAIKU_WINDOW (tip_f), 1);
-  BWindow_sync (FRAME_HAIKU_WINDOW (tip_f));
-  SET_FRAME_VISIBLE (tip_f, 1);
+  BWindow_set_offset (wnd, root_x, root_y);
+  BWindow_set_visible (wnd, true);
+  SET_FRAME_VISIBLE (tip_f, true);
+  FRAME_PIXEL_WIDTH (tip_f) = width;
+  FRAME_PIXEL_HEIGHT (tip_f) = height;
+  BWindow_sync (wnd);
   unblock_input ();
 
   w->must_be_updated_p = true;
   update_single_window (w);
-  haiku_clear_under_internal_border (tip_f);
-
+  flush_frame (tip_f);
   set_buffer_internal_1 (old_buffer);
   unbind_to (count_1, Qnil);
   windows_or_buffers_changed = old_windows_or_buffers_changed;
index 60b59436b87a2e9a6771b314cf53b201fe367948..7de792454f497e87d98d682e983c6d859308853b 100644 (file)
@@ -283,7 +283,7 @@ haiku_new_font (struct frame *f, Lisp_Object font_object, int fontset)
   else
     FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
 
-  if (FRAME_HAIKU_WINDOW (f))
+  if (FRAME_HAIKU_WINDOW (f) && !FRAME_TOOLTIP_P (f))
     {
       adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
                         FRAME_LINES (f) * FRAME_LINE_HEIGHT (f),
@@ -2639,15 +2639,34 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
            struct haiku_resize_event *b = buf;
            struct frame *f = haiku_window_to_frame (b->window);
 
-           if (!f || FRAME_TOOLTIP_P (f))
+           if (!f)
              continue;
 
            int width = lrint (b->px_widthf);
            int height = lrint (b->px_heightf);
 
+           if (FRAME_TOOLTIP_P (f))
+             {
+               if (FRAME_PIXEL_WIDTH (f) != width
+                   || FRAME_PIXEL_HEIGHT (f) != height)
+                 {
+                   SET_FRAME_GARBAGED (f);
+                   BView_draw_lock (FRAME_HAIKU_VIEW (f));
+                   BView_resize_to (FRAME_HAIKU_VIEW (f), width, height);
+                   BView_draw_unlock (FRAME_HAIKU_VIEW (f));
+                 }
+
+               FRAME_PIXEL_WIDTH (f) = width;
+               FRAME_PIXEL_HEIGHT (f) = height;
+
+               haiku_clear_under_internal_border (f);
+               continue;
+             }
+
            BView_draw_lock (FRAME_HAIKU_VIEW (f));
            BView_resize_to (FRAME_HAIKU_VIEW (f), width, height);
            BView_draw_unlock (FRAME_HAIKU_VIEW (f));
+
            if (width != FRAME_PIXEL_WIDTH (f)
                || height != FRAME_PIXEL_HEIGHT (f)
                || (f->new_size_p
@@ -3551,7 +3570,10 @@ put_xrm_resource (Lisp_Object name, Lisp_Object val)
 void
 haiku_clear_under_internal_border (struct frame *f)
 {
-  if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
+  if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
+      /* This is needed because tooltip frames set up the internal
+        border before init_frame_faces.  */
+      && FRAME_FACE_CACHE (f))
     {
       int border = FRAME_INTERNAL_BORDER_WIDTH (f);
       int width = FRAME_PIXEL_WIDTH (f);