root/src/haikufns.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_geometry_from_preferences
  2. haiku_update_after_decoration_change
  3. haiku_change_tool_bar_height
  4. haiku_change_tab_bar_height
  5. haiku_set_no_focus_on_map
  6. haiku_set_tool_bar_lines
  7. haiku_set_tab_bar_lines
  8. gamma_correct
  9. haiku_get_color
  10. haiku_display_info_for_name
  11. check_haiku_display_info
  12. haiku_set_title_bar_text
  13. haiku_set_title
  14. haiku_set_child_frame_border_width
  15. haiku_set_parent_frame
  16. haiku_set_z_group
  17. haiku_explicitly_set_name
  18. haiku_set_no_accept_focus
  19. initial_setup_back_buffer
  20. unwind_create_frame
  21. unwind_create_tip_frame
  22. haiku_decode_color
  23. haiku_set_foreground_color
  24. haiku_create_frame
  25. haiku_create_tip_frame
  26. compute_tip_xy
  27. haiku_hide_tip
  28. haiku_set_undecorated
  29. haiku_set_override_redirect
  30. haiku_set_menu_bar_lines
  31. frame_geometry
  32. haiku_set_background_color
  33. haiku_set_cursor_color
  34. haiku_set_cursor_type
  35. haiku_get_pixel
  36. haiku_put_pixel
  37. haiku_free_frame_resources
  38. haiku_iconify_frame
  39. haiku_visualize_frame
  40. haiku_unvisualize_frame
  41. haiku_set_internal_border_width
  42. haiku_set_frame_visible_invisible
  43. frame_set_mouse_pixel_position
  44. haiku_query_color
  45. check_x_display_info
  46. haiku_set_name
  47. haiku_set_inhibit_double_buffering
  48. haiku_set_sticky
  49. haiku_create_colored_cursor
  50. haiku_free_custom_cursors
  51. haiku_set_mouse_color
  52. haiku_set_use_frame_synchronization
  53. DEFUN
  54. DEFUN
  55. DEFUN
  56. DEFUN
  57. DEFUN
  58. DEFUN
  59. DEFUN
  60. DEFUN
  61. DEFUN
  62. DEFUN
  63. DEFUN
  64. DEFUN
  65. DEFUN
  66. DEFUN
  67. DEFUN
  68. DEFUN
  69. DEFUN
  70. DEFUN
  71. DEFUN
  72. DEFUN
  73. DEFUN
  74. DEFUN
  75. DEFUN
  76. DEFUN
  77. DEFUN
  78. syms_of_haikufns

     1 /* Haiku window system support
     2    Copyright (C) 2021-2023 Free Software Foundation, Inc.
     3 
     4 This file is part of GNU Emacs.
     5 
     6 GNU Emacs is free software: you can redistribute it and/or modify
     7 it under the terms of the GNU General Public License as published by
     8 the Free Software Foundation, either version 3 of the License, or (at
     9 your option) any later version.
    10 
    11 GNU Emacs is distributed in the hope that it will be useful,
    12 but WITHOUT ANY WARRANTY; without even the implied warranty of
    13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14 GNU General Public License for more details.
    15 
    16 You should have received a copy of the GNU General Public License
    17 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    18 
    19 #include <config.h>
    20 
    21 #include <math.h>
    22 
    23 #include "lisp.h"
    24 #include "frame.h"
    25 #include "blockinput.h"
    26 #include "termchar.h"
    27 #include "font.h"
    28 #include "keyboard.h"
    29 #include "buffer.h"
    30 #include "dispextern.h"
    31 
    32 #include "haikugui.h"
    33 #include "haikuterm.h"
    34 #include "haiku_support.h"
    35 #include "termhooks.h"
    36 
    37 #include "bitmaps/leftptr.xbm"
    38 #include "bitmaps/leftpmsk.xbm"
    39 
    40 #include <stdlib.h>
    41 
    42 #include <kernel/OS.h>
    43 
    44 #define RGB_TO_ULONG(r, g, b) \
    45   (((r) << 16) | ((g) << 8) | (b));
    46 #define RED_FROM_ULONG(color)   (((color) >> 16) & 0xff)
    47 #define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
    48 #define BLUE_FROM_ULONG(color)  ((color) & 0xff)
    49 
    50 /* The frame of the currently visible tooltip.  */
    51 Lisp_Object tip_frame;
    52 
    53 /* The X and Y deltas of the last call to `x-show-tip'.  */
    54 Lisp_Object tip_dx, tip_dy;
    55 
    56 /* The window-system window corresponding to the frame of the
    57    currently visible tooltip.  */
    58 static Window tip_window;
    59 
    60 /* A timer that hides or deletes the currently visible tooltip when it
    61    fires.  */
    62 static Lisp_Object tip_timer;
    63 
    64 /* STRING argument of last `x-show-tip' call.  */
    65 static Lisp_Object tip_last_string;
    66 
    67 /* Normalized FRAME argument of last `x-show-tip' call.  */
    68 static Lisp_Object tip_last_frame;
    69 
    70 /* PARMS argument of last `x-show-tip' call.  */
    71 static Lisp_Object tip_last_parms;
    72 
    73 static void haiku_explicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
    74 static void haiku_set_title (struct frame *, Lisp_Object, Lisp_Object);
    75 
    76 /* The number of references to an image cache.  */
    77 static ptrdiff_t image_cache_refcount;
    78 
    79 static Lisp_Object
    80 get_geometry_from_preferences (struct haiku_display_info *dpyinfo,
    81                                Lisp_Object parms)
    82 {
    83   struct {
    84     const char *val;
    85     const char *cls;
    86     Lisp_Object tem;
    87   } r[] = {
    88     { "width",  "Width", Qwidth },
    89     { "height", "Height", Qheight },
    90     { "left", "Left", Qleft },
    91     { "top", "Top", Qtop },
    92   };
    93 
    94   int i;
    95   for (i = 0; i < ARRAYELTS (r); ++i)
    96     {
    97       if (NILP (Fassq (r[i].tem, parms)))
    98         {
    99           Lisp_Object value
   100             = gui_display_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls,
   101                                    RES_TYPE_NUMBER);
   102           if (! BASE_EQ (value, Qunbound))
   103             parms = Fcons (Fcons (r[i].tem, value), parms);
   104         }
   105     }
   106 
   107   return parms;
   108 }
   109 
   110 /* Update the left and top offsets of F after its decorators
   111    change.  */
   112 static void
   113 haiku_update_after_decoration_change (struct frame *f)
   114 {
   115   /* Don't reset offsets during initial frame creation, since the
   116      contents of f->left_pos and f->top_pos won't be applied to the
   117      window until `x-create-frame' finishes, so setting them here will
   118      overwrite the offsets that the window should be moved to.  */
   119 
   120   if (!FRAME_OUTPUT_DATA (f)->configury_done)
   121     return;
   122 
   123   be_send_move_frame_event (FRAME_HAIKU_WINDOW (f));
   124 }
   125 
   126 void
   127 haiku_change_tool_bar_height (struct frame *f, int height)
   128 {
   129   int unit = FRAME_LINE_HEIGHT (f);
   130   int old_height = FRAME_TOOL_BAR_HEIGHT (f);
   131   int lines = (height + unit - 1) / unit;
   132   Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
   133 
   134   /* Make sure we redisplay all windows in this frame.  */
   135   fset_redisplay (f);
   136 
   137   FRAME_TOOL_BAR_HEIGHT (f) = height;
   138   FRAME_TOOL_BAR_LINES (f) = lines;
   139   store_frame_param (f, Qtool_bar_lines, make_fixnum (lines));
   140 
   141   if (FRAME_HAIKU_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
   142     {
   143       clear_frame (f);
   144       clear_current_matrices (f);
   145     }
   146 
   147   if ((height < old_height) && WINDOWP (f->tool_bar_window))
   148     clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
   149 
   150   if (!f->tool_bar_resized)
   151     {
   152       /* As long as tool_bar_resized is false, effectively try to change
   153          F's native height.  */
   154       if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth))
   155         adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
   156                            1, false, Qtool_bar_lines);
   157       else
   158         adjust_frame_size (f, -1, -1, 4, false, Qtool_bar_lines);
   159 
   160       f->tool_bar_resized =  f->tool_bar_redisplayed;
   161     }
   162   else
   163     /* Any other change may leave the native size of F alone.  */
   164     adjust_frame_size (f, -1, -1, 3, false, Qtool_bar_lines);
   165 
   166   /* adjust_frame_size might not have done anything, garbage frame
   167      here.  */
   168   adjust_frame_glyphs (f);
   169   SET_FRAME_GARBAGED (f);
   170 
   171   if (FRAME_HAIKU_WINDOW (f))
   172     haiku_clear_under_internal_border (f);
   173 }
   174 
   175 void
   176 haiku_change_tab_bar_height (struct frame *f, int height)
   177 {
   178   int unit = FRAME_LINE_HEIGHT (f);
   179   int old_height = FRAME_TAB_BAR_HEIGHT (f);
   180 
   181   /* This differs from the tool bar code in that the tab bar height is
   182      not rounded up.  Otherwise, if redisplay_tab_bar decides to grow
   183      the tab bar by even 1 pixel, FRAME_TAB_BAR_LINES will be changed,
   184      leading to the tab bar height being incorrectly set upon the next
   185      call to x_set_font.  (bug#59285) */
   186   int lines = height / unit;
   187   if (lines == 0 && height != 0)
   188     lines = 1;
   189 
   190   /* Make sure we redisplay all windows in this frame.  */
   191   fset_redisplay (f);
   192 
   193   /* Recalculate tab bar and frame text sizes.  */
   194   FRAME_TAB_BAR_HEIGHT (f) = height;
   195   FRAME_TAB_BAR_LINES (f) = lines;
   196   store_frame_param (f, Qtab_bar_lines, make_fixnum (lines));
   197 
   198   if (FRAME_HAIKU_WINDOW (f) && FRAME_TAB_BAR_HEIGHT (f) == 0)
   199     {
   200       clear_frame (f);
   201       clear_current_matrices (f);
   202     }
   203 
   204   if ((height < old_height) && WINDOWP (f->tab_bar_window))
   205     clear_glyph_matrix (XWINDOW (f->tab_bar_window)->current_matrix);
   206 
   207   if (!f->tab_bar_resized)
   208     {
   209       Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
   210 
   211       /* As long as tab_bar_resized is false, effectively try to change
   212          F's native height.  */
   213       if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth))
   214         adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
   215                            1, false, Qtab_bar_lines);
   216       else
   217         adjust_frame_size (f, -1, -1, 4, false, Qtab_bar_lines);
   218 
   219       f->tab_bar_resized = f->tab_bar_redisplayed;
   220     }
   221   else
   222     /* Any other change may leave the native size of F alone.  */
   223     adjust_frame_size (f, -1, -1, 3, false, Qtab_bar_lines);
   224 
   225   /* adjust_frame_size might not have done anything, garbage frame
   226      here.  */
   227   adjust_frame_glyphs (f);
   228   SET_FRAME_GARBAGED (f);
   229   if (FRAME_HAIKU_WINDOW (f))
   230     haiku_clear_under_internal_border (f);
   231 }
   232 
   233 static void
   234 haiku_set_no_focus_on_map (struct frame *f, Lisp_Object value,
   235                            Lisp_Object oldval)
   236 {
   237   if (!EQ (value, oldval))
   238     FRAME_NO_FOCUS_ON_MAP (f) = !NILP (value);
   239 }
   240 
   241 static void
   242 haiku_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
   243 {
   244   if (FRAME_TOOLTIP_P (f))
   245     return;
   246   int nlines;
   247 
   248   /* Treat tool bars like menu bars.  */
   249   if (FRAME_MINIBUF_ONLY_P (f))
   250     return;
   251 
   252   /* Use VALUE only if an int >= 0.  */
   253   if (RANGED_FIXNUMP (0, value, INT_MAX))
   254     nlines = XFIXNAT (value);
   255   else
   256     nlines = 0;
   257 
   258   haiku_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
   259 }
   260 
   261 static void
   262 haiku_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
   263 {
   264   if (FRAME_TOOLTIP_P (f))
   265     return;
   266   int olines = FRAME_TAB_BAR_LINES (f);
   267   int nlines;
   268 
   269   /* Treat tab bars like menu bars.  */
   270   if (FRAME_MINIBUF_ONLY_P (f))
   271     return;
   272 
   273   /* Use VALUE only if an int >= 0.  */
   274   if (RANGED_FIXNUMP (0, value, INT_MAX))
   275     nlines = XFIXNAT (value);
   276   else
   277     nlines = 0;
   278 
   279   if (nlines != olines && (olines == 0 || nlines == 0))
   280     haiku_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
   281 }
   282 
   283 void
   284 gamma_correct (struct frame *f, Emacs_Color *color)
   285 {
   286   if (f->gamma)
   287     {
   288       color->red = (pow (color->red / 65535.0, f->gamma)
   289                     * 65535.0 + 0.5);
   290       color->green = (pow (color->green / 65535.0, f->gamma)
   291                       * 65535.0 + 0.5);
   292       color->blue = (pow (color->blue / 65535.0, f->gamma)
   293                      * 65535.0 + 0.5);
   294       color->pixel = RGB_TO_ULONG (color->red / 256,
   295                                    color->green / 256,
   296                                    color->blue / 256);
   297     }
   298 }
   299 
   300 int
   301 haiku_get_color (const char *name, Emacs_Color *color)
   302 {
   303   unsigned short r16, g16, b16;
   304   Lisp_Object tem, col;
   305   int32 clr, rc;
   306   uint32_t ui_color;
   307   ptrdiff_t size, i;
   308   Lisp_Object string;
   309 
   310   if (parse_color_spec (name, &r16, &g16, &b16))
   311     {
   312       color->pixel = RGB_TO_ULONG (r16 / 256, g16 / 256, b16 / 256);
   313       color->red = r16;
   314       color->green = g16;
   315       color->blue = b16;
   316       return 0;
   317     }
   318   else
   319     {
   320       block_input ();
   321       eassert (x_display_list && !NILP (x_display_list->color_map));
   322       tem = x_display_list->color_map;
   323       for (; CONSP (tem); tem = XCDR (tem))
   324         {
   325           col = XCAR (tem);
   326 
   327           if (CONSP (col) && !xstrcasecmp (SSDATA (XCAR (col)), name))
   328             {
   329               clr = XFIXNUM (XCDR (col));
   330               color->pixel = clr;
   331               color->red = RED_FROM_ULONG (clr) * 257;
   332               color->green = GREEN_FROM_ULONG (clr) * 257;
   333               color->blue = BLUE_FROM_ULONG (clr) * 257;
   334               unblock_input ();
   335               return 0;
   336           }
   337         }
   338       unblock_input ();
   339     }
   340 
   341   rc = 1;
   342   if (VECTORP (Vhaiku_allowed_ui_colors))
   343     {
   344       size = ASIZE (Vhaiku_allowed_ui_colors);
   345 
   346       for (i = 0; i < size; ++i)
   347         {
   348           string = AREF (Vhaiku_allowed_ui_colors, i);
   349 
   350           block_input ();
   351           if (STRINGP (string) && !strcmp (SSDATA (string), name))
   352             rc = be_get_ui_color (name, &ui_color);
   353           unblock_input ();
   354         }
   355     }
   356 
   357   if (!rc)
   358     {
   359       color->pixel = ui_color;
   360       color->red = RED_FROM_ULONG (ui_color) * 257;
   361       color->green = GREEN_FROM_ULONG (ui_color) * 257;
   362       color->blue = BLUE_FROM_ULONG (ui_color) * 257;
   363     }
   364 
   365   return rc;
   366 }
   367 
   368 static struct haiku_display_info *
   369 haiku_display_info_for_name (Lisp_Object name)
   370 {
   371   CHECK_STRING (name);
   372 
   373   if (!strcmp (SSDATA (name), "be"))
   374     {
   375       if (x_display_list)
   376         return x_display_list;
   377 
   378       return haiku_term_init ();
   379     }
   380 
   381   error ("Haiku displays can only be named \"be\"");
   382 }
   383 
   384 static struct haiku_display_info *
   385 check_haiku_display_info (Lisp_Object object)
   386 {
   387   struct haiku_display_info *dpyinfo = NULL;
   388 
   389   if (NILP (object))
   390     {
   391       struct frame *sf = XFRAME (selected_frame);
   392 
   393       if (FRAME_HAIKU_P (sf) && FRAME_LIVE_P (sf))
   394         dpyinfo = FRAME_DISPLAY_INFO (sf);
   395       else if (x_display_list)
   396         dpyinfo = x_display_list;
   397       else
   398         error ("Haiku windowing not present");
   399     }
   400   else if (TERMINALP (object))
   401     {
   402       struct terminal *t = decode_live_terminal (object);
   403 
   404       if (t->type != output_haiku)
   405         error ("Terminal %d is not a Haiku display", t->id);
   406 
   407       dpyinfo = t->display_info.haiku;
   408     }
   409   else if (STRINGP (object))
   410     dpyinfo = haiku_display_info_for_name (object);
   411   else
   412     {
   413       struct frame *f = decode_window_system_frame (object);
   414       dpyinfo = FRAME_DISPLAY_INFO (f);
   415     }
   416 
   417   return dpyinfo;
   418 }
   419 
   420 static void
   421 haiku_set_title_bar_text (struct frame *f, Lisp_Object text)
   422 {
   423   if (FRAME_HAIKU_WINDOW (f))
   424     {
   425       block_input ();
   426       BWindow_retitle (FRAME_HAIKU_WINDOW (f), SSDATA (ENCODE_UTF_8 (text)));
   427       unblock_input ();
   428     }
   429 }
   430 
   431 static void
   432 haiku_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
   433 {
   434   /* Don't change the title if it's already NAME.  */
   435   if (EQ (name, f->title))
   436     return;
   437 
   438   update_mode_lines = 26;
   439 
   440   fset_title (f, name);
   441 
   442   if (NILP (name))
   443     name = f->name;
   444 
   445   haiku_set_title_bar_text (f, name);
   446 }
   447 
   448 static void
   449 haiku_set_child_frame_border_width (struct frame *f,
   450                                     Lisp_Object arg, Lisp_Object oldval)
   451 {
   452   int border;
   453 
   454   if (NILP (arg))
   455     border = -1;
   456   else if (RANGED_FIXNUMP (0, arg, INT_MAX))
   457     border = XFIXNAT (arg);
   458   else
   459     signal_error ("Invalid child frame border width", arg);
   460 
   461   if (border != FRAME_CHILD_FRAME_BORDER_WIDTH (f))
   462     {
   463       f->child_frame_border_width = border;
   464 
   465       if (FRAME_HAIKU_WINDOW (f))
   466         adjust_frame_size (f, -1, -1, 3, 0, Qchild_frame_border_width);
   467 
   468       SET_FRAME_GARBAGED (f);
   469     }
   470 }
   471 
   472 static void
   473 haiku_set_parent_frame (struct frame *f, Lisp_Object new_value,
   474                         Lisp_Object old_value)
   475 {
   476   struct frame *p = NULL;
   477   block_input ();
   478   if (!NILP (new_value)
   479       && (!FRAMEP (new_value)
   480           || !FRAME_LIVE_P (p = XFRAME (new_value))
   481           || !FRAME_HAIKU_P (p)))
   482     {
   483       store_frame_param (f, Qparent_frame, old_value);
   484       unblock_input ();
   485       error ("Invalid specification of `parent-frame'");
   486     }
   487 
   488   if (EQ (new_value, old_value))
   489     {
   490       unblock_input ();
   491       return;
   492     }
   493 
   494   if (!NILP (old_value))
   495     {
   496       EmacsWindow_unparent (FRAME_HAIKU_WINDOW (f));
   497       FRAME_OUTPUT_DATA (f)->parent_desc = NULL;
   498     }
   499 
   500   if (!NILP (new_value))
   501     {
   502       EmacsWindow_parent_to (FRAME_HAIKU_WINDOW (f),
   503                              FRAME_HAIKU_WINDOW (p));
   504       BWindow_set_offset (FRAME_HAIKU_WINDOW (f),
   505                           f->left_pos, f->top_pos);
   506 
   507       /* This isn't actually used for anything, but makes the
   508          `parent-id' parameter correct.  */
   509       FRAME_OUTPUT_DATA (f)->parent_desc = FRAME_HAIKU_WINDOW (p);
   510     }
   511   fset_parent_frame (f, new_value);
   512   unblock_input ();
   513 }
   514 
   515 static void
   516 haiku_set_z_group (struct frame *f, Lisp_Object new_value,
   517                    Lisp_Object old_value)
   518 {
   519   int rc;
   520 
   521   /* Tooltip frames can't have Z groups, since the window feel is
   522      overridden during frame creation.  */
   523   if (FRAME_TOOLTIP_P (f))
   524     return;
   525 
   526   rc = 1;
   527   block_input ();
   528 
   529   if (NILP (new_value))
   530     {
   531       BWindow_set_z_group (FRAME_HAIKU_WINDOW (f), Z_GROUP_NONE);
   532       FRAME_Z_GROUP (f) = z_group_none;
   533     }
   534   else if (EQ (new_value, Qabove))
   535     {
   536       BWindow_set_z_group (FRAME_HAIKU_WINDOW (f), Z_GROUP_ABOVE);
   537       FRAME_Z_GROUP (f) = z_group_above;
   538     }
   539   else if (EQ (new_value, Qbelow))
   540     {
   541       BWindow_set_z_group (FRAME_HAIKU_WINDOW (f), Z_GROUP_BELOW);
   542       FRAME_Z_GROUP (f) = z_group_below;
   543     }
   544   else
   545     rc = 0;
   546 
   547   unblock_input ();
   548 
   549   if (!rc)
   550     error ("Invalid z-group specification");
   551 
   552   /* Setting the Z-group can change the frame's decorator.  */
   553   haiku_update_after_decoration_change (f);
   554 }
   555 
   556 static void
   557 haiku_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
   558 {
   559   haiku_set_name (f, arg, 1);
   560 }
   561 
   562 static void
   563 haiku_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
   564 {
   565   if (!EQ (new_value, old_value))
   566     FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
   567 
   568   block_input ();
   569   if (FRAME_HAIKU_WINDOW (f))
   570     BWindow_set_avoid_focus (FRAME_HAIKU_WINDOW (f),
   571                              FRAME_NO_ACCEPT_FOCUS (f));
   572   unblock_input ();
   573 }
   574 
   575 static void
   576 initial_setup_back_buffer (struct frame *f)
   577 {
   578   block_input ();
   579   if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist))))
   580     EmacsView_set_up_double_buffering (FRAME_HAIKU_VIEW (f));
   581   unblock_input ();
   582 }
   583 
   584 static void
   585 unwind_create_frame (Lisp_Object frame)
   586 {
   587   struct frame *f = XFRAME (frame);
   588 
   589   /* If frame is already dead, nothing to do.  This can happen if the
   590      display is disconnected after the frame has become official, but
   591      before x_create_frame removes the unwind protect.  */
   592   if (!FRAME_LIVE_P (f))
   593     return;
   594 
   595   /* If frame is ``official'', nothing to do.  */
   596   if (NILP (Fmemq (frame, Vframe_list)))
   597     {
   598 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
   599       struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   600 #endif
   601 
   602       /* If the frame's image cache refcount is still the same as our
   603          private shadow variable, it means we are unwinding a frame
   604          for which we didn't yet call init_frame_faces, where the
   605          refcount is incremented.  Therefore, we increment it here, so
   606          that free_frame_faces, called in free_frame_resources later,
   607          will not mistakenly decrement the counter that was not
   608          incremented yet to account for this new frame.  */
   609       if (FRAME_IMAGE_CACHE (f) != NULL
   610           && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
   611         FRAME_IMAGE_CACHE (f)->refcount++;
   612 
   613       haiku_free_frame_resources (f);
   614       free_glyphs (f);
   615 
   616 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
   617       /* Check that reference counts are indeed correct.  */
   618       if (dpyinfo->terminal->image_cache)
   619         eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
   620 #endif
   621     }
   622 }
   623 
   624 static void
   625 unwind_create_tip_frame (Lisp_Object frame)
   626 {
   627   unwind_create_frame (frame);
   628   tip_window = NULL;
   629   tip_frame = Qnil;
   630 }
   631 
   632 static unsigned long
   633 haiku_decode_color (struct frame *f, Lisp_Object color_name)
   634 {
   635   Emacs_Color cdef;
   636 
   637   CHECK_STRING (color_name);
   638 
   639   if (!haiku_get_color (SSDATA (color_name), &cdef))
   640     return cdef.pixel;
   641 
   642   signal_error ("Undefined color", color_name);
   643 }
   644 
   645 static void
   646 haiku_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
   647 {
   648   struct haiku_output *output;
   649   unsigned long fg, old_fg;
   650 
   651   fg = haiku_decode_color (f, arg);
   652   old_fg = FRAME_FOREGROUND_PIXEL (f);
   653   FRAME_FOREGROUND_PIXEL (f) = fg;
   654   output = FRAME_OUTPUT_DATA (f);
   655 
   656   if (FRAME_HAIKU_WINDOW (f))
   657     {
   658       if (output->cursor_color.pixel == old_fg)
   659         haiku_query_color (fg, &output->cursor_color);
   660 
   661       update_face_from_frame_parameter (f, Qforeground_color, arg);
   662 
   663       if (FRAME_VISIBLE_P (f))
   664         redraw_frame (f);
   665     }
   666 }
   667 
   668 static Lisp_Object
   669 haiku_create_frame (Lisp_Object parms)
   670 {
   671   struct frame *f, *cascade_target;
   672   Lisp_Object frame, tem;
   673   Lisp_Object name;
   674   bool minibuffer_only = false;
   675   long window_prompting = 0;
   676   specpdl_ref count = SPECPDL_INDEX ();
   677   Lisp_Object display;
   678   struct haiku_display_info *dpyinfo = NULL;
   679   struct kboard *kb;
   680 
   681   if (x_display_list->focused_frame)
   682     cascade_target = x_display_list->focused_frame;
   683   else if (x_display_list->focus_event_frame)
   684     cascade_target = x_display_list->focus_event_frame;
   685   else
   686     cascade_target = NULL;
   687 
   688   /* Always cascade from the most toplevel frame.  */
   689 
   690   while (cascade_target && FRAME_PARENT_FRAME (cascade_target))
   691     cascade_target = FRAME_PARENT_FRAME (cascade_target);
   692 
   693   parms = Fcopy_alist (parms);
   694 
   695   Vx_resource_name = Vinvocation_name;
   696 
   697   display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0,
   698                                  RES_TYPE_STRING);
   699   if (BASE_EQ (display, Qunbound))
   700     display = Qnil;
   701   dpyinfo = check_haiku_display_info (display);
   702   kb = dpyinfo->terminal->kboard;
   703 
   704   if (!dpyinfo->terminal->name)
   705     error ("Terminal is not live, can't create new frames on it");
   706 
   707   name = gui_display_get_arg (dpyinfo, parms, Qname, 0, 0,
   708                               RES_TYPE_STRING);
   709   if (!STRINGP (name)
   710       && ! BASE_EQ (name, Qunbound)
   711       && ! NILP (name))
   712     error ("Invalid frame name--not a string or nil");
   713 
   714   if (STRINGP (name))
   715     Vx_resource_name = name;
   716 
   717   /* make_frame_without_minibuffer can run Lisp code and garbage collect.  */
   718   /* No need to protect DISPLAY because that's not used after passing
   719      it to make_frame_without_minibuffer.  */
   720   frame = Qnil;
   721   tem = gui_display_get_arg (dpyinfo, parms, Qminibuffer,
   722                              "minibuffer", "Minibuffer",
   723                              RES_TYPE_SYMBOL);
   724   if (EQ (tem, Qnone) || NILP (tem))
   725     f = make_frame_without_minibuffer (Qnil, kb, display);
   726   else if (EQ (tem, Qonly))
   727     {
   728       f = make_minibuffer_frame ();
   729       minibuffer_only = 1;
   730     }
   731   else if (WINDOWP (tem))
   732       f = make_frame_without_minibuffer (tem, kb, display);
   733   else
   734       f = make_frame (1);
   735 
   736   XSETFRAME (frame, f);
   737 
   738   f->terminal = dpyinfo->terminal;
   739 
   740   f->output_method = output_haiku;
   741   f->output_data.haiku = xzalloc (sizeof *f->output_data.haiku);
   742   f->output_data.haiku->wait_for_event_type = -1;
   743   f->output_data.haiku->relief_background = -1;
   744 
   745   fset_icon_name (f, gui_display_get_arg (dpyinfo, parms, Qicon_name,
   746                                           "iconName", "Title",
   747                                           RES_TYPE_STRING));
   748   if (! STRINGP (f->icon_name))
   749     fset_icon_name (f, Qnil);
   750 
   751   FRAME_DISPLAY_INFO (f) = dpyinfo;
   752 
   753   /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
   754   record_unwind_protect (unwind_create_frame, frame);
   755 
   756   /* Set the name; the functions to which we pass f expect the name to
   757      be set.  */
   758   if (BASE_EQ (name, Qunbound) || NILP (name) || ! STRINGP (name))
   759     {
   760       fset_name (f, Vinvocation_name);
   761       f->explicit_name = 0;
   762     }
   763   else
   764     {
   765       fset_name (f, name);
   766       f->explicit_name = 1;
   767       specbind (Qx_resource_name, name);
   768     }
   769 
   770 #ifdef USE_BE_CAIRO
   771   register_font_driver (&ftcrfont_driver, f);
   772 #ifdef HAVE_HARFBUZZ
   773   register_font_driver (&ftcrhbfont_driver, f);
   774 #endif
   775 #endif
   776   register_font_driver (&haikufont_driver, f);
   777 
   778   image_cache_refcount =
   779     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
   780 
   781   gui_default_parameter (f, parms, Qfont_backend, Qnil,
   782                          "fontBackend", "FontBackend", RES_TYPE_STRING);
   783 
   784   FRAME_RIF (f)->default_font_parameter (f, parms);
   785 
   786   if (!FRAME_FONT (f))
   787     {
   788       delete_frame (frame, Qnoelisp);
   789       error ("Invalid frame font");
   790     }
   791 
   792   gui_default_parameter (f, parms, Qborder_width, make_fixnum (0),
   793                          "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
   794   gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (0),
   795                          "internalBorderWidth", "InternalBorderWidth",
   796                          RES_TYPE_NUMBER);
   797   gui_default_parameter (f, parms, Qchild_frame_border_width, Qnil,
   798                          "childFrameBorderWidth", "childFrameBorderWidth",
   799                          RES_TYPE_NUMBER);
   800   gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
   801                          NULL, NULL, RES_TYPE_NUMBER);
   802   gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
   803                          NULL, NULL, RES_TYPE_NUMBER);
   804   gui_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
   805                          "verticalScrollBars", "VerticalScrollBars",
   806                          RES_TYPE_SYMBOL);
   807   gui_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
   808                          "horizontalScrollBars", "HorizontalScrollBars",
   809                          RES_TYPE_SYMBOL);
   810   gui_default_parameter (f, parms, Qforeground_color, build_string ("black"),
   811                          "foreground", "Foreground", RES_TYPE_STRING);
   812   gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
   813                          "background", "Background", RES_TYPE_STRING);
   814   gui_default_parameter (f, parms, Qmouse_color, build_string ("font-color"),
   815                          "pointerColor", "Foreground", RES_TYPE_STRING);
   816   gui_default_parameter (f, parms, Qline_spacing, Qnil,
   817                          "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
   818   gui_default_parameter (f, parms, Qleft_fringe, Qnil,
   819                          "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
   820   gui_default_parameter (f, parms, Qright_fringe, Qnil,
   821                          "rightFringe", "RightFringe", RES_TYPE_NUMBER);
   822   gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
   823                          NULL, NULL, RES_TYPE_BOOLEAN);
   824 
   825   init_frame_faces (f);
   826 
   827   /* Read comment about this code in corresponding place in xfns.c.  */
   828   tem = gui_display_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL,
   829                              RES_TYPE_NUMBER);
   830   if (FIXNUMP (tem))
   831     store_frame_param (f, Qmin_width, tem);
   832   tem = gui_display_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL,
   833                              RES_TYPE_NUMBER);
   834   if (FIXNUMP (tem))
   835     store_frame_param (f, Qmin_height, tem);
   836 
   837   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
   838                      FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1,
   839                      Qx_create_frame_1);
   840 
   841   gui_default_parameter (f, parms, Qno_focus_on_map, Qnil,
   842                          NULL, NULL, RES_TYPE_BOOLEAN);
   843   gui_default_parameter (f, parms, Qno_accept_focus, Qnil,
   844                          NULL, NULL, RES_TYPE_BOOLEAN);
   845 
   846   /* The resources controlling the menu-bar, tool-bar, and tab-bar are
   847      processed specially at startup, and reflected in the mode
   848      variables; ignore them here.  */
   849   gui_default_parameter (f, parms, Qmenu_bar_lines,
   850                          NILP (Vmenu_bar_mode)
   851                          ? make_fixnum (0) : make_fixnum (1),
   852                          NULL, NULL, RES_TYPE_NUMBER);
   853   gui_default_parameter (f, parms, Qtab_bar_lines,
   854                          NILP (Vtab_bar_mode)
   855                          ? make_fixnum (0) : make_fixnum (1),
   856                          NULL, NULL, RES_TYPE_NUMBER);
   857   gui_default_parameter (f, parms, Qtool_bar_lines,
   858                          NILP (Vtool_bar_mode)
   859                          ? make_fixnum (0) : make_fixnum (1),
   860                          NULL, NULL, RES_TYPE_NUMBER);
   861   gui_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
   862                          "BufferPredicate", RES_TYPE_SYMBOL);
   863   gui_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
   864                          RES_TYPE_STRING);
   865 
   866   parms = get_geometry_from_preferences (dpyinfo, parms);
   867   window_prompting = gui_figure_window_size (f, parms, false, true);
   868 
   869   tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0,
   870                              RES_TYPE_BOOLEAN);
   871   f->no_split = minibuffer_only || (!BASE_EQ (tem, Qunbound) && !NILP (tem));
   872 
   873   f->terminal->reference_count++;
   874 
   875   FRAME_OUTPUT_DATA (f)->window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view);
   876 
   877   if (!FRAME_OUTPUT_DATA (f)->window)
   878     xsignal1 (Qerror, build_unibyte_string ("Could not create window"));
   879 
   880   block_input ();
   881   if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
   882     initialize_frame_menubar (f);
   883   unblock_input ();
   884 
   885   Vframe_list = Fcons (frame, Vframe_list);
   886 
   887   Lisp_Object parent_frame = gui_display_get_arg (dpyinfo, parms,
   888                                                   Qparent_frame, NULL, NULL,
   889                                                   RES_TYPE_SYMBOL);
   890 
   891   if (BASE_EQ (parent_frame, Qunbound)
   892       || NILP (parent_frame)
   893       || !FRAMEP (parent_frame)
   894       || !FRAME_LIVE_P (XFRAME (parent_frame)))
   895     parent_frame = Qnil;
   896 
   897   /* It doesn't make sense to center child frames, the resulting
   898      position makes no sense.  */
   899   if (!NILP (parent_frame))
   900     window_prompting |= PPosition;
   901 
   902   fset_parent_frame (f, parent_frame);
   903   store_frame_param (f, Qparent_frame, parent_frame);
   904 
   905   if (!NILP (parent_frame))
   906     haiku_set_parent_frame (f, parent_frame, Qnil);
   907 
   908   gui_default_parameter (f, parms, Qundecorated, Qnil, NULL, NULL, RES_TYPE_BOOLEAN);
   909   gui_default_parameter (f, parms, Qoverride_redirect, Qnil, NULL, NULL, RES_TYPE_BOOLEAN);
   910 
   911   gui_default_parameter (f, parms, Qicon_type, Qnil,
   912                          "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
   913   gui_default_parameter (f, parms, Qauto_raise, Qnil,
   914                          "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
   915   gui_default_parameter (f, parms, Qauto_lower, Qnil,
   916                          "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
   917   gui_default_parameter (f, parms, Qcursor_type, Qbox,
   918                          "cursorType", "CursorType", RES_TYPE_SYMBOL);
   919   gui_default_parameter (f, parms, Qscroll_bar_width, Qnil,
   920                          "scrollBarWidth", "ScrollBarWidth",
   921                          RES_TYPE_NUMBER);
   922   gui_default_parameter (f, parms, Qscroll_bar_height, Qnil,
   923                          "scrollBarHeight", "ScrollBarHeight",
   924                          RES_TYPE_NUMBER);
   925   gui_default_parameter (f, parms, Qalpha, Qnil,
   926                          "alpha", "Alpha", RES_TYPE_NUMBER);
   927   gui_default_parameter (f, parms, Qalpha_background, Qnil,
   928                          "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
   929   gui_default_parameter (f, parms, Qfullscreen, Qnil,
   930                          "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
   931 
   932   gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
   933                          "inhibitDoubleBuffering", "InhibitDoubleBuffering",
   934                          RES_TYPE_BOOLEAN);
   935 
   936   f->can_set_window_size = true;
   937 
   938   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
   939                      0, true, Qx_create_frame_2);
   940 
   941   Lisp_Object visibility;
   942 
   943   visibility = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
   944                                     RES_TYPE_SYMBOL);
   945   if (BASE_EQ (visibility, Qunbound))
   946     visibility = Qt;
   947   if (EQ (visibility, Qicon))
   948     haiku_iconify_frame (f);
   949   else if (!NILP (visibility))
   950     haiku_visualize_frame (f);
   951   else /* Qnil */
   952     {
   953       f->was_invisible = true;
   954     }
   955 
   956   if (FRAME_HAS_MINIBUF_P (f)
   957       && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
   958           || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
   959     kset_default_minibuffer_frame (kb, frame);
   960 
   961   /* Set whether or not frame synchronization is enabled.  */
   962   gui_default_parameter (f, parms, Quse_frame_synchronization, Qt,
   963                          NULL, NULL, RES_TYPE_BOOLEAN);
   964 
   965   gui_default_parameter (f, parms, Qz_group, Qnil,
   966                          NULL, NULL, RES_TYPE_SYMBOL);
   967 
   968   for (tem = parms; CONSP (tem); tem = XCDR (tem))
   969     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
   970       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
   971 
   972   block_input ();
   973   if (window_prompting & (USPosition | PPosition))
   974     haiku_set_offset (f, f->left_pos, f->top_pos, 1);
   975   else if (cascade_target)
   976     haiku_set_offset (f, cascade_target->left_pos + 15,
   977                       cascade_target->top_pos + 15, 1);
   978   else
   979     BWindow_center_on_screen (FRAME_HAIKU_WINDOW (f));
   980   unblock_input ();
   981 
   982   FRAME_OUTPUT_DATA (f)->configury_done = true;
   983 
   984   if (f->want_fullscreen != FULLSCREEN_NONE)
   985     FRAME_TERMINAL (f)->fullscreen_hook (f);
   986 
   987   /* Make sure windows on this frame appear in calls to next-window
   988      and similar functions.  */
   989   Vwindow_list = Qnil;
   990 
   991   return unbind_to (count, frame);
   992 }
   993 
   994 /* Create a frame for a tooltip.  PARMS is a list of frame parameters.
   995    TEXT is the string to display in the tip frame.  Value is the
   996    frame.
   997 
   998    Note that functions called here, esp. gui_default_parameter can
   999    signal errors, for instance when a specified color name is
  1000    undefined.  We have to make sure that we're in a consistent state
  1001    when this happens.  */
  1002 
  1003 static Lisp_Object
  1004 haiku_create_tip_frame (Lisp_Object parms)
  1005 {
  1006   struct frame *f;
  1007   Lisp_Object frame;
  1008   Lisp_Object name;
  1009   specpdl_ref count = SPECPDL_INDEX ();
  1010   bool face_change_before = face_change;
  1011   struct haiku_display_info *dpyinfo = x_display_list;
  1012 
  1013   if (!dpyinfo->terminal->name)
  1014     error ("Terminal is not live, can't create new frames on it");
  1015 
  1016   parms = Fcopy_alist (parms);
  1017 
  1018   /* Get the name of the frame to use for resource lookup.  */
  1019   name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
  1020                               RES_TYPE_STRING);
  1021   if (!STRINGP (name)
  1022       && !BASE_EQ (name, Qunbound)
  1023       && !NILP (name))
  1024     error ("Invalid frame name--not a string or nil");
  1025 
  1026   frame = Qnil;
  1027   f = make_frame (false);
  1028   f->wants_modeline = false;
  1029   XSETFRAME (frame, f);
  1030   record_unwind_protect (unwind_create_tip_frame, frame);
  1031 
  1032   f->terminal = dpyinfo->terminal;
  1033 
  1034   /* By setting the output method, we're essentially saying that
  1035      the frame is live, as per FRAME_LIVE_P.  If we get a signal
  1036      from this point on, x_destroy_window might screw up reference
  1037      counts etc.  */
  1038   f->output_method = output_haiku;
  1039   f->output_data.haiku = xzalloc (sizeof *f->output_data.haiku);
  1040   f->output_data.haiku->wait_for_event_type = -1;
  1041   f->output_data.haiku->relief_background = -1;
  1042 
  1043   f->tooltip = true;
  1044   fset_icon_name (f, Qnil);
  1045   FRAME_DISPLAY_INFO (f) = dpyinfo;
  1046 
  1047   FRAME_OUTPUT_DATA (f)->parent_desc = NULL;
  1048 
  1049   /* Set the name; the functions to which we pass f expect the name to
  1050      be set.  */
  1051   if (BASE_EQ (name, Qunbound) || NILP (name))
  1052     f->explicit_name = false;
  1053   else
  1054     {
  1055       fset_name (f, name);
  1056       f->explicit_name = true;
  1057       /* use the frame's title when getting resources for this frame.  */
  1058       specbind (Qx_resource_name, name);
  1059     }
  1060 
  1061 #ifdef USE_BE_CAIRO
  1062   register_font_driver (&ftcrfont_driver, f);
  1063 #ifdef HAVE_HARFBUZZ
  1064   register_font_driver (&ftcrhbfont_driver, f);
  1065 #endif
  1066 #endif
  1067   register_font_driver (&haikufont_driver, f);
  1068 
  1069   image_cache_refcount =
  1070     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
  1071 
  1072   gui_default_parameter (f, parms, Qfont_backend, Qnil,
  1073                          "fontBackend", "FontBackend", RES_TYPE_STRING);
  1074 
  1075   /* Extract the window parameters from the supplied values that are
  1076      needed to determine window geometry.  */
  1077   FRAME_RIF (f)->default_font_parameter (f, parms);
  1078 
  1079   /* This defaults to 1 in order to match xterm.  We recognize either
  1080      internalBorderWidth or internalBorder (which is what xterm calls
  1081      it).  */
  1082   if (NILP (Fassq (Qinternal_border_width, parms)))
  1083     {
  1084       Lisp_Object value;
  1085 
  1086       value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
  1087                                    "internalBorder", "internalBorder",
  1088                                    RES_TYPE_NUMBER);
  1089       if (! BASE_EQ (value, Qunbound))
  1090         parms = Fcons (Fcons (Qinternal_border_width, value),
  1091                        parms);
  1092     }
  1093 
  1094   gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (1),
  1095                          "internalBorderWidth", "internalBorderWidth",
  1096                          RES_TYPE_NUMBER);
  1097 
  1098   gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
  1099                          NULL, NULL, RES_TYPE_NUMBER);
  1100   gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
  1101                          NULL, NULL, RES_TYPE_NUMBER);
  1102 
  1103   /* Also do the stuff which must be set before the window exists.  */
  1104   gui_default_parameter (f, parms, Qforeground_color, build_string ("black"),
  1105                          "foreground", "Foreground", RES_TYPE_STRING);
  1106 
  1107   gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
  1108                          "background", "Background", RES_TYPE_STRING);
  1109 
  1110   /* FIXME: is there a better method to tell Emacs to not recolor the
  1111      cursors other than setting the color to a special value?  */
  1112   gui_default_parameter (f, parms, Qmouse_color, build_string ("font-color"),
  1113                          "pointerColor", "Foreground", RES_TYPE_STRING);
  1114   gui_default_parameter (f, parms, Qcursor_color, build_string ("black"),
  1115                          "cursorColor", "Foreground", RES_TYPE_STRING);
  1116   gui_default_parameter (f, parms, Qborder_color, build_string ("black"),
  1117                          "borderColor", "BorderColor", RES_TYPE_STRING);
  1118   gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
  1119                          NULL, NULL, RES_TYPE_BOOLEAN);
  1120 
  1121   /* Init faces before gui_default_parameter is called for the
  1122      scroll-bar-width parameter because otherwise we end up in
  1123      init_iterator with a null face cache, which should not happen.  */
  1124   init_frame_faces (f);
  1125 
  1126   gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
  1127                          "inhibitDoubleBuffering", "InhibitDoubleBuffering",
  1128                          RES_TYPE_BOOLEAN);
  1129 
  1130   gui_figure_window_size (f, parms, false, false);
  1131 
  1132   {
  1133     void *window;
  1134 
  1135     block_input ();
  1136     window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view);
  1137 
  1138     FRAME_OUTPUT_DATA (f)->window = window;
  1139     if (!window)
  1140       emacs_abort ();
  1141 
  1142     BWindow_set_tooltip_decoration (window);
  1143     unblock_input ();
  1144   }
  1145 
  1146   gui_default_parameter (f, parms, Qauto_raise, Qnil,
  1147                          "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
  1148   gui_default_parameter (f, parms, Qauto_lower, Qnil,
  1149                          "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
  1150   gui_default_parameter (f, parms, Qcursor_type, Qbox,
  1151                          "cursorType", "CursorType", RES_TYPE_SYMBOL);
  1152   gui_default_parameter (f, parms, Qalpha, Qnil,
  1153                          "alpha", "Alpha", RES_TYPE_NUMBER);
  1154   gui_default_parameter (f, parms, Qalpha_background, Qnil,
  1155                          "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
  1156 
  1157   initial_setup_back_buffer (f);
  1158 
  1159   /* Add `tooltip' frame parameter's default value. */
  1160   if (NILP (Fframe_parameter (frame, Qtooltip)))
  1161     {
  1162       AUTO_FRAME_ARG (arg, Qtooltip, Qt);
  1163       Fmodify_frame_parameters (frame, arg);
  1164     }
  1165 
  1166   /* FIXME - can this be done in a similar way to normal frames?
  1167      https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */
  1168 
  1169   {
  1170     Lisp_Object disptype;
  1171 
  1172     if (be_get_display_planes () == 1)
  1173       disptype = Qmono;
  1174     else if (be_is_display_grayscale ())
  1175       disptype = Qgrayscale;
  1176     else
  1177       disptype = Qcolor;
  1178 
  1179     if (NILP (Fframe_parameter (frame, Qdisplay_type)))
  1180       {
  1181         AUTO_FRAME_ARG (arg, Qdisplay_type, disptype);
  1182         Fmodify_frame_parameters (frame, arg);
  1183       }
  1184   }
  1185 
  1186   /* Set up faces after all frame parameters are known.  This call
  1187      also merges in face attributes specified for new frames.
  1188 
  1189      Frame parameters may be changed if .Xdefaults contains
  1190      specifications for the default font.  For example, if there is an
  1191      `Emacs.default.attributeBackground: pink', the `background-color'
  1192      attribute of the frame gets set, which let's the internal border
  1193      of the tooltip frame appear in pink.  Prevent this.  */
  1194   {
  1195     Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
  1196 
  1197     call2 (Qface_set_after_frame_default, frame, Qnil);
  1198 
  1199     if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
  1200       {
  1201         AUTO_FRAME_ARG (arg, Qbackground_color, bg);
  1202         Fmodify_frame_parameters (frame, arg);
  1203       }
  1204   }
  1205 
  1206   f->no_split = true;
  1207 
  1208   /* Now that the frame will be official, it counts as a reference to
  1209      its display and terminal.  */
  1210   f->terminal->reference_count++;
  1211 
  1212   /* It is now ok to make the frame official even if we get an error
  1213      below.  And the frame needs to be on Vframe_list or making it
  1214      visible won't work.  */
  1215   Vframe_list = Fcons (frame, Vframe_list);
  1216   f->can_set_window_size = true;
  1217   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
  1218                      0, true, Qtip_frame);
  1219 
  1220   /* Setting attributes of faces of the tooltip frame from resources
  1221      and similar will set face_change, which leads to the clearing of
  1222      all current matrices.  Since this isn't necessary here, avoid it
  1223      by resetting face_change to the value it had before we created
  1224      the tip frame.  */
  1225   face_change = face_change_before;
  1226 
  1227   /* Discard the unwind_protect.  */
  1228   return unbind_to (count, frame);
  1229 }
  1230 
  1231 
  1232 static void
  1233 compute_tip_xy (struct frame *f,
  1234                 Lisp_Object parms, Lisp_Object dx, Lisp_Object dy,
  1235                 int width, int height, int *root_x, int *root_y)
  1236 {
  1237   Lisp_Object left, top, right, bottom;
  1238   int min_x = 0, min_y = 0, max_x = 0, max_y = 0;
  1239 
  1240   /* User-specified position?  */
  1241   left = Fcdr (Fassq (Qleft, parms));
  1242   top  = Fcdr (Fassq (Qtop, parms));
  1243   right = Fcdr (Fassq (Qright, parms));
  1244   bottom = Fcdr (Fassq (Qbottom, parms));
  1245 
  1246   /* Move the tooltip window where the mouse pointer is.  Resize and
  1247      show it.  */
  1248   if ((!FIXNUMP (left) && !FIXNUMP (right))
  1249       || (!FIXNUMP (top) && !FIXNUMP (bottom)))
  1250     {
  1251       int x, y;
  1252 
  1253       /* Default min and max values.  */
  1254       min_x = 0;
  1255       min_y = 0;
  1256 
  1257       be_get_screen_dimensions (&max_x, &max_y);
  1258 
  1259       max_x = max_x - 1;
  1260       max_y = max_y - 1;
  1261 
  1262       block_input ();
  1263       BView_get_mouse (FRAME_HAIKU_VIEW (f), &x, &y);
  1264       BView_convert_to_screen (FRAME_HAIKU_VIEW (f), &x, &y);
  1265       *root_x = x;
  1266       *root_y = y;
  1267       unblock_input ();
  1268     }
  1269 
  1270   if (FIXNUMP (top))
  1271     *root_y = XFIXNUM (top);
  1272   else if (FIXNUMP (bottom))
  1273     *root_y = XFIXNUM (bottom) - height;
  1274   else if (*root_y + XFIXNUM (dy) <= min_y)
  1275     *root_y = min_y; /* Can happen for negative dy */
  1276   else if (*root_y + XFIXNUM (dy) + height <= max_y)
  1277     /* It fits below the pointer */
  1278       *root_y += XFIXNUM (dy);
  1279   else if (height + XFIXNUM (dy) + min_y <= *root_y)
  1280     /* It fits above the pointer.  */
  1281     *root_y -= height + XFIXNUM (dy);
  1282   else
  1283     /* Put it on the top.  */
  1284     *root_y = min_y;
  1285 
  1286   if (FIXNUMP (left))
  1287     *root_x = XFIXNUM (left);
  1288   else if (FIXNUMP (right))
  1289     *root_x = XFIXNUM (right) - width;
  1290   else if (*root_x + XFIXNUM (dx) <= min_x)
  1291     *root_x = 0; /* Can happen for negative dx */
  1292   else if (*root_x + XFIXNUM (dx) + width <= max_x)
  1293     /* It fits to the right of the pointer.  */
  1294     *root_x += XFIXNUM (dx);
  1295   else if (width + XFIXNUM (dx) + min_x <= *root_x)
  1296     /* It fits to the left of the pointer.  */
  1297     *root_x -= width + XFIXNUM (dx);
  1298   else
  1299     /* Put it left justified on the screen -- it ought to fit that way.  */
  1300     *root_x = min_x;
  1301 }
  1302 
  1303 static Lisp_Object
  1304 haiku_hide_tip (bool delete)
  1305 {
  1306   Lisp_Object it, frame;
  1307 
  1308   if (!NILP (tip_timer))
  1309     {
  1310       call1 (Qcancel_timer, tip_timer);
  1311       tip_timer = Qnil;
  1312     }
  1313 
  1314   FOR_EACH_FRAME (it, frame)
  1315     if (FRAME_WINDOW_P (XFRAME (frame))
  1316         && FRAME_HAIKU_VIEW (XFRAME (frame)))
  1317       BView_set_tooltip (FRAME_HAIKU_VIEW (XFRAME (frame)), NULL);
  1318 
  1319   if (NILP (tip_frame)
  1320       || (!delete && !NILP (tip_frame)
  1321           && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
  1322     return Qnil;
  1323   else
  1324     {
  1325       Lisp_Object was_open = Qnil;
  1326 
  1327       specpdl_ref count = SPECPDL_INDEX ();
  1328       specbind (Qinhibit_redisplay, Qt);
  1329       specbind (Qinhibit_quit, Qt);
  1330 
  1331       if (!NILP (tip_frame))
  1332         {
  1333           if (FRAME_LIVE_P (XFRAME (tip_frame)))
  1334             {
  1335               if (delete)
  1336                 {
  1337                   delete_frame (tip_frame, Qnil);
  1338                   tip_frame = Qnil;
  1339                 }
  1340               else
  1341                 haiku_unvisualize_frame (XFRAME (tip_frame));
  1342 
  1343               was_open = Qt;
  1344             }
  1345           else
  1346             tip_frame = Qnil;
  1347         }
  1348       else
  1349         tip_frame = Qnil;
  1350 
  1351       return unbind_to (count, was_open);
  1352     }
  1353 }
  1354 
  1355 static void
  1356 haiku_set_undecorated (struct frame *f, Lisp_Object new_value,
  1357                        Lisp_Object old_value)
  1358 {
  1359   if (EQ (new_value, old_value))
  1360     return;
  1361 
  1362   block_input ();
  1363   FRAME_UNDECORATED (f) = !NILP (new_value);
  1364   BWindow_change_decoration (FRAME_HAIKU_WINDOW (f), NILP (new_value));
  1365   unblock_input ();
  1366 
  1367   haiku_update_after_decoration_change (f);
  1368 }
  1369 
  1370 static void
  1371 haiku_set_override_redirect (struct frame *f, Lisp_Object new_value,
  1372                              Lisp_Object old_value)
  1373 {
  1374   if (EQ (new_value, old_value))
  1375     return;
  1376 
  1377   block_input ();
  1378   BWindow_set_override_redirect (FRAME_HAIKU_WINDOW (f),
  1379                                  !NILP (new_value));
  1380   FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value);
  1381   unblock_input ();
  1382 
  1383   haiku_update_after_decoration_change (f);
  1384 }
  1385 
  1386 static void
  1387 haiku_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
  1388 {
  1389   int nlines;
  1390 
  1391   if (FRAME_TOOLTIP_P (f))
  1392     return;
  1393 
  1394   if (TYPE_RANGED_FIXNUMP (int, value))
  1395     nlines = XFIXNUM (value);
  1396   else
  1397     nlines = 0;
  1398 
  1399   fset_redisplay (f);
  1400 
  1401   if (nlines)
  1402     {
  1403       FRAME_EXTERNAL_MENU_BAR (f) = 1;
  1404       if (FRAME_HAIKU_P (f) && !FRAME_HAIKU_MENU_BAR (f))
  1405         XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = 1;
  1406     }
  1407   else
  1408     {
  1409       FRAME_MENU_BAR_LINES (f) = 0;
  1410       FRAME_MENU_BAR_HEIGHT (f) = 0;
  1411 
  1412       if (FRAME_EXTERNAL_MENU_BAR (f))
  1413         free_frame_menubar (f);
  1414 
  1415       FRAME_EXTERNAL_MENU_BAR (f) = 0;
  1416       FRAME_HAIKU_MENU_BAR (f) = 0;
  1417     }
  1418 
  1419   adjust_frame_glyphs (f);
  1420 }
  1421 
  1422 /* Return geometric attributes of FRAME.  According to the value of
  1423    ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the inner
  1424    edges of FRAME, the root window edges of frame (Qroot_edges).  Any
  1425    other value means to return the geometry as returned by
  1426    Fx_frame_geometry.  */
  1427 static Lisp_Object
  1428 frame_geometry (Lisp_Object frame, Lisp_Object attribute)
  1429 {
  1430   struct frame *f, *parent;
  1431   void *window;
  1432   int outer_x, outer_y, outer_width, outer_height;
  1433   int right_off, bottom_off, top_off;
  1434   int native_x, native_y;
  1435 
  1436   f = decode_window_system_frame (frame);
  1437   parent = FRAME_PARENT_FRAME (f);
  1438   window = FRAME_HAIKU_WINDOW (f);
  1439 
  1440   be_lock_window (window);
  1441   be_get_window_decorator_frame (window, &outer_x, &outer_y,
  1442                                  &outer_width, &outer_height);
  1443   be_get_window_decorator_dimensions (window, NULL, &top_off,
  1444                                       &right_off, &bottom_off);
  1445   be_unlock_window (window);
  1446 
  1447   native_x = FRAME_OUTPUT_DATA (f)->frame_x;
  1448   native_y = FRAME_OUTPUT_DATA (f)->frame_y;
  1449 
  1450   if (parent)
  1451     {
  1452       /* Adjust all the coordinates by the coordinates of the parent
  1453          frame.  */
  1454       outer_x -= FRAME_OUTPUT_DATA (parent)->frame_x;
  1455       outer_y -= FRAME_OUTPUT_DATA (parent)->frame_y;
  1456       native_x -= FRAME_OUTPUT_DATA (parent)->frame_x;
  1457       native_y -= FRAME_OUTPUT_DATA (parent)->frame_y;
  1458     }
  1459 
  1460   if (EQ (attribute, Qouter_edges))
  1461     return list4i (outer_x, outer_y,
  1462                    outer_x + outer_width,
  1463                    outer_y + outer_height);
  1464   else if (EQ (attribute, Qnative_edges))
  1465     return list4i (native_x, native_y,
  1466                    native_x + FRAME_PIXEL_WIDTH (f),
  1467                    native_y + FRAME_PIXEL_HEIGHT (f));
  1468   else if (EQ (attribute, Qinner_edges))
  1469     return list4i (native_x + FRAME_INTERNAL_BORDER_WIDTH (f),
  1470                    native_y + FRAME_INTERNAL_BORDER_WIDTH (f)
  1471                    + FRAME_MENU_BAR_HEIGHT (f) + FRAME_TOOL_BAR_HEIGHT (f),
  1472                    native_x - FRAME_INTERNAL_BORDER_WIDTH (f)
  1473                    + FRAME_PIXEL_WIDTH (f),
  1474                    native_y + FRAME_PIXEL_HEIGHT (f)
  1475                    - FRAME_INTERNAL_BORDER_WIDTH (f));
  1476 
  1477   else
  1478     return list (Fcons (Qouter_position,
  1479                         Fcons (make_fixnum (outer_x),
  1480                                make_fixnum (outer_y))),
  1481                  Fcons (Qouter_size,
  1482                         Fcons (make_fixnum (outer_width),
  1483                                make_fixnum (outer_height))),
  1484                  Fcons (Qexternal_border_size,
  1485                         Fcons (make_fixnum (right_off),
  1486                                make_fixnum (bottom_off))),
  1487                  Fcons (Qtitle_bar_size,
  1488                         Fcons (make_fixnum (outer_width),
  1489                                make_fixnum (top_off))),
  1490                  Fcons (Qmenu_bar_external, Qnil),
  1491                  Fcons (Qmenu_bar_size,
  1492                         Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f)
  1493                                             - (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)),
  1494                                make_fixnum (FRAME_MENU_BAR_HEIGHT (f)))),
  1495                  Fcons (Qtool_bar_external, Qnil),
  1496                  Fcons (Qtool_bar_position, Qtop),
  1497                  Fcons (Qtool_bar_size,
  1498                         Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f)
  1499                                             - (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)),
  1500                                make_fixnum (FRAME_TOOL_BAR_HEIGHT (f)))),
  1501                  Fcons (Qinternal_border_width,
  1502                         make_fixnum (FRAME_INTERNAL_BORDER_WIDTH (f))));
  1503 }
  1504 
  1505 void
  1506 haiku_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1507 {
  1508   unsigned long background;
  1509 
  1510   background = haiku_decode_color (f, arg);
  1511 
  1512   FRAME_OUTPUT_DATA (f)->cursor_fg = background;
  1513   FRAME_BACKGROUND_PIXEL (f) = background;
  1514 
  1515   if (FRAME_HAIKU_VIEW (f))
  1516     {
  1517      BView_draw_lock (FRAME_HAIKU_DRAWABLE (f), false, 0, 0, 0, 0);
  1518       BView_SetViewColor (FRAME_HAIKU_DRAWABLE (f), background);
  1519       BView_draw_unlock (FRAME_HAIKU_DRAWABLE (f));
  1520 
  1521       FRAME_OUTPUT_DATA (f)->cursor_fg = background;
  1522       update_face_from_frame_parameter (f, Qbackground_color, arg);
  1523 
  1524       if (FRAME_VISIBLE_P (f))
  1525         redraw_frame (f);
  1526     }
  1527 }
  1528 
  1529 void
  1530 haiku_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1531 {
  1532   unsigned long fore_pixel, pixel;
  1533 
  1534   pixel = haiku_decode_color (f, arg);
  1535 
  1536   if (!NILP (Vx_cursor_fore_pixel))
  1537     {
  1538       fore_pixel = haiku_decode_color (f, Vx_cursor_fore_pixel);
  1539       FRAME_OUTPUT_DATA (f)->cursor_fg = fore_pixel;
  1540     }
  1541   else
  1542     FRAME_OUTPUT_DATA (f)->cursor_fg = FRAME_BACKGROUND_PIXEL (f);
  1543 
  1544   haiku_query_color (pixel, &FRAME_CURSOR_COLOR (f));
  1545 
  1546   if (FRAME_VISIBLE_P (f))
  1547     {
  1548       gui_update_cursor (f, false);
  1549       gui_update_cursor (f, true);
  1550     }
  1551 
  1552   update_face_from_frame_parameter (f, Qcursor_color, arg);
  1553 }
  1554 
  1555 void
  1556 haiku_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1557 {
  1558   set_frame_cursor_types (f, arg);
  1559 }
  1560 
  1561 unsigned long
  1562 haiku_get_pixel (haiku bitmap, int x, int y)
  1563 {
  1564   unsigned char *data;
  1565   int32_t bytes_per_row;
  1566   int mono_p, left, right, top, bottom, byte;
  1567 
  1568   data = BBitmap_data (bitmap);
  1569   BBitmap_dimensions (bitmap, &left, &top, &right, &bottom,
  1570                       &bytes_per_row, &mono_p);
  1571 
  1572   if (x < 0 || x > right - left || y < 0 || y > bottom - top)
  1573     emacs_abort ();
  1574 
  1575   if (!mono_p)
  1576     return ((uint32_t *) (data + (bytes_per_row * y)))[x];
  1577 
  1578   byte = y * bytes_per_row + x / 8;
  1579   return data[byte] & (1 << (x % 8));
  1580 }
  1581 
  1582 void
  1583 haiku_put_pixel (haiku bitmap, int x, int y, unsigned long pixel)
  1584 {
  1585   unsigned char *data, *byte;
  1586   int32_t bytes_per_row;
  1587   int mono_p, left, right, top, bottom;
  1588   ptrdiff_t off, bit, xoff;
  1589 
  1590   data = BBitmap_data (bitmap);
  1591   BBitmap_dimensions (bitmap, &left, &top, &right, &bottom,
  1592                       &bytes_per_row, &mono_p);
  1593 
  1594   if (x < 0 || x > right - left || y < 0 || y > bottom - top)
  1595     emacs_abort ();
  1596 
  1597   if (mono_p)
  1598     {
  1599       off = y * bytes_per_row;
  1600       bit = x % 8;
  1601       xoff = x / 8;
  1602 
  1603       byte = data + off + xoff;
  1604       if (!pixel)
  1605         *byte &= ~(1 << bit);
  1606       else
  1607         *byte |= 1 << bit;
  1608     }
  1609   else
  1610     ((uint32_t *) (data + (bytes_per_row * y)))[x] = pixel;
  1611 }
  1612 
  1613 void
  1614 haiku_free_frame_resources (struct frame *f)
  1615 {
  1616   haiku window, drawable, mbar;
  1617   Mouse_HLInfo *hlinfo;
  1618   struct haiku_display_info *dpyinfo;
  1619   Lisp_Object bar;
  1620   struct scroll_bar *b;
  1621 
  1622   check_window_system (f);
  1623   block_input ();
  1624 
  1625   hlinfo = MOUSE_HL_INFO (f);
  1626   window = FRAME_HAIKU_WINDOW (f);
  1627   drawable = FRAME_HAIKU_VIEW (f);
  1628   mbar = FRAME_HAIKU_MENU_BAR (f);
  1629   dpyinfo = FRAME_DISPLAY_INFO (f);
  1630 
  1631   free_frame_faces (f);
  1632   haiku_free_custom_cursors (f);
  1633 
  1634   /* Free scroll bars */
  1635   for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
  1636     {
  1637       b = XSCROLL_BAR (bar);
  1638       haiku_scroll_bar_remove (b);
  1639     }
  1640 
  1641   if (f == dpyinfo->highlight_frame)
  1642     dpyinfo->highlight_frame = 0;
  1643   if (f == dpyinfo->focused_frame)
  1644     dpyinfo->focused_frame = 0;
  1645   if (f == dpyinfo->last_mouse_motion_frame)
  1646     dpyinfo->last_mouse_motion_frame = NULL;
  1647   if (f == dpyinfo->last_mouse_frame)
  1648     dpyinfo->last_mouse_frame = NULL;
  1649   if (f == dpyinfo->focus_event_frame)
  1650     dpyinfo->focus_event_frame = NULL;
  1651 
  1652   if (f == hlinfo->mouse_face_mouse_frame)
  1653     reset_mouse_highlight (hlinfo);
  1654 
  1655   if (mbar)
  1656     {
  1657       BMenuBar_delete (mbar);
  1658       if (f->output_data.haiku->menu_bar_open_p)
  1659         {
  1660           --popup_activated_p;
  1661           f->output_data.haiku->menu_bar_open_p = 0;
  1662         }
  1663     }
  1664 
  1665   if (drawable)
  1666     BView_emacs_delete (drawable);
  1667 
  1668   if (window)
  1669     BWindow_quit (window);
  1670 
  1671   if (FRAME_OUTPUT_DATA (f)->saved_menu_event)
  1672     xfree (FRAME_OUTPUT_DATA (f)->saved_menu_event);
  1673 
  1674   xfree (FRAME_OUTPUT_DATA (f));
  1675   FRAME_OUTPUT_DATA (f) = NULL;
  1676 
  1677   unblock_input ();
  1678 }
  1679 
  1680 void
  1681 haiku_iconify_frame (struct frame *frame)
  1682 {
  1683   if (FRAME_ICONIFIED_P (frame))
  1684     return;
  1685 
  1686   SET_FRAME_VISIBLE (frame, false);
  1687   SET_FRAME_ICONIFIED (frame, true);
  1688 
  1689   block_input ();
  1690   BWindow_iconify (FRAME_HAIKU_WINDOW (frame));
  1691   unblock_input ();
  1692 }
  1693 
  1694 void
  1695 haiku_visualize_frame (struct frame *f)
  1696 {
  1697   block_input ();
  1698 
  1699   if (!FRAME_VISIBLE_P (f))
  1700     {
  1701       if (FRAME_NO_FOCUS_ON_MAP (f))
  1702         BWindow_set_avoid_focus (FRAME_HAIKU_WINDOW (f), 1);
  1703       BWindow_set_visible (FRAME_HAIKU_WINDOW (f), 1);
  1704       if (FRAME_NO_FOCUS_ON_MAP (f) &&
  1705           !FRAME_NO_ACCEPT_FOCUS (f))
  1706         BWindow_set_avoid_focus (FRAME_HAIKU_WINDOW (f), 0);
  1707       BWindow_sync (FRAME_HAIKU_WINDOW (f));
  1708 
  1709       haiku_set_offset (f, f->left_pos, f->top_pos, 0);
  1710 
  1711       SET_FRAME_VISIBLE (f, 1);
  1712       SET_FRAME_ICONIFIED (f, 0);
  1713     }
  1714 
  1715   unblock_input ();
  1716 }
  1717 
  1718 void
  1719 haiku_unvisualize_frame (struct frame *f)
  1720 {
  1721   block_input ();
  1722 
  1723   BWindow_set_visible (FRAME_HAIKU_WINDOW (f), 0);
  1724   BWindow_sync (FRAME_HAIKU_WINDOW (f));
  1725   SET_FRAME_VISIBLE (f, 0);
  1726   SET_FRAME_ICONIFIED (f, 0);
  1727 
  1728   unblock_input ();
  1729 }
  1730 
  1731 void
  1732 haiku_set_internal_border_width (struct frame *f, Lisp_Object arg,
  1733                                  Lisp_Object oldval)
  1734 {
  1735   int old_width = FRAME_INTERNAL_BORDER_WIDTH (f);
  1736   int new_width = check_int_nonnegative (arg);
  1737 
  1738   if (new_width == old_width)
  1739     return;
  1740 
  1741   f->internal_border_width = new_width;
  1742 
  1743   if (FRAME_HAIKU_WINDOW (f))
  1744     {
  1745       adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width);
  1746       haiku_clear_under_internal_border (f);
  1747     }
  1748 
  1749   SET_FRAME_GARBAGED (f);
  1750 }
  1751 
  1752 void
  1753 haiku_set_frame_visible_invisible (struct frame *f, bool visible_p)
  1754 {
  1755   if (visible_p)
  1756     haiku_visualize_frame (f);
  1757   else
  1758     haiku_unvisualize_frame (f);
  1759 }
  1760 
  1761 void
  1762 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
  1763 {
  1764   block_input ();
  1765 
  1766   BView_convert_to_screen (FRAME_HAIKU_VIEW (f), &pix_x, &pix_y);
  1767   be_warp_pointer (pix_x, pix_y);
  1768 
  1769   unblock_input ();
  1770 }
  1771 
  1772 void
  1773 haiku_query_color (uint32_t col, Emacs_Color *color_def)
  1774 {
  1775   color_def->red = RED_FROM_ULONG (col) * 257;
  1776   color_def->green = GREEN_FROM_ULONG (col) * 257;
  1777   color_def->blue = BLUE_FROM_ULONG (col) * 257;
  1778 
  1779   color_def->pixel = col;
  1780 }
  1781 
  1782 Display_Info *
  1783 check_x_display_info (Lisp_Object object)
  1784 {
  1785   return check_haiku_display_info (object);
  1786 }
  1787 
  1788 /* Rename frame F to NAME.  If NAME is nil, set F's name to the
  1789    default name.  If EXPLICIT_P is non-zero, that indicates Lisp code
  1790    is setting the name, not redisplay; in that case, set F's name to
  1791    NAME and set F->explicit_name; if NAME is nil, clear
  1792    F->explicit_name.
  1793 
  1794    If EXPLICIT_P is zero, it means redisplay is setting the name; the
  1795    name provided will be ignored if explicit_name is set.  */
  1796 void
  1797 haiku_set_name (struct frame *f, Lisp_Object name, bool explicit_p)
  1798 {
  1799   struct haiku_display_info *dpyinfo;
  1800 
  1801   if (explicit_p)
  1802     {
  1803       if (f->explicit_name && NILP (name))
  1804         update_mode_lines = 37;
  1805 
  1806       f->explicit_name = !NILP (name);
  1807     }
  1808   else if (f->explicit_name)
  1809     return;
  1810 
  1811   dpyinfo = FRAME_DISPLAY_INFO (f);
  1812 
  1813   if (NILP (name))
  1814     name = dpyinfo->default_name;
  1815 
  1816   if (!NILP (Fstring_equal (name, f->name)))
  1817     return;
  1818 
  1819   fset_name (f, name);
  1820 
  1821   if (!NILP (f->title))
  1822     name = f->title;
  1823 
  1824   haiku_set_title_bar_text (f, name);
  1825 }
  1826 
  1827 static void
  1828 haiku_set_inhibit_double_buffering (struct frame *f,
  1829                                     Lisp_Object new_value,
  1830                                     Lisp_Object old_value)
  1831 {
  1832   block_input ();
  1833   if (FRAME_HAIKU_WINDOW (f))
  1834     {
  1835 #ifndef USE_BE_CAIRO
  1836       if (NILP (new_value))
  1837 #endif
  1838         EmacsView_set_up_double_buffering (FRAME_HAIKU_VIEW (f));
  1839 #ifndef USE_BE_CAIRO
  1840       else
  1841         EmacsView_disable_double_buffering (FRAME_HAIKU_VIEW (f));
  1842 #endif
  1843 
  1844       SET_FRAME_GARBAGED (f);
  1845     }
  1846   unblock_input ();
  1847 }
  1848 
  1849 static void
  1850 haiku_set_sticky (struct frame *f, Lisp_Object new_value,
  1851                   Lisp_Object old_value)
  1852 {
  1853   block_input ();
  1854   BWindow_set_sticky (FRAME_HAIKU_WINDOW (f), !NILP (new_value));
  1855   unblock_input ();
  1856 }
  1857 
  1858 struct user_cursor_info
  1859 {
  1860   /* A pointer to the Lisp_Object describing the cursor.  */
  1861   Lisp_Object *lisp_cursor;
  1862 
  1863   /* The offset of the cursor in the `struct haiku_output' of each
  1864      frame.  */
  1865   ptrdiff_t output_offset;
  1866 
  1867   /* The offset of the default value of the cursor in the display
  1868      info structure.  */
  1869   ptrdiff_t default_offset;
  1870 };
  1871 
  1872 struct user_cursor_bitmap_info
  1873 {
  1874   /* A bitmap to use instead of the font cursor to create cursors in a
  1875      certain color.  */
  1876   const void *bits;
  1877 
  1878   /* The mask for that bitmap.  */
  1879   const void *mask;
  1880 
  1881   /* The dimensions of the cursor bitmap.  */
  1882   int width, height;
  1883 
  1884   /* The position inside the cursor bitmap corresponding to the
  1885      position of the mouse pointer.  */
  1886   int x, y;
  1887 };
  1888 
  1889 #define INIT_USER_CURSOR(lisp, cursor)                  \
  1890   { (lisp), offsetof (struct haiku_output, cursor),     \
  1891       offsetof (struct haiku_display_info, cursor) }
  1892 
  1893 struct user_cursor_info custom_cursors[] =
  1894   {
  1895     INIT_USER_CURSOR (&Vx_pointer_shape,                text_cursor),
  1896     INIT_USER_CURSOR (NULL,                             nontext_cursor),
  1897     INIT_USER_CURSOR (NULL,                             modeline_cursor),
  1898     INIT_USER_CURSOR (&Vx_sensitive_text_pointer_shape, hand_cursor),
  1899     INIT_USER_CURSOR (&Vx_hourglass_pointer_shape,      hourglass_cursor),
  1900     INIT_USER_CURSOR (NULL,                             horizontal_drag_cursor),
  1901     INIT_USER_CURSOR (NULL,                             vertical_drag_cursor),
  1902     INIT_USER_CURSOR (NULL,                             left_edge_cursor),
  1903     INIT_USER_CURSOR (NULL,                             top_left_corner_cursor),
  1904     INIT_USER_CURSOR (NULL,                             top_edge_cursor),
  1905     INIT_USER_CURSOR (NULL,                             top_right_corner_cursor),
  1906     INIT_USER_CURSOR (NULL,                             right_edge_cursor),
  1907     INIT_USER_CURSOR (NULL,                             bottom_right_corner_cursor),
  1908     INIT_USER_CURSOR (NULL,                             bottom_edge_cursor),
  1909     INIT_USER_CURSOR (NULL,                             bottom_left_corner_cursor),
  1910     INIT_USER_CURSOR (NULL,                             no_cursor),
  1911   };
  1912 
  1913 struct user_cursor_bitmap_info cursor_bitmaps[] =
  1914   {
  1915     { ibeam_ptr_bits, ibeam_ptrmask_bits, 15, 15, 7, 7 },       /* text_cursor */
  1916     { left_ptr_bits, left_ptrmsk_bits, 16, 16, 3, 1 },          /* nontext_cursor */
  1917     { left_ptr_bits, left_ptrmsk_bits, 16, 16, 3, 1 },          /* modeline_cursor */
  1918     { hand_ptr_bits, hand_ptrmask_bits, 15, 15, 4, 3 },         /* hand_cursor */
  1919     { hourglass_bits, hourglass_mask_bits, 15, 15, 7, 7 },      /* hourglass_cursor */
  1920     { horizd_ptr_bits, horizd_ptrmask_bits, 15, 15, 7, 7 },     /* horizontal_drag_cursor */
  1921     { vertd_ptr_bits, vertd_ptrmask_bits, 15, 15, 7, 7 },       /* vertical_drag_cursor */
  1922     { NULL, NULL, 0, 0, 0, 0 },                                 /* left_edge_cursor */
  1923     { NULL, NULL, 0, 0, 0, 0 },                                 /* top_left_corner_cursor */
  1924     { NULL, NULL, 0, 0, 0, 0 },                                 /* top_edge_cursor */
  1925     { NULL, NULL, 0, 0, 0, 0 },                                 /* top_right_corner_cursor */
  1926     { NULL, NULL, 0, 0, 0, 0 },                                 /* right_edge_cursor */
  1927     { NULL, NULL, 0, 0, 0, 0 },                                 /* bottom_right_corner_cursor */
  1928     { NULL, NULL, 0, 0, 0, 0 },                                 /* bottom_edge_cursor */
  1929     { NULL, NULL, 0, 0, 0, 0 },                                 /* bottom_left_corner_cursor */
  1930     { NULL, NULL, 0, 0, 0, 0 },                                 /* no_cursor */
  1931   };
  1932 
  1933 /* Array of cursor bitmaps for each system cursor ID.  This is used to
  1934    color in user-specified cursors.  */
  1935 struct user_cursor_bitmap_info cursor_bitmaps_for_id[28] =
  1936   {
  1937     { NULL, NULL, 0, 0, 0, 0                                    },
  1938     { left_ptr_bits, left_ptrmsk_bits, 16, 16, 3, 1             },
  1939     { ibeam_ptr_bits, ibeam_ptrmask_bits, 15, 15, 7, 7          },
  1940     { NULL, NULL, 0, 0, 0, 0                                    },
  1941     { NULL, NULL, 0, 0, 0, 0                                    },
  1942     { cross_ptr_bits, cross_ptrmask_bits, 30, 30, 15, 15        },
  1943     { NULL, NULL, 0, 0, 0, 0                                    },
  1944     { hand_ptr_bits, hand_ptrmask_bits, 15, 15, 4, 3            },
  1945     { NULL, NULL, 0, 0, 0, 0                                    },
  1946     { NULL, NULL, 0, 0, 0, 0                                    },
  1947     { NULL, NULL, 0, 0, 0, 0                                    },
  1948     { NULL, NULL, 0, 0, 0, 0                                    },
  1949     { NULL, NULL, 0, 0, 0, 0                                    },
  1950     { NULL, NULL, 0, 0, 0, 0                                    },
  1951     { hourglass_bits, hourglass_mask_bits, 15, 15, 7, 7         },
  1952     { NULL, NULL, 0, 0, 0, 0                                    },
  1953     { NULL, NULL, 0, 0, 0, 0                                    },
  1954     { NULL, NULL, 0, 0, 0, 0                                    },
  1955     { NULL, NULL, 0, 0, 0, 0                                    },
  1956     { NULL, NULL, 0, 0, 0, 0                                    },
  1957     { NULL, NULL, 0, 0, 0, 0                                    },
  1958     { NULL, NULL, 0, 0, 0, 0                                    },
  1959     { NULL, NULL, 0, 0, 0, 0                                    },
  1960     { horizd_ptr_bits, horizd_ptrmask_bits, 15, 15, 7, 7        },
  1961     { vertd_ptr_bits, vertd_ptrmask_bits, 15, 15, 7, 7          },
  1962     { NULL, NULL, 0, 0, 0, 0                                    },
  1963     { NULL, NULL, 0, 0, 0, 0                                    },
  1964     { NULL, NULL, 0, 0, 0, 0                                    },
  1965   };
  1966 
  1967 static void *
  1968 haiku_create_colored_cursor (struct user_cursor_bitmap_info *info,
  1969                              uint32_t foreground, uint32_t background)
  1970 {
  1971   const char *bits, *mask;
  1972   void *bitmap, *cursor;
  1973   int width, height, bytes_per_line, x, y;
  1974 
  1975   bits = info->bits;
  1976   mask = info->mask;
  1977   width = info->width;
  1978   height = info->height;
  1979   bytes_per_line = (width + 7) / 8;
  1980 
  1981   bitmap = BBitmap_new (width, height, false);
  1982 
  1983   if (!bitmap)
  1984     memory_full (SIZE_MAX);
  1985 
  1986   for (y = 0; y < height; ++y)
  1987     {
  1988       for (x = 0; x < width; ++x)
  1989         {
  1990           if (mask[x / 8] >> (x % 8) & 1)
  1991             haiku_put_pixel (bitmap, x, y,
  1992                              (bits[x / 8] >> (x % 8) & 1
  1993                               ? (foreground | 255u << 24)
  1994                               : (background | 255u << 24)));
  1995           else
  1996             haiku_put_pixel (bitmap, x, y, 0);
  1997         }
  1998 
  1999       mask += bytes_per_line;
  2000       bits += bytes_per_line;
  2001     }
  2002 
  2003   cursor = be_create_pixmap_cursor (bitmap, info->x, info->y);
  2004   BBitmap_free (bitmap);
  2005 
  2006   return cursor;
  2007 }
  2008 
  2009 /* Free all cursors on F that were allocated specifically for the
  2010    frame.  */
  2011 void
  2012 haiku_free_custom_cursors (struct frame *f)
  2013 {
  2014   struct user_cursor_info *cursor;
  2015   struct haiku_output *output;
  2016   struct haiku_display_info *dpyinfo;
  2017   Emacs_Cursor *frame_cursor;
  2018   Emacs_Cursor *display_cursor;
  2019   int i;
  2020 
  2021   output = FRAME_OUTPUT_DATA (f);
  2022   dpyinfo = FRAME_DISPLAY_INFO (f);
  2023 
  2024   for (i = 0; i < ARRAYELTS (custom_cursors); ++i)
  2025     {
  2026       cursor = &custom_cursors[i];
  2027       frame_cursor = (Emacs_Cursor *) ((char *) output
  2028                                        + cursor->output_offset);
  2029       display_cursor = (Emacs_Cursor *) ((char *) dpyinfo
  2030                                          + cursor->default_offset);
  2031 
  2032       if (*frame_cursor != *display_cursor && *frame_cursor)
  2033         {
  2034           if (output->current_cursor == *frame_cursor)
  2035             output->current_cursor = *display_cursor;
  2036 
  2037           be_delete_cursor (*frame_cursor);
  2038         }
  2039 
  2040       *frame_cursor = *display_cursor;
  2041     }
  2042 }
  2043 
  2044 static void
  2045 haiku_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  2046 {
  2047   struct haiku_output *output;
  2048   Emacs_Cursor *frame_cursor, old, *recolored;
  2049   int i, n, rc;
  2050   bool color_specified_p;
  2051   Emacs_Color color;
  2052 
  2053   CHECK_STRING (arg);
  2054   color_specified_p = true;
  2055 
  2056   if (!strcmp (SSDATA (arg), "font-color"))
  2057     color_specified_p = false;
  2058   else
  2059     rc = haiku_get_color (SSDATA (arg), &color);
  2060 
  2061   if (color_specified_p && rc)
  2062     signal_error ("Undefined color", arg);
  2063 
  2064   output = FRAME_OUTPUT_DATA (f);
  2065 
  2066   /* This will also reset all the cursors back to their default
  2067      values.  */
  2068   haiku_free_custom_cursors (f);
  2069 
  2070   for (i = 0; i < ARRAYELTS (custom_cursors); ++i)
  2071     {
  2072       frame_cursor = (Emacs_Cursor *) ((char *) output
  2073                                        + custom_cursors[i].output_offset);
  2074       old = *frame_cursor;
  2075 
  2076       if (custom_cursors[i].lisp_cursor
  2077           && FIXNUMP (*custom_cursors[i].lisp_cursor))
  2078         {
  2079           if (!RANGED_FIXNUMP (0, *custom_cursors[i].lisp_cursor,
  2080                                28)) /* 28 is the largest Haiku cursor ID.  */
  2081             signal_error ("Invalid cursor",
  2082                           *custom_cursors[i].lisp_cursor);
  2083 
  2084           n = XFIXNUM (*custom_cursors[i].lisp_cursor);
  2085 
  2086           if (color_specified_p && cursor_bitmaps_for_id[n].bits)
  2087             {
  2088               recolored
  2089                 = haiku_create_colored_cursor (&cursor_bitmaps_for_id[n],
  2090                                                color.pixel,
  2091                                                FRAME_BACKGROUND_PIXEL (f));
  2092 
  2093               if (recolored)
  2094                 {
  2095                   *frame_cursor = recolored;
  2096                   continue;
  2097                 }
  2098             }
  2099 
  2100           /* Create and set the custom cursor.  */
  2101           *frame_cursor = be_create_cursor_from_id (n);
  2102         }
  2103       else if (color_specified_p && cursor_bitmaps[i].bits)
  2104         {
  2105           recolored
  2106             = haiku_create_colored_cursor (&cursor_bitmaps[i], color.pixel,
  2107                                            FRAME_BACKGROUND_PIXEL (f));
  2108 
  2109           if (recolored)
  2110             *frame_cursor = recolored;
  2111         }
  2112     }
  2113 
  2114   /* This function can be called before the frame's window is
  2115      created.  */
  2116   if (FRAME_HAIKU_WINDOW (f))
  2117     {
  2118       if (output->current_cursor == old
  2119           && old != *frame_cursor)
  2120         {
  2121           output->current_cursor = *frame_cursor;
  2122 
  2123           BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
  2124                                  *frame_cursor);
  2125         }
  2126     }
  2127 
  2128   update_face_from_frame_parameter (f, Qmouse_color, arg);
  2129 }
  2130 
  2131 static void
  2132 haiku_set_use_frame_synchronization (struct frame *f, Lisp_Object arg,
  2133                                      Lisp_Object oldval)
  2134 {
  2135   be_set_use_frame_synchronization (FRAME_HAIKU_VIEW (f), !NILP (arg));
  2136 }
  2137 
  2138 
  2139 
  2140 DEFUN ("haiku-set-mouse-absolute-pixel-position",
  2141        Fhaiku_set_mouse_absolute_pixel_position,
  2142        Shaiku_set_mouse_absolute_pixel_position, 2, 2, 0,
  2143        doc: /* Move mouse pointer to a pixel position at (X, Y).  The
  2144 coordinates X and Y are interpreted to start from the top-left
  2145 corner of the screen.  */)
  2146   (Lisp_Object x, Lisp_Object y)
  2147 {
  2148   int xval = check_integer_range (x, INT_MIN, INT_MAX);
  2149   int yval = check_integer_range (y, INT_MIN, INT_MAX);
  2150 
  2151   if (!x_display_list)
  2152     error ("Window system not initialized");
  2153 
  2154   block_input ();
  2155   be_warp_pointer (xval, yval);
  2156   unblock_input ();
  2157   return Qnil;
  2158 }
  2159 
  2160 DEFUN ("haiku-mouse-absolute-pixel-position", Fhaiku_mouse_absolute_pixel_position,
  2161        Shaiku_mouse_absolute_pixel_position, 0, 0, 0,
  2162        doc: /* Return absolute position of mouse cursor in pixels.
  2163 The position is returned as a cons cell (X . Y) of the coordinates of
  2164 the mouse cursor position in pixels relative to a position (0, 0) of the
  2165 selected frame's display.  */)
  2166   (void)
  2167 {
  2168   struct frame *f = SELECTED_FRAME ();
  2169   void *view;
  2170   int x, y;
  2171 
  2172   if (FRAME_INITIAL_P (f) || !FRAME_HAIKU_P (f))
  2173     return Qnil;
  2174 
  2175   block_input ();
  2176   view = FRAME_HAIKU_VIEW (f);
  2177   BView_get_mouse (view, &x, &y);
  2178   BView_convert_to_screen (view, &x, &y);
  2179   unblock_input ();
  2180 
  2181   return Fcons (make_fixnum (x), make_fixnum (y));
  2182 }
  2183 
  2184 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
  2185        doc: /* SKIP: real doc in xfns.c.  */)
  2186      (Lisp_Object terminal)
  2187 {
  2188   check_haiku_display_info (terminal);
  2189 
  2190   return be_is_display_grayscale () ? Qnil : Qt;
  2191 }
  2192 
  2193 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
  2194        doc: /* SKIP: real doc in xfns.c.  */)
  2195   (Lisp_Object color, Lisp_Object frame)
  2196 {
  2197   Emacs_Color col;
  2198 
  2199   CHECK_STRING (color);
  2200   decode_window_system_frame (frame);
  2201 
  2202   return haiku_get_color (SSDATA (color), &col) ? Qnil : Qt;
  2203 }
  2204 
  2205 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
  2206        doc: /* SKIP: real doc in xfns.c.  */)
  2207      (Lisp_Object color, Lisp_Object frame)
  2208 {
  2209   Emacs_Color col;
  2210   int rc;
  2211 
  2212   CHECK_STRING (color);
  2213   decode_window_system_frame (frame);
  2214 
  2215   block_input ();
  2216   rc = haiku_get_color (SSDATA (color), &col);
  2217   unblock_input ();
  2218 
  2219   if (rc)
  2220     return Qnil;
  2221 
  2222   return list3i (col.red, col.green, col.blue);
  2223 }
  2224 
  2225 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
  2226        0, 1, 0,
  2227        doc: /* SKIP: real doc in xfns.c.  */)
  2228   (Lisp_Object terminal)
  2229 {
  2230   check_haiku_display_info (terminal);
  2231 
  2232   return be_is_display_grayscale () ? Qt : Qnil;
  2233 }
  2234 
  2235 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
  2236        1, 3, 0, doc: /* SKIP: real doc in xfns.c.  */)
  2237      (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed)
  2238 {
  2239   CHECK_STRING (display);
  2240 
  2241   if (NILP (Fstring_equal (display, build_string ("be"))))
  2242     {
  2243       if (!NILP (must_succeed))
  2244         fatal ("Invalid display %s", SDATA (display));
  2245       else
  2246         signal_error ("Invalid display", display);
  2247     }
  2248 
  2249   if (x_display_list)
  2250     {
  2251       if (!NILP (must_succeed))
  2252         fatal ("A display is already open");
  2253       else
  2254         error ("A display is already open");
  2255     }
  2256 
  2257   haiku_term_init ();
  2258   return Qnil;
  2259 }
  2260 
  2261 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
  2262        0, 1, 0,
  2263        doc: /* SKIP: real doc in xfns.c.  */)
  2264   (Lisp_Object terminal)
  2265 
  2266 {
  2267   int width, height;
  2268   check_haiku_display_info (terminal);
  2269 
  2270   be_get_screen_dimensions (&width, &height);
  2271   return make_fixnum (width);
  2272 }
  2273 
  2274 DEFUN ("x-display-pixel-height", Fx_display_pixel_height, Sx_display_pixel_height,
  2275        0, 1, 0,
  2276        doc: /* SKIP: real doc in xfns.c.  */)
  2277   (Lisp_Object terminal)
  2278 
  2279 {
  2280   int width, height;
  2281   check_haiku_display_info (terminal);
  2282 
  2283   be_get_screen_dimensions (&width, &height);
  2284   return make_fixnum (height);
  2285 }
  2286 
  2287 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
  2288        doc: /* SKIP: real doc in xfns.c.  */)
  2289   (Lisp_Object terminal)
  2290 {
  2291   struct haiku_display_info *dpyinfo = check_haiku_display_info (terminal);
  2292   int width, height;
  2293 
  2294   be_get_screen_dimensions (&width, &height);
  2295   return make_fixnum (height / (dpyinfo->resy / 25.4));
  2296 }
  2297 
  2298 
  2299 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
  2300        doc: /* SKIP: real doc in xfns.c.  */)
  2301   (Lisp_Object terminal)
  2302 {
  2303   struct haiku_display_info *dpyinfo = check_haiku_display_info (terminal);
  2304   int width, height;
  2305 
  2306   be_get_screen_dimensions (&width, &height);
  2307   return make_fixnum (width / (dpyinfo->resx / 25.4));
  2308 }
  2309 
  2310 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
  2311        1, 1, 0,
  2312        doc: /* SKIP: real doc in xfns.c.  */)
  2313      (Lisp_Object parms)
  2314 {
  2315   return haiku_create_frame (parms);
  2316 }
  2317 
  2318 DEFUN ("x-display-visual-class", Fx_display_visual_class,
  2319        Sx_display_visual_class, 0, 1, 0,
  2320        doc: /* SKIP: real doc in xfns.c.  */)
  2321   (Lisp_Object terminal)
  2322 {
  2323   int planes;
  2324   bool grayscale_p;
  2325 
  2326   check_haiku_display_info (terminal);
  2327 
  2328   grayscale_p = be_is_display_grayscale ();
  2329   if (grayscale_p)
  2330     return Qstatic_gray;
  2331 
  2332   planes = be_get_display_planes ();
  2333   if (planes == 8)
  2334     return Qstatic_color;
  2335 
  2336   return Qtrue_color;
  2337 }
  2338 
  2339 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
  2340        doc: /* SKIP: real doc in xfns.c.  */)
  2341   (Lisp_Object string, Lisp_Object frame, Lisp_Object parms,
  2342    Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
  2343 {
  2344   struct frame *f, *tip_f;
  2345   struct window *w;
  2346   int root_x, root_y;
  2347   struct buffer *old_buffer;
  2348   struct text_pos pos;
  2349   int width, height;
  2350   int old_windows_or_buffers_changed = windows_or_buffers_changed;
  2351   specpdl_ref count = SPECPDL_INDEX ();
  2352   Lisp_Object window, size, tip_buf;
  2353   bool displayed;
  2354 #ifdef ENABLE_CHECKING
  2355   struct glyph_row *row, *end;
  2356 #endif
  2357   AUTO_STRING (tip, " *tip*");
  2358 
  2359   specbind (Qinhibit_redisplay, Qt);
  2360 
  2361   CHECK_STRING (string);
  2362   if (SCHARS (string) == 0)
  2363     string = make_unibyte_string (" ", 1);
  2364 
  2365   if (NILP (frame))
  2366     frame = selected_frame;
  2367   f = decode_window_system_frame (frame);
  2368 
  2369   if (NILP (timeout))
  2370     timeout = Vx_show_tooltip_timeout;
  2371   CHECK_FIXNAT (timeout);
  2372 
  2373   if (NILP (dx))
  2374     dx = make_fixnum (5);
  2375   else
  2376     CHECK_FIXNUM (dx);
  2377 
  2378   if (NILP (dy))
  2379     dy = make_fixnum (-10);
  2380   else
  2381     CHECK_FIXNUM (dy);
  2382 
  2383   tip_dx = dx;
  2384   tip_dy = dy;
  2385 
  2386   if (use_system_tooltips)
  2387     {
  2388       int root_x, root_y;
  2389       CHECK_STRING (string);
  2390       if (STRING_MULTIBYTE (string))
  2391         string = ENCODE_UTF_8 (string);
  2392 
  2393       if (NILP (frame))
  2394         frame = selected_frame;
  2395 
  2396       struct frame *f = decode_window_system_frame (frame);
  2397       block_input ();
  2398 
  2399       char *str = xstrdup (SSDATA (string));
  2400       int height = be_plain_font_height ();
  2401       int width;
  2402       char *tok = strtok (str, "\n");
  2403       width = be_string_width_with_plain_font (tok);
  2404 
  2405       while ((tok = strtok (NULL, "\n")))
  2406         {
  2407           height = be_plain_font_height ();
  2408           int w = be_string_width_with_plain_font (tok);
  2409           if (w > width)
  2410             w = width;
  2411         }
  2412       free (str);
  2413 
  2414       height += 16; /* Default margin.  */
  2415       width += 16; /* Ditto.  Unfortunately there isn't a more
  2416                       reliable way to get it.  */
  2417       compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
  2418       BView_convert_from_screen (FRAME_HAIKU_VIEW (f), &root_x, &root_y);
  2419       be_show_sticky_tooltip (FRAME_HAIKU_VIEW (f), SSDATA (string),
  2420                               root_x, root_y);
  2421       unblock_input ();
  2422       goto start_timer;
  2423     }
  2424 
  2425   if (!NILP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
  2426     {
  2427       if (FRAME_VISIBLE_P (XFRAME (tip_frame))
  2428           && !NILP (Fequal_including_properties (tip_last_string, string))
  2429           && !NILP (Fequal (tip_last_parms, parms)))
  2430         {
  2431           /* Only DX and DY have changed.  */
  2432           tip_f = XFRAME (tip_frame);
  2433           if (!NILP (tip_timer))
  2434             {
  2435               call1 (Qcancel_timer, tip_timer);
  2436               tip_timer = Qnil;
  2437             }
  2438 
  2439           block_input ();
  2440           compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
  2441                           FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
  2442           BWindow_set_offset (FRAME_HAIKU_WINDOW (tip_f), root_x, root_y);
  2443           unblock_input ();
  2444 
  2445           goto start_timer;
  2446         }
  2447       else if (tooltip_reuse_hidden_frame && EQ (frame, tip_last_frame))
  2448         {
  2449           bool delete = false;
  2450           Lisp_Object tail, elt, parm, last;
  2451 
  2452           /* Check if every parameter in PARMS has the same value in
  2453              tip_last_parms.  This may destruct tip_last_parms which,
  2454              however, will be recreated below.  */
  2455           for (tail = parms; CONSP (tail); tail = XCDR (tail))
  2456             {
  2457               elt = XCAR (tail);
  2458               parm = Fcar (elt);
  2459               /* The left, top, right and bottom parameters are handled
  2460                  by compute_tip_xy so they can be ignored here.  */
  2461               if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
  2462                   && !EQ (parm, Qright) && !EQ (parm, Qbottom))
  2463                 {
  2464                   last = Fassq (parm, tip_last_parms);
  2465                   if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
  2466                     {
  2467                       /* We lost, delete the old tooltip.  */
  2468                       delete = true;
  2469                       break;
  2470                     }
  2471                   else
  2472                     tip_last_parms =
  2473                       call2 (Qassq_delete_all, parm, tip_last_parms);
  2474                 }
  2475               else
  2476                 tip_last_parms =
  2477                   call2 (Qassq_delete_all, parm, tip_last_parms);
  2478             }
  2479 
  2480           /* Now check if every parameter in what is left of
  2481              tip_last_parms with a non-nil value has an association in
  2482              PARMS.  */
  2483           for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
  2484             {
  2485               elt = XCAR (tail);
  2486               parm = Fcar (elt);
  2487               if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
  2488                   && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
  2489                 {
  2490                   /* We lost, delete the old tooltip.  */
  2491                   delete = true;
  2492                   break;
  2493                 }
  2494             }
  2495 
  2496           haiku_hide_tip (delete);
  2497         }
  2498       else
  2499         haiku_hide_tip (true);
  2500     }
  2501   else
  2502     haiku_hide_tip (true);
  2503 
  2504   tip_last_frame = frame;
  2505   tip_last_string = string;
  2506   tip_last_parms = parms;
  2507 
  2508   if (NILP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
  2509     {
  2510       /* Add default values to frame parameters.  */
  2511       if (NILP (Fassq (Qname, parms)))
  2512         parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
  2513       if (NILP (Fassq (Qinternal_border_width, parms)))
  2514         parms = Fcons (Fcons (Qinternal_border_width, make_fixnum (3)), parms);
  2515       if (NILP (Fassq (Qborder_width, parms)))
  2516         parms = Fcons (Fcons (Qborder_width, make_fixnum (1)), parms);
  2517       if (NILP (Fassq (Qborder_color, parms)))
  2518         parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
  2519       if (NILP (Fassq (Qbackground_color, parms)))
  2520         parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
  2521                        parms);
  2522 
  2523       /* Create a frame for the tooltip, and record it in the global
  2524          variable tip_frame.  */
  2525       if (NILP (tip_frame = haiku_create_tip_frame (parms)))
  2526         /* Creating the tip frame failed.  */
  2527         return unbind_to (count, Qnil);
  2528     }
  2529 
  2530   tip_f = XFRAME (tip_frame);
  2531   window = FRAME_ROOT_WINDOW (tip_f);
  2532   tip_buf = Fget_buffer_create (tip, Qnil);
  2533   /* We will mark the tip window a "pseudo-window" below, and such
  2534      windows cannot have display margins.  */
  2535   bset_left_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
  2536   bset_right_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
  2537   set_window_buffer (window, tip_buf, false, false);
  2538   w = XWINDOW (window);
  2539   w->pseudo_window_p = true;
  2540   /* Try to avoid that `other-window' select us (Bug#47207).  */
  2541   Fset_window_parameter (window, Qno_other_window, Qt);
  2542 
  2543   /* Set up the frame's root window.  Note: The following code does not
  2544      try to size the window or its frame correctly.  Its only purpose is
  2545      to make the subsequent text size calculations work.  The right
  2546      sizes should get installed when the toolkit gets back to us.  */
  2547   w->left_col = 0;
  2548   w->top_line = 0;
  2549   w->pixel_left = 0;
  2550   w->pixel_top = 0;
  2551 
  2552   if (CONSP (Vx_max_tooltip_size)
  2553       && RANGED_FIXNUMP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
  2554       && RANGED_FIXNUMP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
  2555     {
  2556       w->total_cols = XFIXNAT (XCAR (Vx_max_tooltip_size));
  2557       w->total_lines = XFIXNAT (XCDR (Vx_max_tooltip_size));
  2558     }
  2559   else
  2560     {
  2561       w->total_cols = 80;
  2562       w->total_lines = 40;
  2563     }
  2564 
  2565   w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
  2566   w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
  2567   FRAME_TOTAL_COLS (tip_f) = w->total_cols;
  2568   adjust_frame_glyphs (tip_f);
  2569 
  2570   /* Insert STRING into root window's buffer and fit the frame to the
  2571      buffer.  */
  2572   specpdl_ref count_1 = SPECPDL_INDEX ();
  2573   old_buffer = current_buffer;
  2574   set_buffer_internal_1 (XBUFFER (w->contents));
  2575   bset_truncate_lines (current_buffer, Qnil);
  2576   specbind (Qinhibit_read_only, Qt);
  2577   specbind (Qinhibit_modification_hooks, Qt);
  2578   specbind (Qinhibit_point_motion_hooks, Qt);
  2579   Ferase_buffer ();
  2580   Finsert (1, &string);
  2581   clear_glyph_matrix (w->desired_matrix);
  2582   clear_glyph_matrix (w->current_matrix);
  2583   SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
  2584   displayed = try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
  2585 
  2586   if (!displayed && NILP (Vx_max_tooltip_size))
  2587     {
  2588 #ifdef ENABLE_CHECKING
  2589       row = w->desired_matrix->rows;
  2590       end = w->desired_matrix->rows + w->desired_matrix->nrows;
  2591 
  2592       while (row < end)
  2593         {
  2594           if (!row->displays_text_p
  2595               || row->ends_at_zv_p)
  2596             break;
  2597           ++row;
  2598         }
  2599 
  2600       eassert (row < end && row->ends_at_zv_p);
  2601 #endif
  2602     }
  2603 
  2604   /* Calculate size of tooltip window.  */
  2605   size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
  2606                                   make_fixnum (w->pixel_height), Qnil,
  2607                                   Qnil);
  2608   /* Add the frame's internal border to calculated size.  */
  2609   width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
  2610   height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
  2611 
  2612   /* Calculate position of tooltip frame.  */
  2613   compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
  2614 
  2615   /* Show tooltip frame.  */
  2616   block_input ();
  2617   void *wnd = FRAME_HAIKU_WINDOW (tip_f);
  2618   BWindow_resize (wnd, width, height);
  2619   /* The window decorator might cause the actual width and height to
  2620      be larger than WIDTH and HEIGHT, so use the actual sizes.  */
  2621   BWindow_dimensions (wnd, &width, &height);
  2622   BView_resize_to (FRAME_HAIKU_VIEW (tip_f), width, height);
  2623   BView_set_view_cursor (FRAME_HAIKU_VIEW (tip_f),
  2624                          FRAME_OUTPUT_DATA (f)->current_cursor);
  2625   BWindow_set_offset (wnd, root_x, root_y);
  2626   BWindow_set_visible (wnd, true);
  2627   SET_FRAME_VISIBLE (tip_f, true);
  2628   FRAME_PIXEL_WIDTH (tip_f) = width;
  2629   FRAME_PIXEL_HEIGHT (tip_f) = height;
  2630   BWindow_sync (wnd);
  2631 
  2632   /* This is needed because the app server resets the cursor whenever
  2633      a new window is mapped, so we won't see the cursor set on the
  2634      tooltip if the mouse pointer isn't actually over it.  */
  2635   BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
  2636                          FRAME_OUTPUT_DATA (f)->current_cursor);
  2637   unblock_input ();
  2638 
  2639   w->must_be_updated_p = true;
  2640   update_single_window (w);
  2641   flush_frame (tip_f);
  2642   set_buffer_internal_1 (old_buffer);
  2643   unbind_to (count_1, Qnil);
  2644   windows_or_buffers_changed = old_windows_or_buffers_changed;
  2645 
  2646  start_timer:
  2647   /* Let the tip disappear after timeout seconds.  */
  2648   tip_timer = call3 (Qrun_at_time, timeout, Qnil, Qx_hide_tip);
  2649 
  2650   return unbind_to (count, Qnil);
  2651 }
  2652 
  2653 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
  2654        doc: /* SKIP: real doc in xfns.c.  */)
  2655   (void)
  2656 {
  2657   return haiku_hide_tip (!tooltip_reuse_hidden_frame);
  2658 }
  2659 
  2660 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection, 1, 1, 0,
  2661        doc: /* SKIP: real doc in xfns.c.  */
  2662        attributes: noreturn)
  2663   (Lisp_Object terminal)
  2664 {
  2665   check_haiku_display_info (terminal);
  2666 
  2667   error ("Cannot close Haiku displays");
  2668 }
  2669 
  2670 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
  2671        doc: /* SKIP: real doc in xfns.c. */)
  2672   (void)
  2673 {
  2674   if (!x_display_list)
  2675     return Qnil;
  2676 
  2677   return list1 (XCAR (x_display_list->name_list_element));
  2678 }
  2679 
  2680 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
  2681        doc: /* SKIP: real doc in xfns.c.  */)
  2682   (Lisp_Object terminal)
  2683 {
  2684   check_haiku_display_info (terminal);
  2685   return build_string ("Haiku, Inc.");
  2686 }
  2687 
  2688 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
  2689        doc: /* SKIP: real doc in xfns.c. */)
  2690   (Lisp_Object terminal)
  2691 {
  2692   check_haiku_display_info (terminal);
  2693   return list3i (5, 1, 1);
  2694 }
  2695 
  2696 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
  2697        doc: /* SKIP: real doc in xfns.c.  */)
  2698   (Lisp_Object terminal)
  2699 {
  2700   check_haiku_display_info (terminal);
  2701   return make_fixnum (be_get_display_screens ());
  2702 }
  2703 
  2704 DEFUN ("haiku-get-version-string", Fhaiku_get_version_string,
  2705        Shaiku_get_version_string, 0, 0, 0,
  2706        doc: /* Return a string describing the current Haiku version.  */)
  2707   (void)
  2708 {
  2709   char buf[1024];
  2710 
  2711   be_get_version_string ((char *) &buf, sizeof buf);
  2712   return build_string (buf);
  2713 }
  2714 
  2715 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
  2716        0, 1, 0,
  2717        doc: /* SKIP: real doc in xfns.c.  */)
  2718   (Lisp_Object terminal)
  2719 {
  2720   check_haiku_display_info (terminal);
  2721 
  2722   return make_fixnum (be_get_display_color_cells ());
  2723 }
  2724 
  2725 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
  2726        0, 1, 0,
  2727        doc: /* SKIP: real doc in xfns.c.  */)
  2728   (Lisp_Object terminal)
  2729 {
  2730   check_haiku_display_info (terminal);
  2731 
  2732   return make_fixnum (be_get_display_planes ());
  2733 }
  2734 
  2735 DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
  2736        0, 1, 0,
  2737        doc: /* SKIP: real doc in xfns.c.  */)
  2738   (Lisp_Object frame)
  2739 {
  2740   struct frame *f = decode_window_system_frame (frame);
  2741 
  2742   return EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)) ? Qt : Qnil;
  2743 }
  2744 
  2745 DEFUN ("x-display-backing-store", Fx_display_backing_store, Sx_display_backing_store,
  2746        0, 1, 0,
  2747        doc: /* SKIP: real doc in xfns.c.  */)
  2748   (Lisp_Object terminal)
  2749 {
  2750   struct frame *f;
  2751 
  2752   if (FRAMEP (terminal))
  2753     {
  2754       f = decode_window_system_frame (terminal);
  2755 
  2756       if (FRAME_HAIKU_VIEW (f)
  2757           && EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)))
  2758         return FRAME_PARENT_FRAME (f) ? Qwhen_mapped : Qalways;
  2759       else
  2760         return Qnot_useful;
  2761     }
  2762   else
  2763     {
  2764       check_haiku_display_info (terminal);
  2765       return Qnot_useful;
  2766     }
  2767 }
  2768 
  2769 DEFUN ("haiku-frame-geometry", Fhaiku_frame_geometry, Shaiku_frame_geometry, 0, 1, 0,
  2770        doc: /* Return geometric attributes of FRAME.
  2771 FRAME must be a live frame and defaults to the selected one.  The return
  2772 value is an association list of the attributes listed below.  All height
  2773 and width values are in pixels.
  2774 
  2775 `outer-position' is a cons of the outer left and top edges of FRAME
  2776   relative to the origin - the position (0, 0) - of FRAME's display.
  2777 
  2778 `outer-size' is a cons of the outer width and height of FRAME.  The
  2779   outer size includes the title bar and the external borders as well as
  2780   any menu and/or tool bar of frame.
  2781 
  2782 `external-border-size' is a cons of the horizontal and vertical width of
  2783   FRAME's external borders as supplied by the window manager.
  2784 
  2785 `title-bar-size' is a cons of the width and height of the title bar of
  2786   FRAME as supplied by the window manager.  If both of them are zero,
  2787   FRAME has no title bar.  If only the width is zero, Emacs was not
  2788   able to retrieve the width information.
  2789 
  2790 `menu-bar-external', if non-nil, means the menu bar is external (never
  2791   included in the inner edges of FRAME).
  2792 
  2793 `menu-bar-size' is a cons of the width and height of the menu bar of
  2794   FRAME.
  2795 
  2796 `tool-bar-external', if non-nil, means the tool bar is external (never
  2797   included in the inner edges of FRAME).
  2798 
  2799 `tool-bar-position' tells on which side the tool bar on FRAME is and can
  2800   be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
  2801   has no tool bar.
  2802 
  2803 `tool-bar-size' is a cons of the width and height of the tool bar of
  2804   FRAME.
  2805 
  2806 `internal-border-width' is the width of the internal border of
  2807   FRAME.  */)
  2808   (Lisp_Object frame)
  2809 {
  2810   return frame_geometry (frame, Qnil);
  2811 }
  2812 
  2813 DEFUN ("haiku-frame-edges", Fhaiku_frame_edges, Shaiku_frame_edges, 0, 2, 0,
  2814        doc: /* Return edge coordinates of FRAME.
  2815 FRAME must be a live frame and defaults to the selected one.  The return
  2816 value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
  2817 in pixels relative to the origin - the position (0, 0) - of FRAME's
  2818 display.
  2819 
  2820 If optional argument TYPE is the symbol `outer-edges', return the outer
  2821 edges of FRAME.  The outer edges comprise the decorations of the window
  2822 manager (like the title bar or external borders) as well as any external
  2823 menu or tool bar of FRAME.  If optional argument TYPE is the symbol
  2824 `native-edges' or nil, return the native edges of FRAME.  The native
  2825 edges exclude the decorations of the window manager and any external
  2826 menu or tool bar of FRAME.  If TYPE is the symbol `inner-edges', return
  2827 the inner edges of FRAME.  These edges exclude title bar, any borders,
  2828 menu bar or tool bar of FRAME.  */)
  2829   (Lisp_Object frame, Lisp_Object type)
  2830 {
  2831   return frame_geometry (frame, ((EQ (type, Qouter_edges)
  2832                                   || EQ (type, Qinner_edges))
  2833                                  ? type
  2834                                  : Qnative_edges));
  2835 }
  2836 
  2837 DEFUN ("haiku-read-file-name", Fhaiku_read_file_name, Shaiku_read_file_name, 1, 6, 0,
  2838        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
  2839 Optional arg FRAME specifies a frame on which to display the file panel.
  2840 If it is nil, the current frame is used instead.
  2841 The frame being used will be brought to the front of
  2842 the display after the file panel is closed.
  2843 Optional arg DIR, if non-nil, supplies a default directory.
  2844 Optional arg MUSTMATCH, if non-nil, means the returned file or
  2845 directory must exist.
  2846 Optional arg DIR_ONLY_P, if non-nil, means choose only directories.
  2847 Optional arg SAVE_TEXT, if non-nil, specifies some text to show in the entry field.  */)
  2848   (Lisp_Object prompt, Lisp_Object frame, Lisp_Object dir,
  2849    Lisp_Object mustmatch, Lisp_Object dir_only_p, Lisp_Object save_text)
  2850 {
  2851   struct frame *f;
  2852   char *file_name;
  2853   Lisp_Object value;
  2854 
  2855   if (popup_activated_p)
  2856     error ("Trying to use a menu from within a menu-entry");
  2857 
  2858   if (!NILP (dir))
  2859     {
  2860       CHECK_STRING (dir);
  2861       dir = ENCODE_FILE (dir);
  2862     }
  2863 
  2864   if (!NILP (save_text))
  2865     CHECK_STRING (save_text);
  2866 
  2867   if (NILP (frame))
  2868     frame = selected_frame;
  2869 
  2870   CHECK_STRING (prompt);
  2871 
  2872   f = decode_window_system_frame (frame);
  2873 
  2874   ++popup_activated_p;
  2875   unrequest_sigio ();
  2876   file_name = be_popup_file_dialog (!NILP (mustmatch) || !NILP (dir_only_p),
  2877                                     !NILP (dir) ? SSDATA (dir) : NULL,
  2878                                     !NILP (mustmatch), !NILP (dir_only_p),
  2879                                     FRAME_HAIKU_WINDOW (f),
  2880                                     (!NILP (save_text)
  2881                                      ? SSDATA (ENCODE_UTF_8 (save_text)) : NULL),
  2882                                     SSDATA (ENCODE_UTF_8 (prompt)),
  2883                                     process_pending_signals);
  2884   request_sigio ();
  2885   --popup_activated_p;
  2886 
  2887   if (!file_name)
  2888     quit ();
  2889 
  2890   value = build_string (file_name);
  2891   free (file_name);
  2892 
  2893   return DECODE_FILE (value);
  2894 }
  2895 
  2896 DEFUN ("haiku-put-resource", Fhaiku_put_resource, Shaiku_put_resource,
  2897        2, 2, 0, doc: /* Place STRING by the key RESOURCE in the resource database.
  2898 It can later be retrieved with `x-get-resource'.  */)
  2899   (Lisp_Object resource, Lisp_Object string)
  2900 {
  2901   CHECK_STRING (resource);
  2902   if (!NILP (string))
  2903     CHECK_STRING (string);
  2904 
  2905   put_xrm_resource (resource, string);
  2906   return Qnil;
  2907 }
  2908 
  2909 DEFUN ("haiku-frame-list-z-order", Fhaiku_frame_list_z_order,
  2910        Shaiku_frame_list_z_order, 0, 1, 0,
  2911        doc: /* Return list of Emacs' frames, in Z (stacking) order.
  2912 If TERMINAL is non-nil and specifies a live frame, return the child
  2913 frames of that frame in Z (stacking) order.
  2914 
  2915 As it is impossible to reliably determine the frame stacking order on
  2916 Haiku, the selected frame is always the first element of the returned
  2917 list, while the rest are not guaranteed to be in any particular order.
  2918 
  2919 Frames are listed from topmost (first) to bottommost (last).  */)
  2920   (Lisp_Object terminal)
  2921 {
  2922   Lisp_Object frames = Qnil;
  2923   Lisp_Object head, tail;
  2924   Lisp_Object sel = Qnil;
  2925 
  2926   FOR_EACH_FRAME (head, tail)
  2927     {
  2928       struct frame *f = XFRAME (tail);
  2929       if (!FRAME_HAIKU_P (f) ||
  2930           (FRAMEP (terminal) &&
  2931            FRAME_LIVE_P (XFRAME (terminal)) &&
  2932            !EQ (terminal, get_frame_param (f, Qparent_frame))))
  2933         continue;
  2934 
  2935       if (EQ (tail, selected_frame))
  2936         sel = tail;
  2937       else
  2938         frames = Fcons (tail, frames);
  2939     }
  2940 
  2941   if (NILP (sel))
  2942     return frames;
  2943 
  2944   return Fcons (sel, frames);
  2945 }
  2946 
  2947 DEFUN ("x-display-save-under", Fx_display_save_under,
  2948        Sx_display_save_under, 0, 1, 0,
  2949        doc: /* SKIP: real doc in xfns.c.  */)
  2950   (Lisp_Object terminal)
  2951 {
  2952   struct frame *f;
  2953   check_haiku_display_info (terminal);
  2954 
  2955   if (FRAMEP (terminal))
  2956     {
  2957       f = decode_window_system_frame (terminal);
  2958       return ((FRAME_HAIKU_VIEW (f)
  2959                && EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)))
  2960               ? Qt : Qnil);
  2961     }
  2962 
  2963   return Qnil;
  2964 }
  2965 
  2966 DEFUN ("haiku-frame-restack", Fhaiku_frame_restack, Shaiku_frame_restack, 2, 3, 0,
  2967        doc: /* Restack FRAME1 below FRAME2.
  2968 This means that if both frames are visible and the display areas of
  2969 these frames overlap, FRAME2 (partially) obscures FRAME1.  If optional
  2970 third argument ABOVE is non-nil, restack FRAME1 above FRAME2.  This
  2971 means that if both frames are visible and the display areas of these
  2972 frames overlap, FRAME1 (partially) obscures FRAME2.
  2973 
  2974 Some window managers may refuse to restack windows.  */)
  2975   (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
  2976 {
  2977   struct frame *f1 = decode_window_system_frame (frame1);
  2978   struct frame *f2 = decode_window_system_frame (frame2);
  2979 
  2980   block_input ();
  2981 
  2982   if (NILP (above))
  2983     {
  2984       /* If the window that is currently active will be sent behind
  2985          another window, make the window that it is being sent behind
  2986          active first, to avoid both windows being moved to the back of
  2987          the display.  */
  2988 
  2989       if (BWindow_is_active (FRAME_HAIKU_WINDOW (f1))
  2990           /* But don't do this if any of the frames involved have
  2991              child frames, since they are guaranteed to be in front of
  2992              their toplevel parents.  */
  2993           && !FRAME_PARENT_FRAME (f1)
  2994           && !FRAME_PARENT_FRAME (f2))
  2995         {
  2996           BWindow_activate (FRAME_HAIKU_WINDOW (f2));
  2997           BWindow_sync (FRAME_HAIKU_WINDOW (f2));
  2998         }
  2999 
  3000       BWindow_send_behind (FRAME_HAIKU_WINDOW (f1),
  3001                            FRAME_HAIKU_WINDOW (f2));
  3002     }
  3003   else
  3004     {
  3005       if (BWindow_is_active (FRAME_HAIKU_WINDOW (f2))
  3006           && !FRAME_PARENT_FRAME (f1)
  3007           && !FRAME_PARENT_FRAME (f2))
  3008         {
  3009           BWindow_activate (FRAME_HAIKU_WINDOW (f1));
  3010           BWindow_sync (FRAME_HAIKU_WINDOW (f1));
  3011         }
  3012 
  3013       BWindow_send_behind (FRAME_HAIKU_WINDOW (f2),
  3014                            FRAME_HAIKU_WINDOW (f1));
  3015     }
  3016   BWindow_sync (FRAME_HAIKU_WINDOW (f1));
  3017   BWindow_sync (FRAME_HAIKU_WINDOW (f2));
  3018 
  3019   unblock_input ();
  3020 
  3021   return Qnil;
  3022 }
  3023 
  3024 DEFUN ("haiku-save-session-reply", Fhaiku_save_session_reply,
  3025        Shaiku_save_session_reply, 1, 1, 0,
  3026        doc: /* Reply to a `save-session' event.
  3027 QUIT-REPLY means whether or not all files were saved and program
  3028 termination should proceed.
  3029 
  3030 Calls to this function must be balanced by the amount of
  3031 `save-session' events received.  This is done automatically, so do not
  3032 call this function yourself.  */)
  3033   (Lisp_Object quit_reply)
  3034 {
  3035   struct haiku_session_manager_reply reply;
  3036   reply.quit_reply = !NILP (quit_reply);
  3037 
  3038   block_input ();
  3039   unrequest_sigio ();
  3040   write_port (port_emacs_to_session_manager, 0, &reply,
  3041               sizeof reply);
  3042   request_sigio ();
  3043   unblock_input ();
  3044 
  3045   return Qnil;
  3046 }
  3047 
  3048 DEFUN ("haiku-display-monitor-attributes-list",
  3049        Fhaiku_display_monitor_attributes_list,
  3050        Shaiku_display_monitor_attributes_list,
  3051        0, 1, 0,
  3052        doc: /* Return a list of physical monitor attributes on the display TERMINAL.
  3053 
  3054 The optional argument TERMINAL specifies which display to ask about.
  3055 TERMINAL should be a terminal object, a frame or a display name (a string).
  3056 If omitted or nil, that stands for the selected frame's display.
  3057 
  3058 Internal use only, use `display-monitor-attributes-list' instead.  */)
  3059   (Lisp_Object terminal)
  3060 {
  3061   struct MonitorInfo monitor;
  3062   struct haiku_display_info *dpyinfo;
  3063   Lisp_Object frames, tail, tem;
  3064 
  3065   dpyinfo = check_haiku_display_info (terminal);
  3066   frames = Qnil;
  3067 
  3068   FOR_EACH_FRAME (tail, tem)
  3069     {
  3070       maybe_quit ();
  3071 
  3072       if (FRAME_HAIKU_P (XFRAME (tem))
  3073           && !FRAME_TOOLTIP_P (XFRAME (tem)))
  3074         frames = Fcons (tem, frames);
  3075     }
  3076 
  3077   monitor.geom.x = 0;
  3078   monitor.geom.y = 0;
  3079   be_get_screen_dimensions ((int *) &monitor.geom.width,
  3080                             (int *) &monitor.geom.height);
  3081 
  3082   monitor.mm_width = (monitor.geom.width
  3083                       / (dpyinfo->resx / 25.4));
  3084   monitor.mm_height = (monitor.geom.height
  3085                        / (dpyinfo->resy / 25.4));
  3086   monitor.name = (char *) "BeOS monitor";
  3087 
  3088   if (!be_get_explicit_workarea ((int *) &monitor.work.x,
  3089                                  (int *) &monitor.work.y,
  3090                                  (int *) &monitor.work.width,
  3091                                  (int *) &monitor.work.height))
  3092     monitor.work = monitor.geom;
  3093 
  3094   return make_monitor_attribute_list (&monitor, 1, 0,
  3095                                       make_vector (1, frames),
  3096                                       "fallback");
  3097 }
  3098 
  3099 frame_parm_handler haiku_frame_parm_handlers[] =
  3100   {
  3101     gui_set_autoraise,
  3102     gui_set_autolower,
  3103     haiku_set_background_color,
  3104     NULL, /* x_set_border_color */
  3105     gui_set_border_width,
  3106     haiku_set_cursor_color,
  3107     haiku_set_cursor_type,
  3108     gui_set_font,
  3109     haiku_set_foreground_color,
  3110     NULL, /* set icon name */
  3111     NULL, /* set icon type */
  3112     haiku_set_child_frame_border_width,
  3113     haiku_set_internal_border_width,
  3114     gui_set_right_divider_width,
  3115     gui_set_bottom_divider_width,
  3116     haiku_set_menu_bar_lines,
  3117     haiku_set_mouse_color,
  3118     haiku_explicitly_set_name,
  3119     gui_set_scroll_bar_width,
  3120     gui_set_scroll_bar_height,
  3121     haiku_set_title,
  3122     gui_set_unsplittable,
  3123     gui_set_vertical_scroll_bars,
  3124     gui_set_horizontal_scroll_bars,
  3125     gui_set_visibility,
  3126     haiku_set_tab_bar_lines,
  3127     haiku_set_tool_bar_lines,
  3128     NULL, /* set scroll bar fg */
  3129     NULL, /* set scroll bar bkg */
  3130     gui_set_screen_gamma,
  3131     gui_set_line_spacing,
  3132     gui_set_left_fringe,
  3133     gui_set_right_fringe,
  3134     NULL, /* x wait for wm */
  3135     gui_set_fullscreen,
  3136     gui_set_font_backend,
  3137     gui_set_alpha,
  3138     haiku_set_sticky,
  3139     NULL, /* set tool bar pos */
  3140     haiku_set_inhibit_double_buffering,
  3141     haiku_set_undecorated,
  3142     haiku_set_parent_frame,
  3143     NULL, /* set skip taskbar */
  3144     haiku_set_no_focus_on_map,
  3145     haiku_set_no_accept_focus,
  3146     haiku_set_z_group,
  3147     haiku_set_override_redirect,
  3148     gui_set_no_special_glyphs,
  3149     gui_set_alpha_background,
  3150     haiku_set_use_frame_synchronization,
  3151   };
  3152 
  3153 void
  3154 syms_of_haikufns (void)
  3155 {
  3156   DEFSYM (Qfont_parameter, "font-parameter");
  3157   DEFSYM (Qcancel_timer, "cancel-timer");
  3158   DEFSYM (Qassq_delete_all, "assq-delete-all");
  3159 
  3160   DEFSYM (Qrun_at_time, "run-at-time");
  3161   DEFSYM (Qx_hide_tip, "x-hide-tip");
  3162 
  3163   DEFSYM (Qalways, "always");
  3164   DEFSYM (Qnot_useful, "not-useful");
  3165   DEFSYM (Qwhen_mapped, "when-mapped");
  3166   DEFSYM (Qtooltip_reuse_hidden_frame, "tooltip-reuse-hidden-frame");
  3167 
  3168   DEFSYM (Qstatic_color, "static-color");
  3169   DEFSYM (Qstatic_gray, "static-gray");
  3170   DEFSYM (Qtrue_color, "true-color");
  3171   DEFSYM (Qmono, "mono");
  3172   DEFSYM (Qgrayscale, "grayscale");
  3173   DEFSYM (Qcolor, "color");
  3174 
  3175   defsubr (&Sx_hide_tip);
  3176   defsubr (&Sxw_display_color_p);
  3177   defsubr (&Sx_display_grayscale_p);
  3178   defsubr (&Sx_open_connection);
  3179   defsubr (&Sx_create_frame);
  3180   defsubr (&Sx_display_pixel_width);
  3181   defsubr (&Sx_display_pixel_height);
  3182   defsubr (&Sxw_color_values);
  3183   defsubr (&Sxw_color_defined_p);
  3184   defsubr (&Sx_display_visual_class);
  3185   defsubr (&Sx_show_tip);
  3186   defsubr (&Sx_display_mm_height);
  3187   defsubr (&Sx_display_mm_width);
  3188   defsubr (&Sx_close_connection);
  3189   defsubr (&Sx_display_list);
  3190   defsubr (&Sx_server_vendor);
  3191   defsubr (&Sx_server_version);
  3192   defsubr (&Sx_display_screens);
  3193   defsubr (&Shaiku_get_version_string);
  3194   defsubr (&Sx_display_color_cells);
  3195   defsubr (&Sx_display_planes);
  3196   defsubr (&Shaiku_set_mouse_absolute_pixel_position);
  3197   defsubr (&Shaiku_mouse_absolute_pixel_position);
  3198   defsubr (&Shaiku_frame_geometry);
  3199   defsubr (&Shaiku_frame_edges);
  3200   defsubr (&Sx_double_buffered_p);
  3201   defsubr (&Sx_display_backing_store);
  3202   defsubr (&Shaiku_read_file_name);
  3203   defsubr (&Shaiku_put_resource);
  3204   defsubr (&Shaiku_frame_list_z_order);
  3205   defsubr (&Sx_display_save_under);
  3206   defsubr (&Shaiku_frame_restack);
  3207   defsubr (&Shaiku_save_session_reply);
  3208   defsubr (&Shaiku_display_monitor_attributes_list);
  3209 
  3210   tip_timer = Qnil;
  3211   staticpro (&tip_timer);
  3212   tip_frame = Qnil;
  3213   staticpro (&tip_frame);
  3214   tip_last_frame = Qnil;
  3215   staticpro (&tip_last_frame);
  3216   tip_last_string = Qnil;
  3217   staticpro (&tip_last_string);
  3218   tip_last_parms = Qnil;
  3219   staticpro (&tip_last_parms);
  3220   tip_dx = Qnil;
  3221   staticpro (&tip_dx);
  3222   tip_dy = Qnil;
  3223   staticpro (&tip_dy);
  3224 
  3225   DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
  3226                doc: /* SKIP: real doc in xfns.c.  */);
  3227   Vx_max_tooltip_size = Qnil;
  3228 
  3229   DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
  3230                doc: /* SKIP: real doc in xfns.c.  */);
  3231   Vx_cursor_fore_pixel = Qnil;
  3232 
  3233   DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
  3234                doc: /* SKIP: real doc in xfns.c.  */);
  3235   Vx_pointer_shape = Qnil;
  3236 
  3237   DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape,
  3238                doc: /* SKIP: real doc in xfns.c.  */);
  3239   Vx_hourglass_pointer_shape = Qnil;
  3240 
  3241   DEFVAR_LISP ("x-sensitive-text-pointer-shape",
  3242                Vx_sensitive_text_pointer_shape,
  3243                doc: /* SKIP: real doc in xfns.c.  */);
  3244   Vx_sensitive_text_pointer_shape = Qnil;
  3245 
  3246   DEFVAR_LISP ("haiku-allowed-ui-colors", Vhaiku_allowed_ui_colors,
  3247                doc: /* Vector of UI colors that Emacs can look up from the system.
  3248 If this is set up incorrectly, Emacs can crash when encountering an
  3249 invalid color.  */);
  3250   Vhaiku_allowed_ui_colors = Qnil;
  3251 
  3252 #ifdef USE_BE_CAIRO
  3253   DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
  3254                doc: /* Version info for cairo.  */);
  3255   {
  3256     char cairo_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
  3257     int len = sprintf (cairo_version, "%d.%d.%d",
  3258                        CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
  3259                        CAIRO_VERSION_MICRO);
  3260     Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
  3261   }
  3262 #endif
  3263 
  3264   return;
  3265 }

/* [<][>][^][v][top][bottom][index][help] */