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

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