root/src/haikuterm.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_keysym_name
  2. haiku_window_to_frame
  3. haiku_coords_from_parent
  4. haiku_toolkit_position
  5. haiku_delete_terminal
  6. haiku_get_string_resource
  7. haiku_update_size_hints
  8. haiku_clip_to_string
  9. haiku_clip_to_string_exactly
  10. haiku_flip_buffers
  11. haiku_frame_up_to_date
  12. haiku_buffer_flipping_unblocked_hook
  13. haiku_clear_frame_area
  14. haiku_clear_frame
  15. haiku_new_font
  16. haiku_valid_modifier_p
  17. haiku_add_modifier
  18. haiku_modifiers_to_emacs
  19. haiku_rehighlight
  20. haiku_frame_raise_lower
  21. haiku_mouse_or_wdesc_frame
  22. haiku_set_scroll_bar_thumb
  23. haiku_set_horizontal_scroll_bar_thumb
  24. haiku_scroll_bar_from_widget
  25. haiku_focus_frame
  26. haiku_new_focus_frame
  27. haiku_implicitly_set_name
  28. haiku_query_frame_background_color
  29. haiku_defined_color
  30. haiku_draw_box_rect
  31. haiku_calculate_relief_colors
  32. haiku_draw_relief_rect
  33. haiku_get_scale_factor
  34. haiku_draw_underwave
  35. haiku_draw_text_decoration
  36. haiku_draw_string_box
  37. haiku_draw_plain_background
  38. haiku_get_bitmap_rec
  39. haiku_update_bitmap_rec
  40. haiku_draw_stipple_background
  41. haiku_draw_background_rect
  42. haiku_maybe_draw_background
  43. haiku_mouse_face_colors
  44. haiku_draw_glyph_string_foreground
  45. haiku_draw_glyphless_glyph_string_foreground
  46. haiku_draw_stretch_glyph_string
  47. haiku_start_clip
  48. haiku_end_clip
  49. haiku_clip_to_row
  50. haiku_update_begin
  51. haiku_update_end
  52. haiku_draw_composite_glyph_string_foreground
  53. haiku_draw_image_relief
  54. haiku_translate_transform
  55. haiku_draw_image_glyph_string
  56. haiku_draw_glyph_string
  57. haiku_after_update_window_line
  58. haiku_set_window_size
  59. haiku_draw_hollow_cursor
  60. haiku_draw_bar_cursor
  61. haiku_draw_window_cursor
  62. haiku_show_hourglass
  63. haiku_hide_hourglass
  64. haiku_compute_glyph_string_overhangs
  65. haiku_draw_vertical_window_border
  66. haiku_set_scroll_bar_default_width
  67. haiku_set_scroll_bar_default_height
  68. haiku_draw_window_divider
  69. haiku_condemn_scroll_bars
  70. haiku_redeem_scroll_bar
  71. haiku_judge_scroll_bars
  72. haiku_scroll_bar_create
  73. haiku_set_horizontal_scroll_bar
  74. haiku_set_vertical_scroll_bar
  75. haiku_draw_fringe_bitmap
  76. haiku_define_fringe_bitmap
  77. haiku_destroy_fringe_bitmap
  78. haiku_scroll_run
  79. haiku_mouse_position
  80. haiku_flush
  81. haiku_define_frame_cursor
  82. haiku_default_font_parameter
  83. haiku_make_fullscreen_consistent
  84. haiku_flush_dirty_back_buffer_on
  85. haiku_wait_for_event
  86. haiku_read_socket
  87. haiku_get_focus_frame
  88. haiku_frame_rehighlight
  89. haiku_delete_window
  90. haiku_free_pixmap
  91. haiku_flash
  92. haiku_beep
  93. haiku_toggle_invisible_pointer
  94. haiku_fullscreen
  95. haiku_create_terminal
  96. haiku_term_init
  97. put_xrm_resource
  98. haiku_clear_under_internal_border
  99. mark_haiku_display
  100. haiku_scroll_bar_remove
  101. haiku_set_offset
  102. haiku_begin_cr_clip
  103. haiku_end_cr_clip
  104. haiku_merge_cursor_foreground
  105. syms_of_haikuterm

     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 "dispextern.h"
    22 #include "frame.h"
    23 #include "lisp.h"
    24 #include "haikugui.h"
    25 #include "keyboard.h"
    26 #include "haikuterm.h"
    27 #include "blockinput.h"
    28 #include "termchar.h"
    29 #include "termhooks.h"
    30 #include "menu.h"
    31 #include "buffer.h"
    32 #include "haiku_support.h"
    33 #include "thread.h"
    34 #include "window.h"
    35 #include "haikuselect.h"
    36 
    37 #include <math.h>
    38 #include <stdlib.h>
    39 
    40 #ifdef USE_BE_CAIRO
    41 #include <cairo.h>
    42 #endif
    43 
    44 /* Minimum and maximum values used for Haiku scroll bars.  */
    45 #define BE_SB_MAX 12000000
    46 
    47 /* The single Haiku display (if any).  */
    48 struct haiku_display_info *x_display_list;
    49 
    50 /* This is used to determine when to evict the font lookup cache,
    51    which we do every 50 updates.  */
    52 static int up_to_date_count;
    53 
    54 /* List of defined fringe bitmaps.  */
    55 static void **fringe_bmps;
    56 
    57 /* The amount of fringe bitmaps in that list.  */
    58 static int max_fringe_bmp;
    59 
    60 /* Alist of resources to their values.  */
    61 static Lisp_Object rdb;
    62 
    63 /* Non-zero means that a HELP_EVENT has been generated since Emacs
    64    start.  */
    65 static bool any_help_event_p;
    66 
    67 char *
    68 get_keysym_name (int keysym)
    69 {
    70   static char value[16];
    71   sprintf (value, "%d", keysym);
    72   return value;
    73 }
    74 
    75 static struct frame *
    76 haiku_window_to_frame (void *window)
    77 {
    78   Lisp_Object tail, tem;
    79   struct frame *f;
    80 
    81   FOR_EACH_FRAME (tail, tem)
    82     {
    83       f = XFRAME (tem);
    84       if (!FRAME_HAIKU_P (f))
    85         continue;
    86 
    87       eassert (FRAME_DISPLAY_INFO (f) == x_display_list);
    88 
    89       if (FRAME_HAIKU_WINDOW (f) == window)
    90         return f;
    91     }
    92 
    93   return 0;
    94 }
    95 
    96 static void
    97 haiku_coords_from_parent (struct frame *f, int *x, int *y)
    98 {
    99   struct frame *p = FRAME_PARENT_FRAME (f);
   100 
   101   *x -= FRAME_OUTPUT_DATA (p)->frame_x;
   102   *y -= FRAME_OUTPUT_DATA (p)->frame_y;
   103 }
   104 
   105 static void
   106 haiku_toolkit_position (struct frame *f, int x, int y,
   107                         bool *menu_bar_p, bool *tool_bar_p)
   108 {
   109   if (FRAME_OUTPUT_DATA (f)->menubar)
   110     *menu_bar_p = (x >= 0 && x < FRAME_PIXEL_WIDTH (f)
   111                    && y >= 0 && y < FRAME_MENU_BAR_HEIGHT (f));
   112 }
   113 
   114 static void
   115 haiku_delete_terminal (struct terminal *terminal)
   116 {
   117   error ("The Haiku terminal cannot be deleted");
   118 }
   119 
   120 static const char *
   121 haiku_get_string_resource (void *ignored, const char *name,
   122                            const char *class)
   123 {
   124   const char *native;
   125 
   126   if (!name)
   127     return NULL;
   128 
   129   Lisp_Object lval = assoc_no_quit (build_string (name), rdb);
   130 
   131   if (!NILP (lval))
   132     return SSDATA (XCDR (lval));
   133 
   134   if ((native = be_find_setting (name)))
   135     return native;
   136 
   137   return NULL;
   138 }
   139 
   140 static void
   141 haiku_update_size_hints (struct frame *f)
   142 {
   143   if (f->tooltip)
   144     return;
   145 
   146   block_input ();
   147   BWindow_set_size_alignment (FRAME_HAIKU_WINDOW (f),
   148                               (frame_resize_pixelwise
   149                                ? 1 : FRAME_COLUMN_WIDTH (f)),
   150                               (frame_resize_pixelwise
   151                                ? 1 : FRAME_LINE_HEIGHT (f)));
   152   unblock_input ();
   153 }
   154 
   155 static void
   156 haiku_clip_to_string (struct glyph_string *s)
   157 {
   158   struct haiku_rect r[2];
   159   int n = get_glyph_string_clip_rects (s, (struct haiku_rect *) &r, 2);
   160 
   161   if (n)
   162     {
   163       /* If n[FOO].width is 0, it means to not draw at all, so set the
   164          clipping to some impossible value.  */
   165       if (r[0].width <= 0)
   166         BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f),
   167                           FRAME_PIXEL_WIDTH (s->f),
   168                           FRAME_PIXEL_HEIGHT (s->f),
   169                           10, 10);
   170       else
   171         {
   172           BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f), r[0].x,
   173                             r[0].y, r[0].width, r[0].height);
   174           BView_invalidate_region (FRAME_HAIKU_DRAWABLE (s->f), r[0].x,
   175                                    r[0].y, r[0].width, r[0].height);
   176         }
   177     }
   178 
   179   if (n > 1)
   180     {
   181       /* If n[FOO].width is 0, it means to not draw at all, so set the
   182          clipping to some impossible value.  */
   183       if (r[1].width <= 0)
   184         BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f),
   185                           FRAME_PIXEL_WIDTH (s->f),
   186                           FRAME_PIXEL_HEIGHT (s->f),
   187                           10, 10);
   188       else
   189         {
   190           BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f), r[1].x, r[1].y,
   191                             r[1].width, r[1].height);
   192           BView_invalidate_region (FRAME_HAIKU_DRAWABLE (s->f), r[1].x,
   193                                    r[1].y, r[1].width, r[1].height);
   194         }
   195     }
   196 }
   197 
   198 static void
   199 haiku_clip_to_string_exactly (struct glyph_string *s, struct glyph_string *dst)
   200 {
   201   BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f), s->x, s->y,
   202                     s->width, s->height);
   203   BView_invalidate_region (FRAME_HAIKU_DRAWABLE (s->f), s->x,
   204                            s->y, s->width, s->height);
   205 }
   206 
   207 static void
   208 haiku_flip_buffers (struct frame *f)
   209 {
   210   void *view = FRAME_OUTPUT_DATA (f)->view;
   211   block_input ();
   212 
   213   BView_draw_lock (view, false, 0, 0, 0, 0);
   214   FRAME_DIRTY_P (f) = 0;
   215   EmacsView_flip_and_blit (view);
   216   BView_draw_unlock (view);
   217 
   218   unblock_input ();
   219 }
   220 
   221 static void
   222 haiku_frame_up_to_date (struct frame *f)
   223 {
   224   block_input ();
   225   FRAME_MOUSE_UPDATE (f);
   226   if (FRAME_DIRTY_P (f) && !buffer_flipping_blocked_p ())
   227     haiku_flip_buffers (f);
   228 
   229   up_to_date_count++;
   230   if (up_to_date_count == 50)
   231     {
   232       be_evict_font_cache ();
   233       up_to_date_count = 0;
   234     }
   235 
   236   /* Mark the frame as complete.  */
   237   FRAME_COMPLETE_P (f) = true;
   238   unblock_input ();
   239 }
   240 
   241 static void
   242 haiku_buffer_flipping_unblocked_hook (struct frame *f)
   243 {
   244   if (FRAME_DIRTY_P (f))
   245     haiku_flip_buffers (f);
   246 }
   247 
   248 static void
   249 haiku_clear_frame_area (struct frame *f, int x, int y,
   250                         int width, int height)
   251 {
   252   void *vw = FRAME_HAIKU_DRAWABLE (f);
   253   block_input ();
   254   BView_draw_lock (vw, true, x, y, width, height);
   255   BView_StartClip (vw);
   256   BView_ClipToRect (vw, x, y, width, height);
   257   BView_SetHighColor (vw, FRAME_BACKGROUND_PIXEL (f));
   258   BView_FillRectangle (vw, x, y, width, height);
   259   BView_EndClip (vw);
   260   BView_draw_unlock (vw);
   261   unblock_input ();
   262 }
   263 
   264 static void
   265 haiku_clear_frame (struct frame *f)
   266 {
   267   void *view = FRAME_HAIKU_DRAWABLE (f);
   268 
   269   mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
   270 
   271   FRAME_COMPLETE_P (f) = false;
   272 
   273   block_input ();
   274   BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
   275                    FRAME_PIXEL_HEIGHT (f));
   276   BView_StartClip (view);
   277   BView_ClipToRect (view, 0, 0, FRAME_PIXEL_WIDTH (f),
   278                     FRAME_PIXEL_HEIGHT (f));
   279   BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (f));
   280   BView_FillRectangle (view, 0, 0, FRAME_PIXEL_WIDTH (f) ,
   281                        FRAME_PIXEL_HEIGHT (f));
   282   BView_EndClip (view);
   283   BView_draw_unlock (view);
   284   unblock_input ();
   285 }
   286 
   287 /* Give frame F the font FONT-OBJECT as its default font.  The return
   288    value is FONT-OBJECT.  FONTSET is an ID of the fontset for the
   289    frame.  If it is negative, generate a new fontset from
   290    FONT-OBJECT.  */
   291 
   292 static Lisp_Object
   293 haiku_new_font (struct frame *f, Lisp_Object font_object, int fontset)
   294 {
   295   struct font *font;
   296   int ascent, descent, unit;
   297 
   298   font = XFONT_OBJECT (font_object);
   299 
   300   if (fontset < 0)
   301     fontset = fontset_from_font (font_object);
   302 
   303   FRAME_FONTSET (f) = fontset;
   304 
   305   if (FRAME_FONT (f) == font)
   306     return font_object;
   307 
   308   FRAME_FONT (f) = font;
   309   FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
   310   FRAME_COLUMN_WIDTH (f) = font->average_width;
   311 
   312   get_font_ascent_descent (font, &ascent, &descent);
   313   FRAME_LINE_HEIGHT (f) = ascent + descent;
   314   FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
   315 
   316   unit = FRAME_COLUMN_WIDTH (f);
   317   if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
   318     FRAME_CONFIG_SCROLL_BAR_COLS (f)
   319       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
   320   else
   321     FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
   322 
   323   if (FRAME_HAIKU_WINDOW (f) && !FRAME_TOOLTIP_P (f))
   324     adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
   325                        FRAME_LINES (f) * FRAME_LINE_HEIGHT (f),
   326                        3, false, Qfont);
   327 
   328   return font_object;
   329 }
   330 
   331 static int
   332 haiku_valid_modifier_p (Lisp_Object sym)
   333 {
   334   return EQ (sym, Qcommand) || EQ (sym, Qshift)
   335     || EQ (sym, Qcontrol) || EQ (sym, Qoption);
   336 }
   337 
   338 #define MODIFIER_OR(obj, def) (haiku_valid_modifier_p (obj) ? obj : def)
   339 
   340 static void
   341 haiku_add_modifier (int modifier, int toput, Lisp_Object qtem, int *modifiers)
   342 {
   343   if ((modifier & HAIKU_MODIFIER_ALT && EQ (qtem, Qcommand))
   344       || (modifier & HAIKU_MODIFIER_SHIFT && EQ (qtem, Qshift))
   345       || (modifier & HAIKU_MODIFIER_CTRL && EQ (qtem, Qcontrol))
   346       || (modifier & HAIKU_MODIFIER_SUPER && EQ (qtem, Qoption)))
   347     *modifiers |= toput;
   348 }
   349 
   350 static int
   351 haiku_modifiers_to_emacs (int haiku_key)
   352 {
   353   int modifiers = 0;
   354   haiku_add_modifier (haiku_key, shift_modifier,
   355                       MODIFIER_OR (Vhaiku_shift_keysym, Qshift), &modifiers);
   356   haiku_add_modifier (haiku_key, super_modifier,
   357                       MODIFIER_OR (Vhaiku_super_keysym, Qoption), &modifiers);
   358   haiku_add_modifier (haiku_key, meta_modifier,
   359                       MODIFIER_OR (Vhaiku_meta_keysym, Qcommand), &modifiers);
   360   haiku_add_modifier (haiku_key, ctrl_modifier,
   361                       MODIFIER_OR (Vhaiku_control_keysym, Qcontrol), &modifiers);
   362   return modifiers;
   363 }
   364 
   365 #undef MODIFIER_OR
   366 
   367 static void
   368 haiku_rehighlight (void)
   369 {
   370   eassert (x_display_list && !x_display_list->next);
   371 
   372   block_input ();
   373 
   374   struct frame *old_hl = x_display_list->highlight_frame;
   375 
   376   if (x_display_list->focused_frame)
   377     {
   378       x_display_list->highlight_frame
   379         = ((FRAMEP (FRAME_FOCUS_FRAME (x_display_list->focused_frame)))
   380            ? XFRAME (FRAME_FOCUS_FRAME (x_display_list->focused_frame))
   381            : x_display_list->focused_frame);
   382       if (!FRAME_LIVE_P (x_display_list->highlight_frame))
   383         {
   384           fset_focus_frame (x_display_list->focused_frame, Qnil);
   385           x_display_list->highlight_frame = x_display_list->focused_frame;
   386         }
   387     }
   388   else
   389     x_display_list->highlight_frame = 0;
   390 
   391   if (old_hl)
   392     gui_update_cursor (old_hl, true);
   393 
   394   if (x_display_list->highlight_frame)
   395     gui_update_cursor (x_display_list->highlight_frame, true);
   396   unblock_input ();
   397 }
   398 
   399 static void
   400 haiku_frame_raise_lower (struct frame *f, bool raise_p)
   401 {
   402   if (raise_p)
   403     {
   404       block_input ();
   405       BWindow_activate (FRAME_HAIKU_WINDOW (f));
   406       BWindow_sync (FRAME_HAIKU_WINDOW (f));
   407       unblock_input ();
   408     }
   409   else
   410     {
   411       block_input ();
   412       BWindow_send_behind (FRAME_HAIKU_WINDOW (f), NULL);
   413       BWindow_sync (FRAME_HAIKU_WINDOW (f));
   414       unblock_input ();
   415     }
   416 }
   417 
   418 static struct frame *
   419 haiku_mouse_or_wdesc_frame (void *window, bool accept_tooltip)
   420 {
   421   struct frame *lm_f = (gui_mouse_grabbed (x_display_list)
   422                         ? x_display_list->last_mouse_frame
   423                         : NULL);
   424 
   425   if (lm_f && !EQ (track_mouse, Qdropping)
   426       && !EQ (track_mouse, Qdrag_source))
   427     return lm_f;
   428   else
   429     {
   430       struct frame *w_f = haiku_window_to_frame (window);
   431 
   432       /* Do not return a tooltip frame.  */
   433       if (!w_f || (FRAME_TOOLTIP_P (w_f) && !accept_tooltip))
   434         return EQ (track_mouse, Qdropping) ? lm_f : NULL;
   435       else
   436         /* When dropping it would be probably nice to raise w_f
   437            here.  */
   438         return w_f;
   439     }
   440 }
   441 
   442 /* Set the thumb size and position of scroll bar BAR.  We are
   443    currently displaying PORTION out of a whole WHOLE, and our position
   444    POSITION.  */
   445 
   446 static void
   447 haiku_set_scroll_bar_thumb (struct scroll_bar *bar, int portion,
   448                             int position, int whole)
   449 {
   450   void *scroll_bar = bar->scroll_bar;
   451   double top, shown, size, value;
   452 
   453   if (scroll_bar_adjust_thumb_portion_p)
   454     {
   455       /* We use an estimate of 30 chars per line rather than the real
   456          `portion' value.  This has the disadvantage that the thumb
   457          size is not very representative, but it makes our life a lot
   458          easier.  Otherwise, we have to constantly adjust the thumb
   459          size, which we can't always do quickly enough: while
   460          dragging, the size of the thumb might prevent the user from
   461          dragging the thumb all the way to the end.  */
   462       portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
   463       /* When the thumb is at the bottom, position == whole.  So we
   464          need to increase `whole' to make space for the thumb.  */
   465       whole += portion;
   466     }
   467   else
   468     bar->page_size = 0;
   469 
   470   if (whole <= 0)
   471     top = 0, shown = 1;
   472   else
   473     {
   474       top = (double) position / whole;
   475       shown = (double) portion / whole;
   476     }
   477 
   478   /* Slider size.  Must be in the range [1 .. MAX - MIN] where MAX
   479      is the scroll bar's maximum and MIN is the scroll bar's minimum
   480      value.  */
   481   size = clip_to_bounds (1, shown * BE_SB_MAX, BE_SB_MAX);
   482 
   483   /* Position.  Must be in the range [MIN .. MAX - SLIDER_SIZE].  */
   484   value = top * BE_SB_MAX;
   485   value = min (value, BE_SB_MAX - size);
   486 
   487   if (!bar->dragging && scroll_bar_adjust_thumb_portion_p)
   488     bar->page_size = size;
   489 
   490   BView_scroll_bar_update (scroll_bar, lrint (size),
   491                            BE_SB_MAX, ceil (value),
   492                            (scroll_bar_adjust_thumb_portion_p
   493                             ? bar->dragging : bar->dragging ? -1 : 0),
   494                            !scroll_bar_adjust_thumb_portion_p);
   495 }
   496 
   497 static void
   498 haiku_set_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion,
   499                                        int position, int whole)
   500 {
   501   void *scroll_bar = bar->scroll_bar;
   502   double size, value, shown, top;
   503 
   504   shown = (double) portion / whole;
   505   top = (double) position / whole;
   506 
   507   size = shown * BE_SB_MAX;
   508   value = top * BE_SB_MAX;
   509 
   510   if (!bar->dragging)
   511     bar->page_size = size;
   512 
   513   BView_scroll_bar_update (scroll_bar, lrint (size), BE_SB_MAX,
   514                            ceil (value), bar->dragging ? -1 : 0, true);
   515 }
   516 
   517 static struct scroll_bar *
   518 haiku_scroll_bar_from_widget (void *scroll_bar, void *window)
   519 {
   520   Lisp_Object tem;
   521   struct frame *frame = haiku_window_to_frame (window);
   522 
   523   if (!frame)
   524     return NULL;
   525 
   526   if (!scroll_bar)
   527     return NULL;
   528 
   529   if (!NILP (FRAME_SCROLL_BARS (frame)))
   530     {
   531       for (tem = FRAME_SCROLL_BARS (frame); !NILP (tem);
   532            tem = XSCROLL_BAR (tem)->next)
   533         {
   534           if (XSCROLL_BAR (tem)->scroll_bar == scroll_bar)
   535             return XSCROLL_BAR (tem);
   536         }
   537     }
   538 
   539   return NULL;
   540 }
   541 
   542 /* Unfortunately, NOACTIVATE is not implementable on Haiku.  */
   543 static void
   544 haiku_focus_frame (struct frame *frame, bool noactivate)
   545 {
   546   if (x_display_list->focused_frame != frame)
   547     haiku_frame_raise_lower (frame, 1);
   548 }
   549 
   550 static void
   551 haiku_new_focus_frame (struct frame *frame)
   552 {
   553   eassert (x_display_list && !x_display_list->next);
   554 
   555   block_input ();
   556   if (frame != x_display_list->focused_frame)
   557     {
   558       if (x_display_list->focused_frame &&
   559           x_display_list->focused_frame->auto_lower)
   560         haiku_frame_raise_lower (x_display_list->focused_frame, 0);
   561 
   562       x_display_list->focused_frame = frame;
   563 
   564       if (frame && frame->auto_raise && !popup_activated_p)
   565         haiku_frame_raise_lower (frame, 1);
   566     }
   567   unblock_input ();
   568 
   569   haiku_rehighlight ();
   570 }
   571 
   572 static void
   573 haiku_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
   574 {
   575   haiku_set_name (f, arg, 0);
   576 }
   577 
   578 static void
   579 haiku_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor)
   580 {
   581   haiku_query_color (FRAME_BACKGROUND_PIXEL (f), bgcolor);
   582 }
   583 
   584 static bool
   585 haiku_defined_color (struct frame *f, const char *name,
   586                      Emacs_Color *color, bool alloc, bool make_index)
   587 {
   588   int rc;
   589 
   590   rc = !haiku_get_color (name, color);
   591 
   592   if (rc && f->gamma && alloc)
   593     gamma_correct (f, color);
   594 
   595   return rc;
   596 }
   597 
   598 /* Adapted from xterm `x_draw_box_rect'.  */
   599 static void
   600 haiku_draw_box_rect (struct glyph_string *s, int left_x, int top_y,
   601                      int right_x, int bottom_y, int hwidth, int vwidth,
   602                      bool left_p, bool right_p, struct haiku_rect *clip_rect)
   603 {
   604   void *view = FRAME_HAIKU_DRAWABLE (s->f);
   605   struct face *face = s->face;
   606 
   607   BView_SetHighColor (view, face->box_color);
   608   if (clip_rect)
   609     BView_ClipToRect (view, clip_rect->x, clip_rect->y, clip_rect->width,
   610                       clip_rect->height);
   611   BView_FillRectangle (view, left_x, top_y, right_x - left_x + 1, hwidth);
   612   if (left_p)
   613     BView_FillRectangle (view, left_x, top_y, vwidth, bottom_y - top_y + 1);
   614 
   615   BView_FillRectangle (view, left_x, bottom_y - hwidth + 1,
   616                        right_x - left_x + 1, hwidth);
   617   if (right_p)
   618     BView_FillRectangle (view, right_x - vwidth + 1,
   619                          top_y, vwidth, bottom_y - top_y + 1);
   620 }
   621 
   622 static void
   623 haiku_calculate_relief_colors (struct glyph_string *s, uint32_t *rgbout_w,
   624                                uint32_t *rgbout_b)
   625 {
   626   double h, cs, l;
   627   uint32_t rgbin;
   628   struct haiku_output *di;
   629 
   630   if (s->face->use_box_color_for_shadows_p)
   631     rgbin = s->face->box_color;
   632   else if (s->first_glyph->type == IMAGE_GLYPH
   633            && s->img->pixmap
   634            && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
   635     rgbin = IMAGE_BACKGROUND (s->img, s->f, 0);
   636   else
   637     rgbin = s->face->background;
   638 
   639   di = FRAME_OUTPUT_DATA (s->f);
   640 
   641   if (s->hl == DRAW_CURSOR)
   642     rgbin = FRAME_CURSOR_COLOR (s->f).pixel;
   643 
   644   if (di->relief_background != rgbin)
   645     {
   646       di->relief_background = rgbin & 0xffffffff;
   647 
   648       rgb_color_hsl (rgbin, &h, &cs, &l);
   649       hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 0.6),
   650                      &di->black_relief_pixel);
   651       hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 1.2),
   652                      &di->white_relief_pixel);
   653     }
   654 
   655   *rgbout_w = di->white_relief_pixel;
   656   *rgbout_b = di->black_relief_pixel;
   657 }
   658 
   659 static void
   660 haiku_draw_relief_rect (struct glyph_string *s, int left_x, int top_y,
   661                         int right_x, int bottom_y, int hwidth, int vwidth,
   662                         bool raised_p, bool top_p, bool bot_p, bool left_p,
   663                         bool right_p, struct haiku_rect *clip_rect)
   664 {
   665   uint32_t color_white, color_black;
   666   void *view;
   667 
   668   view = FRAME_HAIKU_DRAWABLE (s->f);
   669   haiku_calculate_relief_colors (s, &color_white, &color_black);
   670 
   671   BView_SetHighColor (view, raised_p ? color_white : color_black);
   672 
   673   if (clip_rect)
   674     {
   675       BView_StartClip (view);
   676       haiku_clip_to_string (s);
   677       BView_ClipToRect (view, clip_rect->x, clip_rect->y,
   678                         clip_rect->width, clip_rect->height);
   679     }
   680 
   681   if (top_p)
   682     BView_FillRectangle (view, left_x, top_y,
   683                          right_x - left_x + 1, hwidth);
   684 
   685   if (left_p)
   686     BView_FillRectangle (view, left_x, top_y,
   687                          vwidth, bottom_y - top_y + 1);
   688 
   689   BView_SetHighColor (view, !raised_p ? color_white : color_black);
   690 
   691   if (bot_p)
   692     BView_FillRectangle (view, left_x, bottom_y - hwidth + 1,
   693                          right_x - left_x + 1, hwidth);
   694   if (right_p)
   695     BView_FillRectangle (view, right_x - vwidth + 1, top_y,
   696                          vwidth, bottom_y - top_y + 1);
   697 
   698   /* Draw the triangle for the bottom-left corner.  */
   699   if (bot_p && left_p)
   700     {
   701       BView_SetHighColor (view, raised_p ? color_white : color_black);
   702       BView_FillTriangle (view, left_x, bottom_y - hwidth, left_x + vwidth,
   703                           bottom_y - hwidth, left_x, bottom_y);
   704     }
   705 
   706   /* Now draw the triangle for the top-right corner.  */
   707   if (top_p && right_p)
   708     {
   709       BView_SetHighColor (view, raised_p ? color_white : color_black);
   710       BView_FillTriangle (view, right_x - vwidth, top_y,
   711                           right_x, top_y,
   712                           right_x - vwidth, top_y + hwidth);
   713     }
   714 
   715   /* If (h/v)width is > 1, we draw the outer-most line on each side in the
   716      black relief color.  */
   717 
   718   BView_SetHighColor (view, color_black);
   719 
   720   if (hwidth > 1 && top_p)
   721     BView_StrokeLine (view, left_x, top_y, right_x, top_y);
   722   if (hwidth > 1 && bot_p)
   723     BView_StrokeLine (view, left_x, bottom_y, right_x, bottom_y);
   724   if (vwidth > 1 && left_p)
   725     BView_StrokeLine (view, left_x, top_y, left_x, bottom_y);
   726   if (vwidth > 1 && right_p)
   727     BView_StrokeLine (view, right_x, top_y, right_x, bottom_y);
   728 
   729   BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (s->f));
   730 
   731   /* Omit corner pixels.  */
   732   if (hwidth > 1 && vwidth > 1)
   733     {
   734       if (left_p && top_p)
   735         BView_FillRectangle (view, left_x, top_y, 1, 1);
   736       if (left_p && bot_p)
   737         BView_FillRectangle (view, left_x, bottom_y, 1, 1);
   738       if (right_p && top_p)
   739         BView_FillRectangle (view, right_x, top_y, 1, 1);
   740       if (right_p && bot_p)
   741         BView_FillRectangle (view, right_x, bottom_y, 1, 1);
   742     }
   743 
   744   if (clip_rect)
   745     BView_EndClip (view);
   746 }
   747 
   748 static void
   749 haiku_get_scale_factor (int *scale_x, int *scale_y)
   750 {
   751   struct haiku_display_info *dpyinfo = x_display_list;
   752 
   753   if (dpyinfo->resx > 96)
   754     *scale_x = floor (dpyinfo->resx / 96);
   755   if (dpyinfo->resy > 96)
   756     *scale_y = floor (dpyinfo->resy / 96);
   757 }
   758 
   759 static void
   760 haiku_draw_underwave (struct glyph_string *s, int width, int x)
   761 {
   762   int wave_height, wave_length;
   763   int y, dx, dy, odd, xmax, scale_x, scale_y;
   764   float ax, ay, bx, by;
   765   void *view;
   766 
   767   scale_x = 1;
   768   scale_y = 1;
   769   haiku_get_scale_factor (&scale_x, &scale_y);
   770   wave_height = 3 * scale_y;
   771   wave_length = 2 * scale_x;
   772 
   773   dx = wave_length;
   774   dy = wave_height - 1;
   775   y = s->ybase - wave_height + 3;
   776   xmax = x + width;
   777   view = FRAME_HAIKU_DRAWABLE (s->f);
   778 
   779   BView_StartClip (view);
   780   haiku_clip_to_string (s);
   781   BView_ClipToRect (view, x, y, width, wave_height);
   782 
   783   ax = x - ((int) (x) % dx) + (float) 0.5;
   784   bx = ax + dx;
   785   odd = (int) (ax / dx) % 2;
   786   ay = by = y + 0.5;
   787 
   788   if (odd)
   789     ay += dy;
   790   else
   791     by += dy;
   792 
   793   BView_SetPenSize (view, scale_y);
   794 
   795   while (ax <= xmax)
   796     {
   797       BView_StrokeLine (view, ax, ay, bx, by);
   798       ax = bx, ay = by;
   799       bx += dx, by = y + 0.5 + odd * dy;
   800       odd = !odd;
   801     }
   802 
   803   BView_SetPenSize (view, 1);
   804   BView_EndClip (view);
   805 }
   806 
   807 static void
   808 haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
   809                             int width, int x)
   810 {
   811   unsigned long cursor_color;
   812 
   813   if (s->for_overlaps)
   814     return;
   815 
   816   if (s->hl == DRAW_CURSOR)
   817     haiku_merge_cursor_foreground (s, &cursor_color, NULL);
   818 
   819   void *view = FRAME_HAIKU_DRAWABLE (s->f);
   820 
   821   if (face->underline)
   822     {
   823       if (s->hl == DRAW_CURSOR)
   824         BView_SetHighColor (view, cursor_color);
   825       else if (!face->underline_defaulted_p)
   826         BView_SetHighColor (view, face->underline_color);
   827       else
   828         BView_SetHighColor (view, face->foreground);
   829 
   830       if (face->underline == FACE_UNDER_WAVE)
   831         haiku_draw_underwave (s, width, x);
   832       else if (face->underline == FACE_UNDER_LINE)
   833         {
   834           unsigned long thickness, position;
   835           int y;
   836 
   837           if (s->prev
   838               && s->prev->face->underline == FACE_UNDER_LINE
   839               && (s->prev->face->underline_at_descent_line_p
   840                   == s->face->underline_at_descent_line_p)
   841               && (s->prev->face->underline_pixels_above_descent_line
   842                   == s->face->underline_pixels_above_descent_line))
   843             {
   844               /* We use the same underline style as the previous one.  */
   845               thickness = s->prev->underline_thickness;
   846               position = s->prev->underline_position;
   847             }
   848           else
   849             {
   850               struct font *font = font_for_underline_metrics (s);
   851               unsigned long minimum_offset;
   852               bool underline_at_descent_line;
   853               bool use_underline_position_properties;
   854               Lisp_Object val = (WINDOW_BUFFER_LOCAL_VALUE
   855                                  (Qunderline_minimum_offset, s->w));
   856 
   857               if (FIXNUMP (val))
   858                 minimum_offset = max (0, XFIXNUM (val));
   859               else
   860                 minimum_offset = 1;
   861 
   862               val = (WINDOW_BUFFER_LOCAL_VALUE
   863                      (Qx_underline_at_descent_line, s->w));
   864               underline_at_descent_line
   865                 = (!(NILP (val) || BASE_EQ (val, Qunbound))
   866                    || s->face->underline_at_descent_line_p);
   867 
   868               val = (WINDOW_BUFFER_LOCAL_VALUE
   869                      (Qx_use_underline_position_properties, s->w));
   870               use_underline_position_properties
   871                 = !(NILP (val) || BASE_EQ (val, Qunbound));
   872 
   873               /* Get the underline thickness.  Default is 1 pixel.  */
   874               if (font && font->underline_thickness > 0)
   875                 thickness = font->underline_thickness;
   876               else
   877                 thickness = 1;
   878               if (underline_at_descent_line)
   879                 position = ((s->height - thickness)
   880                             - (s->ybase - s->y)
   881                             - s->face->underline_pixels_above_descent_line);
   882               else
   883                 {
   884                   /* Get the underline position.  This is the
   885                      recommended vertical offset in pixels from
   886                      the baseline to the top of the underline.
   887                      This is a signed value according to the
   888                      specs, and its default is
   889 
   890                      ROUND ((maximum descent) / 2), with
   891                      ROUND(x) = floor (x + 0.5)  */
   892 
   893                   if (use_underline_position_properties
   894                       && font && font->underline_position >= 0)
   895                     position = font->underline_position;
   896                   else if (font)
   897                     position = (font->descent + 1) / 2;
   898                   else
   899                     position = minimum_offset;
   900                 }
   901               position = max (position, minimum_offset);
   902             }
   903           /* Check the sanity of thickness and position.  We should
   904              avoid drawing underline out of the current line area.  */
   905           if (s->y + s->height <= s->ybase + position)
   906             position = (s->height - 1) - (s->ybase - s->y);
   907           if (s->y + s->height < s->ybase + position + thickness)
   908             thickness = (s->y + s->height) - (s->ybase + position);
   909           s->underline_thickness = thickness;
   910           s->underline_position = position;
   911           y = s->ybase + position;
   912 
   913           BView_FillRectangle (view, s->x, y, s->width, thickness);
   914         }
   915     }
   916 
   917   if (face->overline_p)
   918     {
   919       unsigned long dy = 0, h = 1;
   920       if (s->hl == DRAW_CURSOR)
   921         BView_SetHighColor (view, cursor_color);
   922       else if (!face->overline_color_defaulted_p)
   923         BView_SetHighColor (view, face->overline_color);
   924       else
   925         BView_SetHighColor (view, face->foreground);
   926 
   927       BView_FillRectangle (view, s->x, s->y + dy, s->width, h);
   928     }
   929 
   930   if (face->strike_through_p)
   931     {
   932       /* Y-coordinate and height of the glyph string's first
   933          glyph.  We cannot use s->y and s->height because those
   934          could be larger if there are taller display elements
   935          (e.g., characters displayed with a larger font) in the
   936          same glyph row.  */
   937       int glyph_y = s->ybase - s->first_glyph->ascent;
   938       int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
   939       /* Strike-through width and offset from the glyph string's
   940          top edge.  */
   941       unsigned long h = 1;
   942       unsigned long dy = (glyph_height - h) / 2;
   943 
   944       if (s->hl == DRAW_CURSOR)
   945         BView_SetHighColor (view, cursor_color);
   946       else if (!face->strike_through_color_defaulted_p)
   947         BView_SetHighColor (view, face->strike_through_color);
   948       else
   949         BView_SetHighColor (view, face->foreground);
   950 
   951       BView_FillRectangle (view, s->x, glyph_y + dy, s->width, h);
   952     }
   953 }
   954 
   955 static void
   956 haiku_draw_string_box (struct glyph_string *s)
   957 {
   958   int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
   959   bool raised_p, left_p, right_p;
   960   struct glyph *last_glyph;
   961   struct face *face = s->face;
   962 
   963   last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
   964             ? WINDOW_RIGHT_EDGE_X (s->w)
   965             : window_box_right (s->w, s->area));
   966 
   967   /* The glyph that may have a right box line.  For static
   968      compositions and images, the right-box flag is on the first glyph
   969      of the glyph string; for other types it's on the last glyph.  */
   970   if (s->cmp || s->img)
   971     last_glyph = s->first_glyph;
   972   else if (s->first_glyph->type == COMPOSITE_GLYPH
   973            && s->first_glyph->u.cmp.automatic)
   974     {
   975       /* For automatic compositions, we need to look up the last glyph
   976          in the composition.  */
   977         struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area];
   978         struct glyph *g = s->first_glyph;
   979         for (last_glyph = g++;
   980              g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id
   981                && g->slice.cmp.to < s->cmp_to;
   982              last_glyph = g++)
   983           ;
   984     }
   985   else
   986     last_glyph = s->first_glyph + s->nchars - 1;
   987 
   988   vwidth = eabs (face->box_vertical_line_width);
   989   hwidth = eabs (face->box_horizontal_line_width);
   990   raised_p = face->box == FACE_RAISED_BOX;
   991   left_x = s->x;
   992   right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
   993              ? last_x - 1
   994              : min (last_x, s->x + s->background_width) - 1);
   995 
   996   top_y = s->y;
   997   bottom_y = top_y + s->height - 1;
   998 
   999   left_p = (s->first_glyph->left_box_line_p
  1000             || (s->hl == DRAW_MOUSE_FACE
  1001                 && (s->prev == NULL
  1002                     || s->prev->hl != s->hl)));
  1003   right_p = (last_glyph->right_box_line_p
  1004              || (s->hl == DRAW_MOUSE_FACE
  1005                  && (s->next == NULL
  1006                      || s->next->hl != s->hl)));
  1007 
  1008   if (face->box == FACE_SIMPLE_BOX)
  1009     haiku_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
  1010                          vwidth, left_p, right_p, NULL);
  1011   else
  1012     haiku_draw_relief_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
  1013                             vwidth, raised_p, true, true, left_p, right_p,
  1014                             NULL);
  1015 }
  1016 
  1017 static void
  1018 haiku_draw_plain_background (struct glyph_string *s, struct face *face,
  1019                              int x, int y, int width, int height)
  1020 {
  1021   void *view = FRAME_HAIKU_DRAWABLE (s->f);
  1022   unsigned long cursor_color;
  1023 
  1024   if (s->hl == DRAW_CURSOR)
  1025     {
  1026       haiku_merge_cursor_foreground (s, NULL, &cursor_color);
  1027       BView_SetHighColor (view, cursor_color);
  1028     }
  1029   else
  1030     BView_SetHighColor (view, face->background_defaulted_p ?
  1031                         FRAME_BACKGROUND_PIXEL (s->f) :
  1032                         face->background);
  1033 
  1034   BView_FillRectangle (view, x, y, width, height);
  1035 }
  1036 
  1037 static struct haiku_bitmap_record *
  1038 haiku_get_bitmap_rec (struct frame *f, ptrdiff_t id)
  1039 {
  1040   return &FRAME_DISPLAY_INFO (f)->bitmaps[id - 1];
  1041 }
  1042 
  1043 static void
  1044 haiku_update_bitmap_rec (struct haiku_bitmap_record *rec,
  1045                          uint32_t new_foreground,
  1046                          uint32_t new_background)
  1047 {
  1048   char *bits;
  1049   int x, y, bytes_per_line;
  1050 
  1051   if (new_foreground == rec->stipple_foreground
  1052       && new_background == rec->stipple_background)
  1053     return;
  1054 
  1055   bits = rec->stipple_bits;
  1056   bytes_per_line = (rec->width + 7) / 8;
  1057 
  1058   for (y = 0; y < rec->height; y++)
  1059     {
  1060       for (x = 0; x < rec->width; x++)
  1061         haiku_put_pixel (rec->img, x, y,
  1062                          ((bits[x / 8] >> (x % 8)) & 1
  1063                           ? new_foreground : new_background));
  1064 
  1065       bits += bytes_per_line;
  1066     }
  1067 
  1068   rec->stipple_foreground = new_foreground;
  1069   rec->stipple_background = new_background;
  1070 }
  1071 
  1072 static void
  1073 haiku_draw_stipple_background (struct glyph_string *s, struct face *face,
  1074                                int x, int y, int width, int height,
  1075                                bool explicit_colors_p,
  1076                                uint32 explicit_background,
  1077                                uint32 explicit_foreground)
  1078 {
  1079   struct haiku_bitmap_record *rec;
  1080   unsigned long foreground, background;
  1081   void *view;
  1082 
  1083   view = FRAME_HAIKU_DRAWABLE (s->f);
  1084   rec = haiku_get_bitmap_rec (s->f, s->face->stipple);
  1085 
  1086   if (explicit_colors_p)
  1087     {
  1088       background = explicit_background;
  1089       foreground = explicit_foreground;
  1090     }
  1091   else if (s->hl == DRAW_CURSOR)
  1092     haiku_merge_cursor_foreground (s, &foreground, &background);
  1093   else
  1094     {
  1095       foreground = s->face->foreground;
  1096       background = s->face->background;
  1097     }
  1098 
  1099   haiku_update_bitmap_rec (rec, foreground, background);
  1100 
  1101   BView_StartClip (view);
  1102   haiku_clip_to_string (s);
  1103   BView_ClipToRect (view, x, y, width, height);
  1104   BView_DrawBitmapTiled (view, rec->img, 0, 0, -1, -1,
  1105                          0, 0, x + width, y + height);
  1106   BView_EndClip (view);
  1107 }
  1108 
  1109 void
  1110 haiku_draw_background_rect (struct glyph_string *s, struct face *face,
  1111                             int x, int y, int width, int height)
  1112 {
  1113   if (!s->stippled_p)
  1114     haiku_draw_plain_background (s, face, x, y, width, height);
  1115   else
  1116     haiku_draw_stipple_background (s, face, x, y, width, height,
  1117                                    false, 0, 0);
  1118 }
  1119 
  1120 static void
  1121 haiku_maybe_draw_background (struct glyph_string *s, int force_p)
  1122 {
  1123   if ((s->first_glyph->type != IMAGE_GLYPH) && !s->background_filled_p)
  1124     {
  1125       struct face *face = s->face;
  1126       int box_line_width = max (face->box_horizontal_line_width, 0);
  1127       int box_vline_width = max (face->box_vertical_line_width, 0);
  1128 
  1129       if (FONT_HEIGHT (s->font) < s->height - 2 * box_vline_width
  1130           || FONT_TOO_HIGH (s->font)
  1131           || s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
  1132         {
  1133           haiku_draw_background_rect (s, s->face, s->x, s->y + box_line_width,
  1134                                       s->background_width,
  1135                                       s->height - 2 * box_line_width);
  1136 
  1137           s->background_filled_p = 1;
  1138         }
  1139     }
  1140 }
  1141 
  1142 static void
  1143 haiku_mouse_face_colors (struct glyph_string *s, uint32_t *fg,
  1144                          uint32_t *bg)
  1145 {
  1146   int face_id;
  1147   struct face *face;
  1148 
  1149   /* What face has to be used last for the mouse face?  */
  1150   face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
  1151   face = FACE_FROM_ID_OR_NULL (s->f, face_id);
  1152   if (face == NULL)
  1153     face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
  1154 
  1155   if (s->first_glyph->type == CHAR_GLYPH)
  1156     face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
  1157   else
  1158     face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
  1159 
  1160   face = FACE_FROM_ID (s->f, face_id);
  1161   prepare_face_for_display (s->f, s->face);
  1162 
  1163   if (fg)
  1164     *fg = face->foreground;
  1165   if (bg)
  1166     *bg = face->background;
  1167 }
  1168 
  1169 static void
  1170 haiku_draw_glyph_string_foreground (struct glyph_string *s)
  1171 {
  1172   struct face *face = s->face;
  1173 
  1174   int i, x;
  1175   if (face->box != FACE_NO_BOX
  1176       && s->first_glyph->left_box_line_p)
  1177     x = s->x + max (face->box_vertical_line_width, 0);
  1178   else
  1179     x = s->x;
  1180 
  1181   void *view = FRAME_HAIKU_DRAWABLE (s->f);
  1182 
  1183   if (s->font_not_found_p)
  1184     {
  1185       if (s->hl == DRAW_CURSOR)
  1186         BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
  1187       else
  1188         BView_SetHighColor (view, face->foreground);
  1189       for (i = 0; i < s->nchars; ++i)
  1190         {
  1191           struct glyph *g = s->first_glyph + i;
  1192 
  1193           BView_SetPenSize (view, 1);
  1194           BView_StrokeRectangle (view, x, s->y, g->pixel_width,
  1195                                  s->height);
  1196           x += g->pixel_width;
  1197         }
  1198     }
  1199   else
  1200     {
  1201       struct font *ft = s->font;
  1202       int off = ft->baseline_offset;
  1203       int y;
  1204 
  1205       if (ft->vertical_centering)
  1206         off = VCENTER_BASELINE_OFFSET (ft, s->f) - off;
  1207       y = s->ybase - off;
  1208       if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR))
  1209         ft->driver->draw (s, 0, s->nchars, x, y, false);
  1210       else
  1211         ft->driver->draw (s, 0, s->nchars, x, y, true);
  1212 
  1213       if (face->overstrike)
  1214         ft->driver->draw (s, 0, s->nchars, x + 1, y, false);
  1215     }
  1216 }
  1217 
  1218 static void
  1219 haiku_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
  1220 {
  1221   struct glyph *glyph = s->first_glyph;
  1222   unsigned char2b[8];
  1223   int x, i, j;
  1224   struct face *face = s->face;
  1225   unsigned long color;
  1226 
  1227   /* If first glyph of S has a left box line, start drawing the text
  1228      of S to the right of that box line.  */
  1229   if (face && face->box != FACE_NO_BOX
  1230       && s->first_glyph->left_box_line_p)
  1231     x = s->x + max (face->box_vertical_line_width, 0);
  1232   else
  1233     x = s->x;
  1234 
  1235   s->char2b = char2b;
  1236 
  1237   for (i = 0; i < s->nchars; i++, glyph++)
  1238     {
  1239 #ifdef GCC_LINT
  1240       enum { PACIFY_GCC_BUG_81401 = 1 };
  1241 #else
  1242       enum { PACIFY_GCC_BUG_81401 = 0 };
  1243 #endif
  1244       char buf[7 + PACIFY_GCC_BUG_81401];
  1245       char *str = NULL;
  1246       int len = glyph->u.glyphless.len;
  1247 
  1248       if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
  1249         {
  1250           if (len > 0
  1251               && CHAR_TABLE_P (Vglyphless_char_display)
  1252               && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
  1253                   >= 1))
  1254             {
  1255               Lisp_Object acronym
  1256                 = (! glyph->u.glyphless.for_no_font
  1257                    ? CHAR_TABLE_REF (Vglyphless_char_display,
  1258                                      glyph->u.glyphless.ch)
  1259                    : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
  1260               if (CONSP (acronym))
  1261                 acronym = XCAR (acronym);
  1262               if (STRINGP (acronym))
  1263                 str = SSDATA (acronym);
  1264             }
  1265         }
  1266       else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
  1267         {
  1268           unsigned int ch = glyph->u.glyphless.ch;
  1269           eassume (ch <= MAX_CHAR);
  1270           sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
  1271           str = buf;
  1272         }
  1273 
  1274       if (str)
  1275         {
  1276           int upper_len = (len + 1) / 2;
  1277 
  1278           /* It is assured that all LEN characters in STR is ASCII.  */
  1279           for (j = 0; j < len; j++)
  1280             char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
  1281 
  1282           s->font->driver->draw (s, 0, upper_len,
  1283                                  x + glyph->slice.glyphless.upper_xoff,
  1284                                  s->ybase + glyph->slice.glyphless.upper_yoff,
  1285                                  false);
  1286           s->font->driver->draw (s, upper_len, len,
  1287                                  x + glyph->slice.glyphless.lower_xoff,
  1288                                  s->ybase + glyph->slice.glyphless.lower_yoff,
  1289                                  false);
  1290         }
  1291 
  1292       if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
  1293         {
  1294           if (s->hl == DRAW_CURSOR)
  1295             haiku_merge_cursor_foreground (s, NULL, &color);
  1296           else
  1297             color = s->face->foreground;
  1298 
  1299           BView_SetHighColor (FRAME_HAIKU_DRAWABLE (s->f), color);
  1300           BView_SetPenSize (FRAME_HAIKU_DRAWABLE (s->f), 1);
  1301           BView_StrokeRectangle (FRAME_HAIKU_DRAWABLE (s->f),
  1302                                  x, s->ybase - glyph->ascent,
  1303                                  glyph->pixel_width,
  1304                                  glyph->ascent + glyph->descent);
  1305         }
  1306       x += glyph->pixel_width;
  1307    }
  1308 }
  1309 
  1310 static void
  1311 haiku_draw_stretch_glyph_string (struct glyph_string *s)
  1312 {
  1313   struct face *face = s->face;
  1314   uint32_t bkg;
  1315 
  1316   if (s->hl == DRAW_CURSOR && !x_stretch_cursor_p)
  1317     {
  1318       int width, background_width = s->background_width;
  1319       int x = s->x;
  1320 
  1321       if (!s->row->reversed_p)
  1322         {
  1323           int left_x = window_box_left_offset (s->w, TEXT_AREA);
  1324 
  1325           if (x < left_x)
  1326             {
  1327               background_width -= left_x - x;
  1328               x = left_x;
  1329             }
  1330         }
  1331       else
  1332         {
  1333           /* In R2L rows, draw the cursor on the right edge of the
  1334              stretch glyph.  */
  1335           int right_x = window_box_right (s->w, TEXT_AREA);
  1336           if (x + background_width > right_x)
  1337             background_width -= x - right_x;
  1338           x += background_width;
  1339         }
  1340 
  1341       width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
  1342       if (s->row->reversed_p)
  1343         x -= width;
  1344 
  1345       void *view = FRAME_HAIKU_DRAWABLE (s->f);
  1346       unsigned long cursor_color;
  1347 
  1348       haiku_merge_cursor_foreground (s, NULL, &cursor_color);
  1349       BView_SetHighColor (view, cursor_color);
  1350       BView_FillRectangle (view, x, s->y, width, s->height);
  1351 
  1352       if (width < background_width)
  1353         {
  1354           if (!s->row->reversed_p)
  1355             x += width;
  1356           else
  1357             x = s->x;
  1358 
  1359           int y = s->y;
  1360           int w = background_width - width, h = s->height;
  1361 
  1362           /* Draw stipples manually because we want the background
  1363              part of a stretch glyph to have a stipple even if the
  1364              cursor is visible on top.  */
  1365           if (!face->stipple)
  1366             {
  1367               if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w))
  1368                 haiku_mouse_face_colors (s, NULL, &bkg);
  1369               else
  1370                 bkg = face->background;
  1371 
  1372               BView_SetHighColor (view, bkg);
  1373               BView_FillRectangle (view, x, y, w, h);
  1374             }
  1375           else
  1376             {
  1377               if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w))
  1378                 haiku_mouse_face_colors (s, NULL, &bkg);
  1379               else
  1380                 bkg = face->background;
  1381 
  1382               haiku_draw_stipple_background (s, s->face, x, y, w, h,
  1383                                              true, bkg, face->foreground);
  1384             }
  1385         }
  1386     }
  1387   else if (!s->background_filled_p)
  1388     {
  1389       int background_width = s->background_width;
  1390       int x = s->x, text_left_x = window_box_left (s->w, TEXT_AREA);
  1391 
  1392       /* Don't draw into left fringe or scrollbar area except for
  1393          header line and mode line.  */
  1394       if (s->area == TEXT_AREA
  1395           && x < text_left_x && !s->row->mode_line_p)
  1396         {
  1397           background_width -= text_left_x - x;
  1398           x = text_left_x;
  1399         }
  1400 
  1401       if (background_width > 0)
  1402         haiku_draw_background_rect (s, s->face, s->x, s->y,
  1403                                     background_width, s->height);
  1404     }
  1405   s->background_filled_p = 1;
  1406 }
  1407 
  1408 static void
  1409 haiku_start_clip (struct glyph_string *s)
  1410 {
  1411   void *view = FRAME_HAIKU_DRAWABLE (s->f);
  1412   BView_StartClip (view);
  1413 }
  1414 
  1415 static void
  1416 haiku_end_clip (struct glyph_string *s)
  1417 {
  1418   void *view = FRAME_HAIKU_DRAWABLE (s->f);
  1419   BView_EndClip (view);
  1420 }
  1421 
  1422 static void
  1423 haiku_clip_to_row (struct window *w, struct glyph_row *row,
  1424                    enum glyph_row_area area)
  1425 {
  1426   struct frame *f = WINDOW_XFRAME (w);
  1427   int window_x, window_y, window_width;
  1428   int x, y, width, height;
  1429 
  1430   window_box (w, area, &window_x, &window_y, &window_width, 0);
  1431 
  1432   x = window_x;
  1433   y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
  1434   y = max (y, window_y);
  1435   width = window_width;
  1436   height = row->visible_height;
  1437 
  1438   BView_ClipToRect (FRAME_HAIKU_DRAWABLE (f), x, y, width, height);
  1439 }
  1440 
  1441 static void
  1442 haiku_update_begin (struct frame *f)
  1443 {
  1444   /* Mark the frame as incomplete so it is not flushed upon handling
  1445      input.  */
  1446   FRAME_COMPLETE_P (f) = false;
  1447 }
  1448 
  1449 static void
  1450 haiku_update_end (struct frame *f)
  1451 {
  1452   MOUSE_HL_INFO (f)->mouse_face_defer = false;
  1453   BWindow_Flush (FRAME_HAIKU_WINDOW (f));
  1454 }
  1455 
  1456 static void
  1457 haiku_draw_composite_glyph_string_foreground (struct glyph_string *s)
  1458 {
  1459   int i, j, x;
  1460   struct font *font = s->font;
  1461   void *view = FRAME_HAIKU_DRAWABLE (s->f);
  1462   struct face *face = s->face;
  1463 
  1464   /* If first glyph of S has a left box line, start drawing the text
  1465      of S to the right of that box line.  */
  1466   if (face && face->box != FACE_NO_BOX
  1467       && s->first_glyph->left_box_line_p)
  1468     x = s->x + max (face->box_vertical_line_width, 0);
  1469   else
  1470     x = s->x;
  1471 
  1472   /* S is a glyph string for a composition.  S->cmp_from is the index
  1473      of the first character drawn for glyphs of this composition.
  1474      S->cmp_from == 0 means we are drawing the very first character of
  1475      this composition.  */
  1476 
  1477   /* Draw a rectangle for the composition if the font for the very
  1478      first character of the composition could not be loaded.  */
  1479   if (s->font_not_found_p && !s->cmp_from)
  1480     {
  1481       if (s->hl == DRAW_CURSOR)
  1482         BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
  1483       else
  1484         BView_SetHighColor (view, s->face->foreground);
  1485 
  1486       BView_SetPenSize (view, 1);
  1487       BView_StrokeRectangle (view, s->x, s->y,
  1488                              s->width, s->height);
  1489     }
  1490   else if (!s->first_glyph->u.cmp.automatic)
  1491     {
  1492       int y = s->ybase;
  1493 
  1494       for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
  1495         /* TAB in a composition means display glyphs with padding
  1496            space on the left or right.  */
  1497         if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
  1498           {
  1499             int xx = x + s->cmp->offsets[j * 2];
  1500             int yy = y - s->cmp->offsets[j * 2 + 1];
  1501 
  1502             font->driver->draw (s, j, j + 1, xx, yy, false);
  1503             if (face->overstrike)
  1504               font->driver->draw (s, j, j + 1, xx + 1, yy, false);
  1505           }
  1506     }
  1507   else
  1508     {
  1509       Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
  1510       Lisp_Object glyph;
  1511       int y = s->ybase;
  1512       int width = 0;
  1513 
  1514       for (i = j = s->cmp_from; i < s->cmp_to; i++)
  1515         {
  1516           glyph = LGSTRING_GLYPH (gstring, i);
  1517           if (NILP (LGLYPH_ADJUSTMENT (glyph)))
  1518             width += LGLYPH_WIDTH (glyph);
  1519           else
  1520             {
  1521               int xoff, yoff, wadjust;
  1522 
  1523               if (j < i)
  1524                 {
  1525                   font->driver->draw (s, j, i, x, y, false);
  1526                   if (s->face->overstrike)
  1527                     font->driver->draw (s, j, i, x + 1, y, false);
  1528                   x += width;
  1529                 }
  1530               xoff = LGLYPH_XOFF (glyph);
  1531               yoff = LGLYPH_YOFF (glyph);
  1532               wadjust = LGLYPH_WADJUST (glyph);
  1533               font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
  1534               if (face->overstrike)
  1535                 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
  1536                                     false);
  1537               x += wadjust;
  1538               j = i + 1;
  1539               width = 0;
  1540             }
  1541         }
  1542       if (j < i)
  1543         {
  1544           font->driver->draw (s, j, i, x, y, false);
  1545           if (face->overstrike)
  1546             font->driver->draw (s, j, i, x + 1, y, false);
  1547         }
  1548     }
  1549 }
  1550 
  1551 static void
  1552 haiku_draw_image_relief (struct glyph_string *s)
  1553 {
  1554   int x1, y1, thick;
  1555   bool raised_p, top_p, bot_p, left_p, right_p;
  1556   int extra_x, extra_y;
  1557   struct haiku_rect r;
  1558   int x = s->x;
  1559   int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
  1560 
  1561   struct face *face = s->face;
  1562 
  1563   /* If first glyph of S has a left box line, start drawing it to the
  1564      right of that line.  */
  1565   if (face->box != FACE_NO_BOX
  1566       && s->first_glyph->left_box_line_p
  1567       && s->slice.x == 0)
  1568     x += max (face->box_vertical_line_width, 0);
  1569 
  1570   /* If there is a margin around the image, adjust x- and y-position
  1571      by that margin.  */
  1572   if (s->slice.x == 0)
  1573     x += s->img->hmargin;
  1574   if (s->slice.y == 0)
  1575     y += s->img->vmargin;
  1576 
  1577   if (s->hl == DRAW_IMAGE_SUNKEN
  1578       || s->hl == DRAW_IMAGE_RAISED)
  1579     {
  1580       if (s->face->id == TAB_BAR_FACE_ID)
  1581         thick = (tab_bar_button_relief < 0
  1582                  ? DEFAULT_TAB_BAR_BUTTON_RELIEF
  1583                  : min (tab_bar_button_relief, 1000000));
  1584       else
  1585         thick = (tool_bar_button_relief < 0
  1586                  ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
  1587                  : min (tool_bar_button_relief, 1000000));
  1588       raised_p = s->hl == DRAW_IMAGE_RAISED;
  1589     }
  1590   else
  1591     {
  1592       thick = eabs (s->img->relief);
  1593       raised_p = s->img->relief > 0;
  1594     }
  1595 
  1596   x1 = x + s->slice.width - 1;
  1597   y1 = y + s->slice.height - 1;
  1598 
  1599   extra_x = extra_y = 0;
  1600 
  1601   if (s->face->id == TAB_BAR_FACE_ID)
  1602     {
  1603       if (CONSP (Vtab_bar_button_margin)
  1604           && FIXNUMP (XCAR (Vtab_bar_button_margin))
  1605           && FIXNUMP (XCDR (Vtab_bar_button_margin)))
  1606         {
  1607           extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick;
  1608           extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick;
  1609         }
  1610       else if (FIXNUMP (Vtab_bar_button_margin))
  1611         extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick;
  1612     }
  1613 
  1614   if (s->face->id == TOOL_BAR_FACE_ID)
  1615     {
  1616       if (CONSP (Vtool_bar_button_margin)
  1617           && FIXNUMP (XCAR (Vtool_bar_button_margin))
  1618           && FIXNUMP (XCDR (Vtool_bar_button_margin)))
  1619         {
  1620           extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
  1621           extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
  1622         }
  1623       else if (FIXNUMP (Vtool_bar_button_margin))
  1624         extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
  1625     }
  1626 
  1627   top_p = bot_p = left_p = right_p = 0;
  1628 
  1629   if (s->slice.x == 0)
  1630     x -= thick + extra_x, left_p = 1;
  1631   if (s->slice.y == 0)
  1632     y -= thick + extra_y, top_p = 1;
  1633   if (s->slice.x + s->slice.width == s->img->width)
  1634     x1 += thick + extra_x, right_p = 1;
  1635   if (s->slice.y + s->slice.height == s->img->height)
  1636     y1 += thick + extra_y, bot_p = 1;
  1637 
  1638   get_glyph_string_clip_rect (s, &r);
  1639   haiku_draw_relief_rect (s, x, y, x1, y1, thick, thick, raised_p,
  1640                           top_p, bot_p, left_p, right_p, &r);
  1641 }
  1642 
  1643 static void
  1644 haiku_translate_transform (double (*transform)[3], double dx,
  1645                            double dy)
  1646 {
  1647   transform[0][2] += dx;
  1648   transform[1][2] += dy;
  1649 }
  1650 
  1651 static void
  1652 haiku_draw_image_glyph_string (struct glyph_string *s)
  1653 {
  1654   struct face *face = s->face;
  1655   void *view, *bitmap, *mask;
  1656   int box_line_hwidth = max (face->box_vertical_line_width, 0);
  1657   int box_line_vwidth = max (face->box_horizontal_line_width, 0);
  1658   int x, y, height, width, relief;
  1659   struct haiku_rect nr;
  1660   Emacs_Rectangle cr, ir, r;
  1661   unsigned long background;
  1662   double image_transform[3][3];
  1663 
  1664   height = s->height;
  1665   if (s->slice.y == 0)
  1666     height -= box_line_vwidth;
  1667   if (s->slice.y + s->slice.height >= s->img->height)
  1668     height -= box_line_vwidth;
  1669 
  1670   width = s->background_width;
  1671   x = s->x;
  1672   if (s->first_glyph->left_box_line_p
  1673       && s->slice.x == 0)
  1674     {
  1675       x += box_line_hwidth;
  1676       width -= box_line_hwidth;
  1677     }
  1678 
  1679   y = s->y;
  1680   if (s->slice.y == 0)
  1681     y += box_line_vwidth;
  1682 
  1683   view = FRAME_HAIKU_DRAWABLE (s->f);
  1684   bitmap = s->img->pixmap;
  1685 
  1686   s->stippled_p = face->stipple != 0;
  1687 
  1688   if (s->hl == DRAW_CURSOR)
  1689     haiku_merge_cursor_foreground (s, NULL, &background);
  1690   else
  1691     background = face->background;
  1692 
  1693   haiku_draw_background_rect (s, face, x, y,
  1694                               width, height);
  1695 
  1696   if (bitmap)
  1697     {
  1698       get_glyph_string_clip_rect (s, &nr);
  1699       CONVERT_TO_EMACS_RECT (cr, nr);
  1700       x = s->x;
  1701       y = s->ybase - image_ascent (s->img, face, &s->slice);
  1702 
  1703       if (s->slice.x == 0)
  1704         x += s->img->hmargin;
  1705       if (s->slice.y == 0)
  1706         y += s->img->vmargin;
  1707 
  1708       if (face->box != FACE_NO_BOX
  1709           && s->first_glyph->left_box_line_p
  1710           && s->slice.x == 0)
  1711         x += max (face->box_vertical_line_width, 0);
  1712 
  1713       ir.x = x;
  1714       ir.y = y;
  1715       ir.width = s->slice.width;
  1716       ir.height = s->slice.height;
  1717       r = ir;
  1718 
  1719       mask = s->img->mask;
  1720 
  1721       if (gui_intersect_rectangles (&cr, &ir, &r))
  1722         {
  1723           memcpy (&image_transform, &s->img->transform,
  1724                   sizeof image_transform);
  1725 
  1726           if (s->slice.x != x || s->slice.y != y
  1727               || s->slice.width != s->img->width
  1728               || s->slice.height != s->img->height)
  1729             {
  1730               BView_StartClip (view);
  1731               BView_ClipToRect (view, r.x, r.y, r.width, r.height);
  1732             }
  1733 
  1734           haiku_translate_transform (image_transform,
  1735                                      x - s->slice.x,
  1736                                      y - s->slice.y);
  1737 
  1738           be_apply_affine_transform (view,
  1739                                      image_transform[0][0],
  1740                                      image_transform[0][1],
  1741                                      image_transform[0][2],
  1742                                      image_transform[1][0],
  1743                                      image_transform[1][1],
  1744                                      image_transform[1][2]);
  1745 
  1746           if (!s->stippled_p || !mask)
  1747             {
  1748               BView_DrawBitmap (view, bitmap, 0, 0,
  1749                                 s->img->original_width,
  1750                                 s->img->original_height,
  1751                                 0, 0,
  1752                                 s->img->original_width,
  1753                                 s->img->original_height,
  1754                                 s->img->use_bilinear_filtering);
  1755 
  1756               if (mask)
  1757                 be_draw_image_mask (mask, view, 0, 0,
  1758                                     s->img->original_width,
  1759                                     s->img->original_height,
  1760                                     0, 0,
  1761                                     s->img->original_width,
  1762                                     s->img->original_height,
  1763                                     background);
  1764             }
  1765           else
  1766             /* In order to make sure the stipple background remains
  1767                visible, use the mask for the alpha channel of BITMAP
  1768                and composite it onto the view instead.  */
  1769             be_draw_bitmap_with_mask (view, bitmap, mask, 0, 0,
  1770                                       s->img->original_width,
  1771                                       s->img->original_height,
  1772                                       0, 0,
  1773                                       s->img->original_width,
  1774                                       s->img->original_height,
  1775                                       s->img->use_bilinear_filtering);
  1776 
  1777           if (s->slice.x != x || s->slice.y != y
  1778               || s->slice.width != s->img->width
  1779               || s->slice.height != s->img->height)
  1780             BView_EndClip (view);
  1781 
  1782           be_apply_affine_transform (view, 1, 0, 0, 0, 1, 0);
  1783         }
  1784 
  1785       if (!s->img->mask)
  1786         {
  1787           /* When the image has a mask, we can expect that at
  1788              least part of a mouse highlight or a block cursor will
  1789              be visible.  If the image doesn't have a mask, make
  1790              a block cursor visible by drawing a rectangle around
  1791              the image.  I believe it's looking better if we do
  1792              nothing here for mouse-face.  */
  1793 
  1794           if (s->hl == DRAW_CURSOR)
  1795             {
  1796               relief = eabs (s->img->relief);
  1797 
  1798               BView_SetPenSize (view, 1);
  1799               BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
  1800               BView_StrokeRectangle (view, x - relief, y - relief,
  1801                                      s->slice.width + relief * 2,
  1802                                      s->slice.height + relief * 2);
  1803             }
  1804         }
  1805     }
  1806 
  1807   if (s->img->relief
  1808       || s->hl == DRAW_IMAGE_RAISED
  1809       || s->hl == DRAW_IMAGE_SUNKEN)
  1810     haiku_draw_image_relief (s);
  1811 }
  1812 
  1813 static void
  1814 haiku_draw_glyph_string (struct glyph_string *s)
  1815 {
  1816   void *view = FRAME_HAIKU_DRAWABLE (s->f);;
  1817   struct face *face = s->face;
  1818 
  1819   block_input ();
  1820   BView_draw_lock (view, false, 0, 0, 0, 0);
  1821   prepare_face_for_display (s->f, s->face);
  1822 
  1823   s->stippled_p = s->hl != DRAW_CURSOR && face->stipple;
  1824 
  1825   if (s->next && s->right_overhang && !s->for_overlaps)
  1826     {
  1827       int width;
  1828       struct glyph_string *next;
  1829 
  1830       for (width = 0, next = s->next;
  1831            next && width < s->right_overhang;
  1832            width += next->width, next = next->next)
  1833         if (next->first_glyph->type != IMAGE_GLYPH)
  1834           {
  1835             prepare_face_for_display (s->f, next->face);
  1836             next->stippled_p
  1837               = next->hl != DRAW_CURSOR && next->face->stipple;
  1838 
  1839             haiku_start_clip (next);
  1840             haiku_clip_to_string (next);
  1841             if (next->first_glyph->type != STRETCH_GLYPH)
  1842               haiku_maybe_draw_background (next, true);
  1843             else
  1844               haiku_draw_stretch_glyph_string (next);
  1845             haiku_end_clip (s);
  1846           }
  1847     }
  1848 
  1849   haiku_start_clip (s);
  1850 
  1851   int box_filled_p = 0;
  1852 
  1853   if (!s->for_overlaps && face->box != FACE_NO_BOX
  1854       && (s->first_glyph->type == CHAR_GLYPH
  1855           || s->first_glyph->type == COMPOSITE_GLYPH))
  1856     {
  1857       haiku_clip_to_string (s);
  1858       haiku_maybe_draw_background (s, 1);
  1859       box_filled_p = 1;
  1860       haiku_draw_string_box (s);
  1861     }
  1862   else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
  1863            && !s->clip_tail
  1864            && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
  1865                || (s->next && s->next->hl != s->hl && s->right_overhang)))
  1866     /* We must clip just this glyph.  left_overhang part has already
  1867        drawn when s->prev was drawn, and right_overhang part will be
  1868        drawn later when s->next is drawn. */
  1869     haiku_clip_to_string_exactly (s, s);
  1870   else
  1871     haiku_clip_to_string (s);
  1872 
  1873   if (s->for_overlaps)
  1874     s->background_filled_p = 1;
  1875 
  1876   switch (s->first_glyph->type)
  1877     {
  1878     case COMPOSITE_GLYPH:
  1879       if (s->for_overlaps || (s->cmp_from > 0
  1880                               && ! s->first_glyph->u.cmp.automatic))
  1881         s->background_filled_p = 1;
  1882       else
  1883         haiku_maybe_draw_background (s, 1);
  1884       haiku_draw_composite_glyph_string_foreground (s);
  1885       break;
  1886     case CHAR_GLYPH:
  1887       if (s->for_overlaps)
  1888         s->background_filled_p = 1;
  1889       else
  1890         haiku_maybe_draw_background (s, 0);
  1891       haiku_draw_glyph_string_foreground (s);
  1892       break;
  1893     case STRETCH_GLYPH:
  1894       haiku_draw_stretch_glyph_string (s);
  1895       break;
  1896     case IMAGE_GLYPH:
  1897       haiku_draw_image_glyph_string (s);
  1898       break;
  1899     case GLYPHLESS_GLYPH:
  1900       if (s->for_overlaps)
  1901         s->background_filled_p = 1;
  1902       else
  1903         haiku_maybe_draw_background (s, 1);
  1904       haiku_draw_glyphless_glyph_string_foreground (s);
  1905       break;
  1906     default:
  1907       emacs_abort ();
  1908     }
  1909 
  1910   if (!s->for_overlaps)
  1911     {
  1912       if (!box_filled_p && face->box != FACE_NO_BOX)
  1913         haiku_draw_string_box (s);
  1914       else
  1915         haiku_draw_text_decoration (s, face, s->width, s->x);
  1916 
  1917       if (s->prev)
  1918         {
  1919           struct glyph_string *prev;
  1920 
  1921           for (prev = s->prev; prev; prev = prev->prev)
  1922             if (prev->hl != s->hl
  1923                 && prev->x + prev->width + prev->right_overhang > s->x)
  1924               {
  1925                 /* As prev was drawn while clipped to its own area, we
  1926                    must draw the right_overhang part using s->hl now.  */
  1927                 enum draw_glyphs_face save = prev->hl;
  1928 
  1929                 prev->hl = s->hl;
  1930                 haiku_start_clip (s);
  1931                 haiku_clip_to_string (s);
  1932                 haiku_clip_to_string_exactly (s, prev);
  1933                 if (prev->first_glyph->type == CHAR_GLYPH)
  1934                   haiku_draw_glyph_string_foreground (prev);
  1935                 else
  1936                   haiku_draw_composite_glyph_string_foreground (prev);
  1937                 haiku_end_clip (s);
  1938                 prev->hl = save;
  1939               }
  1940         }
  1941 
  1942       if (s->next)
  1943         {
  1944           struct glyph_string *next;
  1945 
  1946           for (next = s->next; next; next = next->next)
  1947             if (next->hl != s->hl
  1948                 && next->x - next->left_overhang < s->x + s->width)
  1949               {
  1950                 /* As next will be drawn while clipped to its own area,
  1951                    we must draw the left_overhang part using s->hl now.  */
  1952                 enum draw_glyphs_face save = next->hl;
  1953 
  1954                 next->hl = s->hl;
  1955                 haiku_start_clip (s);
  1956                 haiku_clip_to_string (s);
  1957                 haiku_clip_to_string_exactly (s, next);
  1958                 if (next->first_glyph->type == CHAR_GLYPH)
  1959                   haiku_draw_glyph_string_foreground (next);
  1960                 else
  1961                   haiku_draw_composite_glyph_string_foreground (next);
  1962                 haiku_end_clip (s);
  1963 
  1964                 next->hl = save;
  1965                 next->clip_head = s->next;
  1966               }
  1967         }
  1968     }
  1969 
  1970   haiku_end_clip (s);
  1971   BView_draw_unlock (view);
  1972 
  1973   /* Set the stipple_p flag indicating whether or not a stipple was
  1974      drawn in s->row.  That is the case either when s is a stretch
  1975      glyph string and s->face->stipple is not NULL, or when
  1976      s->face->stipple exists and s->hl is not DRAW_CURSOR.  */
  1977   if (s->face->stipple
  1978       && (s->first_glyph->type == STRETCH_GLYPH
  1979           || s->hl != DRAW_CURSOR))
  1980     s->row->stipple_p = true;
  1981 
  1982   unblock_input ();
  1983 }
  1984 
  1985 static void
  1986 haiku_after_update_window_line (struct window *w,
  1987                                 struct glyph_row *desired_row)
  1988 {
  1989   eassert (w);
  1990   struct frame *f;
  1991   int width, height;
  1992 
  1993   if (!desired_row->mode_line_p && !w->pseudo_window_p)
  1994     desired_row->redraw_fringe_bitmaps_p = true;
  1995 
  1996   if (windows_or_buffers_changed
  1997       && desired_row->full_width_p
  1998       && (f = XFRAME (w->frame),
  1999           width = FRAME_INTERNAL_BORDER_WIDTH (f),
  2000           width != 0)
  2001       && (height = desired_row->visible_height,
  2002           height > 0))
  2003     {
  2004       int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
  2005       int face_id =
  2006         !NILP (Vface_remapping_alist)
  2007         ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
  2008         : INTERNAL_BORDER_FACE_ID;
  2009       struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
  2010 
  2011       block_input ();
  2012       if (face)
  2013         {
  2014           void *view = FRAME_HAIKU_DRAWABLE (f);
  2015           BView_draw_lock (view, false, 0, 0, 0, 0);
  2016           BView_StartClip (view);
  2017           BView_SetHighColor (view, (face->background_defaulted_p
  2018                                      ? FRAME_BACKGROUND_PIXEL (f)
  2019                                      : face->background));
  2020           BView_FillRectangle (view, 0, y, width, height);
  2021           BView_FillRectangle (view, FRAME_PIXEL_WIDTH (f) - width,
  2022                                y, width, height);
  2023           BView_invalidate_region (FRAME_HAIKU_DRAWABLE (f),
  2024                                    0, y, width, height);
  2025           BView_invalidate_region (view, FRAME_PIXEL_WIDTH (f) - width,
  2026                                    y, width, height);
  2027           BView_EndClip (view);
  2028           BView_draw_unlock (view);
  2029         }
  2030       else
  2031         {
  2032           haiku_clear_frame_area (f, 0, y, width, height);
  2033           haiku_clear_frame_area (f, FRAME_PIXEL_WIDTH (f) - width,
  2034                                   y, width, height);
  2035         }
  2036       unblock_input ();
  2037     }
  2038 }
  2039 
  2040 static void
  2041 haiku_set_window_size (struct frame *f, bool change_gravity,
  2042                        int width, int height)
  2043 {
  2044   Lisp_Object frame;
  2045 
  2046   /* On X Windows, window managers typically disallow resizing a
  2047      window when it is fullscreen.  Do the same here.  */
  2048 
  2049   XSETFRAME (frame, f);
  2050   if (!NILP (Fframe_parameter (frame, Qfullscreen))
  2051       /* Only do this if the fullscreen status has actually been
  2052          applied.  */
  2053       && f->want_fullscreen == FULLSCREEN_NONE
  2054       /* And if the configury during frame creation has been
  2055          completed.  Otherwise, there will be no valid "old size" to
  2056          go back to.  */
  2057       && FRAME_OUTPUT_DATA (f)->configury_done)
  2058     return;
  2059 
  2060   haiku_update_size_hints (f);
  2061 
  2062   if (FRAME_HAIKU_WINDOW (f))
  2063     {
  2064       block_input ();
  2065       BWindow_resize (FRAME_HAIKU_WINDOW (f),
  2066                       width, height);
  2067 
  2068       if (FRAME_VISIBLE_P (f)
  2069           && (width != FRAME_PIXEL_WIDTH (f)
  2070               || height != FRAME_PIXEL_HEIGHT (f)))
  2071         haiku_wait_for_event (f, FRAME_RESIZED);
  2072       unblock_input ();
  2073     }
  2074 
  2075   do_pending_window_change (false);
  2076 }
  2077 
  2078 static void
  2079 haiku_draw_hollow_cursor (struct window *w, struct glyph_row *row)
  2080 {
  2081   struct frame *f;
  2082   int x, y, wd, h;
  2083   struct glyph *cursor_glyph;
  2084   uint32_t foreground;
  2085   void *view;
  2086 
  2087   f = XFRAME (WINDOW_FRAME (w));
  2088   view = FRAME_HAIKU_DRAWABLE (f);
  2089 
  2090   /* Get the glyph the cursor is on.  If we can't tell because
  2091      the current matrix is invalid or such, give up.  */
  2092   cursor_glyph = get_phys_cursor_glyph (w);
  2093   if (cursor_glyph == NULL)
  2094     return;
  2095 
  2096   /* Compute frame-relative coordinates for phys cursor.  */
  2097   get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
  2098   wd = w->phys_cursor_width;
  2099 
  2100   /* The foreground of cursor_gc is typically the same as the normal
  2101      background color, which can cause the cursor box to be invisible.  */
  2102   foreground = FRAME_CURSOR_COLOR (f).pixel;
  2103 
  2104   /* When on R2L character, show cursor at the right edge of the
  2105      glyph, unless the cursor box is as wide as the glyph or wider
  2106      (the latter happens when x-stretch-cursor is non-nil).  */
  2107   if ((cursor_glyph->resolved_level & 1) != 0
  2108       && cursor_glyph->pixel_width > wd)
  2109     x += cursor_glyph->pixel_width - wd;
  2110 
  2111   /* Set clipping, draw the rectangle, and reset clipping again.
  2112      This also marks the region as invalidated.  */
  2113 
  2114   BView_draw_lock (view, true, x, y, wd, h);
  2115   BView_StartClip (view);
  2116   haiku_clip_to_row (w, row, TEXT_AREA);
  2117 
  2118   /* Now set the foreground color and pen size.  */
  2119   BView_SetHighColor (view, foreground);
  2120   BView_SetPenSize (view, 1);
  2121 
  2122   /* Actually draw the rectangle.  */
  2123   BView_StrokeRectangle (view, x, y, wd, h);
  2124 
  2125   /* Reset clipping.  */
  2126   BView_EndClip (view);
  2127   BView_draw_unlock (view);
  2128 }
  2129 
  2130 static void
  2131 haiku_draw_bar_cursor (struct window *w, struct glyph_row *row,
  2132                        int width, enum text_cursor_kinds kind)
  2133 {
  2134   struct frame *f;
  2135   struct glyph *cursor_glyph;
  2136   struct glyph_row *r;
  2137   struct face *face;
  2138   uint32_t foreground;
  2139   void *view;
  2140   int x, y, dummy_x, dummy_y, dummy_h;
  2141 
  2142   f = XFRAME (w->frame);
  2143 
  2144   /* If cursor is out of bounds, don't draw garbage.  This can happen
  2145      in mini-buffer windows when switching between echo area glyphs
  2146      and mini-buffer.  */
  2147   cursor_glyph = get_phys_cursor_glyph (w);
  2148   if (cursor_glyph == NULL)
  2149     return;
  2150 
  2151   /* If on an image, draw like a normal cursor.  That's usually better
  2152      visible than drawing a bar, esp. if the image is large so that
  2153      the bar might not be in the window.  */
  2154   if (cursor_glyph->type == IMAGE_GLYPH)
  2155     {
  2156       r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
  2157       draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
  2158     }
  2159   else
  2160     {
  2161       view = FRAME_HAIKU_DRAWABLE (f);
  2162       face = FACE_FROM_ID (f, cursor_glyph->face_id);
  2163 
  2164       /* If the glyph's background equals the color we normally draw
  2165          the bars cursor in, the bar cursor in its normal color is
  2166          invisible.  Use the glyph's foreground color instead in this
  2167          case, on the assumption that the glyph's colors are chosen so
  2168          that the glyph is legible.  */
  2169       if (face->background == FRAME_CURSOR_COLOR (f).pixel)
  2170         foreground = face->foreground;
  2171       else
  2172         foreground = FRAME_CURSOR_COLOR (f).pixel;
  2173 
  2174       BView_draw_lock (view, false, 0, 0, 0, 0);
  2175       BView_StartClip (view);
  2176       BView_SetHighColor (view, foreground);
  2177       haiku_clip_to_row (w, row, TEXT_AREA);
  2178 
  2179       if (kind == BAR_CURSOR)
  2180         {
  2181           x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
  2182           y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
  2183 
  2184           if (width < 0)
  2185             width = FRAME_CURSOR_WIDTH (f);
  2186           width = min (cursor_glyph->pixel_width, width);
  2187 
  2188           w->phys_cursor_width = width;
  2189 
  2190           /* If the character under cursor is R2L, draw the bar cursor
  2191              on the right of its glyph, rather than on the left.  */
  2192           if ((cursor_glyph->resolved_level & 1) != 0)
  2193             x += cursor_glyph->pixel_width - width;
  2194 
  2195           BView_FillRectangle (view, x, y, width, row->height);
  2196           BView_invalidate_region (view, x, y, width, row->height);
  2197         }
  2198       else /* HBAR_CURSOR */
  2199         {
  2200           x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
  2201           y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
  2202                                            row->height - width);
  2203 
  2204           if (width < 0)
  2205             width = row->height;
  2206 
  2207           width = min (row->height, width);
  2208 
  2209           get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
  2210                                     &dummy_y, &dummy_h);
  2211 
  2212           if ((cursor_glyph->resolved_level & 1) != 0
  2213               && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
  2214             x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
  2215 
  2216           BView_FillRectangle (view, x, y, w->phys_cursor_width - 1,
  2217                                width);
  2218           BView_invalidate_region (view, x, y, w->phys_cursor_width - 1,
  2219                                    width);
  2220         }
  2221 
  2222       BView_EndClip (view);
  2223       BView_draw_unlock (view);
  2224     }
  2225 }
  2226 
  2227 static void
  2228 haiku_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
  2229                           int x, int y, enum text_cursor_kinds cursor_type,
  2230                           int cursor_width, bool on_p, bool active_p)
  2231 {
  2232   if (on_p)
  2233     {
  2234       w->phys_cursor_type = cursor_type;
  2235       w->phys_cursor_on_p = true;
  2236 
  2237       if (glyph_row->exact_window_width_line_p
  2238           && (glyph_row->reversed_p
  2239               ? (w->phys_cursor.hpos < 0)
  2240               : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
  2241         {
  2242           glyph_row->cursor_in_fringe_p = true;
  2243           draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
  2244         }
  2245       else
  2246         {
  2247           switch (cursor_type)
  2248             {
  2249             case HOLLOW_BOX_CURSOR:
  2250               haiku_draw_hollow_cursor (w, glyph_row);
  2251               break;
  2252 
  2253             case FILLED_BOX_CURSOR:
  2254               draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
  2255               break;
  2256 
  2257             case BAR_CURSOR:
  2258               haiku_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
  2259               break;
  2260 
  2261             case HBAR_CURSOR:
  2262               haiku_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
  2263               break;
  2264 
  2265             case NO_CURSOR:
  2266               w->phys_cursor_width = 0;
  2267               break;
  2268 
  2269             default:
  2270               emacs_abort ();
  2271             }
  2272         }
  2273     }
  2274 }
  2275 
  2276 static void
  2277 haiku_show_hourglass (struct frame *f)
  2278 {
  2279   if (FRAME_TOOLTIP_P (f)
  2280       || FRAME_OUTPUT_DATA (f)->hourglass_p)
  2281     return;
  2282 
  2283   block_input ();
  2284   FRAME_OUTPUT_DATA (f)->hourglass_p = 1;
  2285 
  2286   if (FRAME_HAIKU_VIEW (f))
  2287     BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
  2288                            FRAME_OUTPUT_DATA (f)->hourglass_cursor);
  2289   unblock_input ();
  2290 }
  2291 
  2292 static void
  2293 haiku_hide_hourglass (struct frame *f)
  2294 {
  2295   if (FRAME_TOOLTIP_P (f)
  2296       || !FRAME_OUTPUT_DATA (f)->hourglass_p)
  2297     return;
  2298 
  2299   block_input ();
  2300   FRAME_OUTPUT_DATA (f)->hourglass_p = 0;
  2301 
  2302   if (FRAME_HAIKU_VIEW (f))
  2303     BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
  2304                            FRAME_OUTPUT_DATA (f)->current_cursor);
  2305   unblock_input ();
  2306 }
  2307 
  2308 static void
  2309 haiku_compute_glyph_string_overhangs (struct glyph_string *s)
  2310 {
  2311   if (s->cmp == NULL
  2312       && (s->first_glyph->type == CHAR_GLYPH
  2313           || s->first_glyph->type == COMPOSITE_GLYPH))
  2314     {
  2315       struct font_metrics metrics;
  2316 
  2317       if (s->first_glyph->type == CHAR_GLYPH)
  2318         {
  2319           struct font *font = s->font;
  2320           font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
  2321         }
  2322       else
  2323         {
  2324           Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
  2325 
  2326           composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
  2327         }
  2328       s->right_overhang = (metrics.rbearing > metrics.width
  2329                            ? metrics.rbearing - metrics.width : 0);
  2330       s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
  2331     }
  2332   else if (s->cmp)
  2333     {
  2334       s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
  2335       s->left_overhang = - s->cmp->lbearing;
  2336     }
  2337 }
  2338 
  2339 static void
  2340 haiku_draw_vertical_window_border (struct window *w,
  2341                                    int x, int y_0, int y_1)
  2342 {
  2343   struct frame *f = XFRAME (WINDOW_FRAME (w));
  2344   struct face *face;
  2345 
  2346   face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
  2347   void *view = FRAME_HAIKU_DRAWABLE (f);
  2348   BView_draw_lock (view, true, x, y_0, 1, y_1);
  2349   BView_StartClip (view);
  2350   if (face)
  2351     BView_SetHighColor (view, face->foreground);
  2352   BView_StrokeLine (view, x, y_0, x, y_1);
  2353   BView_EndClip (view);
  2354   BView_draw_unlock (view);
  2355 }
  2356 
  2357 static void
  2358 haiku_set_scroll_bar_default_width (struct frame *f)
  2359 {
  2360   int unit, size;
  2361 
  2362   unit = FRAME_COLUMN_WIDTH (f);
  2363   size = BScrollBar_default_size (0) + 1;
  2364 
  2365   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = size;
  2366   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (size + unit - 1) / unit;
  2367 }
  2368 
  2369 static void
  2370 haiku_set_scroll_bar_default_height (struct frame *f)
  2371 {
  2372   int height, size;
  2373 
  2374   height = FRAME_LINE_HEIGHT (f);
  2375   size = BScrollBar_default_size (true) + 1;
  2376 
  2377   FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = size;
  2378   FRAME_CONFIG_SCROLL_BAR_LINES (f) = (size + height - 1) / height;
  2379 }
  2380 
  2381 static void
  2382 haiku_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
  2383 {
  2384   struct frame *f = XFRAME (WINDOW_FRAME (w));
  2385   struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
  2386   struct face *face_first
  2387     = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
  2388   struct face *face_last
  2389     = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
  2390   unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
  2391   unsigned long color_first = (face_first
  2392                                ? face_first->foreground
  2393                                : FRAME_FOREGROUND_PIXEL (f));
  2394   unsigned long color_last = (face_last
  2395                               ? face_last->foreground
  2396                               : FRAME_FOREGROUND_PIXEL (f));
  2397   void *view = FRAME_HAIKU_DRAWABLE (f);
  2398 
  2399   BView_draw_lock (view, true, x0, y0, x1 - x0 + 1, y1 - y0 + 1);
  2400   BView_StartClip (view);
  2401 
  2402   if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
  2403     /* A vertical divider, at least three pixels wide: Draw first and
  2404        last pixels differently.  */
  2405     {
  2406       BView_SetHighColor (view, color_first);
  2407       BView_StrokeLine (view, x0, y0, x0, y1 - 1);
  2408       BView_SetHighColor (view, color);
  2409       BView_FillRectangle (view, x0 + 1, y0, x1 - x0 - 2, y1 - y0);
  2410       BView_SetHighColor (view, color_last);
  2411       BView_StrokeLine (view, x1 - 1, y0, x1 - 1, y1 - 1);
  2412     }
  2413   else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
  2414     /* A horizontal divider, at least three pixels high: Draw first and
  2415        last pixels differently.  */
  2416     {
  2417       BView_SetHighColor (view, color_first);
  2418       BView_StrokeLine (view, x0, y0, x1 - 1, y0);
  2419       BView_SetHighColor (view, color);
  2420       BView_FillRectangle (view, x0, y0 + 1, x1 - x0, y1 - y0 - 2);
  2421       BView_SetHighColor (view, color_last);
  2422       BView_FillRectangle (view, x0, y1 - 1, x1 - x0, 1);
  2423     }
  2424   else
  2425     {
  2426       BView_SetHighColor (view, color);
  2427       BView_FillRectangleAbs (view, x0, y0, x1, y1);
  2428     }
  2429   BView_EndClip (view);
  2430   BView_draw_unlock (view);
  2431 }
  2432 
  2433 static void
  2434 haiku_condemn_scroll_bars (struct frame *frame)
  2435 {
  2436   if (!NILP (FRAME_SCROLL_BARS (frame)))
  2437     {
  2438       if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
  2439         {
  2440           /* Prepend scrollbars to already condemned ones.  */
  2441           Lisp_Object last = FRAME_SCROLL_BARS (frame);
  2442 
  2443           while (!NILP (XSCROLL_BAR (last)->next))
  2444             last = XSCROLL_BAR (last)->next;
  2445 
  2446           XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
  2447           XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
  2448         }
  2449 
  2450       fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
  2451       fset_scroll_bars (frame, Qnil);
  2452     }
  2453 }
  2454 
  2455 static void
  2456 haiku_redeem_scroll_bar (struct window *w)
  2457 {
  2458   struct scroll_bar *bar;
  2459   Lisp_Object barobj;
  2460   struct frame *f;
  2461 
  2462   if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
  2463     {
  2464       bar = XSCROLL_BAR (w->vertical_scroll_bar);
  2465       /* Unlink it from the condemned list.  */
  2466       f = XFRAME (WINDOW_FRAME (w));
  2467       if (NILP (bar->prev))
  2468         {
  2469           /* If the prev pointer is nil, it must be the first in one of
  2470              the lists.  */
  2471           if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
  2472             /* It's not condemned.  Everything's fine.  */
  2473             goto horizontal;
  2474           else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
  2475                        w->vertical_scroll_bar))
  2476             fset_condemned_scroll_bars (f, bar->next);
  2477           else
  2478             /* If its prev pointer is nil, it must be at the front of
  2479                one or the other!  */
  2480             emacs_abort ();
  2481         }
  2482       else
  2483         XSCROLL_BAR (bar->prev)->next = bar->next;
  2484 
  2485       if (! NILP (bar->next))
  2486         XSCROLL_BAR (bar->next)->prev = bar->prev;
  2487 
  2488       bar->next = FRAME_SCROLL_BARS (f);
  2489       bar->prev = Qnil;
  2490       XSETVECTOR (barobj, bar);
  2491       fset_scroll_bars (f, barobj);
  2492       if (! NILP (bar->next))
  2493         XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  2494     }
  2495  horizontal:
  2496   if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
  2497     {
  2498       bar = XSCROLL_BAR (w->horizontal_scroll_bar);
  2499       /* Unlink it from the condemned list.  */
  2500       f = XFRAME (WINDOW_FRAME (w));
  2501       if (NILP (bar->prev))
  2502         {
  2503           /* If the prev pointer is nil, it must be the first in one of
  2504              the lists.  */
  2505           if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
  2506             /* It's not condemned.  Everything's fine.  */
  2507             return;
  2508           else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
  2509                        w->horizontal_scroll_bar))
  2510             fset_condemned_scroll_bars (f, bar->next);
  2511           else
  2512             /* If its prev pointer is nil, it must be at the front of
  2513                one or the other!  */
  2514             emacs_abort ();
  2515         }
  2516       else
  2517         XSCROLL_BAR (bar->prev)->next = bar->next;
  2518 
  2519       if (! NILP (bar->next))
  2520         XSCROLL_BAR (bar->next)->prev = bar->prev;
  2521 
  2522       bar->next = FRAME_SCROLL_BARS (f);
  2523       bar->prev = Qnil;
  2524       XSETVECTOR (barobj, bar);
  2525       fset_scroll_bars (f, barobj);
  2526       if (! NILP (bar->next))
  2527         XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  2528     }
  2529 }
  2530 
  2531 static void
  2532 haiku_judge_scroll_bars (struct frame *f)
  2533 {
  2534   Lisp_Object bar, next;
  2535 
  2536   bar = FRAME_CONDEMNED_SCROLL_BARS (f);
  2537 
  2538   /* Clear out the condemned list now so we won't try to process any
  2539      more events on the hapless scroll bars.  */
  2540   fset_condemned_scroll_bars (f, Qnil);
  2541 
  2542   for (; ! NILP (bar); bar = next)
  2543     {
  2544       struct scroll_bar *b = XSCROLL_BAR (bar);
  2545 
  2546       haiku_scroll_bar_remove (b);
  2547 
  2548       next = b->next;
  2549       b->next = b->prev = Qnil;
  2550     }
  2551 
  2552   /* Now there should be no references to the condemned scroll bars,
  2553      and they should get garbage-collected.  */
  2554 }
  2555 
  2556 static struct scroll_bar *
  2557 haiku_scroll_bar_create (struct window *w, int left, int top,
  2558                          int width, int height, bool horizontal_p)
  2559 {
  2560   struct frame *f;
  2561   Lisp_Object barobj;
  2562   struct scroll_bar *bar;
  2563   void *scroll_bar;
  2564   void *view;
  2565 
  2566   f = XFRAME (WINDOW_FRAME (w));
  2567   view = FRAME_HAIKU_DRAWABLE (f);
  2568 
  2569   block_input ();
  2570   bar = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER);
  2571 
  2572   XSETWINDOW (bar->window, w);
  2573   bar->top = top;
  2574   bar->left = left;
  2575   bar->width = width;
  2576   bar->height = height;
  2577   bar->position = 0;
  2578   bar->total = 0;
  2579   bar->dragging = 0;
  2580   bar->update = -1;
  2581   bar->horizontal = horizontal_p;
  2582 
  2583   scroll_bar = be_make_scroll_bar_for_view (view, horizontal_p,
  2584                                             left, top, left + width - 1,
  2585                                             top + height - 1);
  2586   BView_publish_scroll_bar (view, left, top, width, height);
  2587 
  2588   bar->next = FRAME_SCROLL_BARS (f);
  2589   bar->prev = Qnil;
  2590   bar->scroll_bar = scroll_bar;
  2591   XSETVECTOR (barobj, bar);
  2592   fset_scroll_bars (f, barobj);
  2593 
  2594   if (!NILP (bar->next))
  2595     XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  2596 
  2597   unblock_input ();
  2598   return bar;
  2599 }
  2600 
  2601 static void
  2602 haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
  2603 {
  2604   Lisp_Object barobj;
  2605   struct scroll_bar *bar;
  2606   int top, height, left, width;
  2607   int window_x, window_width;
  2608   void *view;
  2609 
  2610   eassert (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w));
  2611   /* Get window dimensions.  */
  2612   window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
  2613   left = window_x;
  2614   width = window_width;
  2615   top = WINDOW_SCROLL_BAR_AREA_Y (w);
  2616   height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
  2617   view = FRAME_HAIKU_DRAWABLE (WINDOW_XFRAME (w));
  2618 
  2619   block_input ();
  2620 
  2621   if (NILP (w->horizontal_scroll_bar))
  2622     {
  2623       bar = haiku_scroll_bar_create (w, left, top, width, height, true);
  2624       bar->update = position;
  2625       bar->position = position;
  2626       bar->total = whole;
  2627     }
  2628   else
  2629     {
  2630       bar = XSCROLL_BAR (w->horizontal_scroll_bar);
  2631 
  2632       if (bar->left != left || bar->top != top
  2633           || bar->width != width || bar->height != height)
  2634         {
  2635           BView_forget_scroll_bar (view, bar->left, bar->top,
  2636                                    bar->width, bar->height);
  2637           BView_move_frame (bar->scroll_bar, left, top,
  2638                             left + width - 1, top + height - 1);
  2639           BView_publish_scroll_bar (view, left, top, width, height);
  2640 
  2641           bar->left = left;
  2642           bar->top = top;
  2643           bar->width = width;
  2644           bar->height = height;
  2645         }
  2646     }
  2647 
  2648   haiku_set_horizontal_scroll_bar_thumb (bar, portion, position, whole);
  2649   bar->position = position;
  2650   bar->total = whole;
  2651   XSETVECTOR (barobj, bar);
  2652   wset_horizontal_scroll_bar (w, barobj);
  2653   unblock_input ();
  2654 }
  2655 
  2656 static void
  2657 haiku_set_vertical_scroll_bar (struct window *w, int portion, int whole, int position)
  2658 {
  2659   Lisp_Object barobj;
  2660   struct scroll_bar *bar;
  2661   int top, height, left, width;
  2662   int window_y, window_height;
  2663   void *view;
  2664 
  2665   eassert (WINDOW_HAS_VERTICAL_SCROLL_BAR (w));
  2666 
  2667   /* Get window dimensions.  */
  2668   window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
  2669   top = window_y;
  2670   height = window_height;
  2671 
  2672   /* Compute the left edge and the width of the scroll bar area.  */
  2673   left = WINDOW_SCROLL_BAR_AREA_X (w);
  2674   width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
  2675 
  2676   view = FRAME_HAIKU_DRAWABLE (WINDOW_XFRAME (w));
  2677 
  2678   block_input ();
  2679   if (NILP (w->vertical_scroll_bar))
  2680     {
  2681       bar = haiku_scroll_bar_create (w, left, top, width, height, false);
  2682       bar->position = position;
  2683       bar->total = whole;
  2684     }
  2685   else
  2686     {
  2687       bar = XSCROLL_BAR (w->vertical_scroll_bar);
  2688 
  2689       if (bar->left != left || bar->top != top
  2690           || bar->width != width || bar->height != height)
  2691         {
  2692           BView_forget_scroll_bar (view, bar->left, bar->top,
  2693                                    bar->width, bar->height);
  2694           BView_move_frame (bar->scroll_bar, left, top,
  2695                             left + width - 1, top + height - 1);
  2696           BView_publish_scroll_bar (view, left, top, width, height);
  2697 
  2698           bar->left = left;
  2699           bar->top = top;
  2700           bar->width = width;
  2701           bar->height = height;
  2702         }
  2703     }
  2704 
  2705   haiku_set_scroll_bar_thumb (bar, portion, position, whole);
  2706   bar->position = position;
  2707   bar->total = whole;
  2708 
  2709   XSETVECTOR (barobj, bar);
  2710   wset_vertical_scroll_bar (w, barobj);
  2711   unblock_input ();
  2712 }
  2713 
  2714 static void
  2715 haiku_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
  2716                           struct draw_fringe_bitmap_params *p)
  2717 {
  2718   struct face *face;
  2719   struct frame *f;
  2720   struct haiku_bitmap_record *rec;
  2721   void *view, *bitmap;
  2722   uint32 col;
  2723 
  2724   f = XFRAME (WINDOW_FRAME (w));
  2725   view = FRAME_HAIKU_DRAWABLE (f);
  2726   face = p->face;
  2727 
  2728   block_input ();
  2729   BView_draw_lock (view, true, 0, 0, 0, 0);
  2730   BView_StartClip (view);
  2731 
  2732   if (p->wd && p->h)
  2733     BView_invalidate_region (view, p->x, p->y, p->wd, p->h);
  2734 
  2735   haiku_clip_to_row (w, row, ANY_AREA);
  2736 
  2737   if (p->bx >= 0 && !p->overlay_p)
  2738     {
  2739       BView_invalidate_region (view, p->bx, p->by, p->nx, p->ny);
  2740 
  2741       if (!face->stipple)
  2742         {
  2743           BView_SetHighColor (view, face->background);
  2744           BView_FillRectangle (view, p->bx, p->by, p->nx, p->ny);
  2745         }
  2746       else
  2747         {
  2748           rec = haiku_get_bitmap_rec (f, face->stipple);
  2749           haiku_update_bitmap_rec (rec, face->foreground,
  2750                                    face->background);
  2751 
  2752           BView_StartClip (view);
  2753           haiku_clip_to_row (w, row, ANY_AREA);
  2754           BView_ClipToRect (view, p->bx, p->by, p->nx, p->ny);
  2755           BView_DrawBitmapTiled (view, rec->img, 0, 0, -1, -1,
  2756                                  0, 0, FRAME_PIXEL_WIDTH (f),
  2757                                  FRAME_PIXEL_HEIGHT (f));
  2758           BView_EndClip (view);
  2759 
  2760           row->stipple_p = true;
  2761         }
  2762     }
  2763 
  2764   if (p->which
  2765       && p->which < max_fringe_bmp
  2766       && p->which < max_used_fringe_bitmap)
  2767     {
  2768       bitmap = fringe_bmps[p->which];
  2769 
  2770       if (!bitmap)
  2771         {
  2772           /* This fringe bitmap is known to fringe.c, but lacks the
  2773              BBitmap which shadows that bitmap.  This is typical to
  2774              define-fringe-bitmap being called when the selected frame
  2775              was not a GUI frame, for example, when packages that
  2776              define fringe bitmaps are loaded by a daemon Emacs.
  2777              Create the missing pattern now.  */
  2778           gui_define_fringe_bitmap (WINDOW_XFRAME (w), p->which);
  2779           bitmap = fringe_bmps[p->which];
  2780         }
  2781 
  2782       if (!p->cursor_p)
  2783         col = face->foreground;
  2784       else if (p->overlay_p)
  2785         col = face->background;
  2786       else
  2787         col = FRAME_CURSOR_COLOR (XFRAME (WINDOW_FRAME (w))).pixel;
  2788 
  2789       if (!p->overlay_p)
  2790         {
  2791           BView_SetHighColor (view, face->background);
  2792           BView_FillRectangle (view, p->x, p->y, p->wd, p->h);
  2793         }
  2794 
  2795       BView_SetLowColor (view, col);
  2796       BView_DrawBitmapWithEraseOp (view, bitmap, p->x, p->y, p->wd, p->h);
  2797     }
  2798   BView_EndClip (view);
  2799   BView_draw_unlock (view);
  2800   unblock_input ();
  2801 }
  2802 
  2803 static void
  2804 haiku_define_fringe_bitmap (int which, unsigned short *bits,
  2805                             int h, int wd)
  2806 {
  2807   if (which >= max_fringe_bmp)
  2808     {
  2809       int i = max_fringe_bmp;
  2810       max_fringe_bmp = which + 20;
  2811       fringe_bmps = !i ? xmalloc (max_fringe_bmp * sizeof (void *)) :
  2812         xrealloc (fringe_bmps, max_fringe_bmp * sizeof (void *));
  2813 
  2814       while (i < max_fringe_bmp)
  2815         fringe_bmps[i++] = NULL;
  2816     }
  2817 
  2818   block_input ();
  2819   fringe_bmps[which] = BBitmap_new (wd, h, 1);
  2820   if (!fringe_bmps[which])
  2821     memory_full (SIZE_MAX);
  2822   BBitmap_import_fringe_bitmap (fringe_bmps[which], bits, wd, h);
  2823   unblock_input ();
  2824 }
  2825 
  2826 static void
  2827 haiku_destroy_fringe_bitmap (int which)
  2828 {
  2829   if (which >= max_fringe_bmp)
  2830     return;
  2831 
  2832   if (fringe_bmps[which])
  2833     BBitmap_free (fringe_bmps[which]);
  2834   fringe_bmps[which] = NULL;
  2835 }
  2836 
  2837 static void
  2838 haiku_scroll_run (struct window *w, struct run *run)
  2839 {
  2840   struct frame *f = XFRAME (w->frame);
  2841   void *view = FRAME_HAIKU_DRAWABLE (f);
  2842   int x, y, width, height, from_y, to_y, bottom_y;
  2843   window_box (w, ANY_AREA, &x, &y, &width, &height);
  2844 
  2845   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
  2846   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
  2847   bottom_y = y + height;
  2848 
  2849   if (to_y < from_y)
  2850     {
  2851       /* Scrolling up.  Make sure we don't copy part of the mode
  2852          line at the bottom.  */
  2853       if (from_y + run->height > bottom_y)
  2854         height = bottom_y - from_y;
  2855       else
  2856         height = run->height;
  2857     }
  2858   else
  2859     {
  2860       /* Scrolling down.  Make sure we don't copy over the mode line.
  2861          at the bottom.  */
  2862       if (to_y + run->height > bottom_y)
  2863         height = bottom_y - to_y;
  2864       else
  2865         height = run->height;
  2866     }
  2867 
  2868   block_input ();
  2869   gui_clear_cursor (w);
  2870 
  2871   BView_draw_lock (view, true, x, to_y, width, height);
  2872   BView_StartClip (view);
  2873   BView_CopyBits (view, x, from_y, width, height,
  2874                   x, to_y, width, height);
  2875   BView_EndClip (view);
  2876   BView_draw_unlock (view);
  2877 
  2878   unblock_input ();
  2879 }
  2880 
  2881 /* Haiku doesn't provide any way to get the frame actually underneath
  2882    the pointer, so we typically return dpyinfo->last_mouse_frame if
  2883    the display is grabbed and `track-mouse' is not `dropping' or
  2884    `drag-source'; failing that, we return the selected frame, and
  2885    finally a random window system frame (as long as `track-mouse' is
  2886    not `drag-source') if that didn't work either.  */
  2887 static void
  2888 haiku_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
  2889                       enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
  2890                       Time *timestamp)
  2891 {
  2892   Lisp_Object frame, tail;
  2893   struct frame *f1;
  2894   int screen_x, screen_y;
  2895   void *view;
  2896 
  2897   if (!fp)
  2898     return;
  2899 
  2900   f1 = NULL;
  2901   block_input ();
  2902 
  2903   FOR_EACH_FRAME (tail, frame)
  2904     {
  2905       if (FRAME_HAIKU_P (XFRAME (frame)))
  2906         XFRAME (frame)->mouse_moved = false;
  2907     }
  2908 
  2909   if (gui_mouse_grabbed (x_display_list)
  2910       && !EQ (track_mouse, Qdropping)
  2911       && !EQ (track_mouse, Qdrag_source))
  2912     f1 = x_display_list->last_mouse_frame;
  2913   else
  2914     f1 = x_display_list->last_mouse_motion_frame;
  2915 
  2916   if (!f1 && FRAME_HAIKU_P (SELECTED_FRAME ()))
  2917     f1 = SELECTED_FRAME ();
  2918 
  2919   if (!f1 || (!FRAME_HAIKU_P (f1) && (insist > 0)))
  2920     FOR_EACH_FRAME (tail, frame)
  2921       if (FRAME_HAIKU_P (XFRAME (frame)) &&
  2922           !FRAME_TOOLTIP_P (XFRAME (frame)))
  2923         f1 = XFRAME (frame);
  2924 
  2925   if (f1 && FRAME_TOOLTIP_P (f1))
  2926     f1 = NULL;
  2927 
  2928   if (f1 && FRAME_HAIKU_P (f1))
  2929     {
  2930       view = FRAME_HAIKU_VIEW (f1);
  2931 
  2932       if (view)
  2933         {
  2934           BView_get_mouse (view, &screen_x, &screen_y);
  2935           remember_mouse_glyph (f1, screen_x, screen_y,
  2936                                 &x_display_list->last_mouse_glyph);
  2937           x_display_list->last_mouse_glyph_frame = f1;
  2938 
  2939           *bar_window = Qnil;
  2940           *part = scroll_bar_nowhere;
  2941 
  2942           /* If track-mouse is `drag-source' and the mouse pointer is
  2943              certain to not be actually under the chosen frame, return
  2944              NULL in FP to at least try being consistent with X.  */
  2945           if (EQ (track_mouse, Qdrag_source)
  2946               && (screen_x < 0 || screen_y < 0
  2947                   || screen_x >= FRAME_PIXEL_WIDTH (f1)
  2948                   || screen_y >= FRAME_PIXEL_HEIGHT (f1)))
  2949             *fp = NULL;
  2950           else
  2951             *fp = f1;
  2952 
  2953           *timestamp = x_display_list->last_mouse_movement_time;
  2954           XSETINT (*x, screen_x);
  2955           XSETINT (*y, screen_y);
  2956         }
  2957     }
  2958 
  2959   unblock_input ();
  2960 }
  2961 
  2962 static void
  2963 haiku_flush (struct frame *f)
  2964 {
  2965   /* This is needed for tooltip frames to work properly with double
  2966      buffering.  */
  2967   if (FRAME_DIRTY_P (f) && !buffer_flipping_blocked_p ())
  2968     haiku_flip_buffers (f);
  2969 
  2970   /* The frame is complete again as its contents were just
  2971      flushed.  */
  2972   FRAME_COMPLETE_P (f) = true;
  2973 
  2974   if (FRAME_VISIBLE_P (f) && !FRAME_TOOLTIP_P (f))
  2975     BWindow_Flush (FRAME_HAIKU_WINDOW (f));
  2976 }
  2977 
  2978 static void
  2979 haiku_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
  2980 {
  2981   if (FRAME_TOOLTIP_P (f))
  2982     return;
  2983 
  2984   block_input ();
  2985   if (!f->pointer_invisible && FRAME_HAIKU_VIEW (f)
  2986       && !FRAME_OUTPUT_DATA (f)->hourglass_p)
  2987     BView_set_view_cursor (FRAME_HAIKU_VIEW (f), cursor);
  2988   unblock_input ();
  2989   FRAME_OUTPUT_DATA (f)->current_cursor = cursor;
  2990 }
  2991 
  2992 static void
  2993 haiku_default_font_parameter (struct frame *f, Lisp_Object parms)
  2994 {
  2995   struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
  2996   Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
  2997                                                 RES_TYPE_STRING);
  2998   Lisp_Object font = Qnil;
  2999   if (BASE_EQ (font_param, Qunbound))
  3000     font_param = Qnil;
  3001 
  3002   if (NILP (font_param))
  3003     /* System font should take precedence over X resources.  We
  3004        suggest this regardless of font-use-system-font because .emacs
  3005        may not have been read yet.  Returning a font-spec is Haiku
  3006        specific behavior.  */
  3007     font = font_open_by_spec (f, Ffont_get_system_font ());
  3008 
  3009   if (NILP (font))
  3010     font = (!NILP (font_param)
  3011             ? font_param
  3012             : gui_display_get_arg (dpyinfo, parms, Qfont,
  3013                                    "font", "Font",
  3014                                    RES_TYPE_STRING));
  3015 
  3016   if (! FONTP (font) && ! STRINGP (font))
  3017     {
  3018       const char **names = (const char *[]) { "monospace-12",
  3019                                               "Noto Sans Mono-12",
  3020                                               "Source Code Pro-12",
  3021                                               NULL };
  3022       int i;
  3023 
  3024       for (i = 0; names[i]; i++)
  3025         {
  3026           font
  3027             = font_open_by_name (f, build_unibyte_string (names[i]));
  3028           if (!NILP (font))
  3029             break;
  3030         }
  3031       if (NILP (font))
  3032         error ("No suitable font was found");
  3033     }
  3034 
  3035   gui_default_parameter (f, parms, Qfont, font, "font", "Font",
  3036                          RES_TYPE_STRING);
  3037 }
  3038 
  3039 static struct redisplay_interface haiku_redisplay_interface =
  3040   {
  3041     haiku_frame_parm_handlers,
  3042     gui_produce_glyphs,
  3043     gui_write_glyphs,
  3044     gui_insert_glyphs,
  3045     gui_clear_end_of_line,
  3046     haiku_scroll_run,
  3047     haiku_after_update_window_line,
  3048     NULL, /* update_window_begin */
  3049     NULL, /* update_window_end */
  3050     haiku_flush,
  3051     gui_clear_window_mouse_face,
  3052     gui_get_glyph_overhangs,
  3053     gui_fix_overlapping_area,
  3054     haiku_draw_fringe_bitmap,
  3055     haiku_define_fringe_bitmap,
  3056     haiku_destroy_fringe_bitmap,
  3057     haiku_compute_glyph_string_overhangs,
  3058     haiku_draw_glyph_string,
  3059     haiku_define_frame_cursor,
  3060     haiku_clear_frame_area,
  3061     haiku_clear_under_internal_border,
  3062     haiku_draw_window_cursor,
  3063     haiku_draw_vertical_window_border,
  3064     haiku_draw_window_divider,
  3065     NULL, /* shift glyphs for insert */
  3066     haiku_show_hourglass,
  3067     haiku_hide_hourglass,
  3068     haiku_default_font_parameter,
  3069   };
  3070 
  3071 static void
  3072 haiku_make_fullscreen_consistent (struct frame *f)
  3073 {
  3074   Lisp_Object lval;
  3075   struct haiku_output *output;
  3076 
  3077   output = FRAME_OUTPUT_DATA (f);
  3078 
  3079   if (output->fullscreen_mode == FULLSCREEN_MODE_BOTH)
  3080     lval = Qfullboth;
  3081   else if (output->fullscreen_mode == FULLSCREEN_MODE_WIDTH)
  3082     lval = Qfullwidth;
  3083   else if (output->fullscreen_mode == FULLSCREEN_MODE_HEIGHT)
  3084     lval = Qfullheight;
  3085   else if (output->fullscreen_mode == FULLSCREEN_MODE_MAXIMIZED)
  3086     lval = Qmaximized;
  3087   else
  3088     lval = Qnil;
  3089 
  3090   store_frame_param (f, Qfullscreen, lval);
  3091 }
  3092 
  3093 static void
  3094 haiku_flush_dirty_back_buffer_on (struct frame *f)
  3095 {
  3096   if (FRAME_GARBAGED_P (f)
  3097       || buffer_flipping_blocked_p ()
  3098       /* If the frame is not already up to date, do not flush buffers
  3099          on input, as that will result in flicker.  */
  3100       || !FRAME_COMPLETE_P (f)
  3101       || !FRAME_DIRTY_P (f))
  3102     return;
  3103 
  3104   haiku_flip_buffers (f);
  3105 }
  3106 
  3107 /* N.B. that support for TYPE must be explicitly added to
  3108    haiku_read_socket.  */
  3109 void
  3110 haiku_wait_for_event (struct frame *f, int type)
  3111 {
  3112   int input_blocked_to;
  3113   object_wait_info info;
  3114   specpdl_ref depth;
  3115 
  3116   input_blocked_to = interrupt_input_blocked;
  3117   info.object = port_application_to_emacs;
  3118   info.type = B_OBJECT_TYPE_PORT;
  3119   info.events = B_EVENT_READ;
  3120 
  3121   depth = SPECPDL_INDEX ();
  3122   specbind (Qinhibit_quit, Qt);
  3123 
  3124   FRAME_OUTPUT_DATA (f)->wait_for_event_type = type;
  3125 
  3126   while (FRAME_OUTPUT_DATA (f)->wait_for_event_type == type)
  3127     {
  3128       if (wait_for_objects (&info, 1) < B_OK)
  3129         continue;
  3130 
  3131       pending_signals = true;
  3132       /* This will call the read_socket_hook.  */
  3133       totally_unblock_input ();
  3134       interrupt_input_blocked = input_blocked_to;
  3135       info.events = B_EVENT_READ;
  3136     }
  3137 
  3138   unbind_to (depth, Qnil);
  3139 }
  3140 
  3141 static int
  3142 haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
  3143 {
  3144   int message_count;
  3145   void *buf;
  3146   ssize_t b_size;
  3147   int button_or_motion_p, do_help;
  3148   enum haiku_event_type type;
  3149   struct input_event inev, inev2;
  3150   struct frame *mouse_frame;
  3151 
  3152   message_count = 0;
  3153   button_or_motion_p = 0;
  3154   do_help = 0;
  3155 
  3156   buf = alloca (200);
  3157 
  3158   block_input ();
  3159   haiku_read_size (&b_size, false);
  3160   while (b_size >= 0)
  3161     {
  3162       if (b_size > 200)
  3163         emacs_abort ();
  3164 
  3165       EVENT_INIT (inev);
  3166       EVENT_INIT (inev2);
  3167       inev.kind = NO_EVENT;
  3168       inev2.kind = NO_EVENT;
  3169       inev.arg = Qnil;
  3170       inev2.arg = Qnil;
  3171 
  3172       button_or_motion_p = 0;
  3173       haiku_read (&type, buf, b_size);
  3174 
  3175       switch (type)
  3176         {
  3177         case QUIT_REQUESTED:
  3178           {
  3179             struct haiku_quit_requested_event *b = buf;
  3180             struct frame *f = haiku_window_to_frame (b->window);
  3181 
  3182             if (!f)
  3183               continue;
  3184 
  3185             inev.kind = DELETE_WINDOW_EVENT;
  3186             XSETFRAME (inev.frame_or_window, f);
  3187             break;
  3188           }
  3189         case FRAME_RESIZED:
  3190           {
  3191             struct haiku_resize_event *b = buf;
  3192             struct frame *f = haiku_window_to_frame (b->window);
  3193 
  3194             if (!f)
  3195               continue;
  3196 
  3197             int width = lrint (b->width);
  3198             int height = lrint (b->height);
  3199 
  3200             if (FRAME_OUTPUT_DATA (f)->wait_for_event_type
  3201                 == FRAME_RESIZED)
  3202               FRAME_OUTPUT_DATA (f)->wait_for_event_type = -1;
  3203 
  3204             if (FRAME_TOOLTIP_P (f))
  3205               {
  3206                 if (FRAME_PIXEL_WIDTH (f) != width
  3207                     || FRAME_PIXEL_HEIGHT (f) != height)
  3208                   SET_FRAME_GARBAGED (f);
  3209 
  3210                 FRAME_PIXEL_WIDTH (f) = width;
  3211                 FRAME_PIXEL_HEIGHT (f) = height;
  3212 
  3213                 haiku_clear_under_internal_border (f);
  3214 
  3215                 /* Flush the frame and flip buffers here.  It is
  3216                    necessary for tooltips displayed inside menus, as
  3217                    redisplay cannot happen.  */
  3218                 haiku_flush (f);
  3219                 continue;
  3220               }
  3221 
  3222             BView_draw_lock (FRAME_HAIKU_DRAWABLE (f), false, 0, 0, 0, 0);
  3223             BView_resize_to (FRAME_HAIKU_DRAWABLE (f), width, height);
  3224             BView_draw_unlock (FRAME_HAIKU_DRAWABLE (f));
  3225 
  3226             if (width != FRAME_PIXEL_WIDTH (f)
  3227                 || height != FRAME_PIXEL_HEIGHT (f)
  3228                 || (f->new_size_p
  3229                     && ((f->new_width >= 0 && width != f->new_width)
  3230                         || (f->new_height >= 0 && height != f->new_height))))
  3231               {
  3232                 change_frame_size (f, width, height, false, true, false);
  3233                 SET_FRAME_GARBAGED (f);
  3234                 cancel_mouse_face (f);
  3235                 haiku_clear_under_internal_border (f);
  3236               }
  3237 
  3238             break;
  3239           }
  3240         case FRAME_EXPOSED:
  3241           {
  3242             struct haiku_expose_event *b = buf;
  3243             struct frame *f = haiku_window_to_frame (b->window);
  3244 
  3245             if (!f)
  3246               continue;
  3247 
  3248             expose_frame (f, b->x, b->y, b->width, b->height);
  3249             haiku_clear_under_internal_border (f);
  3250             break;
  3251           }
  3252         case KEY_DOWN:
  3253           {
  3254             struct haiku_key_event *b = buf;
  3255             Mouse_HLInfo *hlinfo = &x_display_list->mouse_highlight;
  3256             struct frame *f = haiku_window_to_frame (b->window);
  3257 
  3258             if (!f)
  3259               continue;
  3260 
  3261             /* If mouse-highlight is an integer, input clears out
  3262                mouse highlighting.  */
  3263             if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
  3264                 && (f == 0
  3265                     || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
  3266                     || !EQ (f->tab_bar_window, hlinfo->mouse_face_window)))
  3267               {
  3268                 mouse_frame = hlinfo->mouse_face_mouse_frame;
  3269 
  3270                 clear_mouse_face (hlinfo);
  3271                 hlinfo->mouse_face_hidden = true;
  3272 
  3273                 if (mouse_frame)
  3274                   haiku_flush_dirty_back_buffer_on (mouse_frame);
  3275               }
  3276 
  3277             inev.code = b->keysym ? b->keysym : b->multibyte_char;
  3278 
  3279             if (b->keysym)
  3280               inev.kind = NON_ASCII_KEYSTROKE_EVENT;
  3281             else
  3282               inev.kind = inev.code > 127 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT :
  3283                 ASCII_KEYSTROKE_EVENT;
  3284 
  3285             inev.timestamp = b->time / 1000;
  3286             inev.modifiers = (haiku_modifiers_to_emacs (b->modifiers)
  3287                               | (extra_keyboard_modifiers
  3288                                  & (meta_modifier
  3289                                     | hyper_modifier
  3290                                     | ctrl_modifier
  3291                                     | alt_modifier
  3292                                     | shift_modifier)));
  3293 
  3294             XSETFRAME (inev.frame_or_window, f);
  3295             break;
  3296           }
  3297         case ACTIVATION:
  3298           {
  3299             struct haiku_activation_event *b = buf;
  3300             struct frame *f = haiku_window_to_frame (b->window);
  3301 
  3302             if (!f)
  3303               continue;
  3304 
  3305             if ((x_display_list->focus_event_frame != f && b->activated_p)
  3306                 || (x_display_list->focus_event_frame == f && !b->activated_p))
  3307               {
  3308                 haiku_new_focus_frame (b->activated_p ? f : NULL);
  3309                 if (b->activated_p)
  3310                   x_display_list->focus_event_frame = f;
  3311                 else
  3312                   x_display_list->focus_event_frame = NULL;
  3313                 inev.kind = b->activated_p ? FOCUS_IN_EVENT : FOCUS_OUT_EVENT;
  3314                 XSETFRAME (inev.frame_or_window, f);
  3315               }
  3316 
  3317             break;
  3318           }
  3319         case MENU_BAR_LEFT:
  3320           {
  3321             struct haiku_menu_bar_left_event *b = buf;
  3322             struct frame *f = haiku_window_to_frame (b->window);
  3323 
  3324             if (!f)
  3325               continue;
  3326 
  3327             if (b->y > 0 && b->y <= FRAME_PIXEL_HEIGHT (f)
  3328                 && b->x > 0 && b->x <= FRAME_PIXEL_WIDTH (f))
  3329               break;
  3330 
  3331             if (f->auto_lower && !popup_activated_p)
  3332               haiku_frame_raise_lower (f, 0);
  3333 
  3334             break;
  3335           }
  3336         case MOUSE_MOTION:
  3337           {
  3338             struct haiku_mouse_motion_event *b = buf;
  3339             struct frame *f = haiku_mouse_or_wdesc_frame (b->window, true);
  3340             Mouse_HLInfo *hlinfo = &x_display_list->mouse_highlight;
  3341             Lisp_Object frame;
  3342 
  3343             if (!f)
  3344               continue;
  3345 
  3346             if (FRAME_TOOLTIP_P (f))
  3347               {
  3348                 /* Dismiss the tooltip if the mouse moves onto a
  3349                    tooltip frame (except when drag-and-drop is in
  3350                    progress and we are trying to move the tooltip
  3351                    along with the mouse pointer).  FIXME: for some
  3352                    reason we don't get leave notification events for
  3353                    this.  */
  3354 
  3355                 if (any_help_event_p
  3356                     && !(be_drag_and_drop_in_progress ()
  3357                          && haiku_dnd_follow_tooltip)
  3358                     && !((EQ (track_mouse, Qdrag_source)
  3359                           || EQ (track_mouse, Qdropping))
  3360                          && gui_mouse_grabbed (x_display_list)))
  3361                   do_help = -1;
  3362                 break;
  3363               }
  3364 
  3365             XSETFRAME (frame, f);
  3366 
  3367             x_display_list->last_mouse_movement_time = b->time / 1000;
  3368             button_or_motion_p = 1;
  3369 
  3370             if (hlinfo->mouse_face_hidden)
  3371               {
  3372                 hlinfo->mouse_face_hidden = false;
  3373                 clear_mouse_face (hlinfo);
  3374                 haiku_flush_dirty_back_buffer_on (f);
  3375               }
  3376 
  3377             if (b->just_exited_p)
  3378               {
  3379                 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
  3380 
  3381                 if (f == hlinfo->mouse_face_mouse_frame)
  3382                   {
  3383                     /* If we move outside the frame, then we're
  3384                        certainly no longer on any text in the frame.  */
  3385                     clear_mouse_face (hlinfo);
  3386                     hlinfo->mouse_face_mouse_frame = 0;
  3387 
  3388                     haiku_flush_dirty_back_buffer_on (f);
  3389                   }
  3390 
  3391                 if (f == x_display_list->last_mouse_glyph_frame)
  3392                   x_display_list->last_mouse_glyph_frame = NULL;
  3393 
  3394                 if (f->auto_lower && !popup_activated_p
  3395                     /* Don't do this if the mouse entered a scroll bar.  */
  3396                     && !BView_inside_scroll_bar (FRAME_HAIKU_VIEW (f),
  3397                                                  b->x, b->y))
  3398                   {
  3399                     /* If we're leaving towards the menu bar, don't
  3400                        auto-lower here, and wait for a exit
  3401                        notification from the menu bar instead.  */
  3402                     if (b->x > FRAME_PIXEL_WIDTH (f)
  3403                         || b->y >= FRAME_MENU_BAR_HEIGHT (f)
  3404                         || b->x < 0
  3405                         || b->y < 0)
  3406                       haiku_frame_raise_lower (f, 0);
  3407                   }
  3408 
  3409                 haiku_new_focus_frame (x_display_list->focused_frame);
  3410 
  3411                 if (any_help_event_p
  3412                     && !((EQ (track_mouse, Qdrag_source)
  3413                           || EQ (track_mouse, Qdropping))
  3414                          && gui_mouse_grabbed (x_display_list)))
  3415                   do_help = -1;
  3416               }
  3417             else
  3418               {
  3419                 struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
  3420                 struct haiku_rect r = dpyinfo->last_mouse_glyph;
  3421 
  3422                 /* For an unknown reason Haiku sends phantom motion events when a
  3423                    tooltip frame is visible.  FIXME */
  3424                 if (FRAMEP (tip_frame)
  3425                     && FRAME_LIVE_P (XFRAME (tip_frame))
  3426                     && FRAME_VISIBLE_P (XFRAME (tip_frame))
  3427                     && f == dpyinfo->last_mouse_motion_frame
  3428                     && b->x == dpyinfo->last_mouse_motion_x
  3429                     && b->y == dpyinfo->last_mouse_motion_y)
  3430                   continue;
  3431 
  3432                 dpyinfo->last_mouse_motion_x = b->x;
  3433                 dpyinfo->last_mouse_motion_y = b->y;
  3434                 dpyinfo->last_mouse_motion_frame = f;
  3435 
  3436                 previous_help_echo_string = help_echo_string;
  3437                 help_echo_string = Qnil;
  3438 
  3439                 /* A crossing event might be sent out-of-order with
  3440                    regard to motion events from other windows, such as
  3441                    when the mouse pointer rapidly moves from an
  3442                    undecorated child frame to its parent.  This can
  3443                    cause a failure to clear the mouse face on the
  3444                    former if an event for the latter is read by Emacs
  3445                    first and ends up showing the mouse face there.
  3446 
  3447                    Work around the problem by clearing the mouse face
  3448                    now if it is currently shown on a different
  3449                    frame.  */
  3450 
  3451                 if (hlinfo->mouse_face_hidden
  3452                     || (f != hlinfo->mouse_face_mouse_frame
  3453                         && !NILP (hlinfo->mouse_face_window)))
  3454                   {
  3455                     hlinfo->mouse_face_hidden = 0;
  3456                     clear_mouse_face (hlinfo);
  3457                   }
  3458 
  3459                 if (f != dpyinfo->last_mouse_glyph_frame
  3460                     || b->x < r.x || b->x >= r.x + r.width
  3461                     || b->y < r.y || b->y >= r.y + r.height)
  3462                   {
  3463                     f->mouse_moved = true;
  3464                     note_mouse_highlight (f, b->x, b->y);
  3465                     remember_mouse_glyph (f, b->x, b->y,
  3466                                           &FRAME_DISPLAY_INFO (f)->last_mouse_glyph);
  3467                     dpyinfo->last_mouse_glyph_frame = f;
  3468                   }
  3469                 else
  3470                   help_echo_string = previous_help_echo_string;
  3471 
  3472                 if (!NILP (Vmouse_autoselect_window))
  3473                   {
  3474                     static Lisp_Object last_mouse_window;
  3475                     Lisp_Object window = window_from_coordinates (f, b->x, b->y, 0, 0, 0);
  3476 
  3477                     if (WINDOWP (window)
  3478                         && !EQ (window, last_mouse_window)
  3479                         && !EQ (window, selected_window)
  3480                         && !popup_activated_p
  3481                         && !MINI_WINDOW_P (XWINDOW (selected_window))
  3482                         && (!NILP (focus_follows_mouse)
  3483                             || f == SELECTED_FRAME ()))
  3484                       {
  3485                         inev2.kind = SELECT_WINDOW_EVENT;
  3486                         inev2.frame_or_window = window;
  3487                       }
  3488 
  3489                     last_mouse_window = window;
  3490                   }
  3491 
  3492                 if (f->auto_raise)
  3493                   {
  3494                     if (!BWindow_is_active (FRAME_HAIKU_WINDOW (f)))
  3495                       haiku_frame_raise_lower (f, 1);
  3496                   }
  3497 
  3498                 if (!NILP (help_echo_string)
  3499                     || !NILP (previous_help_echo_string))
  3500                   do_help = 1;
  3501 
  3502                 if (b->dnd_message)
  3503                   {
  3504                     /* It doesn't make sense to show tooltips when
  3505                        another program is dragging stuff over us.  */
  3506 
  3507                     if (any_help_event_p || do_help)
  3508                       do_help = -1;
  3509 
  3510                     if (!be_drag_and_drop_in_progress ())
  3511                       {
  3512                         inev.kind = DRAG_N_DROP_EVENT;
  3513                         inev.arg = Qlambda;
  3514 
  3515                         XSETINT (inev.x, b->x);
  3516                         XSETINT (inev.y, b->y);
  3517                         XSETFRAME (inev.frame_or_window, f);
  3518                       }
  3519                     else
  3520                       haiku_note_drag_motion ();
  3521 
  3522                     break;
  3523                   }
  3524               }
  3525 
  3526             if (FRAME_DIRTY_P (f))
  3527               haiku_flush_dirty_back_buffer_on (f);
  3528             break;
  3529           }
  3530         case BUTTON_UP:
  3531         case BUTTON_DOWN:
  3532           {
  3533             struct haiku_button_event *b = buf;
  3534             struct frame *f = haiku_mouse_or_wdesc_frame (b->window, false);
  3535             Lisp_Object tab_bar_arg = Qnil;
  3536             int tab_bar_p = 0, tool_bar_p = 0;
  3537             bool up_okay_p = false;
  3538             struct scroll_bar *bar;
  3539 
  3540             if (popup_activated_p || !f)
  3541               continue;
  3542 
  3543             inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
  3544             bar = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
  3545 
  3546             x_display_list->last_mouse_glyph_frame = 0;
  3547             x_display_list->last_mouse_movement_time = b->time / 1000;
  3548             button_or_motion_p = 1;
  3549 
  3550             /* Is this in the tab-bar?  */
  3551             if (WINDOWP (f->tab_bar_window)
  3552                 && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
  3553               {
  3554                 Lisp_Object window;
  3555                 int x = b->x;
  3556                 int y = b->y;
  3557 
  3558                 window = window_from_coordinates (f, x, y, 0, true, true);
  3559                 tab_bar_p = EQ (window, f->tab_bar_window);
  3560 
  3561                 if (tab_bar_p)
  3562                   {
  3563                     tab_bar_arg = handle_tab_bar_click
  3564                       (f, x, y, type == BUTTON_DOWN, inev.modifiers);
  3565                     haiku_flush_dirty_back_buffer_on (f);
  3566                   }
  3567               }
  3568 
  3569             if (WINDOWP (f->tool_bar_window)
  3570                 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
  3571               {
  3572                 Lisp_Object window;
  3573                 int x = b->x;
  3574                 int y = b->y;
  3575 
  3576                 window = window_from_coordinates (f, x, y, 0, true, true);
  3577                 tool_bar_p = (EQ (window, f->tool_bar_window)
  3578                               && (type != BUTTON_UP
  3579                                   || f->last_tool_bar_item != -1));
  3580 
  3581                 if (tool_bar_p)
  3582                   {
  3583                     handle_tool_bar_click
  3584                       (f, x, y, type == BUTTON_DOWN, inev.modifiers);
  3585                     haiku_flush_dirty_back_buffer_on (f);
  3586                   }
  3587               }
  3588 
  3589             if (type == BUTTON_UP)
  3590               {
  3591                 inev.modifiers |= up_modifier;
  3592                 up_okay_p = (x_display_list->grabbed & (1 << b->btn_no));
  3593                 x_display_list->grabbed &= ~(1 << b->btn_no);
  3594               }
  3595             else
  3596               {
  3597                 up_okay_p = true;
  3598                 inev.modifiers |= down_modifier;
  3599                 x_display_list->last_mouse_frame = f;
  3600                 x_display_list->grabbed |= (1 << b->btn_no);
  3601                 if (f && !tab_bar_p)
  3602                   f->last_tab_bar_item = -1;
  3603                 if (f && !tool_bar_p)
  3604                   f->last_tool_bar_item = -1;
  3605               }
  3606 
  3607             if (bar)
  3608               {
  3609                 inev.kind = (bar->horizontal
  3610                              ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
  3611                              : SCROLL_BAR_CLICK_EVENT);
  3612                 inev.part = (bar->horizontal
  3613                              ? scroll_bar_horizontal_handle
  3614                              : scroll_bar_handle);
  3615               }
  3616             else if (up_okay_p
  3617                      && !(tab_bar_p && NILP (tab_bar_arg))
  3618                      && !tool_bar_p)
  3619               inev.kind = MOUSE_CLICK_EVENT;
  3620 
  3621             inev.arg = tab_bar_arg;
  3622             inev.code = b->btn_no;
  3623 
  3624             f->mouse_moved = false;
  3625 
  3626             if (bar)
  3627               {
  3628                 if (bar->horizontal)
  3629                   {
  3630                     XSETINT (inev.x, min (max (0, b->x - bar->left),
  3631                                           bar->width));
  3632                     XSETINT (inev.y, bar->width);
  3633                   }
  3634                 else
  3635                   {
  3636                     XSETINT (inev.x, min (max (0, b->y - bar->top),
  3637                                           bar->height));
  3638                     XSETINT (inev.y, bar->height);
  3639                   }
  3640 
  3641                 inev.frame_or_window = bar->window;
  3642               }
  3643             else
  3644               {
  3645                 XSETINT (inev.x, b->x);
  3646                 XSETINT (inev.y, b->y);
  3647                 XSETFRAME (inev.frame_or_window, f);
  3648               }
  3649 
  3650             break;
  3651           }
  3652         case ICONIFICATION:
  3653           {
  3654             struct haiku_iconification_event *b = buf;
  3655             struct frame *f = haiku_window_to_frame (b->window);
  3656 
  3657             if (!f)
  3658               continue;
  3659 
  3660             if (!b->iconified_p)
  3661               {
  3662                 SET_FRAME_VISIBLE (f, 1);
  3663                 SET_FRAME_ICONIFIED (f, 0);
  3664                 inev.kind = DEICONIFY_EVENT;
  3665 
  3666                 /* Haiku doesn't expose frames on deiconification, but
  3667                    if we are double-buffered, the previous screen
  3668                    contents should have been preserved. */
  3669                 if (!EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)))
  3670                   {
  3671                     SET_FRAME_GARBAGED (f);
  3672                     expose_frame (f, 0, 0, 0, 0);
  3673                   }
  3674               }
  3675             else
  3676               {
  3677                 SET_FRAME_VISIBLE (f, 0);
  3678                 SET_FRAME_ICONIFIED (f, 1);
  3679                 inev.kind = ICONIFY_EVENT;
  3680               }
  3681 
  3682             XSETFRAME (inev.frame_or_window, f);
  3683             break;
  3684           }
  3685         case MOVE_EVENT:
  3686           {
  3687             struct haiku_move_event *b = buf;
  3688             struct frame *f = haiku_window_to_frame (b->window);
  3689             int top, left;
  3690             struct frame *p;
  3691 
  3692             if (!f)
  3693               continue;
  3694 
  3695             FRAME_OUTPUT_DATA (f)->frame_x = b->x;
  3696             FRAME_OUTPUT_DATA (f)->frame_y = b->y;
  3697 
  3698             if (FRAME_PARENT_FRAME (f))
  3699               haiku_coords_from_parent (f, &b->x, &b->y);
  3700 
  3701             left = b->x - b->decorator_width;
  3702             top = b->y - b->decorator_height;
  3703 
  3704             if (left != f->left_pos || top != f->top_pos)
  3705               {
  3706                 inev.kind = MOVE_FRAME_EVENT;
  3707 
  3708                 XSETINT (inev.x, left);
  3709                 XSETINT (inev.y, top);
  3710 
  3711                 f->left_pos = left;
  3712                 f->top_pos = top;
  3713 
  3714                 p = FRAME_PARENT_FRAME (f);
  3715 
  3716                 if (p)
  3717                   EmacsWindow_move_weak_child (FRAME_HAIKU_WINDOW (p),
  3718                                                b->window, left, top);
  3719 
  3720                 XSETFRAME (inev.frame_or_window, f);
  3721               }
  3722 
  3723             haiku_make_fullscreen_consistent (f);
  3724             break;
  3725           }
  3726         case SCROLL_BAR_VALUE_EVENT:
  3727           {
  3728             struct haiku_scroll_bar_value_event *b = buf;
  3729             struct scroll_bar *bar
  3730               = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
  3731             int portion, whole;
  3732 
  3733             if (!bar)
  3734               continue;
  3735 
  3736             struct window *w = XWINDOW (bar->window);
  3737 
  3738             if (bar->update != -1)
  3739               {
  3740                 bar->update = -1;
  3741                 break;
  3742               }
  3743 
  3744             if (bar->position != b->position)
  3745               {
  3746                 inev.kind = (bar->horizontal
  3747                              ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT :
  3748                              SCROLL_BAR_CLICK_EVENT);
  3749                 inev.part = (bar->horizontal
  3750                              ? scroll_bar_horizontal_handle
  3751                              : scroll_bar_handle);
  3752 
  3753                 if (bar->horizontal)
  3754                   {
  3755                     portion = bar->total * ((float) b->position
  3756                                             / BE_SB_MAX);
  3757                     whole = (bar->total
  3758                              * ((float) (BE_SB_MAX - bar->page_size)
  3759                                 / BE_SB_MAX));
  3760                     portion = min (portion, whole);
  3761                   }
  3762                 else
  3763                   {
  3764                     whole = BE_SB_MAX - bar->page_size;
  3765                     portion = min (b->position, whole);
  3766                   }
  3767 
  3768                 XSETINT (inev.x, portion);
  3769                 XSETINT (inev.y, whole);
  3770                 XSETWINDOW (inev.frame_or_window, w);
  3771               }
  3772             break;
  3773           }
  3774         case SCROLL_BAR_PART_EVENT:
  3775           {
  3776             struct haiku_scroll_bar_part_event *b = buf;
  3777             struct scroll_bar *bar
  3778               = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
  3779 
  3780             if (!bar)
  3781               continue;
  3782 
  3783             inev.kind = (bar->horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
  3784                          : SCROLL_BAR_CLICK_EVENT);
  3785 
  3786             bar->dragging = 0;
  3787 
  3788             switch (b->part)
  3789               {
  3790               case HAIKU_SCROLL_BAR_UP_BUTTON:
  3791                 inev.part = (bar->horizontal
  3792                              ? scroll_bar_left_arrow
  3793                              : scroll_bar_up_arrow);
  3794                 break;
  3795               case HAIKU_SCROLL_BAR_DOWN_BUTTON:
  3796                 inev.part = (bar->horizontal
  3797                              ? scroll_bar_right_arrow
  3798                              : scroll_bar_down_arrow);
  3799                 break;
  3800               }
  3801 
  3802             XSETINT (inev.x, 0);
  3803             XSETINT (inev.y, 0);
  3804             inev.frame_or_window = bar->window;
  3805 
  3806             break;
  3807           }
  3808         case SCROLL_BAR_DRAG_EVENT:
  3809           {
  3810             struct haiku_scroll_bar_drag_event *b = buf;
  3811             struct scroll_bar *bar
  3812               = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
  3813 
  3814             if (!bar)
  3815               continue;
  3816 
  3817             bar->dragging = b->dragging_p;
  3818             if (!b->dragging_p && bar->horizontal)
  3819               set_horizontal_scroll_bar (XWINDOW (bar->window));
  3820             else if (!b->dragging_p)
  3821               set_vertical_scroll_bar (XWINDOW (bar->window));
  3822             break;
  3823           }
  3824         case WHEEL_MOVE_EVENT:
  3825           {
  3826             struct haiku_wheel_move_event *b = buf;
  3827             struct frame *f = haiku_window_to_frame (b->window);
  3828             int x, y, scroll_width, scroll_height;
  3829             static float px = 0.0f, py = 0.0f;
  3830             Lisp_Object wheel_window;
  3831 
  3832             if (!f)
  3833               continue;
  3834 
  3835             BView_get_mouse (FRAME_HAIKU_VIEW (f), &x, &y);
  3836 
  3837             wheel_window = window_from_coordinates (f, x, y, 0, false, false);
  3838 
  3839             if (NILP (wheel_window))
  3840               {
  3841                 scroll_width = FRAME_PIXEL_WIDTH (f);
  3842                 scroll_height = FRAME_PIXEL_HEIGHT (f);
  3843               }
  3844             else
  3845               {
  3846                 scroll_width = XWINDOW (wheel_window)->pixel_width;
  3847                 scroll_height = XWINDOW (wheel_window)->pixel_height;
  3848               }
  3849 
  3850             inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
  3851 
  3852             inev2.modifiers = inev.modifiers;
  3853 
  3854             if (signbit (px) != signbit (b->delta_x))
  3855               px = 0;
  3856 
  3857             if (signbit (py) != signbit (b->delta_y))
  3858               py = 0;
  3859 
  3860             px += (b->delta_x
  3861                    * powf (scroll_width, 2.0f / 3.0f));
  3862             py += (b->delta_y
  3863                    * powf (scroll_height, 2.0f / 3.0f));
  3864 
  3865             if (fabsf (py) >= FRAME_LINE_HEIGHT (f)
  3866                 || fabsf (px) >= FRAME_COLUMN_WIDTH (f)
  3867                 || !mwheel_coalesce_scroll_events)
  3868               {
  3869                 inev.kind = (fabsf (px) > fabsf (py)
  3870                              ? HORIZ_WHEEL_EVENT
  3871                              : WHEEL_EVENT);
  3872                 inev.code = 0;
  3873 
  3874                 XSETINT (inev.x, x);
  3875                 XSETINT (inev.y, y);
  3876                 inev.arg = list3 (Qnil, make_float (-px),
  3877                                   make_float (-py));
  3878                 XSETFRAME (inev.frame_or_window, f);
  3879 
  3880                 inev.modifiers |= (signbit (inev.kind == HORIZ_WHEEL_EVENT
  3881                                             ? px : py)
  3882                                    ? up_modifier
  3883                                    : down_modifier);
  3884                 py = 0.0f;
  3885                 px = 0.0f;
  3886 
  3887                 if (be_drag_and_drop_in_progress ())
  3888                   haiku_note_drag_wheel (&inev);
  3889               }
  3890 
  3891             break;
  3892           }
  3893         case MENU_BAR_RESIZE:
  3894           {
  3895             struct haiku_menu_bar_resize_event *b = buf;
  3896             struct frame *f = haiku_window_to_frame (b->window);
  3897 
  3898             if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
  3899               continue;
  3900 
  3901             if (FRAME_OUTPUT_DATA (f)->wait_for_event_type
  3902                 == MENU_BAR_RESIZE)
  3903               FRAME_OUTPUT_DATA (f)->wait_for_event_type = -1;
  3904 
  3905             int old_height = FRAME_MENU_BAR_HEIGHT (f);
  3906 
  3907             FRAME_MENU_BAR_HEIGHT (f) = b->height;
  3908             FRAME_MENU_BAR_LINES (f)
  3909               = (b->height + FRAME_LINE_HEIGHT (f)) / FRAME_LINE_HEIGHT (f);
  3910 
  3911             if (old_height != b->height)
  3912               {
  3913                 adjust_frame_size (f, -1, -1, 3, true, Qmenu_bar_lines);
  3914                 haiku_clear_under_internal_border (f);
  3915               }
  3916             break;
  3917           }
  3918         case MENU_BAR_CLICK:
  3919           {
  3920             struct haiku_menu_bar_click_event *b = buf;
  3921             struct frame *f = haiku_window_to_frame (b->window);
  3922 
  3923             if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
  3924               continue;
  3925 
  3926             if (!FRAME_OUTPUT_DATA (f)->saved_menu_event)
  3927               FRAME_OUTPUT_DATA (f)->saved_menu_event = xmalloc (sizeof *b);
  3928             *FRAME_OUTPUT_DATA (f)->saved_menu_event = *b;
  3929             inev.kind = MENU_BAR_ACTIVATE_EVENT;
  3930             XSETFRAME (inev.frame_or_window, f);
  3931             break;
  3932           }
  3933         case MENU_BAR_OPEN:
  3934         case MENU_BAR_CLOSE:
  3935           {
  3936             struct haiku_menu_bar_state_event *b = buf;
  3937             struct frame *f = haiku_window_to_frame (b->window);
  3938 
  3939             if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
  3940               continue;
  3941 
  3942             if (type == MENU_BAR_OPEN)
  3943               {
  3944                 FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
  3945                 popup_activated_p += 1;
  3946               }
  3947             else
  3948               {
  3949                 if (!popup_activated_p)
  3950                   emacs_abort ();
  3951 
  3952                 if (FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
  3953                   {
  3954                     FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 0;
  3955                     popup_activated_p -= 1;
  3956                   }
  3957               }
  3958             break;
  3959           }
  3960         case MENU_BAR_SELECT_EVENT:
  3961           {
  3962             struct haiku_menu_bar_select_event *b = buf;
  3963             struct frame *f = haiku_window_to_frame (b->window);
  3964 
  3965             if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
  3966               continue;
  3967 
  3968             find_and_call_menu_selection (f, f->menu_bar_items_used,
  3969                                           f->menu_bar_vector, b->ptr);
  3970             break;
  3971           }
  3972         case MENU_BAR_HELP_EVENT:
  3973           {
  3974             struct haiku_menu_bar_help_event *b = buf;
  3975 
  3976             if (!popup_activated_p)
  3977               continue;
  3978 
  3979             struct frame *f = haiku_window_to_frame (b->window);
  3980             if (!f || !FRAME_EXTERNAL_MENU_BAR (f)
  3981                 || !FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
  3982               continue;
  3983 
  3984             run_menu_bar_help_event (f, b->mb_idx);
  3985             break;
  3986           }
  3987         case ZOOM_EVENT:
  3988           {
  3989             struct haiku_zoom_event *b = buf;
  3990             struct frame *f = haiku_window_to_frame (b->window);
  3991 
  3992             if (!f)
  3993               continue;
  3994 
  3995             if (b->fullscreen_mode == FULLSCREEN_MODE_MAXIMIZED)
  3996               f->want_fullscreen = FULLSCREEN_NONE;
  3997             else
  3998               f->want_fullscreen = FULLSCREEN_MAXIMIZED;
  3999 
  4000             FRAME_TERMINAL (f)->fullscreen_hook (f);
  4001             break;
  4002           }
  4003         case DRAG_AND_DROP_EVENT:
  4004           {
  4005             struct haiku_drag_and_drop_event *b = buf;
  4006             struct frame *f = haiku_window_to_frame (b->window);
  4007 
  4008             if (!f)
  4009               {
  4010                 BMessage_delete (b->message);
  4011                 continue;
  4012               }
  4013 
  4014             inev.kind = DRAG_N_DROP_EVENT;
  4015             inev.arg = haiku_message_to_lisp (b->message);
  4016 
  4017             XSETINT (inev.x, b->x);
  4018             XSETINT (inev.y, b->y);
  4019             XSETFRAME (inev.frame_or_window, f);
  4020 
  4021             BMessage_delete (b->message);
  4022             break;
  4023           }
  4024         case SCREEN_CHANGED_EVENT:
  4025           {
  4026             struct haiku_screen_changed_event *b = buf;
  4027 
  4028             inev.kind = MONITORS_CHANGED_EVENT;
  4029             XSETTERMINAL (inev.arg, x_display_list->terminal);
  4030             inev.timestamp = b->when / 1000;
  4031             break;
  4032           }
  4033         case CLIPBOARD_CHANGED_EVENT:
  4034           be_handle_clipboard_changed_message ();
  4035           break;
  4036         case APP_QUIT_REQUESTED_EVENT:
  4037           inev.kind = SAVE_SESSION_EVENT;
  4038           inev.arg = Qt;
  4039           break;
  4040         case FONT_CHANGE_EVENT:
  4041           /* This generates CONFIG_CHANGED_EVENTs, which are then
  4042              handled in Lisp.  */
  4043           haiku_handle_font_change_event (buf, &inev);
  4044           break;
  4045         case KEY_UP:
  4046         case DUMMY_EVENT:
  4047         default:
  4048           break;
  4049         }
  4050 
  4051       haiku_read_size (&b_size, false);
  4052 
  4053       if (inev.kind != NO_EVENT)
  4054         {
  4055           if (inev.kind != HELP_EVENT && !inev.timestamp)
  4056             inev.timestamp = (button_or_motion_p
  4057                               ? x_display_list->last_mouse_movement_time
  4058                               : system_time () / 1000);
  4059           kbd_buffer_store_event_hold (&inev, hold_quit);
  4060           ++message_count;
  4061         }
  4062 
  4063       if (inev2.kind != NO_EVENT)
  4064         {
  4065           if (inev2.kind != HELP_EVENT && !inev.timestamp)
  4066             inev2.timestamp = (button_or_motion_p
  4067                                ? x_display_list->last_mouse_movement_time
  4068                                : system_time () / 1000);
  4069           kbd_buffer_store_event_hold (&inev2, hold_quit);
  4070           ++message_count;
  4071         }
  4072     }
  4073 
  4074   if (do_help && !(hold_quit && hold_quit->kind != NO_EVENT))
  4075     {
  4076       Lisp_Object help_frame = Qnil;
  4077 
  4078       if (x_display_list->last_mouse_frame)
  4079         XSETFRAME (help_frame,
  4080                    x_display_list->last_mouse_frame);
  4081 
  4082       if (do_help > 0)
  4083         {
  4084           any_help_event_p = true;
  4085           gen_help_event (help_echo_string, help_frame,
  4086                           help_echo_window, help_echo_object,
  4087                           help_echo_pos);
  4088         }
  4089       else
  4090         {
  4091           help_echo_string = Qnil;
  4092           gen_help_event (Qnil, help_frame, Qnil, Qnil, 0);
  4093         }
  4094     }
  4095 
  4096   unblock_input ();
  4097 
  4098   return message_count;
  4099 }
  4100 
  4101 static Lisp_Object
  4102 haiku_get_focus_frame (struct frame *f)
  4103 {
  4104   Lisp_Object lisp_focus;
  4105   struct frame *focus;
  4106 
  4107   focus = FRAME_DISPLAY_INFO (f)->focused_frame;
  4108 
  4109   if (!focus)
  4110     return Qnil;
  4111 
  4112   XSETFRAME (lisp_focus, focus);
  4113   return lisp_focus;
  4114 }
  4115 
  4116 static void
  4117 haiku_frame_rehighlight (struct frame *frame)
  4118 {
  4119   haiku_rehighlight ();
  4120 }
  4121 
  4122 static void
  4123 haiku_delete_window (struct frame *f)
  4124 {
  4125   check_window_system (f);
  4126   haiku_free_frame_resources (f);
  4127 }
  4128 
  4129 static void
  4130 haiku_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
  4131 {
  4132   BBitmap_free (pixmap);
  4133 }
  4134 
  4135 static void
  4136 haiku_flash (struct frame *f)
  4137 {
  4138   /* Get the height not including a menu bar widget.  */
  4139   int height = FRAME_PIXEL_HEIGHT (f);
  4140   /* Height of each line to flash.  */
  4141   int flash_height = FRAME_LINE_HEIGHT (f);
  4142   /* These will be the left and right margins of the rectangles.  */
  4143   int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
  4144   int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
  4145   int width = flash_right - flash_left;
  4146   void *view = FRAME_HAIKU_DRAWABLE (f);
  4147   object_wait_info info;
  4148   bigtime_t wakeup;
  4149 
  4150   info.object = port_application_to_emacs;
  4151   info.type = B_OBJECT_TYPE_PORT;
  4152   info.events = B_EVENT_READ;
  4153   wakeup = system_time () + 150000;
  4154 
  4155   BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
  4156                    FRAME_PIXEL_HEIGHT (f));
  4157   BView_StartClip (view);
  4158   /* If window is tall, flash top and bottom line.  */
  4159   if (height > 3 * FRAME_LINE_HEIGHT (f))
  4160     {
  4161       BView_InvertRect (view, flash_left,
  4162                         (FRAME_INTERNAL_BORDER_WIDTH (f)
  4163                          + FRAME_TOP_MARGIN_HEIGHT (f)),
  4164                         width, flash_height);
  4165 
  4166       BView_InvertRect (view, flash_left,
  4167                         (height - flash_height
  4168                          - FRAME_INTERNAL_BORDER_WIDTH (f)
  4169                          - FRAME_BOTTOM_MARGIN_HEIGHT (f)),
  4170                         width, flash_height);
  4171     }
  4172   else
  4173     /* If it is short, flash it all.  */
  4174     BView_InvertRect (view, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
  4175                       width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
  4176   BView_EndClip (view);
  4177   BView_draw_unlock (view);
  4178 
  4179   flush_frame (f);
  4180 
  4181   if (EmacsView_double_buffered_p (view))
  4182     haiku_flip_buffers (f);
  4183 
  4184   /* Keep waiting until past the time wakeup or any input gets
  4185      available.  */
  4186   while (!detect_input_pending ())
  4187     {
  4188       /* Break if result would not be positive.  */
  4189       if (wakeup < system_time ())
  4190         break;
  4191 
  4192       /* Try to wait that long--but we might wake up sooner.  */
  4193       wait_for_objects_etc (&info, 1, B_ABSOLUTE_TIMEOUT, wakeup);
  4194 
  4195       if (info.events & B_EVENT_READ)
  4196         break;
  4197 
  4198       info.events = B_EVENT_READ;
  4199     }
  4200 
  4201   BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
  4202                    FRAME_PIXEL_HEIGHT (f));
  4203   BView_StartClip (view);
  4204   /* If window is tall, flash top and bottom line.  */
  4205   if (height > 3 * FRAME_LINE_HEIGHT (f))
  4206     {
  4207       BView_InvertRect (view, flash_left,
  4208                         (FRAME_INTERNAL_BORDER_WIDTH (f)
  4209                          + FRAME_TOP_MARGIN_HEIGHT (f)),
  4210                         width, flash_height);
  4211 
  4212       BView_InvertRect (view, flash_left,
  4213                         (height - flash_height
  4214                          - FRAME_INTERNAL_BORDER_WIDTH (f)
  4215                          - FRAME_BOTTOM_MARGIN_HEIGHT (f)),
  4216                         width, flash_height);
  4217     }
  4218   else
  4219     /* If it is short, flash it all.  */
  4220     BView_InvertRect (view, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
  4221                       width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
  4222   BView_EndClip (view);
  4223   BView_draw_unlock (view);
  4224 
  4225   flush_frame (f);
  4226   if (EmacsView_double_buffered_p (view))
  4227     haiku_flip_buffers (f);
  4228 }
  4229 
  4230 static void
  4231 haiku_beep (struct frame *f)
  4232 {
  4233   if (visible_bell)
  4234     {
  4235       void *view = FRAME_HAIKU_VIEW (f);
  4236       if (view)
  4237         {
  4238           block_input ();
  4239           haiku_flash (f);
  4240           unblock_input ();
  4241         }
  4242     }
  4243   else
  4244     haiku_ring_bell ();
  4245 }
  4246 
  4247 static void
  4248 haiku_toggle_invisible_pointer (struct frame *f, bool invisible_p)
  4249 {
  4250   void *view = FRAME_HAIKU_VIEW (f);
  4251 
  4252   if (view && !FRAME_TOOLTIP_P (f))
  4253     {
  4254       block_input ();
  4255       BView_set_view_cursor (view, (invisible_p
  4256                                     ? FRAME_OUTPUT_DATA (f)->no_cursor
  4257                                     : FRAME_OUTPUT_DATA (f)->current_cursor));
  4258       f->pointer_invisible = invisible_p;
  4259       unblock_input ();
  4260     }
  4261 }
  4262 
  4263 static void
  4264 haiku_fullscreen (struct frame *f)
  4265 {
  4266   enum haiku_fullscreen_mode mode;
  4267 
  4268   /* When FRAME_OUTPUT_DATA (f)->configury_done is false, the frame is
  4269      being created, and its regular width and height have not yet been
  4270      set.  This function will be called again by haiku_create_frame,
  4271      so do nothing.  */
  4272   if (!FRAME_OUTPUT_DATA (f)->configury_done)
  4273     return;
  4274 
  4275   if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
  4276     mode = FULLSCREEN_MODE_MAXIMIZED;
  4277   else if (f->want_fullscreen == FULLSCREEN_BOTH)
  4278     mode = FULLSCREEN_MODE_BOTH;
  4279   else if (f->want_fullscreen == FULLSCREEN_WIDTH)
  4280     mode = FULLSCREEN_MODE_WIDTH;
  4281   else if (f->want_fullscreen == FULLSCREEN_HEIGHT)
  4282     mode = FULLSCREEN_MODE_HEIGHT;
  4283   else
  4284     mode = FULLSCREEN_MODE_NONE;
  4285 
  4286   f->want_fullscreen = FULLSCREEN_NONE;
  4287   be_set_window_fullscreen_mode (FRAME_HAIKU_WINDOW (f), mode);
  4288   FRAME_OUTPUT_DATA (f)->fullscreen_mode = mode;
  4289 
  4290   haiku_update_size_hints (f);
  4291   haiku_make_fullscreen_consistent (f);
  4292 }
  4293 
  4294 static struct terminal *
  4295 haiku_create_terminal (struct haiku_display_info *dpyinfo)
  4296 {
  4297   struct terminal *terminal;
  4298 
  4299   terminal = create_terminal (output_haiku, &haiku_redisplay_interface);
  4300 
  4301   terminal->display_info.haiku = dpyinfo;
  4302   dpyinfo->terminal = terminal;
  4303   terminal->kboard = allocate_kboard (Qhaiku);
  4304 
  4305   terminal->iconify_frame_hook = haiku_iconify_frame;
  4306   terminal->focus_frame_hook = haiku_focus_frame;
  4307   terminal->ring_bell_hook = haiku_beep;
  4308   terminal->popup_dialog_hook = haiku_popup_dialog;
  4309   terminal->frame_visible_invisible_hook = haiku_set_frame_visible_invisible;
  4310   terminal->set_frame_offset_hook = haiku_set_offset;
  4311   terminal->delete_terminal_hook = haiku_delete_terminal;
  4312   terminal->get_string_resource_hook = haiku_get_string_resource;
  4313   terminal->set_new_font_hook = haiku_new_font;
  4314   terminal->defined_color_hook = haiku_defined_color;
  4315   terminal->set_window_size_hook = haiku_set_window_size;
  4316   terminal->read_socket_hook = haiku_read_socket;
  4317   terminal->implicit_set_name_hook = haiku_implicitly_set_name;
  4318   terminal->mouse_position_hook = haiku_mouse_position;
  4319   terminal->delete_frame_hook = haiku_delete_window;
  4320   terminal->frame_up_to_date_hook = haiku_frame_up_to_date;
  4321   terminal->buffer_flipping_unblocked_hook = haiku_buffer_flipping_unblocked_hook;
  4322   terminal->clear_frame_hook = haiku_clear_frame;
  4323   terminal->change_tab_bar_height_hook = haiku_change_tab_bar_height;
  4324   terminal->change_tool_bar_height_hook = haiku_change_tool_bar_height;
  4325   terminal->set_vertical_scroll_bar_hook = haiku_set_vertical_scroll_bar;
  4326   terminal->set_horizontal_scroll_bar_hook = haiku_set_horizontal_scroll_bar;
  4327   terminal->set_scroll_bar_default_height_hook = haiku_set_scroll_bar_default_height;
  4328   terminal->set_scroll_bar_default_width_hook = haiku_set_scroll_bar_default_width;
  4329   terminal->judge_scroll_bars_hook = haiku_judge_scroll_bars;
  4330   terminal->condemn_scroll_bars_hook = haiku_condemn_scroll_bars;
  4331   terminal->redeem_scroll_bar_hook = haiku_redeem_scroll_bar;
  4332   terminal->update_begin_hook = haiku_update_begin;
  4333   terminal->update_end_hook = haiku_update_end;
  4334   terminal->frame_rehighlight_hook = haiku_frame_rehighlight;
  4335   terminal->query_frame_background_color = haiku_query_frame_background_color;
  4336   terminal->free_pixmap = haiku_free_pixmap;
  4337   terminal->frame_raise_lower_hook = haiku_frame_raise_lower;
  4338   terminal->menu_show_hook = haiku_menu_show;
  4339   terminal->toggle_invisible_pointer_hook = haiku_toggle_invisible_pointer;
  4340   terminal->fullscreen_hook = haiku_fullscreen;
  4341   terminal->toolkit_position_hook = haiku_toolkit_position;
  4342   terminal->activate_menubar_hook = haiku_activate_menubar;
  4343   terminal->get_focus_frame = haiku_get_focus_frame;
  4344 
  4345   return terminal;
  4346 }
  4347 
  4348 struct haiku_display_info *
  4349 haiku_term_init (void)
  4350 {
  4351   struct haiku_display_info *dpyinfo;
  4352   struct terminal *terminal;
  4353   Lisp_Object color_file, color_map, system_name;
  4354   ptrdiff_t nbytes;
  4355   void *name_buffer;
  4356 
  4357   block_input ();
  4358 
  4359   Fset_input_interrupt_mode (Qt);
  4360   baud_rate = 19200;
  4361   dpyinfo = xzalloc (sizeof *dpyinfo);
  4362   haiku_io_init ();
  4363 
  4364   if (port_application_to_emacs < B_OK
  4365       || port_emacs_to_session_manager < B_OK)
  4366     emacs_abort ();
  4367 
  4368   color_file = Fexpand_file_name (build_string ("rgb.txt"),
  4369                                   Fsymbol_value (Qdata_directory));
  4370   color_map = Fx_load_color_file (color_file);
  4371 
  4372   if (NILP (color_map))
  4373     fatal ("Could not read %s.\n", SDATA (color_file));
  4374 
  4375   dpyinfo->color_map = color_map;
  4376   dpyinfo->display = BApplication_setup ();
  4377   dpyinfo->next = x_display_list;
  4378   dpyinfo->n_planes = be_get_display_planes ();
  4379   be_get_display_resolution (&dpyinfo->resx, &dpyinfo->resy);
  4380 
  4381   x_display_list = dpyinfo;
  4382 
  4383   terminal = haiku_create_terminal (dpyinfo);
  4384   if (current_kboard == initial_kboard)
  4385     current_kboard = terminal->kboard;
  4386 
  4387   terminal->kboard->reference_count++;
  4388   /* Never delete haiku displays -- there can only ever be one,
  4389      anyhow.  */
  4390   terminal->reference_count++;
  4391   terminal->name = xstrdup ("be");
  4392 
  4393   dpyinfo->name_list_element = Fcons (build_string ("be"), Qnil);
  4394   dpyinfo->smallest_font_height = 1;
  4395   dpyinfo->smallest_char_width = 1;
  4396 
  4397   gui_init_fringe (terminal->rif);
  4398 
  4399 #define ASSIGN_CURSOR(cursor, cursor_id)                        \
  4400   (dpyinfo->cursor = be_create_cursor_from_id (cursor_id))
  4401   ASSIGN_CURSOR (text_cursor,                   CURSOR_ID_I_BEAM);
  4402   ASSIGN_CURSOR (nontext_cursor,                CURSOR_ID_SYSTEM_DEFAULT);
  4403   ASSIGN_CURSOR (modeline_cursor,               CURSOR_ID_CONTEXT_MENU);
  4404   ASSIGN_CURSOR (hand_cursor,                   CURSOR_ID_GRAB);
  4405   ASSIGN_CURSOR (hourglass_cursor,              CURSOR_ID_PROGRESS);
  4406   ASSIGN_CURSOR (horizontal_drag_cursor,        CURSOR_ID_RESIZE_EAST_WEST);
  4407   ASSIGN_CURSOR (vertical_drag_cursor,          CURSOR_ID_RESIZE_NORTH_SOUTH);
  4408   ASSIGN_CURSOR (left_edge_cursor,              CURSOR_ID_RESIZE_WEST);
  4409   ASSIGN_CURSOR (top_left_corner_cursor,        CURSOR_ID_RESIZE_NORTH_WEST);
  4410   ASSIGN_CURSOR (top_edge_cursor,               CURSOR_ID_RESIZE_NORTH);
  4411   ASSIGN_CURSOR (top_right_corner_cursor,       CURSOR_ID_RESIZE_NORTH_EAST);
  4412   ASSIGN_CURSOR (right_edge_cursor,             CURSOR_ID_RESIZE_EAST);
  4413   ASSIGN_CURSOR (bottom_right_corner_cursor,    CURSOR_ID_RESIZE_SOUTH_EAST);
  4414   ASSIGN_CURSOR (bottom_edge_cursor,            CURSOR_ID_RESIZE_SOUTH);
  4415   ASSIGN_CURSOR (bottom_left_corner_cursor,     CURSOR_ID_RESIZE_SOUTH_WEST);
  4416   ASSIGN_CURSOR (no_cursor,                     CURSOR_ID_NO_CURSOR);
  4417 #undef ASSIGN_CURSOR
  4418 
  4419   system_name = Fsystem_name ();
  4420 
  4421   if (STRINGP (system_name))
  4422     {
  4423       nbytes = sizeof "GNU Emacs" + sizeof " at ";
  4424 
  4425       if (ckd_add (&nbytes, nbytes, SBYTES (system_name)))
  4426         memory_full (SIZE_MAX);
  4427 
  4428       name_buffer = alloca (nbytes);
  4429       sprintf (name_buffer, "%s%s%s", "GNU Emacs",
  4430                " at ", SDATA (system_name));
  4431       dpyinfo->default_name = build_string (name_buffer);
  4432     }
  4433   else
  4434     dpyinfo->default_name = build_string ("GNU Emacs");
  4435 
  4436   haiku_start_watching_selections ();
  4437 
  4438   /* Start listening for font configuration changes.  */
  4439   be_listen_font_settings ();
  4440   unblock_input ();
  4441 
  4442   return dpyinfo;
  4443 }
  4444 
  4445 void
  4446 put_xrm_resource (Lisp_Object name, Lisp_Object val)
  4447 {
  4448   eassert (STRINGP (name));
  4449   eassert (STRINGP (val) || NILP (val));
  4450 
  4451   Lisp_Object lval = assoc_no_quit (name, rdb);
  4452   if (!NILP (lval))
  4453     Fsetcdr (lval, val);
  4454   else
  4455     rdb = Fcons (Fcons (name, val), rdb);
  4456 }
  4457 
  4458 void
  4459 haiku_clear_under_internal_border (struct frame *f)
  4460 {
  4461   if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
  4462       /* This is needed because tooltip frames set up the internal
  4463          border before init_frame_faces.  */
  4464       && FRAME_FACE_CACHE (f))
  4465     {
  4466       int border = FRAME_INTERNAL_BORDER_WIDTH (f);
  4467       int width = FRAME_PIXEL_WIDTH (f);
  4468       int height = FRAME_PIXEL_HEIGHT (f);
  4469       int margin = FRAME_TOP_MARGIN_HEIGHT (f);
  4470       int bottom_margin = FRAME_BOTTOM_MARGIN_HEIGHT (f);
  4471       int face_id = (FRAME_PARENT_FRAME (f)
  4472                      ? (!NILP (Vface_remapping_alist)
  4473                         ? lookup_basic_face (NULL, f,
  4474                                              CHILD_FRAME_BORDER_FACE_ID)
  4475                         : CHILD_FRAME_BORDER_FACE_ID)
  4476                      : (!NILP (Vface_remapping_alist)
  4477                         ? lookup_basic_face (NULL, f,
  4478                                              INTERNAL_BORDER_FACE_ID)
  4479                         : INTERNAL_BORDER_FACE_ID));
  4480       struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
  4481       void *view = FRAME_HAIKU_DRAWABLE (f);
  4482 
  4483       block_input ();
  4484       BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
  4485                        FRAME_PIXEL_HEIGHT (f));
  4486       BView_StartClip (view);
  4487       BView_ClipToRect (view, 0, 0, FRAME_PIXEL_WIDTH (f),
  4488                         FRAME_PIXEL_HEIGHT (f));
  4489 
  4490       if (face)
  4491         BView_SetHighColor (view, face->background);
  4492       else
  4493         BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (f));
  4494 
  4495       BView_FillRectangle (view, 0, margin, width, border);
  4496       BView_FillRectangle (view, 0, 0, border, height);
  4497       BView_FillRectangle (view, 0, margin, width, border);
  4498       BView_FillRectangle (view, width - border, 0, border, height);
  4499       BView_FillRectangle (view, 0, height - bottom_margin - border,
  4500                            width, border);
  4501       BView_EndClip (view);
  4502       BView_draw_unlock (view);
  4503       unblock_input ();
  4504     }
  4505 }
  4506 
  4507 void
  4508 mark_haiku_display (void)
  4509 {
  4510   if (x_display_list)
  4511     {
  4512       mark_object (x_display_list->color_map);
  4513       mark_object (x_display_list->default_name);
  4514     }
  4515 }
  4516 
  4517 void
  4518 haiku_scroll_bar_remove (struct scroll_bar *bar)
  4519 {
  4520   void *view;
  4521   struct frame *f;
  4522 
  4523   f = WINDOW_XFRAME (XWINDOW (bar->window));
  4524   view = FRAME_HAIKU_DRAWABLE (f);
  4525 
  4526   block_input ();
  4527   BView_forget_scroll_bar (view, bar->left, bar->top,
  4528                            bar->width, bar->height);
  4529   BScrollBar_delete (bar->scroll_bar);
  4530   expose_frame (WINDOW_XFRAME (XWINDOW (bar->window)),
  4531                 bar->left, bar->top, bar->width, bar->height);
  4532 
  4533   if (bar->horizontal)
  4534     wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
  4535   else
  4536     wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
  4537   unblock_input ();
  4538 };
  4539 
  4540 void
  4541 haiku_set_offset (struct frame *frame, int x, int y,
  4542                   int change_gravity)
  4543 {
  4544   Lisp_Object lframe;
  4545 
  4546   /* Don't allow moving a fullscreen frame: the semantics of that are
  4547      unclear.  */
  4548 
  4549   XSETFRAME (lframe, frame);
  4550   if (EQ (Fframe_parameter (lframe, Qfullscreen), Qfullboth)
  4551       /* Only do this if the fullscreen status has actually been
  4552          applied.  */
  4553       && frame->want_fullscreen == FULLSCREEN_NONE
  4554       /* And if the configury during frame creation has been
  4555          completed.  Otherwise, there will be no valid "old position"
  4556          to go back to.  */
  4557       && FRAME_OUTPUT_DATA (frame)->configury_done)
  4558     return;
  4559 
  4560   if (change_gravity > 0)
  4561     {
  4562       frame->top_pos = y;
  4563       frame->left_pos = x;
  4564       frame->size_hint_flags &= ~ (XNegative | YNegative);
  4565       if (x < 0)
  4566         frame->size_hint_flags |= XNegative;
  4567       if (y < 0)
  4568         frame->size_hint_flags |= YNegative;
  4569       frame->win_gravity = NorthWestGravity;
  4570     }
  4571 
  4572   haiku_update_size_hints (frame);
  4573 
  4574   block_input ();
  4575   if (change_gravity)
  4576     BWindow_set_offset (FRAME_HAIKU_WINDOW (frame), x, y);
  4577   unblock_input ();
  4578 }
  4579 
  4580 #ifdef USE_BE_CAIRO
  4581 cairo_t *
  4582 haiku_begin_cr_clip (struct frame *f, struct glyph_string *s)
  4583 {
  4584   cairo_t *cr = FRAME_CR_CONTEXT (f);
  4585 
  4586   if (!cr)
  4587     return NULL;
  4588 
  4589   cairo_save (cr);
  4590   return cr;
  4591 }
  4592 
  4593 void
  4594 haiku_end_cr_clip (cairo_t *cr)
  4595 {
  4596   if (!cr)
  4597     return;
  4598 
  4599   cairo_restore (cr);
  4600 }
  4601 #endif
  4602 
  4603 void
  4604 haiku_merge_cursor_foreground (struct glyph_string *s,
  4605                                unsigned long *foreground_out,
  4606                                unsigned long *background_out)
  4607 {
  4608   unsigned long background = FRAME_CURSOR_COLOR (s->f).pixel;
  4609   unsigned long foreground = s->face->background;
  4610 
  4611   if (background == foreground)
  4612     foreground = s->face->background;
  4613   if (background == foreground)
  4614     foreground = FRAME_OUTPUT_DATA (s->f)->cursor_fg;
  4615   if (background == foreground)
  4616     foreground = s->face->foreground;
  4617 
  4618   if (background == s->face->background
  4619       && foreground == s->face->foreground)
  4620     {
  4621       background = s->face->foreground;
  4622       foreground = s->face->background;
  4623     }
  4624 
  4625   if (foreground_out)
  4626     *foreground_out = foreground;
  4627   if (background_out)
  4628     *background_out = background;
  4629 }
  4630 
  4631 void
  4632 syms_of_haikuterm (void)
  4633 {
  4634   DEFVAR_BOOL ("haiku-initialized", haiku_initialized,
  4635      doc: /* Non-nil if the Haiku terminal backend has been initialized.  */);
  4636 
  4637   DEFVAR_BOOL ("x-use-underline-position-properties",
  4638                x_use_underline_position_properties,
  4639      doc: /* SKIP: real doc in xterm.c.  */);
  4640   x_use_underline_position_properties = 1;
  4641 
  4642   DEFVAR_BOOL ("x-underline-at-descent-line",
  4643                x_underline_at_descent_line,
  4644      doc: /* SKIP: real doc in xterm.c.  */);
  4645   x_underline_at_descent_line = 0;
  4646 
  4647   DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
  4648      doc: /* SKIP: real doc in xterm.c.  */);
  4649   Vx_toolkit_scroll_bars = Qt;
  4650 
  4651   DEFVAR_BOOL ("haiku-debug-on-fatal-error", haiku_debug_on_fatal_error,
  4652      doc: /* If non-nil, Emacs will launch the system debugger upon a fatal error.  */);
  4653   haiku_debug_on_fatal_error = 1;
  4654 
  4655   DEFSYM (Qshift, "shift");
  4656   DEFSYM (Qcontrol, "control");
  4657   DEFSYM (Qoption, "option");
  4658   DEFSYM (Qcommand, "command");
  4659 
  4660   DEFSYM (Qdata_directory, "data-directory");
  4661 
  4662   DEFVAR_LISP ("haiku-meta-keysym", Vhaiku_meta_keysym,
  4663      doc: /* Which key Emacs uses as the meta modifier.
  4664 This is either one of the symbols `shift', `control', `command', and
  4665 `option', or nil, in which case it is treated as `command'.
  4666 
  4667 Setting it to any other value is equivalent to `command'.  */);
  4668   Vhaiku_meta_keysym = Qnil;
  4669 
  4670   DEFVAR_LISP ("haiku-control-keysym", Vhaiku_control_keysym,
  4671      doc: /* Which key Emacs uses as the control modifier.
  4672 This is either one of the symbols `shift', `control', `command', and
  4673 `option', or nil, in which case it is treated as `control'.
  4674 
  4675 Setting it to any other value is equivalent to `control'.  */);
  4676   Vhaiku_control_keysym = Qnil;
  4677 
  4678   DEFVAR_LISP ("haiku-super-keysym", Vhaiku_super_keysym,
  4679      doc: /* Which key Emacs uses as the super modifier.
  4680 This is either one of the symbols `shift', `control', `command', and
  4681 `option', or nil, in which case it is treated as `option'.
  4682 
  4683 Setting it to any other value is equivalent to `option'.  */);
  4684   Vhaiku_super_keysym = Qnil;
  4685 
  4686   DEFVAR_LISP ("haiku-shift-keysym", Vhaiku_shift_keysym,
  4687      doc: /* Which key Emacs uses as the shift modifier.
  4688 This is either one of the symbols `shift', `control', `command', and
  4689 `option', or nil, in which case it is treated as `shift'.
  4690 
  4691 Setting it to any other value is equivalent to `shift'.  */);
  4692   Vhaiku_shift_keysym = Qnil;
  4693 
  4694   DEFSYM (Qx_use_underline_position_properties,
  4695           "x-use-underline-position-properties");
  4696 
  4697   DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
  4698 
  4699   rdb = Qnil;
  4700   staticpro (&rdb);
  4701 
  4702   Fprovide (Qhaiku, Qnil);
  4703 #ifdef USE_BE_CAIRO
  4704   Fprovide (intern_c_string ("cairo"), Qnil);
  4705 #endif
  4706 }

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