1 /* Haiku window system support
2    Copyright (C) 2021 Free Software Foundation, Inc.
3 
4 This file is part of GNU Emacs.
5 
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or (at
9 your option) any later version.
10 
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
18 
19 #include <config.h>
20 
21 #include <math.h>
22 
23 #include "lisp.h"
24 #include "frame.h"
25 #include "blockinput.h"
26 #include "termchar.h"
27 #include "font.h"
28 #include "keyboard.h"
29 #include "buffer.h"
30 #include "dispextern.h"
31 
32 #include "haikugui.h"
33 #include "haikuterm.h"
34 #include "haiku_support.h"
35 #include "termhooks.h"
36 
37 #include <stdlib.h>
38 
39 #include <kernel/OS.h>
40 
41 #define RGB_TO_ULONG(r, g, b) \
42   (((r) << 16) | ((g) << 8) | (b));
43 #define RED_FROM_ULONG(color)	(((color) >> 16) & 0xff)
44 #define GREEN_FROM_ULONG(color)	(((color) >> 8) & 0xff)
45 #define BLUE_FROM_ULONG(color)	((color) & 0xff)
46 
47 /* The frame of the currently visible tooltip.  */
48 static Lisp_Object tip_frame;
49 
50 /* The window-system window corresponding to the frame of the
51    currently visible tooltip.  */
52 static Window tip_window;
53 
54 /* A timer that hides or deletes the currently visible tooltip when it
55    fires.  */
56 static Lisp_Object tip_timer;
57 
58 /* STRING argument of last `x-show-tip' call.  */
59 static Lisp_Object tip_last_string;
60 
61 /* Normalized FRAME argument of last `x-show-tip' call.  */
62 static Lisp_Object tip_last_frame;
63 
64 /* PARMS argument of last `x-show-tip' call.  */
65 static Lisp_Object tip_last_parms;
66 
67 static void
68 haiku_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval);
69 static void
70 haiku_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name);
71 
72 static ptrdiff_t image_cache_refcount;
73 
74 static Lisp_Object
get_geometry_from_preferences(struct haiku_display_info * dpyinfo,Lisp_Object parms)75 get_geometry_from_preferences (struct haiku_display_info *dpyinfo,
76                                Lisp_Object parms)
77 {
78   struct {
79     const char *val;
80     const char *cls;
81     Lisp_Object tem;
82   } r[] = {
83     { "width",  "Width", Qwidth },
84     { "height", "Height", Qheight },
85     { "left", "Left", Qleft },
86     { "top", "Top", Qtop },
87   };
88 
89   int i;
90   for (i = 0; i < ARRAYELTS (r); ++i)
91     {
92       if (NILP (Fassq (r[i].tem, parms)))
93         {
94           Lisp_Object value
95             = gui_display_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls,
96                                    RES_TYPE_NUMBER);
97           if (! EQ (value, Qunbound))
98             parms = Fcons (Fcons (r[i].tem, value), parms);
99         }
100     }
101 
102   return parms;
103 }
104 
105 void
haiku_change_tool_bar_height(struct frame * f,int height)106 haiku_change_tool_bar_height (struct frame *f, int height)
107 {
108   int unit = FRAME_LINE_HEIGHT (f);
109   int old_height = FRAME_TOOL_BAR_HEIGHT (f);
110   int lines = (height + unit - 1) / unit;
111   Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
112 
113   /* Make sure we redisplay all windows in this frame.  */
114   fset_redisplay (f);
115 
116   FRAME_TOOL_BAR_HEIGHT (f) = height;
117   FRAME_TOOL_BAR_LINES (f) = lines;
118   store_frame_param (f, Qtool_bar_lines, make_fixnum (lines));
119 
120   if (FRAME_HAIKU_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
121     {
122       clear_frame (f);
123       clear_current_matrices (f);
124     }
125 
126   if ((height < old_height) && WINDOWP (f->tool_bar_window))
127     clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
128 
129   if (!f->tool_bar_resized)
130     {
131       /* As long as tool_bar_resized is false, effectively try to change
132 	 F's native height.  */
133       if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth))
134 	adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
135 			   1, false, Qtool_bar_lines);
136       else
137 	adjust_frame_size (f, -1, -1, 4, false, Qtool_bar_lines);
138 
139       f->tool_bar_resized =  f->tool_bar_redisplayed;
140     }
141   else
142     /* Any other change may leave the native size of F alone.  */
143     adjust_frame_size (f, -1, -1, 3, false, Qtool_bar_lines);
144 
145   /* adjust_frame_size might not have done anything, garbage frame
146      here.  */
147   adjust_frame_glyphs (f);
148   SET_FRAME_GARBAGED (f);
149 
150   if (FRAME_HAIKU_WINDOW (f))
151     haiku_clear_under_internal_border (f);
152 }
153 
154 void
haiku_change_tab_bar_height(struct frame * f,int height)155 haiku_change_tab_bar_height (struct frame *f, int height)
156 {
157   int unit = FRAME_LINE_HEIGHT (f);
158   int old_height = FRAME_TAB_BAR_HEIGHT (f);
159   int lines = (height + unit - 1) / unit;
160   Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
161 
162   /* Make sure we redisplay all windows in this frame.  */
163   fset_redisplay (f);
164 
165   /* Recalculate tab bar and frame text sizes.  */
166   FRAME_TAB_BAR_HEIGHT (f) = height;
167   FRAME_TAB_BAR_LINES (f) = lines;
168   store_frame_param (f, Qtab_bar_lines, make_fixnum (lines));
169 
170   if (FRAME_HAIKU_WINDOW (f) && FRAME_TAB_BAR_HEIGHT (f) == 0)
171     {
172       clear_frame (f);
173       clear_current_matrices (f);
174     }
175 
176   if ((height < old_height) && WINDOWP (f->tab_bar_window))
177     clear_glyph_matrix (XWINDOW (f->tab_bar_window)->current_matrix);
178 
179   if (!f->tab_bar_resized)
180     {
181       /* As long as tab_bar_resized is false, effectively try to change
182 	 F's native height.  */
183       if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth))
184 	adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
185 			   1, false, Qtab_bar_lines);
186       else
187 	adjust_frame_size (f, -1, -1, 4, false, Qtab_bar_lines);
188 
189       f->tab_bar_resized = f->tab_bar_redisplayed;
190     }
191   else
192     /* Any other change may leave the native size of F alone.  */
193     adjust_frame_size (f, -1, -1, 3, false, Qtab_bar_lines);
194 
195   /* adjust_frame_size might not have done anything, garbage frame
196      here.  */
197   adjust_frame_glyphs (f);
198   SET_FRAME_GARBAGED (f);
199   if (FRAME_HAIKU_WINDOW (f))
200     haiku_clear_under_internal_border (f);
201 }
202 
203 static void
haiku_set_no_focus_on_map(struct frame * f,Lisp_Object value,Lisp_Object oldval)204 haiku_set_no_focus_on_map (struct frame *f, Lisp_Object value,
205 			   Lisp_Object oldval)
206 {
207   if (!EQ (value, oldval))
208     FRAME_NO_FOCUS_ON_MAP (f) = !NILP (value);
209 }
210 
211 static void
haiku_set_tool_bar_lines(struct frame * f,Lisp_Object value,Lisp_Object oldval)212 haiku_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
213 {
214   if (FRAME_TOOLTIP_P (f))
215     return;
216   int nlines;
217 
218   /* Treat tool bars like menu bars.  */
219   if (FRAME_MINIBUF_ONLY_P (f))
220     return;
221 
222   /* Use VALUE only if an int >= 0.  */
223   if (RANGED_FIXNUMP (0, value, INT_MAX))
224     nlines = XFIXNAT (value);
225   else
226     nlines = 0;
227 
228   haiku_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
229 }
230 
231 static void
haiku_set_tab_bar_lines(struct frame * f,Lisp_Object value,Lisp_Object oldval)232 haiku_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
233 {
234   if (FRAME_TOOLTIP_P (f))
235     return;
236   int olines = FRAME_TAB_BAR_LINES (f);
237   int nlines;
238 
239   /* Treat tab bars like menu bars.  */
240   if (FRAME_MINIBUF_ONLY_P (f))
241     return;
242 
243   /* Use VALUE only if an int >= 0.  */
244   if (RANGED_FIXNUMP (0, value, INT_MAX))
245     nlines = XFIXNAT (value);
246   else
247     nlines = 0;
248 
249   if (nlines != olines && (olines == 0 || nlines == 0))
250     haiku_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
251 }
252 
253 
254 int
haiku_get_color(const char * name,Emacs_Color * color)255 haiku_get_color (const char *name, Emacs_Color *color)
256 {
257   unsigned short r16, g16, b16;
258   Lisp_Object tem;
259 
260   if (parse_color_spec (name, &r16, &g16, &b16))
261     {
262       color->pixel = RGB_TO_ULONG (r16 / 256, g16 / 256, b16 / 256);
263       color->red = r16;
264       color->green = g16;
265       color->blue = b16;
266       return 0;
267     }
268   else
269     {
270       block_input ();
271       eassert (x_display_list && !NILP (x_display_list->color_map));
272       tem = x_display_list->color_map;
273       for (; CONSP (tem); tem = XCDR (tem))
274 	{
275 	  Lisp_Object col = XCAR (tem);
276 	  if (CONSP (col) && !xstrcasecmp (SSDATA (XCAR (col)), name))
277 	    {
278 	      int32_t clr = XFIXNUM (XCDR (col));
279 	      color->pixel = clr;
280 	      color->red = RED_FROM_ULONG (clr) * 257;
281 	      color->green = GREEN_FROM_ULONG (clr) * 257;
282 	      color->blue = BLUE_FROM_ULONG (clr) * 257;
283 	      unblock_input ();
284 	      return 0;
285 	  }
286 	}
287 
288       unblock_input ();
289     }
290 
291   return 1;
292 }
293 
294 static struct haiku_display_info *
haiku_display_info_for_name(Lisp_Object name)295 haiku_display_info_for_name (Lisp_Object name)
296 {
297   CHECK_STRING (name);
298 
299   if (!NILP (Fstring_equal (name, build_string ("be"))))
300     {
301       if (!x_display_list)
302 	return x_display_list;
303 
304       error ("Be windowing not initialized");
305     }
306 
307   error ("Be displays can only be named \"be\"");
308 }
309 
310 static struct haiku_display_info *
check_haiku_display_info(Lisp_Object object)311 check_haiku_display_info (Lisp_Object object)
312 {
313   struct haiku_display_info *dpyinfo = NULL;
314 
315   if (NILP (object))
316     {
317       struct frame *sf = XFRAME (selected_frame);
318 
319       if (FRAME_HAIKU_P (sf) && FRAME_LIVE_P (sf))
320 	dpyinfo = FRAME_DISPLAY_INFO (sf);
321       else if (x_display_list)
322 	dpyinfo = x_display_list;
323       else
324 	error ("Be windowing not present");
325     }
326   else if (TERMINALP (object))
327     {
328       struct terminal *t = decode_live_terminal (object);
329 
330       if (t->type != output_haiku)
331 	error ("Terminal %d is not a Be display", t->id);
332 
333       dpyinfo = t->display_info.haiku;
334     }
335   else if (STRINGP (object))
336     dpyinfo = haiku_display_info_for_name (object);
337   else
338     {
339       struct frame *f = decode_window_system_frame (object);
340       dpyinfo = FRAME_DISPLAY_INFO (f);
341     }
342 
343   return dpyinfo;
344 }
345 
346 static void
haiku_set_title_bar_text(struct frame * f,Lisp_Object text)347 haiku_set_title_bar_text (struct frame *f, Lisp_Object text)
348 {
349   if (FRAME_HAIKU_WINDOW (f))
350     {
351       block_input ();
352       BWindow_retitle (FRAME_HAIKU_WINDOW (f), SSDATA (ENCODE_UTF_8 (text)));
353       unblock_input ();
354     }
355 }
356 
357 static void
haiku_set_title(struct frame * f,Lisp_Object name,Lisp_Object old_name)358 haiku_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
359 {
360   /* Don't change the title if it's already NAME.  */
361   if (EQ (name, f->title))
362     return;
363 
364   update_mode_lines = 26;
365 
366   fset_title (f, name);
367 
368   if (NILP (name))
369     name = f->name;
370 
371   haiku_set_title_bar_text (f, name);
372 }
373 
374 static void
haiku_set_child_frame_border_width(struct frame * f,Lisp_Object arg,Lisp_Object oldval)375 haiku_set_child_frame_border_width (struct frame *f,
376 				    Lisp_Object arg, Lisp_Object oldval)
377 {
378   int border;
379 
380   if (NILP (arg))
381     border = -1;
382   else if (RANGED_FIXNUMP (0, arg, INT_MAX))
383     border = XFIXNAT (arg);
384   else
385     signal_error ("Invalid child frame border width", arg);
386 
387   if (border != FRAME_CHILD_FRAME_BORDER_WIDTH (f))
388     {
389       f->child_frame_border_width = border;
390 
391       if (FRAME_HAIKU_WINDOW (f))
392 	adjust_frame_size (f, -1, -1, 3, 0, Qchild_frame_border_width);
393 
394       SET_FRAME_GARBAGED (f);
395     }
396 }
397 
398 static void
haiku_set_parent_frame(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)399 haiku_set_parent_frame (struct frame *f,
400 			Lisp_Object new_value, Lisp_Object old_value)
401 {
402   struct frame *p = NULL;
403   block_input ();
404   if (!NILP (new_value)
405       && (!FRAMEP (new_value)
406 	  || !FRAME_LIVE_P (p = XFRAME (new_value))
407 	  || !FRAME_HAIKU_P (p)))
408     {
409       store_frame_param (f, Qparent_frame, old_value);
410       unblock_input ();
411       error ("Invalid specification of `parent-frame'");
412     }
413 
414   if (EQ (new_value, old_value))
415     {
416       unblock_input ();
417       return;
418     }
419 
420   if (!NILP (old_value))
421     EmacsWindow_unparent (FRAME_HAIKU_WINDOW (f));
422   if (!NILP (new_value))
423     {
424       EmacsWindow_parent_to (FRAME_HAIKU_WINDOW (f),
425 			     FRAME_HAIKU_WINDOW (p));
426       BWindow_set_offset (FRAME_HAIKU_WINDOW (f),
427 			  f->left_pos, f->top_pos);
428     }
429   fset_parent_frame (f, new_value);
430   unblock_input ();
431 }
432 
433 static void
haiku_explicitly_set_name(struct frame * f,Lisp_Object arg,Lisp_Object oldval)434 haiku_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
435 {
436   haiku_set_name (f, arg, 1);
437 }
438 
439 static void
haiku_set_no_accept_focus(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)440 haiku_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
441 {
442   block_input ();
443   if (!EQ (new_value, old_value))
444     FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
445 
446   if (FRAME_HAIKU_WINDOW (f))
447     {
448       BWindow_set_avoid_focus (FRAME_HAIKU_WINDOW (f),
449 			       FRAME_NO_ACCEPT_FOCUS (f));
450     }
451   unblock_input ();
452 }
453 
454 static void
unwind_create_frame(Lisp_Object frame)455 unwind_create_frame (Lisp_Object frame)
456 {
457   struct frame *f = XFRAME (frame);
458 
459   /* If frame is already dead, nothing to do.  This can happen if the
460      display is disconnected after the frame has become official, but
461      before x_create_frame removes the unwind protect.  */
462   if (!FRAME_LIVE_P (f))
463     return;
464 
465   /* If frame is ``official'', nothing to do.  */
466   if (NILP (Fmemq (frame, Vframe_list)))
467     {
468 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
469       struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
470 #endif
471 
472       /* If the frame's image cache refcount is still the same as our
473 	 private shadow variable, it means we are unwinding a frame
474 	 for which we didn't yet call init_frame_faces, where the
475 	 refcount is incremented.  Therefore, we increment it here, so
476 	 that free_frame_faces, called in free_frame_resources later,
477 	 will not mistakenly decrement the counter that was not
478 	 incremented yet to account for this new frame.  */
479       if (FRAME_IMAGE_CACHE (f) != NULL
480 	  && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
481 	FRAME_IMAGE_CACHE (f)->refcount++;
482 
483       haiku_free_frame_resources (f);
484       free_glyphs (f);
485 
486 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
487       /* Check that reference counts are indeed correct.  */
488       if (dpyinfo->terminal->image_cache)
489 	eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
490 #endif
491     }
492 }
493 
494 static void
unwind_create_tip_frame(Lisp_Object frame)495 unwind_create_tip_frame (Lisp_Object frame)
496 {
497   unwind_create_frame (frame);
498   tip_window = NULL;
499   tip_frame = Qnil;
500 }
501 
502 static void
haiku_set_foreground_color(struct frame * f,Lisp_Object arg,Lisp_Object oldval)503 haiku_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
504 {
505   struct haiku_output *output = FRAME_OUTPUT_DATA (f);
506   unsigned long old_fg;
507 
508   Emacs_Color color;
509 
510   if (haiku_get_color (SSDATA (arg), &color))
511     {
512       store_frame_param (f, Qforeground_color, oldval);
513       unblock_input ();
514       error ("Bad color");
515     }
516 
517   old_fg = FRAME_FOREGROUND_PIXEL (f);
518   FRAME_FOREGROUND_PIXEL (f) = color.pixel;
519 
520   if (FRAME_HAIKU_WINDOW (f))
521     {
522 
523       block_input ();
524       if (output->cursor_color.pixel == old_fg)
525 	{
526 	  output->cursor_color.pixel = old_fg;
527 	  output->cursor_color.red = RED_FROM_ULONG (old_fg);
528 	  output->cursor_color.green = GREEN_FROM_ULONG (old_fg);
529 	  output->cursor_color.blue = BLUE_FROM_ULONG (old_fg);
530 	}
531 
532       unblock_input ();
533 
534       update_face_from_frame_parameter (f, Qforeground_color, arg);
535 
536       if (FRAME_VISIBLE_P (f))
537         redraw_frame (f);
538     }
539 }
540 
541 static void
unwind_popup(void)542 unwind_popup (void)
543 {
544   if (!popup_activated_p)
545     emacs_abort ();
546   --popup_activated_p;
547 }
548 
549 static Lisp_Object
haiku_create_frame(Lisp_Object parms,int ttip_p)550 haiku_create_frame (Lisp_Object parms, int ttip_p)
551 {
552   struct frame *f;
553   Lisp_Object frame, tem;
554   Lisp_Object name;
555   bool minibuffer_only = false;
556   bool face_change_before = face_change;
557   long window_prompting = 0;
558   ptrdiff_t count = SPECPDL_INDEX ();
559   Lisp_Object display;
560   struct haiku_display_info *dpyinfo = NULL;
561   struct kboard *kb;
562 
563   parms = Fcopy_alist (parms);
564 
565   Vx_resource_name = Vinvocation_name;
566 
567   display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0,
568                                  RES_TYPE_STRING);
569   if (EQ (display, Qunbound))
570     display = Qnil;
571   dpyinfo = check_haiku_display_info (display);
572   kb = dpyinfo->terminal->kboard;
573 
574   if (!dpyinfo->terminal->name)
575     error ("Terminal is not live, can't create new frames on it");
576 
577   name = gui_display_get_arg (dpyinfo, parms, Qname, 0, 0,
578                               RES_TYPE_STRING);
579   if (!STRINGP (name)
580       && ! EQ (name, Qunbound)
581       && ! NILP (name))
582     error ("Invalid frame name--not a string or nil");
583 
584   if (STRINGP (name))
585     Vx_resource_name = name;
586 
587   block_input ();
588 
589   /* make_frame_without_minibuffer can run Lisp code and garbage collect.  */
590   /* No need to protect DISPLAY because that's not used after passing
591      it to make_frame_without_minibuffer.  */
592   frame = Qnil;
593   tem = gui_display_get_arg (dpyinfo, parms, Qminibuffer,
594                              "minibuffer", "Minibuffer",
595                              RES_TYPE_SYMBOL);
596   if (ttip_p)
597     f = make_frame (0);
598   else if (EQ (tem, Qnone) || NILP (tem))
599       f = make_frame_without_minibuffer (Qnil, kb, display);
600   else if (EQ (tem, Qonly))
601     {
602       f = make_minibuffer_frame ();
603       minibuffer_only = 1;
604     }
605   else if (WINDOWP (tem))
606       f = make_frame_without_minibuffer (tem, kb, display);
607   else
608       f = make_frame (1);
609   XSETFRAME (frame, f);
610 
611   f->terminal = dpyinfo->terminal;
612 
613   f->output_method = output_haiku;
614   f->output_data.haiku = xzalloc (sizeof *f->output_data.haiku);
615 
616   f->output_data.haiku->pending_zoom_x = INT_MIN;
617   f->output_data.haiku->pending_zoom_y = INT_MIN;
618   f->output_data.haiku->pending_zoom_width = INT_MIN;
619   f->output_data.haiku->pending_zoom_height = INT_MIN;
620 
621   if (ttip_p)
622     f->wants_modeline = false;
623 
624   fset_icon_name (f, gui_display_get_arg (dpyinfo, parms, Qicon_name,
625                                           "iconName", "Title",
626                                           RES_TYPE_STRING));
627   if (! STRINGP (f->icon_name) || ttip_p)
628     fset_icon_name (f, Qnil);
629 
630   FRAME_DISPLAY_INFO (f) = dpyinfo;
631 
632   /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
633   if (!ttip_p)
634     record_unwind_protect (unwind_create_frame, frame);
635   else
636     record_unwind_protect (unwind_create_tip_frame, frame);
637 
638   FRAME_OUTPUT_DATA (f)->parent_desc = NULL;
639   FRAME_OUTPUT_DATA (f)->explicit_parent = 0;
640 
641   /* Set the name; the functions to which we pass f expect the name to
642      be set.  */
643   if (EQ (name, Qunbound) || NILP (name) || ! STRINGP (name))
644     {
645       fset_name (f, Vinvocation_name);
646       f->explicit_name = 0;
647     }
648   else
649     {
650       fset_name (f, name);
651       f->explicit_name = 1;
652       specbind (Qx_resource_name, name);
653     }
654 
655 #ifdef USE_BE_CAIRO
656   register_font_driver (&ftcrfont_driver, f);
657 #ifdef HAVE_HARFBUZZ
658   register_font_driver (&ftcrhbfont_driver, f);
659 #endif
660 #endif
661   register_font_driver (&haikufont_driver, f);
662 
663   f->tooltip = ttip_p;
664 
665   image_cache_refcount =
666     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
667 
668   gui_default_parameter (f, parms, Qfont_backend, Qnil,
669                          "fontBackend", "FontBackend", RES_TYPE_STRING);
670 
671   FRAME_RIF (f)->default_font_parameter (f, parms);
672 
673   unblock_input ();
674 
675   gui_default_parameter (f, parms, Qborder_width, make_fixnum (0),
676                          "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
677   gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (ttip_p ? 1 : 2),
678                          "internalBorderWidth", "InternalBorderWidth",
679                          RES_TYPE_NUMBER);
680   gui_default_parameter (f, parms, Qchild_frame_border_width, Qnil,
681 			 "childFrameBorderWidth", "childFrameBorderWidth",
682 			 RES_TYPE_NUMBER);
683   gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
684 		       NULL, NULL, RES_TYPE_NUMBER);
685   gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
686 		       NULL, NULL, RES_TYPE_NUMBER);
687   gui_default_parameter (f, parms, Qvertical_scroll_bars, !ttip_p ? Qt : Qnil,
688 			 "verticalScrollBars", "VerticalScrollBars",
689 			 RES_TYPE_SYMBOL);
690   gui_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
691                          "horizontalScrollBars", "HorizontalScrollBars",
692                          RES_TYPE_SYMBOL);
693   gui_default_parameter (f, parms, Qforeground_color, build_string ("black"),
694                          "foreground", "Foreground", RES_TYPE_STRING);
695   gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
696                          "background", "Background", RES_TYPE_STRING);
697   gui_default_parameter (f, parms, Qline_spacing, Qnil,
698                          "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
699   gui_default_parameter (f, parms, Qleft_fringe, Qnil,
700                          "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
701   gui_default_parameter (f, parms, Qright_fringe, Qnil,
702                          "rightFringe", "RightFringe", RES_TYPE_NUMBER);
703   gui_default_parameter (f, parms, Qno_special_glyphs, ttip_p ? Qnil : Qt,
704                          NULL, NULL, RES_TYPE_BOOLEAN);
705 
706   init_frame_faces (f);
707 
708   /* Read comment about this code in corresponding place in xfns.c.  */
709   tem = gui_display_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL,
710                              RES_TYPE_NUMBER);
711   if (FIXNUMP (tem))
712     store_frame_param (f, Qmin_width, tem);
713   tem = gui_display_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL,
714                              RES_TYPE_NUMBER);
715   if (FIXNUMP (tem))
716     store_frame_param (f, Qmin_height, tem);
717   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
718 		     FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1,
719 		     Qx_create_frame_1);
720 
721   if (!ttip_p)
722     {
723       gui_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL);
724       gui_default_parameter (f, parms, Qno_focus_on_map, Qnil,
725 			     NULL, NULL, RES_TYPE_BOOLEAN);
726       gui_default_parameter (f, parms, Qno_accept_focus, Qnil,
727 			     NULL, NULL, RES_TYPE_BOOLEAN);
728 
729       /* The resources controlling the menu-bar, tool-bar, and tab-bar are
730 	 processed specially at startup, and reflected in the mode
731 	 variables; ignore them here.  */
732       gui_default_parameter (f, parms, Qmenu_bar_lines,
733 			     NILP (Vmenu_bar_mode)
734 			     ? make_fixnum (0) : make_fixnum (1),
735 			     NULL, NULL, RES_TYPE_NUMBER);
736       gui_default_parameter (f, parms, Qtab_bar_lines,
737 			     NILP (Vtab_bar_mode)
738 			     ? make_fixnum (0) : make_fixnum (1),
739 			     NULL, NULL, RES_TYPE_NUMBER);
740       gui_default_parameter (f, parms, Qtool_bar_lines,
741 			     NILP (Vtool_bar_mode)
742 			     ? make_fixnum (0) : make_fixnum (1),
743 			     NULL, NULL, RES_TYPE_NUMBER);
744       gui_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
745 			     "BufferPredicate", RES_TYPE_SYMBOL);
746       gui_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
747 			     RES_TYPE_STRING);
748     }
749 
750   parms = get_geometry_from_preferences (dpyinfo, parms);
751   window_prompting = gui_figure_window_size (f, parms, false, true);
752 
753   if (ttip_p)
754     {
755        /* No fringes on tip frame.  */
756       f->fringe_cols = 0;
757       f->left_fringe_width = 0;
758       f->right_fringe_width = 0;
759       /* No dividers on tip frame.  */
760       f->right_divider_width = 0;
761       f->bottom_divider_width = 0;
762     }
763 
764   tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0,
765                              RES_TYPE_BOOLEAN);
766   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !NILP (tem));
767 
768   /* Add `tooltip' frame parameter's default value.  */
769   if (NILP (Fframe_parameter (frame, Qtooltip)) && ttip_p)
770     Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));
771 
772 #define ASSIGN_CURSOR(cursor, be_cursor) \
773   (FRAME_OUTPUT_DATA (f)->cursor = be_cursor)
774 
775   ASSIGN_CURSOR (text_cursor, BCursor_create_i_beam ());
776   ASSIGN_CURSOR (nontext_cursor, BCursor_create_default ());
777   ASSIGN_CURSOR (modeline_cursor, BCursor_create_modeline ());
778   ASSIGN_CURSOR (hand_cursor, BCursor_create_grab ());
779   ASSIGN_CURSOR (hourglass_cursor, BCursor_create_progress_cursor ());
780   ASSIGN_CURSOR (horizontal_drag_cursor,
781 		 BCursor_from_id (CURSOR_ID_RESIZE_EAST_WEST));
782   ASSIGN_CURSOR (vertical_drag_cursor,
783 		 BCursor_from_id (CURSOR_ID_RESIZE_NORTH_SOUTH));
784   ASSIGN_CURSOR (left_edge_cursor,
785 		 BCursor_from_id (CURSOR_ID_RESIZE_WEST));
786   ASSIGN_CURSOR (top_left_corner_cursor,
787 		 BCursor_from_id (CURSOR_ID_RESIZE_NORTH_WEST));
788   ASSIGN_CURSOR (top_edge_cursor,
789 		 BCursor_from_id (CURSOR_ID_RESIZE_NORTH));
790   ASSIGN_CURSOR (top_right_corner_cursor,
791 		 BCursor_from_id (CURSOR_ID_RESIZE_NORTH_EAST));
792   ASSIGN_CURSOR (right_edge_cursor,
793 		 BCursor_from_id (CURSOR_ID_RESIZE_EAST));
794   ASSIGN_CURSOR (bottom_right_corner_cursor,
795 		 BCursor_from_id (CURSOR_ID_RESIZE_SOUTH_EAST));
796   ASSIGN_CURSOR (bottom_edge_cursor,
797 		 BCursor_from_id (CURSOR_ID_RESIZE_SOUTH));
798   ASSIGN_CURSOR (bottom_left_corner_cursor,
799 		 BCursor_from_id (CURSOR_ID_RESIZE_SOUTH_WEST));
800   ASSIGN_CURSOR (no_cursor,
801 		 BCursor_from_id (CURSOR_ID_NO_CURSOR));
802 
803   ASSIGN_CURSOR (current_cursor, FRAME_OUTPUT_DATA (f)->text_cursor);
804 #undef ASSIGN_CURSOR
805 
806 
807   if (ttip_p)
808     f->no_split = true;
809   f->terminal->reference_count++;
810 
811   FRAME_OUTPUT_DATA (f)->window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view);
812   if (!FRAME_OUTPUT_DATA (f)->window)
813     xsignal1 (Qerror, build_unibyte_string ("Could not create window"));
814 
815   if (!minibuffer_only && !ttip_p && FRAME_EXTERNAL_MENU_BAR (f))
816     initialize_frame_menubar (f);
817 
818   FRAME_OUTPUT_DATA (f)->window_desc = FRAME_OUTPUT_DATA (f)->window;
819 
820   Vframe_list = Fcons (frame, Vframe_list);
821 
822   Lisp_Object parent_frame = gui_display_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
823 						  RES_TYPE_SYMBOL);
824 
825   if (EQ (parent_frame, Qunbound)
826       || NILP (parent_frame)
827       || !FRAMEP (parent_frame)
828       || !FRAME_LIVE_P (XFRAME (parent_frame)))
829     parent_frame = Qnil;
830 
831   fset_parent_frame (f, parent_frame);
832   store_frame_param (f, Qparent_frame, parent_frame);
833 
834   if (!NILP (parent_frame))
835     haiku_set_parent_frame (f, parent_frame, Qnil);
836 
837   gui_default_parameter (f, parms, Qundecorated, Qnil, NULL, NULL, RES_TYPE_BOOLEAN);
838 
839   gui_default_parameter (f, parms, Qicon_type, Qnil,
840                          "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
841   if (ttip_p)
842     {
843       gui_default_parameter (f, parms, Qundecorated, Qt, NULL, NULL, RES_TYPE_BOOLEAN);
844       gui_default_parameter (f, parms, Qno_accept_focus, Qt, NULL, NULL,
845 			     RES_TYPE_BOOLEAN);
846     }
847   else
848     {
849       gui_default_parameter (f, parms, Qauto_raise, Qnil,
850 			     "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
851       gui_default_parameter (f, parms, Qauto_lower, Qnil,
852 			     "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
853       gui_default_parameter (f, parms, Qcursor_type, Qbox,
854 			     "cursorType", "CursorType", RES_TYPE_SYMBOL);
855       gui_default_parameter (f, parms, Qscroll_bar_width, Qnil,
856 			     "scrollBarWidth", "ScrollBarWidth",
857 			     RES_TYPE_NUMBER);
858       gui_default_parameter (f, parms, Qscroll_bar_height, Qnil,
859 			     "scrollBarHeight", "ScrollBarHeight",
860 			     RES_TYPE_NUMBER);
861       gui_default_parameter (f, parms, Qalpha, Qnil,
862 			     "alpha", "Alpha", RES_TYPE_NUMBER);
863       gui_default_parameter (f, parms, Qfullscreen, Qnil,
864 			     "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
865     }
866 
867   gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
868 			 "inhibitDoubleBuffering", "InhibitDoubleBuffering",
869 			 RES_TYPE_BOOLEAN);
870 
871   if (ttip_p)
872     {
873       Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
874 
875       call2 (Qface_set_after_frame_default, frame, Qnil);
876 
877       if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
878 	{
879 	  AUTO_FRAME_ARG (arg, Qbackground_color, bg);
880 	  Fmodify_frame_parameters (frame, arg);
881 	}
882     }
883 
884   if (ttip_p)
885     face_change = face_change_before;
886 
887   f->can_set_window_size = true;
888 
889   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
890 		     0, true, ttip_p ? Qtip_frame : Qx_create_frame_2);
891 
892   if (!FRAME_OUTPUT_DATA (f)->explicit_parent && !ttip_p)
893     {
894       Lisp_Object visibility;
895 
896       visibility = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
897                                         RES_TYPE_SYMBOL);
898       if (EQ (visibility, Qunbound))
899 	visibility = Qt;
900       if (EQ (visibility, Qicon))
901 	haiku_iconify_frame (f);
902       else if (!NILP (visibility))
903 	haiku_visualize_frame (f);
904       else /* Qnil */
905 	{
906 	  f->was_invisible = true;
907 	}
908     }
909 
910   if (!ttip_p)
911     {
912       if (FRAME_HAS_MINIBUF_P (f)
913 	  && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
914 	      || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
915 	kset_default_minibuffer_frame (kb, frame);
916     }
917 
918   for (tem = parms; CONSP (tem); tem = XCDR (tem))
919     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
920       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
921 
922   if (window_prompting & (USPosition | PPosition))
923     haiku_set_offset (f, f->left_pos, f->top_pos, 1);
924   else
925     BWindow_center_on_screen (FRAME_HAIKU_WINDOW (f));
926 
927   /* Make sure windows on this frame appear in calls to next-window
928      and similar functions.  */
929   Vwindow_list = Qnil;
930 
931   if (ttip_p)
932     adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
933 		       0, true, Qtip_frame);
934 
935   return unbind_to (count, frame);
936 }
937 
938 static void
compute_tip_xy(struct frame * f,Lisp_Object parms,Lisp_Object dx,Lisp_Object dy,int width,int height,int * root_x,int * root_y)939 compute_tip_xy (struct frame *f,
940 		Lisp_Object parms, Lisp_Object dx, Lisp_Object dy,
941 		int width, int height, int *root_x, int *root_y)
942 {
943   Lisp_Object left, top, right, bottom;
944   int min_x = 0, min_y = 0, max_x = 0, max_y = 0;
945 
946   /* User-specified position?  */
947   left = Fcdr (Fassq (Qleft, parms));
948   top  = Fcdr (Fassq (Qtop, parms));
949   right = Fcdr (Fassq (Qright, parms));
950   bottom = Fcdr (Fassq (Qbottom, parms));
951 
952   /* Move the tooltip window where the mouse pointer is.  Resize and
953      show it.  */
954   if ((!FIXNUMP (left) && !FIXNUMP (right))
955       || (!FIXNUMP (top) && !FIXNUMP (bottom)))
956     {
957       int x, y;
958 
959       /* Default min and max values.  */
960       min_x = 0;
961       min_y = 0;
962       BScreen_px_dim (&max_x, &max_y);
963 
964       block_input ();
965       BView_get_mouse (FRAME_HAIKU_VIEW (f), &x, &y);
966       BView_convert_to_screen (FRAME_HAIKU_VIEW (f), &x, &y);
967       *root_x = x;
968       *root_y = y;
969       unblock_input ();
970     }
971 
972   if (FIXNUMP (top))
973     *root_y = XFIXNUM (top);
974   else if (FIXNUMP (bottom))
975     *root_y = XFIXNUM (bottom) - height;
976   else if (*root_y + XFIXNUM (dy) <= min_y)
977     *root_y = min_y; /* Can happen for negative dy */
978   else if (*root_y + XFIXNUM (dy) + height <= max_y)
979     /* It fits below the pointer */
980       *root_y += XFIXNUM (dy);
981   else if (height + XFIXNUM (dy) + min_y <= *root_y)
982     /* It fits above the pointer.  */
983     *root_y -= height + XFIXNUM (dy);
984   else
985     /* Put it on the top.  */
986     *root_y = min_y;
987 
988   if (FIXNUMP (left))
989     *root_x = XFIXNUM (left);
990   else if (FIXNUMP (right))
991     *root_x = XFIXNUM (right) - width;
992   else if (*root_x + XFIXNUM (dx) <= min_x)
993     *root_x = 0; /* Can happen for negative dx */
994   else if (*root_x + XFIXNUM (dx) + width <= max_x)
995     /* It fits to the right of the pointer.  */
996     *root_x += XFIXNUM (dx);
997   else if (width + XFIXNUM (dx) + min_x <= *root_x)
998     /* It fits to the left of the pointer.  */
999     *root_x -= width + XFIXNUM (dx);
1000   else
1001     /* Put it left justified on the screen -- it ought to fit that way.  */
1002     *root_x = min_x;
1003 }
1004 
1005 static Lisp_Object
haiku_hide_tip(bool delete)1006 haiku_hide_tip (bool delete)
1007 {
1008   if (!NILP (tip_timer))
1009     {
1010       call1 (Qcancel_timer, tip_timer);
1011       tip_timer = Qnil;
1012     }
1013 
1014   Lisp_Object it, frame;
1015   FOR_EACH_FRAME (it, frame)
1016     if (FRAME_WINDOW_P (XFRAME (frame)) &&
1017 	FRAME_HAIKU_VIEW (XFRAME (frame)))
1018       BView_set_tooltip (FRAME_HAIKU_VIEW (XFRAME (frame)), NULL);
1019 
1020   if (NILP (tip_frame)
1021       || (!delete && !NILP (tip_frame)
1022 	  && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
1023     return Qnil;
1024   else
1025     {
1026       ptrdiff_t count;
1027       Lisp_Object was_open = Qnil;
1028 
1029       count = SPECPDL_INDEX ();
1030       specbind (Qinhibit_redisplay, Qt);
1031       specbind (Qinhibit_quit, Qt);
1032 
1033       if (!NILP (tip_frame))
1034 	{
1035 	  if (FRAME_LIVE_P (XFRAME (tip_frame)))
1036 	    {
1037 	      if (delete)
1038 		{
1039 		  delete_frame (tip_frame, Qnil);
1040 		  tip_frame = Qnil;
1041 		}
1042 	      else
1043 		haiku_unvisualize_frame (XFRAME (tip_frame));
1044 
1045 	      was_open = Qt;
1046 	    }
1047 	  else
1048 	    tip_frame = Qnil;
1049 	}
1050       else
1051 	tip_frame = Qnil;
1052 
1053       return unbind_to (count, was_open);
1054     }
1055 }
1056 
1057 static void
haiku_set_undecorated(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)1058 haiku_set_undecorated (struct frame *f, Lisp_Object new_value,
1059 		       Lisp_Object old_value)
1060 {
1061   if (EQ (new_value, old_value))
1062     return;
1063 
1064   block_input ();
1065   FRAME_UNDECORATED (f) = !NILP (new_value);
1066   BWindow_change_decoration (FRAME_HAIKU_WINDOW (f), NILP (new_value));
1067   unblock_input ();
1068 }
1069 
1070 static void
haiku_set_menu_bar_lines(struct frame * f,Lisp_Object value,Lisp_Object oldval)1071 haiku_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1072 {
1073   if (FRAME_TOOLTIP_P (f))
1074     return;
1075   int nlines;
1076   if (TYPE_RANGED_FIXNUMP (int, value))
1077     nlines = XFIXNUM (value);
1078   else
1079     nlines = 0;
1080 
1081   fset_redisplay (f);
1082 
1083   FRAME_MENU_BAR_LINES (f) = 0;
1084   FRAME_MENU_BAR_HEIGHT (f) = 0;
1085 
1086   if (nlines)
1087     {
1088       FRAME_EXTERNAL_MENU_BAR (f) = 1;
1089       if (FRAME_HAIKU_P (f) && !FRAME_HAIKU_MENU_BAR (f))
1090 	XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = 1;
1091     }
1092   else
1093     {
1094       if (FRAME_EXTERNAL_MENU_BAR (f))
1095 	free_frame_menubar (f);
1096       FRAME_EXTERNAL_MENU_BAR (f) = 0;
1097       if (FRAME_HAIKU_P (f))
1098 	FRAME_HAIKU_MENU_BAR (f) = 0;
1099     }
1100 
1101   adjust_frame_glyphs (f);
1102 }
1103 
1104 /* Return geometric attributes of FRAME.  According to the value of
1105    ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the inner
1106    edges of FRAME, the root window edges of frame (Qroot_edges).  Any
1107    other value means to return the geometry as returned by
1108    Fx_frame_geometry.  */
1109 static Lisp_Object
frame_geometry(Lisp_Object frame,Lisp_Object attribute)1110 frame_geometry (Lisp_Object frame, Lisp_Object attribute)
1111 {
1112   struct frame *f = decode_live_frame (frame);
1113   check_window_system (f);
1114 
1115   if (EQ (attribute, Qouter_edges))
1116     return list4i (f->left_pos, f->top_pos,
1117 		   f->left_pos, f->top_pos);
1118   else if (EQ (attribute, Qnative_edges))
1119     return list4i (f->left_pos, f->top_pos,
1120 		   f->left_pos + FRAME_PIXEL_WIDTH (f),
1121 		   f->top_pos + FRAME_PIXEL_HEIGHT (f));
1122   else if (EQ (attribute, Qinner_edges))
1123     return list4i (f->left_pos + FRAME_INTERNAL_BORDER_WIDTH (f),
1124 		   f->top_pos + FRAME_INTERNAL_BORDER_WIDTH (f) +
1125 		   FRAME_MENU_BAR_HEIGHT (f) + FRAME_TOOL_BAR_HEIGHT (f),
1126 		   f->left_pos - FRAME_INTERNAL_BORDER_WIDTH (f) +
1127 		   FRAME_PIXEL_WIDTH (f),
1128 		   f->top_pos + FRAME_PIXEL_HEIGHT (f) -
1129 		   FRAME_INTERNAL_BORDER_WIDTH (f));
1130 
1131   else
1132     return
1133       list (Fcons (Qouter_position,
1134 		   Fcons (make_fixnum (f->left_pos),
1135 			  make_fixnum (f->top_pos))),
1136 	    Fcons (Qouter_size,
1137 		   Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f)),
1138 			  make_fixnum (FRAME_PIXEL_HEIGHT (f)))),
1139 	    Fcons (Qexternal_border_size,
1140 		   Fcons (make_fixnum (0), make_fixnum (0))),
1141 	    Fcons (Qtitle_bar_size,
1142 		   Fcons (make_fixnum (0), make_fixnum (0))),
1143 	    Fcons (Qmenu_bar_external, Qnil),
1144 	    Fcons (Qmenu_bar_size, Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) -
1145 						       (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)),
1146 					  make_fixnum (FRAME_MENU_BAR_HEIGHT (f)))),
1147 	    Fcons (Qtool_bar_external, Qnil),
1148 	    Fcons (Qtool_bar_position, Qtop),
1149 	    Fcons (Qtool_bar_size, Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) -
1150 						       (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)),
1151 					  make_fixnum (FRAME_TOOL_BAR_HEIGHT (f)))),
1152 	    Fcons (Qinternal_border_width, make_fixnum (FRAME_INTERNAL_BORDER_WIDTH (f))));
1153 }
1154 
1155 void
haiku_set_background_color(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1156 haiku_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1157 {
1158   CHECK_STRING (arg);
1159 
1160   block_input ();
1161   Emacs_Color color;
1162 
1163   if (haiku_get_color (SSDATA (arg), &color))
1164     {
1165       store_frame_param (f, Qbackground_color, oldval);
1166       unblock_input ();
1167       error ("Bad color");
1168     }
1169 
1170   FRAME_OUTPUT_DATA (f)->cursor_fg = color.pixel;
1171   FRAME_BACKGROUND_PIXEL (f) = color.pixel;
1172 
1173   if (FRAME_HAIKU_VIEW (f))
1174     {
1175       struct face *defface;
1176 
1177       BView_draw_lock (FRAME_HAIKU_VIEW (f));
1178       BView_SetViewColor (FRAME_HAIKU_VIEW (f), color.pixel);
1179       BView_draw_unlock (FRAME_HAIKU_VIEW (f));
1180 
1181       defface = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
1182       if (defface)
1183 	{
1184 	  defface->background = color.pixel;
1185 	  update_face_from_frame_parameter (f, Qbackground_color, arg);
1186 	  clear_frame (f);
1187 	}
1188     }
1189 
1190   if (FRAME_VISIBLE_P (f))
1191     SET_FRAME_GARBAGED (f);
1192   unblock_input ();
1193 }
1194 
1195 void
haiku_set_cursor_color(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1196 haiku_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1197 {
1198   CHECK_STRING (arg);
1199 
1200   block_input ();
1201   Emacs_Color color;
1202 
1203   if (haiku_get_color (SSDATA (arg), &color))
1204     {
1205       store_frame_param (f, Qcursor_color, oldval);
1206       unblock_input ();
1207       error ("Bad color");
1208     }
1209 
1210   FRAME_CURSOR_COLOR (f) = color;
1211   if (FRAME_VISIBLE_P (f))
1212     {
1213       gui_update_cursor (f, 0);
1214       gui_update_cursor (f, 1);
1215     }
1216   update_face_from_frame_parameter (f, Qcursor_color, arg);
1217   unblock_input ();
1218 }
1219 
1220 void
haiku_set_cursor_type(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1221 haiku_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1222 {
1223   set_frame_cursor_types (f, arg);
1224 }
1225 
1226 unsigned long
haiku_get_pixel(haiku bitmap,int x,int y)1227 haiku_get_pixel (haiku bitmap, int x, int y)
1228 {
1229   unsigned char *data;
1230   int32_t bytes_per_row;
1231   int mono_p;
1232   int left;
1233   int right;
1234   int top;
1235   int bottom;
1236 
1237   data = BBitmap_data (bitmap);
1238   BBitmap_dimensions (bitmap, &left, &top, &right, &bottom,
1239 		      &bytes_per_row, &mono_p);
1240 
1241   if (x < left || x > right || y < top || y > bottom)
1242     emacs_abort ();
1243 
1244   if (!mono_p)
1245     return ((uint32_t *) (data + (bytes_per_row * y)))[x];
1246 
1247   int byte = y * bytes_per_row + x / 8;
1248   return data[byte] & (1 << (x % 8));
1249 }
1250 
1251 void
haiku_put_pixel(haiku bitmap,int x,int y,unsigned long pixel)1252 haiku_put_pixel (haiku bitmap, int x, int y, unsigned long pixel)
1253 {
1254   unsigned char *data;
1255   int32_t bytes_per_row;
1256   int mono_p;
1257   int left;
1258   int right;
1259   int top;
1260   int bottom;
1261 
1262   data = BBitmap_data (bitmap);
1263   BBitmap_dimensions (bitmap, &left, &top, &right, &bottom,
1264 		      &bytes_per_row, &mono_p);
1265 
1266   if (x < left || x > right || y < top || y > bottom)
1267     emacs_abort ();
1268 
1269   if (mono_p)
1270     {
1271       ptrdiff_t off = y * bytes_per_row;
1272       ptrdiff_t bit = x % 8;
1273       ptrdiff_t xoff = x / 8;
1274 
1275       unsigned char *byte = data + off + xoff;
1276       if (!pixel)
1277 	*byte &= ~(1 << bit);
1278       else
1279 	*byte |= 1 << bit;
1280     }
1281   else
1282     ((uint32_t *) (data + (bytes_per_row * y)))[x] = pixel;
1283 }
1284 
1285 void
haiku_free_frame_resources(struct frame * f)1286 haiku_free_frame_resources (struct frame *f)
1287 {
1288   haiku window, drawable, mbar;
1289   Mouse_HLInfo *hlinfo;
1290   struct haiku_display_info *dpyinfo;
1291   Lisp_Object bar;
1292   struct scroll_bar *b;
1293 
1294   block_input ();
1295   check_window_system (f);
1296 
1297   hlinfo = MOUSE_HL_INFO (f);
1298   window = FRAME_HAIKU_WINDOW (f);
1299   drawable = FRAME_HAIKU_VIEW (f);
1300   mbar = FRAME_HAIKU_MENU_BAR (f);
1301   dpyinfo = FRAME_DISPLAY_INFO (f);
1302 
1303   free_frame_faces (f);
1304 
1305   /* Free scroll bars */
1306   for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
1307     {
1308       b = XSCROLL_BAR (bar);
1309       haiku_scroll_bar_remove (b);
1310     }
1311 
1312   if (f == dpyinfo->highlight_frame)
1313     dpyinfo->highlight_frame = 0;
1314   if (f == dpyinfo->focused_frame)
1315     dpyinfo->focused_frame = 0;
1316   if (f == dpyinfo->last_mouse_motion_frame)
1317     dpyinfo->last_mouse_motion_frame = NULL;
1318   if (f == dpyinfo->last_mouse_frame)
1319     dpyinfo->last_mouse_frame = NULL;
1320   if (f == dpyinfo->focus_event_frame)
1321     dpyinfo->focus_event_frame = NULL;
1322 
1323   if (f == hlinfo->mouse_face_mouse_frame)
1324     reset_mouse_highlight (hlinfo);
1325 
1326   if (mbar)
1327     {
1328       BMenuBar_delete (mbar);
1329       if (f->output_data.haiku->menu_bar_open_p)
1330 	{
1331 	  --popup_activated_p;
1332 	  f->output_data.haiku->menu_bar_open_p = 0;
1333 	}
1334     }
1335 
1336   if (drawable)
1337     BView_emacs_delete (drawable);
1338 
1339   if (window)
1340     BWindow_quit (window);
1341 
1342   /* Free cursors */
1343 
1344   BCursor_delete (f->output_data.haiku->text_cursor);
1345   BCursor_delete (f->output_data.haiku->nontext_cursor);
1346   BCursor_delete (f->output_data.haiku->modeline_cursor);
1347   BCursor_delete (f->output_data.haiku->hand_cursor);
1348   BCursor_delete (f->output_data.haiku->hourglass_cursor);
1349   BCursor_delete (f->output_data.haiku->horizontal_drag_cursor);
1350   BCursor_delete (f->output_data.haiku->vertical_drag_cursor);
1351   BCursor_delete (f->output_data.haiku->left_edge_cursor);
1352   BCursor_delete (f->output_data.haiku->top_left_corner_cursor);
1353   BCursor_delete (f->output_data.haiku->top_edge_cursor);
1354   BCursor_delete (f->output_data.haiku->top_right_corner_cursor);
1355   BCursor_delete (f->output_data.haiku->right_edge_cursor);
1356   BCursor_delete (f->output_data.haiku->bottom_right_corner_cursor);
1357   BCursor_delete (f->output_data.haiku->bottom_edge_cursor);
1358   BCursor_delete (f->output_data.haiku->bottom_left_corner_cursor);
1359   BCursor_delete (f->output_data.haiku->no_cursor);
1360 
1361   xfree (FRAME_OUTPUT_DATA (f));
1362   FRAME_OUTPUT_DATA (f) = NULL;
1363 
1364   unblock_input ();
1365 }
1366 
1367 void
haiku_iconify_frame(struct frame * frame)1368 haiku_iconify_frame (struct frame *frame)
1369 {
1370   if (FRAME_ICONIFIED_P (frame))
1371     return;
1372 
1373   block_input ();
1374 
1375   SET_FRAME_VISIBLE (frame, false);
1376   SET_FRAME_ICONIFIED (frame, true);
1377 
1378   BWindow_iconify (FRAME_HAIKU_WINDOW (frame));
1379 
1380   unblock_input ();
1381 }
1382 
1383 void
haiku_visualize_frame(struct frame * f)1384 haiku_visualize_frame (struct frame *f)
1385 {
1386   block_input ();
1387 
1388   if (!FRAME_VISIBLE_P (f))
1389     {
1390       if (FRAME_NO_FOCUS_ON_MAP (f))
1391 	BWindow_set_avoid_focus (FRAME_HAIKU_WINDOW (f), 1);
1392       BWindow_set_visible (FRAME_HAIKU_WINDOW (f), 1);
1393       if (FRAME_NO_FOCUS_ON_MAP (f) &&
1394 	  !FRAME_NO_ACCEPT_FOCUS (f))
1395 	BWindow_set_avoid_focus (FRAME_HAIKU_WINDOW (f), 0);
1396 
1397       haiku_set_offset (f, f->left_pos, f->top_pos, 0);
1398 
1399       SET_FRAME_VISIBLE (f, 1);
1400       SET_FRAME_ICONIFIED (f, 0);
1401     }
1402 
1403   unblock_input ();
1404 }
1405 
1406 void
haiku_unvisualize_frame(struct frame * f)1407 haiku_unvisualize_frame (struct frame *f)
1408 {
1409   block_input ();
1410 
1411   BWindow_set_visible (FRAME_HAIKU_WINDOW (f), 0);
1412   SET_FRAME_VISIBLE (f, 0);
1413   SET_FRAME_ICONIFIED (f, 0);
1414 
1415   unblock_input ();
1416 }
1417 
1418 void
haiku_set_internal_border_width(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1419 haiku_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1420 {
1421   int old_width = FRAME_INTERNAL_BORDER_WIDTH (f);
1422   int new_width = check_int_nonnegative (arg);
1423 
1424   if (new_width == old_width)
1425     return;
1426   f->internal_border_width = new_width;
1427 
1428   if (FRAME_HAIKU_WINDOW (f))
1429     {
1430       adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width);
1431       haiku_clear_under_internal_border (f);
1432     }
1433 
1434   SET_FRAME_GARBAGED (f);
1435 }
1436 
1437 void
haiku_set_frame_visible_invisible(struct frame * f,bool visible_p)1438 haiku_set_frame_visible_invisible (struct frame *f, bool visible_p)
1439 {
1440   if (visible_p)
1441     haiku_visualize_frame (f);
1442   else
1443     haiku_unvisualize_frame (f);
1444 }
1445 
1446 void
frame_set_mouse_pixel_position(struct frame * f,int pix_x,int pix_y)1447 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
1448 {
1449   block_input ();
1450 
1451   BView_convert_to_screen (FRAME_HAIKU_VIEW (f), &pix_x, &pix_y);
1452   be_warp_pointer (pix_x, pix_y);
1453 
1454   unblock_input ();
1455 }
1456 
1457 void
haiku_query_color(uint32_t col,Emacs_Color * color_def)1458 haiku_query_color (uint32_t col, Emacs_Color *color_def)
1459 {
1460   color_def->red = RED_FROM_ULONG (col) * 257;
1461   color_def->green = GREEN_FROM_ULONG (col) * 257;
1462   color_def->blue = BLUE_FROM_ULONG (col) * 257;
1463 
1464   color_def->pixel = col;
1465 }
1466 
1467 Display_Info *
check_x_display_info(Lisp_Object object)1468 check_x_display_info (Lisp_Object object)
1469 {
1470   return check_haiku_display_info (object);
1471 }
1472 
1473 /* Rename frame F to NAME.  If NAME is nil, set F's name to "GNU
1474    Emacs".  If EXPLICIT_P is non-zero, that indicates Lisp code is
1475    setting the name, not redisplay; in that case, set F's name to NAME
1476    and set F->explicit_name; if NAME is nil, clear F->explicit_name.
1477 
1478    If EXPLICIT_P is zero, it means redisplay is setting the name; the
1479    name provided will be ignored if explicit_name is set.  */
1480 void
haiku_set_name(struct frame * f,Lisp_Object name,bool explicit_p)1481 haiku_set_name (struct frame *f, Lisp_Object name, bool explicit_p)
1482 {
1483   if (explicit_p)
1484     {
1485       if (f->explicit_name && NILP (name))
1486 	update_mode_lines = 24;
1487 
1488       f->explicit_name = !NILP (name);
1489     }
1490   else if (f->explicit_name)
1491     return;
1492 
1493   if (NILP (name))
1494     name = build_unibyte_string ("GNU Emacs");
1495 
1496   if (!NILP (Fstring_equal (name, f->name)))
1497     return;
1498 
1499   fset_name (f, name);
1500 
1501   if (!NILP (f->title))
1502     name = f->title;
1503 
1504   haiku_set_title_bar_text (f, name);
1505 }
1506 
1507 static void
haiku_set_inhibit_double_buffering(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)1508 haiku_set_inhibit_double_buffering (struct frame *f,
1509 				    Lisp_Object new_value,
1510 				    Lisp_Object old_value)
1511 {
1512   block_input ();
1513 #ifndef USE_BE_CAIRO
1514   if (FRAME_HAIKU_WINDOW (f))
1515     {
1516       if (NILP (new_value))
1517 	{
1518 #endif
1519 	  EmacsView_set_up_double_buffering (FRAME_HAIKU_VIEW (f));
1520 	  if (!NILP (old_value))
1521 	    {
1522 	      SET_FRAME_GARBAGED (f);
1523 	      expose_frame (f, 0, 0, 0, 0);
1524 	    }
1525 #ifndef USE_BE_CAIRO
1526 	}
1527       else
1528 	EmacsView_disable_double_buffering (FRAME_HAIKU_VIEW (f));
1529     }
1530 #endif
1531   unblock_input ();
1532 }
1533 
1534 
1535 
1536 DEFUN ("haiku-set-mouse-absolute-pixel-position",
1537        Fhaiku_set_mouse_absolute_pixel_position,
1538        Shaiku_set_mouse_absolute_pixel_position, 2, 2, 0,
1539        doc: /* Move mouse pointer to a pixel position at (X, Y).  The
1540 coordinates X and Y are interpreted to start from the top-left
1541 corner of the screen.  */)
1542   (Lisp_Object x, Lisp_Object y)
1543 {
1544   int xval = check_integer_range (x, INT_MIN, INT_MAX);
1545   int yval = check_integer_range (y, INT_MIN, INT_MAX);
1546 
1547   if (!x_display_list)
1548     error ("Window system not initialized");
1549 
1550   block_input ();
1551   be_warp_pointer (xval, yval);
1552   unblock_input ();
1553   return Qnil;
1554 }
1555 
1556 DEFUN ("haiku-mouse-absolute-pixel-position", Fhaiku_mouse_absolute_pixel_position,
1557        Shaiku_mouse_absolute_pixel_position, 0, 0, 0,
1558        doc: /* Return absolute position of mouse cursor in pixels.
1559 The position is returned as a cons cell (X . Y) of the coordinates of
1560 the mouse cursor position in pixels relative to a position (0, 0) of the
1561 selected frame's display.  */)
1562   (void)
1563 {
1564   if (!x_display_list)
1565     return Qnil;
1566 
1567   struct frame *f = SELECTED_FRAME ();
1568 
1569   if (FRAME_INITIAL_P (f) || !FRAME_HAIKU_P (f)
1570       || !FRAME_HAIKU_VIEW (f))
1571     return Qnil;
1572 
1573   block_input ();
1574   void *view = FRAME_HAIKU_VIEW (f);
1575 
1576   int x, y;
1577   BView_get_mouse (view, &x, &y);
1578   BView_convert_to_screen (view, &x, &y);
1579   unblock_input ();
1580 
1581   return Fcons (make_fixnum (x), make_fixnum (y));
1582 }
1583 
1584 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
1585        doc: /* SKIP: real doc in xfns.c.  */)
1586      (Lisp_Object terminal)
1587 {
1588   return Qt;
1589 }
1590 
1591 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
1592        doc: /* SKIP: real doc in xfns.c.  */)
1593   (Lisp_Object color, Lisp_Object frame)
1594 {
1595   Emacs_Color col;
1596   CHECK_STRING (color);
1597   decode_window_system_frame (frame);
1598 
1599   return haiku_get_color (SSDATA (color), &col) ? Qnil : Qt;
1600 }
1601 
1602 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
1603        doc: /* SKIP: real doc in xfns.c.  */)
1604      (Lisp_Object color, Lisp_Object frame)
1605 {
1606   Emacs_Color col;
1607   CHECK_STRING (color);
1608   decode_window_system_frame (frame);
1609 
1610   block_input ();
1611   if (haiku_get_color (SSDATA (color), &col))
1612     {
1613       unblock_input ();
1614       return Qnil;
1615     }
1616   unblock_input ();
1617   return list3i (lrint (col.red), lrint (col.green), lrint (col.blue));
1618 }
1619 
1620 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
1621        0, 1, 0,
1622        doc: /* SKIP: real doc in xfns.c.  */)
1623   (Lisp_Object terminal)
1624 {
1625   return Qnil;
1626 }
1627 
1628 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1629        1, 3, 0,
1630        doc: /* SKIP: real doc in xfns.c.  */)
1631      (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed)
1632 {
1633   struct haiku_display_info *dpy_info;
1634   CHECK_STRING (display);
1635 
1636   if (NILP (Fstring_equal (display, build_string ("be"))))
1637     !NILP (must_succeed) ? fatal ("Bad display") : error ("Bad display");
1638   dpy_info = haiku_term_init ();
1639 
1640   if (!dpy_info)
1641     !NILP (must_succeed) ? fatal ("Display not responding") :
1642       error ("Display not responding");
1643 
1644   return Qnil;
1645 }
1646 
1647 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
1648        0, 1, 0,
1649        doc: /* SKIP: real doc in xfns.c.  */)
1650   (Lisp_Object terminal)
1651 
1652 {
1653   check_haiku_display_info (terminal);
1654 
1655   int width, height;
1656   BScreen_px_dim (&width, &height);
1657   return make_fixnum (width);
1658 }
1659 
1660 DEFUN ("x-display-pixel-height", Fx_display_pixel_height, Sx_display_pixel_height,
1661        0, 1, 0,
1662        doc: /* SKIP: real doc in xfns.c.  */)
1663   (Lisp_Object terminal)
1664 
1665 {
1666   check_haiku_display_info (terminal);
1667 
1668   int width, height;
1669   BScreen_px_dim (&width, &height);
1670   return make_fixnum (width);
1671 }
1672 
1673 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
1674        doc: /* SKIP: real doc in xfns.c.  */)
1675   (Lisp_Object terminal)
1676 {
1677   struct haiku_display_info *dpyinfo = check_haiku_display_info (terminal);
1678 
1679   int width, height;
1680   BScreen_px_dim (&width, &height);
1681 
1682   return make_fixnum (height / (dpyinfo->resy / 25.4));
1683 }
1684 
1685 
1686 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
1687        doc: /* SKIP: real doc in xfns.c.  */)
1688   (Lisp_Object terminal)
1689 {
1690   struct haiku_display_info *dpyinfo = check_haiku_display_info (terminal);
1691 
1692   int width, height;
1693   BScreen_px_dim (&width, &height);
1694 
1695   return make_fixnum (height / (dpyinfo->resy / 25.4));
1696 }
1697 
1698 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1699        1, 1, 0,
1700        doc: /* SKIP: real doc in xfns.c.  */)
1701      (Lisp_Object parms)
1702 {
1703   return haiku_create_frame (parms, 0);
1704 }
1705 
1706 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1707        Sx_display_visual_class, 0, 1, 0,
1708        doc: /* SKIP: real doc in xfns.c.  */)
1709   (Lisp_Object terminal)
1710 {
1711   check_haiku_display_info (terminal);
1712 
1713   int planes = be_get_display_planes ();
1714 
1715   if (planes == 8)
1716     return intern ("static-color");
1717   else if (planes == 16 || planes == 15)
1718     return intern ("pseudo-color");
1719 
1720   return intern ("direct-color");
1721 }
1722 
1723 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
1724        doc: /* SKIP: real doc in xfns.c.  */)
1725   (Lisp_Object string, Lisp_Object frame, Lisp_Object parms,
1726    Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
1727 {
1728   struct frame *tip_f;
1729   struct window *w;
1730   int root_x, root_y;
1731   struct buffer *old_buffer;
1732   struct text_pos pos;
1733   int width, height;
1734   int old_windows_or_buffers_changed = windows_or_buffers_changed;
1735   ptrdiff_t count = SPECPDL_INDEX ();
1736   ptrdiff_t count_1;
1737   Lisp_Object window, size, tip_buf;
1738 
1739   AUTO_STRING (tip, " *tip*");
1740 
1741   specbind (Qinhibit_redisplay, Qt);
1742 
1743   CHECK_STRING (string);
1744 
1745   if (NILP (frame))
1746     frame = selected_frame;
1747   decode_window_system_frame (frame);
1748 
1749   if (NILP (timeout))
1750     timeout = make_fixnum (5);
1751   else
1752     CHECK_FIXNAT (timeout);
1753 
1754   if (NILP (dx))
1755     dx = make_fixnum (5);
1756   else
1757     CHECK_FIXNUM (dx);
1758 
1759   if (NILP (dy))
1760     dy = make_fixnum (-10);
1761   else
1762     CHECK_FIXNUM (dy);
1763 
1764   if (haiku_use_system_tooltips)
1765     {
1766       int root_x, root_y;
1767       CHECK_STRING (string);
1768       if (STRING_MULTIBYTE (string))
1769 	string = ENCODE_UTF_8 (string);
1770 
1771       if (NILP (frame))
1772 	frame = selected_frame;
1773 
1774       struct frame *f = decode_window_system_frame (frame);
1775       block_input ();
1776 
1777       char *str = xstrdup (SSDATA (string));
1778       int height = be_plain_font_height ();
1779       int width;
1780       char *tok = strtok (str, "\n");
1781       width = be_string_width_with_plain_font (tok);
1782 
1783       while ((tok = strtok (NULL, "\n")))
1784 	{
1785 	  height = be_plain_font_height ();
1786 	  int w = be_string_width_with_plain_font (tok);
1787 	  if (w > width)
1788 	    w = width;
1789 	}
1790       free (str);
1791 
1792       height += 16; /* Default margin.  */
1793       width += 16; /* Ditto.  Unfortunately there isn't a more
1794 		      reliable way to get it.  */
1795       compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
1796       BView_convert_from_screen (FRAME_HAIKU_VIEW (f), &root_x, &root_y);
1797       BView_set_and_show_sticky_tooltip (FRAME_HAIKU_VIEW (f), SSDATA (string),
1798 					 root_x, root_y);
1799       unblock_input ();
1800       goto start_timer;
1801     }
1802 
1803   if (!NILP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
1804     {
1805       if (FRAME_VISIBLE_P (XFRAME (tip_frame))
1806 	  && EQ (frame, tip_last_frame)
1807 	  && !NILP (Fequal_including_properties (string, tip_last_string))
1808 	  && !NILP (Fequal (parms, tip_last_parms)))
1809 	{
1810 	  /* Only DX and DY have changed.  */
1811 	  tip_f = XFRAME (tip_frame);
1812 	  if (!NILP (tip_timer))
1813 	    {
1814 	      Lisp_Object timer = tip_timer;
1815 
1816 	      tip_timer = Qnil;
1817 	      call1 (Qcancel_timer, timer);
1818 	    }
1819 
1820 	  block_input ();
1821 	  compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
1822 			  FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
1823 	  haiku_set_offset (tip_f, root_x, root_y, 1);
1824 	  haiku_visualize_frame (tip_f);
1825 	  unblock_input ();
1826 
1827 	  goto start_timer;
1828 	}
1829       else if (tooltip_reuse_hidden_frame && EQ (frame, tip_last_frame))
1830 	{
1831 	  bool delete = false;
1832 	  Lisp_Object tail, elt, parm, last;
1833 
1834 	  /* Check if every parameter in PARMS has the same value in
1835 	     tip_last_parms.  This may destruct tip_last_parms
1836 	     which, however, will be recreated below.  */
1837 	  for (tail = parms; CONSP (tail); tail = XCDR (tail))
1838 	    {
1839 	      elt = XCAR (tail);
1840 	      parm = Fcar (elt);
1841 	      /* The left, top, right and bottom parameters are handled
1842 		 by compute_tip_xy so they can be ignored here.  */
1843 	      if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
1844 		  && !EQ (parm, Qright) && !EQ (parm, Qbottom))
1845 		{
1846 		  last = Fassq (parm, tip_last_parms);
1847 		  if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
1848 		    {
1849 		      /* We lost, delete the old tooltip.  */
1850 		      delete = true;
1851 		      break;
1852 		    }
1853 		  else
1854 		    tip_last_parms =
1855 		      call2 (Qassq_delete_all, parm, tip_last_parms);
1856 		}
1857 	      else
1858 		tip_last_parms =
1859 		  call2 (Qassq_delete_all, parm, tip_last_parms);
1860 	    }
1861 
1862 	  /* Now check if there's a parameter left in tip_last_parms with a
1863 	     non-nil value.  */
1864 	  for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
1865 	    {
1866 	      elt = XCAR (tail);
1867 	      parm = Fcar (elt);
1868 	      if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
1869 		  && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
1870 		{
1871 		  /* We lost, delete the old tooltip.  */
1872 		  delete = true;
1873 		  break;
1874 		}
1875 	    }
1876 
1877 	  haiku_hide_tip (delete);
1878 	}
1879       else
1880 	haiku_hide_tip (true);
1881     }
1882   else
1883     haiku_hide_tip (true);
1884 
1885   tip_last_frame = frame;
1886   tip_last_string = string;
1887   tip_last_parms = parms;
1888 
1889   /* Block input until the tip has been fully drawn, to avoid crashes
1890      when drawing tips in menus.  */
1891   block_input ();
1892 
1893   if (NILP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
1894     {
1895       /* Add default values to frame parameters.  */
1896       if (NILP (Fassq (Qname, parms)))
1897 	parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
1898       if (NILP (Fassq (Qinternal_border_width, parms)))
1899 	parms = Fcons (Fcons (Qinternal_border_width, make_fixnum (3)), parms);
1900       if (NILP (Fassq (Qborder_width, parms)))
1901 	parms = Fcons (Fcons (Qborder_width, make_fixnum (1)), parms);
1902       if (NILP (Fassq (Qborder_color, parms)))
1903 	parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")),
1904 		       parms);
1905       if (NILP (Fassq (Qbackground_color, parms)))
1906 	parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
1907 		       parms);
1908 
1909       /* Create a frame for the tooltip and record it in the global
1910 	 variable tip_frame.  */
1911 
1912       if (NILP (tip_frame = haiku_create_frame (parms, 1)))
1913 	{
1914 	  /* Creating the tip frame failed.  */
1915 	  unblock_input ();
1916 	  return unbind_to (count, Qnil);
1917 	}
1918     }
1919 
1920   tip_f = XFRAME (tip_frame);
1921   window = FRAME_ROOT_WINDOW (tip_f);
1922   tip_buf = Fget_buffer_create (tip, Qnil);
1923   /* We will mark the tip window a "pseudo-window" below, and such
1924      windows cannot have display margins.  */
1925   bset_left_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
1926   bset_right_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
1927   set_window_buffer (window, tip_buf, false, false);
1928   w = XWINDOW (window);
1929   w->pseudo_window_p = true;
1930   /* Try to avoid that `other-window' select us (Bug#47207).  */
1931   Fset_window_parameter (window, Qno_other_window, Qt);
1932 
1933   /* Set up the frame's root window.  Note: The following code does not
1934      try to size the window or its frame correctly.  Its only purpose is
1935      to make the subsequent text size calculations work.  The right
1936      sizes should get installed when the toolkit gets back to us.  */
1937   w->left_col = 0;
1938   w->top_line = 0;
1939   w->pixel_left = 0;
1940   w->pixel_top = 0;
1941 
1942   if (CONSP (Vx_max_tooltip_size)
1943       && RANGED_FIXNUMP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
1944       && RANGED_FIXNUMP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
1945     {
1946       w->total_cols = XFIXNAT (XCAR (Vx_max_tooltip_size));
1947       w->total_lines = XFIXNAT (XCDR (Vx_max_tooltip_size));
1948     }
1949   else
1950     {
1951       w->total_cols = 80;
1952       w->total_lines = 40;
1953     }
1954 
1955   w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
1956   w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
1957   FRAME_TOTAL_COLS (tip_f) = WINDOW_TOTAL_COLS (w);
1958   adjust_frame_glyphs (tip_f);
1959 
1960   /* Insert STRING into the root window's buffer and fit the frame to
1961      the buffer.  */
1962   count_1 = SPECPDL_INDEX ();
1963   old_buffer = current_buffer;
1964   set_buffer_internal_1 (XBUFFER (w->contents));
1965   bset_truncate_lines (current_buffer, Qnil);
1966   specbind (Qinhibit_read_only, Qt);
1967   specbind (Qinhibit_modification_hooks, Qt);
1968   specbind (Qinhibit_point_motion_hooks, Qt);
1969   Ferase_buffer ();
1970   Finsert (1, &string);
1971   clear_glyph_matrix (w->desired_matrix);
1972   clear_glyph_matrix (w->current_matrix);
1973   SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
1974   try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
1975   /* Calculate size of tooltip window.  */
1976   size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
1977 				  make_fixnum (w->pixel_height), Qnil,
1978 				  Qnil);
1979   /* Add the frame's internal border to calculated size.  */
1980   width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
1981   height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
1982   /* Calculate position of tooltip frame.  */
1983   compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
1984   BWindow_resize (FRAME_HAIKU_WINDOW (tip_f), width, height);
1985   haiku_set_offset (tip_f, root_x, root_y, 1);
1986   BWindow_set_tooltip_decoration (FRAME_HAIKU_WINDOW (tip_f));
1987   BView_set_view_cursor (FRAME_HAIKU_VIEW (tip_f),
1988 			 FRAME_OUTPUT_DATA (XFRAME (frame))->current_cursor);
1989   SET_FRAME_VISIBLE (tip_f, 1);
1990   BWindow_set_visible (FRAME_HAIKU_WINDOW (tip_f), 1);
1991 
1992   w->must_be_updated_p = true;
1993   flush_frame (tip_f);
1994   update_single_window (w);
1995   set_buffer_internal_1 (old_buffer);
1996   unbind_to (count_1, Qnil);
1997   unblock_input ();
1998   windows_or_buffers_changed = old_windows_or_buffers_changed;
1999 
2000  start_timer:
2001   /* Let the tip disappear after timeout seconds.  */
2002   tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
2003 		     intern ("x-hide-tip"));
2004 
2005   return unbind_to (count, Qnil);
2006 }
2007 
2008 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2009        doc: /* SKIP: real doc in xfns.c.  */)
2010   (void)
2011 {
2012   return haiku_hide_tip (!tooltip_reuse_hidden_frame);
2013 }
2014 
2015 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection, 1, 1, 0,
2016        doc: /* SKIP: real doc in xfns.c.  */
2017        attributes: noreturn)
2018   (Lisp_Object terminal)
2019 {
2020   check_haiku_display_info (terminal);
2021 
2022   error ("Cannot close Haiku displays");
2023 }
2024 
2025 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
2026        doc: /* SKIP: real doc in xfns.c. */)
2027   (void)
2028 {
2029   if (!x_display_list)
2030     return Qnil;
2031 
2032   return list1 (XCAR (x_display_list->name_list_element));
2033 }
2034 
2035 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
2036        doc: /* SKIP: real doc in xfns.c.  */)
2037   (Lisp_Object terminal)
2038 {
2039   check_haiku_display_info (terminal);
2040   return build_string ("Haiku, Inc.");
2041 }
2042 
2043 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
2044        doc: /* SKIP: real doc in xfns.c. */)
2045   (Lisp_Object terminal)
2046 {
2047   check_haiku_display_info (terminal);
2048   return list3i (5, 1, 1);
2049 }
2050 
2051 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
2052        doc: /* SKIP: real doc in xfns.c.  */)
2053   (Lisp_Object terminal)
2054 {
2055   check_haiku_display_info (terminal);
2056   return make_fixnum (be_get_display_screens ());
2057 }
2058 
2059 DEFUN ("haiku-get-version-string", Fhaiku_get_version_string,
2060        Shaiku_get_version_string, 0, 0, 0,
2061        doc: /* Return a string describing the current Haiku version.  */)
2062   (void)
2063 {
2064   char buf[1024];
2065 
2066   be_get_version_string ((char *) &buf, sizeof buf);
2067   return build_string (buf);
2068 }
2069 
2070 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
2071        0, 1, 0,
2072        doc: /* SKIP: real doc in xfns.c.  */)
2073   (Lisp_Object terminal)
2074 {
2075   check_haiku_display_info (terminal);
2076 
2077   return make_fixnum (be_get_display_color_cells ());
2078 }
2079 
2080 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2081        0, 1, 0,
2082        doc: /* SKIP: real doc in xfns.c.  */)
2083   (Lisp_Object terminal)
2084 {
2085   check_haiku_display_info (terminal);
2086 
2087   return make_fixnum (be_get_display_planes ());
2088 }
2089 
2090 DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
2091        0, 1, 0,
2092        doc: /* SKIP: real doc in xfns.c.  */)
2093   (Lisp_Object frame)
2094 {
2095   struct frame *f = decode_live_frame (frame);
2096   check_window_system (f);
2097 
2098   return EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)) ? Qt : Qnil;
2099 }
2100 
2101 DEFUN ("x-display-backing-store", Fx_display_backing_store, Sx_display_backing_store,
2102        0, 1, 0,
2103        doc: /* SKIP: real doc in xfns.c.  */)
2104   (Lisp_Object terminal)
2105 {
2106   if (FRAMEP (terminal))
2107     {
2108       CHECK_LIVE_FRAME (terminal);
2109       struct frame *f = decode_window_system_frame (terminal);
2110 
2111       if (FRAME_HAIKU_VIEW (f) &&
2112 	  EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)))
2113 	return FRAME_PARENT_FRAME (f) ? Qwhen_mapped : Qalways;
2114       else
2115 	return Qnot_useful;
2116     }
2117   else
2118     {
2119       check_haiku_display_info (terminal);
2120       return Qnot_useful;
2121     }
2122 }
2123 
2124 DEFUN ("haiku-frame-geometry", Fhaiku_frame_geometry, Shaiku_frame_geometry, 0, 1, 0,
2125        doc: /* Return geometric attributes of FRAME.
2126 FRAME must be a live frame and defaults to the selected one.  The return
2127 value is an association list of the attributes listed below.  All height
2128 and width values are in pixels.
2129 
2130 `outer-position' is a cons of the outer left and top edges of FRAME
2131   relative to the origin - the position (0, 0) - of FRAME's display.
2132 
2133 `outer-size' is a cons of the outer width and height of FRAME.  The
2134   outer size includes the title bar and the external borders as well as
2135   any menu and/or tool bar of frame.
2136 
2137 `external-border-size' is a cons of the horizontal and vertical width of
2138   FRAME's external borders as supplied by the window manager.
2139 
2140 `title-bar-size' is a cons of the width and height of the title bar of
2141   FRAME as supplied by the window manager.  If both of them are zero,
2142   FRAME has no title bar.  If only the width is zero, Emacs was not
2143   able to retrieve the width information.
2144 
2145 `menu-bar-external', if non-nil, means the menu bar is external (never
2146   included in the inner edges of FRAME).
2147 
2148 `menu-bar-size' is a cons of the width and height of the menu bar of
2149   FRAME.
2150 
2151 `tool-bar-external', if non-nil, means the tool bar is external (never
2152   included in the inner edges of FRAME).
2153 
2154 `tool-bar-position' tells on which side the tool bar on FRAME is and can
2155   be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
2156   has no tool bar.
2157 
2158 `tool-bar-size' is a cons of the width and height of the tool bar of
2159   FRAME.
2160 
2161 `internal-border-width' is the width of the internal border of
2162   FRAME.  */)
2163   (Lisp_Object frame)
2164 {
2165   return frame_geometry (frame, Qnil);
2166 }
2167 
2168 DEFUN ("haiku-frame-edges", Fhaiku_frame_edges, Shaiku_frame_edges, 0, 2, 0,
2169        doc: /* Return edge coordinates of FRAME.
2170 FRAME must be a live frame and defaults to the selected one.  The return
2171 value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
2172 in pixels relative to the origin - the position (0, 0) - of FRAME's
2173 display.
2174 
2175 If optional argument TYPE is the symbol `outer-edges', return the outer
2176 edges of FRAME.  The outer edges comprise the decorations of the window
2177 manager (like the title bar or external borders) as well as any external
2178 menu or tool bar of FRAME.  If optional argument TYPE is the symbol
2179 `native-edges' or nil, return the native edges of FRAME.  The native
2180 edges exclude the decorations of the window manager and any external
2181 menu or tool bar of FRAME.  If TYPE is the symbol `inner-edges', return
2182 the inner edges of FRAME.  These edges exclude title bar, any borders,
2183 menu bar or tool bar of FRAME.  */)
2184   (Lisp_Object frame, Lisp_Object type)
2185 {
2186   return frame_geometry (frame, ((EQ (type, Qouter_edges)
2187 				  || EQ (type, Qinner_edges))
2188 				 ? type
2189 				 : Qnative_edges));
2190 }
2191 
2192 DEFUN ("haiku-read-file-name", Fhaiku_read_file_name, Shaiku_read_file_name, 1, 6, 0,
2193        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
2194 Optional arg FRAME specifies a frame on which to display the file panel.
2195 If it is nil, the current frame is used instead.
2196 The frame being used will be brought to the front of
2197 the display after the file panel is closed.
2198 Optional arg DIR, if non-nil, supplies a default directory.
2199 Optional arg MUSTMATCH, if non-nil, means the returned file or
2200 directory must exist.
2201 Optional arg DIR_ONLY_P, if non-nil, means choose only directories.
2202 Optional arg SAVE_TEXT, if non-nil, specifies some text to show in the entry field.  */)
2203   (Lisp_Object prompt, Lisp_Object frame,
2204    Lisp_Object dir, Lisp_Object mustmatch,
2205    Lisp_Object dir_only_p, Lisp_Object save_text)
2206 {
2207   ptrdiff_t idx;
2208   if (!x_display_list)
2209     error ("Be windowing not initialized");
2210 
2211   if (!NILP (dir))
2212     CHECK_STRING (dir);
2213 
2214   if (!NILP (save_text))
2215     CHECK_STRING (save_text);
2216 
2217   if (NILP (frame))
2218     frame = selected_frame;
2219 
2220   CHECK_STRING (prompt);
2221 
2222   CHECK_LIVE_FRAME (frame);
2223   check_window_system (XFRAME (frame));
2224 
2225   idx = SPECPDL_INDEX ();
2226   record_unwind_protect_void (unwind_popup);
2227 
2228   struct frame *f = XFRAME (frame);
2229 
2230   FRAME_DISPLAY_INFO (f)->focus_event_frame = f;
2231 
2232   ++popup_activated_p;
2233   char *fn = be_popup_file_dialog (!NILP (mustmatch) || !NILP (dir_only_p),
2234 				   !NILP (dir) ? SSDATA (ENCODE_UTF_8 (dir)) : NULL,
2235 				   !NILP (mustmatch), !NILP (dir_only_p),
2236 				   FRAME_HAIKU_WINDOW (f),
2237 				   !NILP (save_text) ? SSDATA (ENCODE_UTF_8 (save_text)) : NULL,
2238 				   SSDATA (ENCODE_UTF_8 (prompt)),
2239 				   block_input, unblock_input);
2240 
2241   unbind_to (idx, Qnil);
2242 
2243   block_input ();
2244   BWindow_activate (FRAME_HAIKU_WINDOW (f));
2245   unblock_input ();
2246 
2247   if (!fn)
2248     return Qnil;
2249 
2250   Lisp_Object p = build_string_from_utf8 (fn);
2251   free (fn);
2252   return p;
2253 }
2254 
2255 DEFUN ("haiku-put-resource", Fhaiku_put_resource, Shaiku_put_resource,
2256        2, 2, 0, doc: /* Place STRING by the key RESOURCE in the resource database.
2257 It can later be retrieved with `x-get-resource'.  */)
2258   (Lisp_Object resource, Lisp_Object string)
2259 {
2260   CHECK_STRING (resource);
2261   if (!NILP (string))
2262     CHECK_STRING (string);
2263 
2264   put_xrm_resource (resource, string);
2265   return Qnil;
2266 }
2267 
2268 DEFUN ("haiku-frame-list-z-order", Fhaiku_frame_list_z_order,
2269        Shaiku_frame_list_z_order, 0, 1, 0,
2270        doc: /* Return list of Emacs' frames, in Z (stacking) order.
2271 If TERMINAL is non-nil and specifies a live frame, return the child
2272 frames of that frame in Z (stacking) order.
2273 
2274 As it is impossible to reliably determine the frame stacking order on
2275 Haiku, the selected frame is always the first element of the returned
2276 list, while the rest are not guaranteed to be in any particular order.
2277 
2278 Frames are listed from topmost (first) to bottommost (last).  */)
2279   (Lisp_Object terminal)
2280 {
2281   Lisp_Object frames = Qnil;
2282   Lisp_Object head, tail;
2283   Lisp_Object sel = Qnil;
2284 
FOR_EACH_FRAME(head,tail)2285   FOR_EACH_FRAME (head, tail)
2286     {
2287       struct frame *f = XFRAME (tail);
2288       if (!FRAME_HAIKU_P (f) ||
2289 	  (FRAMEP (terminal) &&
2290 	   FRAME_LIVE_P (XFRAME (terminal)) &&
2291 	   !EQ (terminal, get_frame_param (f, Qparent_frame))))
2292 	continue;
2293 
2294       if (EQ (tail, selected_frame))
2295 	sel = tail;
2296       else
2297 	frames = Fcons (tail, frames);
2298     }
2299 
2300   if (NILP (sel))
2301     return frames;
2302   return Fcons (sel, frames);
2303 }
2304 
2305 DEFUN ("x-display-save-under", Fx_display_save_under,
2306        Sx_display_save_under, 0, 1, 0,
2307        doc: /* SKIP: real doc in xfns.c.  */)
2308   (Lisp_Object terminal)
2309 {
2310   check_haiku_display_info (terminal);
2311 
2312   if (FRAMEP (terminal))
2313     {
2314       struct frame *f = decode_window_system_frame (terminal);
2315       return FRAME_HAIKU_VIEW (f) && EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)) ?
2316 	Qt : Qnil;
2317     }
2318 
2319   return Qnil;
2320 }
2321 
2322 frame_parm_handler haiku_frame_parm_handlers[] =
2323   {
2324     gui_set_autoraise,
2325     gui_set_autolower,
2326     haiku_set_background_color,
2327     NULL, /* x_set_border_color */
2328     gui_set_border_width,
2329     haiku_set_cursor_color,
2330     haiku_set_cursor_type,
2331     gui_set_font,
2332     haiku_set_foreground_color,
2333     NULL, /* set icon name */
2334     NULL, /* set icon type */
2335     haiku_set_child_frame_border_width,
2336     haiku_set_internal_border_width,
2337     gui_set_right_divider_width,
2338     gui_set_bottom_divider_width,
2339     haiku_set_menu_bar_lines,
2340     NULL, /* set mouse color */
2341     haiku_explicitly_set_name,
2342     gui_set_scroll_bar_width,
2343     gui_set_scroll_bar_height,
2344     haiku_set_title,
2345     gui_set_unsplittable,
2346     gui_set_vertical_scroll_bars,
2347     gui_set_horizontal_scroll_bars,
2348     gui_set_visibility,
2349     haiku_set_tab_bar_lines,
2350     haiku_set_tool_bar_lines,
2351     NULL, /* set scroll bar fg */
2352     NULL, /* set scroll bar bkg */
2353     gui_set_screen_gamma,
2354     gui_set_line_spacing,
2355     gui_set_left_fringe,
2356     gui_set_right_fringe,
2357     NULL, /* x wait for wm */
2358     gui_set_fullscreen,
2359     gui_set_font_backend,
2360     gui_set_alpha,
2361     NULL, /* set sticky */
2362     NULL, /* set tool bar pos */
2363     haiku_set_inhibit_double_buffering,
2364     haiku_set_undecorated,
2365     haiku_set_parent_frame,
2366     NULL, /* set skip taskbar */
2367     haiku_set_no_focus_on_map,
2368     haiku_set_no_accept_focus,
2369     NULL, /* set z group */
2370     NULL, /* set override redir */
2371     gui_set_no_special_glyphs
2372   };
2373 
2374 void
syms_of_haikufns(void)2375 syms_of_haikufns (void)
2376 {
2377   DEFSYM (Qfont_parameter, "font-parameter");
2378   DEFSYM (Qcancel_timer, "cancel-timer");
2379   DEFSYM (Qassq_delete_all, "assq-delete-all");
2380 
2381   DEFSYM (Qalways, "always");
2382   DEFSYM (Qnot_useful, "not-useful");
2383   DEFSYM (Qwhen_mapped, "when-mapped");
2384 
2385   defsubr (&Sx_hide_tip);
2386   defsubr (&Sxw_display_color_p);
2387   defsubr (&Sx_display_grayscale_p);
2388   defsubr (&Sx_open_connection);
2389   defsubr (&Sx_create_frame);
2390   defsubr (&Sx_display_pixel_width);
2391   defsubr (&Sx_display_pixel_height);
2392   defsubr (&Sxw_color_values);
2393   defsubr (&Sxw_color_defined_p);
2394   defsubr (&Sx_display_visual_class);
2395   defsubr (&Sx_show_tip);
2396   defsubr (&Sx_display_mm_height);
2397   defsubr (&Sx_display_mm_width);
2398   defsubr (&Sx_close_connection);
2399   defsubr (&Sx_display_list);
2400   defsubr (&Sx_server_vendor);
2401   defsubr (&Sx_server_version);
2402   defsubr (&Sx_display_screens);
2403   defsubr (&Shaiku_get_version_string);
2404   defsubr (&Sx_display_color_cells);
2405   defsubr (&Sx_display_planes);
2406   defsubr (&Shaiku_set_mouse_absolute_pixel_position);
2407   defsubr (&Shaiku_mouse_absolute_pixel_position);
2408   defsubr (&Shaiku_frame_geometry);
2409   defsubr (&Shaiku_frame_edges);
2410   defsubr (&Sx_double_buffered_p);
2411   defsubr (&Sx_display_backing_store);
2412   defsubr (&Shaiku_read_file_name);
2413   defsubr (&Shaiku_put_resource);
2414   defsubr (&Shaiku_frame_list_z_order);
2415   defsubr (&Sx_display_save_under);
2416 
2417   tip_timer = Qnil;
2418   staticpro (&tip_timer);
2419   tip_frame = Qnil;
2420   staticpro (&tip_frame);
2421   tip_last_frame = Qnil;
2422   staticpro (&tip_last_frame);
2423   tip_last_string = Qnil;
2424   staticpro (&tip_last_string);
2425   tip_last_parms = Qnil;
2426   staticpro (&tip_last_parms);
2427 
2428   DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
2429 	       doc: /* SKIP: real doc in xfns.c.  */);
2430   Vx_max_tooltip_size = Fcons (make_fixnum (80), make_fixnum (40));
2431 
2432   DEFVAR_BOOL ("haiku-use-system-tooltips", haiku_use_system_tooltips,
2433 	       doc: /* When non-nil, Emacs will display tooltips using the App Kit.
2434 This can avoid a great deal of consing that does not play
2435 well with the Haiku memory allocator, but comes with the
2436 disadvantage of not being able to use special display properties
2437 within tooltips.  */);
2438   haiku_use_system_tooltips = 1;
2439 
2440 #ifdef USE_BE_CAIRO
2441   DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
2442                doc: /* Version info for cairo.  */);
2443   {
2444     char cairo_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
2445     int len = sprintf (cairo_version, "%d.%d.%d",
2446 		       CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
2447                        CAIRO_VERSION_MICRO);
2448     Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
2449   }
2450 #endif
2451 
2452   return;
2453 }
2454