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 "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
36 #include <math.h>
37 #include <stdlib.h>
38
39 #ifdef USE_BE_CAIRO
40 #include <cairo.h>
41 #endif
42
43 struct haiku_display_info *x_display_list = NULL;
44 extern frame_parm_handler haiku_frame_parm_handlers[];
45
46 static void **fringe_bmps;
47 static int fringe_bitmap_fillptr = 0;
48
49 static Lisp_Object rdb;
50
51 struct unhandled_event
52 {
53 struct unhandled_event *next;
54 enum haiku_event_type type;
55 uint8_t buffer[200];
56 };
57
58 char *
get_keysym_name(int keysym)59 get_keysym_name (int keysym)
60 {
61 static char value[16];
62 sprintf (value, "%d", keysym);
63 return value;
64 }
65
66 static struct frame *
haiku_window_to_frame(void * window)67 haiku_window_to_frame (void *window)
68 {
69 Lisp_Object tail, tem;
70 struct frame *f;
71
72 FOR_EACH_FRAME (tail, tem)
73 {
74 f = XFRAME (tem);
75 if (!FRAME_HAIKU_P (f))
76 continue;
77
78 eassert (FRAME_DISPLAY_INFO (f) == x_display_list);
79
80 if (FRAME_HAIKU_WINDOW (f) == window)
81 return f;
82 }
83
84 return 0;
85 }
86
87 static void
haiku_coords_from_parent(struct frame * f,int * x,int * y)88 haiku_coords_from_parent (struct frame *f, int *x, int *y)
89 {
90 struct frame *p = FRAME_PARENT_FRAME (f);
91 eassert (p);
92
93 for (struct frame *parent = p; parent;
94 parent = FRAME_PARENT_FRAME (parent))
95 {
96 *x -= parent->left_pos;
97 *y -= parent->top_pos;
98 }
99 }
100
101 static void
haiku_delete_terminal(struct terminal * terminal)102 haiku_delete_terminal (struct terminal *terminal)
103 {
104 emacs_abort ();
105 }
106
107 static const char *
get_string_resource(void * ignored,const char * name,const char * class)108 get_string_resource (void *ignored, const char *name, const char *class)
109 {
110 if (!name)
111 return NULL;
112
113 Lisp_Object lval = assoc_no_quit (build_string (name), rdb);
114
115 if (!NILP (lval))
116 return SSDATA (XCDR (lval));
117
118 return NULL;
119 }
120
121 static void
haiku_update_size_hints(struct frame * f)122 haiku_update_size_hints (struct frame *f)
123 {
124 int base_width, base_height;
125 eassert (FRAME_HAIKU_P (f) && FRAME_HAIKU_WINDOW (f));
126
127 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
128 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
129
130 block_input ();
131 BWindow_set_size_alignment (FRAME_HAIKU_WINDOW (f),
132 frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f),
133 frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f));
134 BWindow_set_min_size (FRAME_HAIKU_WINDOW (f), base_width,
135 base_height
136 + FRAME_TOOL_BAR_HEIGHT (f)
137 + FRAME_MENU_BAR_HEIGHT (f));
138 unblock_input ();
139 }
140
141 static void
haiku_clip_to_string(struct glyph_string * s)142 haiku_clip_to_string (struct glyph_string *s)
143 {
144 struct haiku_rect r[2];
145 int n = get_glyph_string_clip_rects (s, (struct haiku_rect *) &r, 2);
146
147 if (n)
148 BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), r[0].x, r[0].y,
149 r[0].width, r[0].height);
150 if (n > 1)
151 {
152 BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), r[1].x, r[1].y,
153 r[1].width, r[1].height);
154 }
155
156 s->num_clips = n;
157 }
158
159 static void
haiku_clip_to_string_exactly(struct glyph_string * s,struct glyph_string * dst)160 haiku_clip_to_string_exactly (struct glyph_string *s, struct glyph_string *dst)
161 {
162 BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), s->x, s->y,
163 s->width, s->height);
164 dst->num_clips = 1;
165 }
166
167 static void
haiku_flip_buffers(struct frame * f)168 haiku_flip_buffers (struct frame *f)
169 {
170 void *view = FRAME_OUTPUT_DATA (f)->view;
171 block_input ();
172
173 BView_draw_lock (view);
174 FRAME_DIRTY_P (f) = 0;
175 EmacsView_flip_and_blit (view);
176 BView_draw_unlock (view);
177
178 unblock_input ();
179 }
180
181 static void
haiku_frame_up_to_date(struct frame * f)182 haiku_frame_up_to_date (struct frame *f)
183 {
184 block_input ();
185 FRAME_MOUSE_UPDATE (f);
186 if (FRAME_DIRTY_P (f) && !buffer_flipping_blocked_p ())
187 haiku_flip_buffers (f);
188 unblock_input ();
189 }
190
191 static void
haiku_buffer_flipping_unblocked_hook(struct frame * f)192 haiku_buffer_flipping_unblocked_hook (struct frame *f)
193 {
194 if (FRAME_DIRTY_P (f))
195 haiku_flip_buffers (f);
196 }
197
198 static void
haiku_clear_frame_area(struct frame * f,int x,int y,int width,int height)199 haiku_clear_frame_area (struct frame *f, int x, int y,
200 int width, int height)
201 {
202 void *vw = FRAME_HAIKU_VIEW (f);
203 block_input ();
204 BView_draw_lock (vw);
205 BView_StartClip (vw);
206 BView_ClipToRect (vw, x, y, width, height);
207 BView_SetHighColor (vw, FRAME_BACKGROUND_PIXEL (f));
208 BView_FillRectangle (vw, x, y, width, height);
209 BView_EndClip (vw);
210 BView_draw_unlock (vw);
211 unblock_input ();
212 }
213
214 static void
haiku_clear_frame(struct frame * f)215 haiku_clear_frame (struct frame *f)
216 {
217 void *view = FRAME_HAIKU_VIEW (f);
218 block_input ();
219 BView_draw_lock (view);
220 BView_StartClip (view);
221 BView_ClipToRect (view, 0, 0, FRAME_PIXEL_WIDTH (f) + 1,
222 FRAME_PIXEL_HEIGHT (f) + 1);
223 BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (f));
224 BView_FillRectangle (view, 0, 0, FRAME_PIXEL_WIDTH (f) + 1,
225 FRAME_PIXEL_HEIGHT (f) + 1);
226 BView_EndClip (view);
227 BView_draw_unlock (view);
228 unblock_input ();
229 }
230
231 /* Give frame F the font FONT-OBJECT as its default font. The return
232 value is FONT-OBJECT. FONTSET is an ID of the fontset for the
233 frame. If it is negative, generate a new fontset from
234 FONT-OBJECT. */
235
236 static Lisp_Object
haiku_new_font(struct frame * f,Lisp_Object font_object,int fontset)237 haiku_new_font (struct frame *f, Lisp_Object font_object, int fontset)
238 {
239 struct font *font = XFONT_OBJECT (font_object);
240 if (fontset < 0)
241 fontset = fontset_from_font (font_object);
242
243 FRAME_FONTSET (f) = fontset;
244 if (FRAME_FONT (f) == font)
245 return font_object;
246
247 FRAME_FONT (f) = font;
248 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
249 FRAME_COLUMN_WIDTH (f) = font->average_width;
250
251 int ascent, descent;
252 get_font_ascent_descent (font, &ascent, &descent);
253 FRAME_LINE_HEIGHT (f) = ascent + descent;
254 FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
255
256 int unit = FRAME_COLUMN_WIDTH (f);
257 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
258 FRAME_CONFIG_SCROLL_BAR_COLS (f)
259 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
260 else
261 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
262
263 if (FRAME_HAIKU_WINDOW (f))
264 {
265 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
266 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f),
267 3, false, Qfont);
268
269 haiku_clear_under_internal_border (f);
270 }
271 return font_object;
272 }
273
274 static int
haiku_valid_modifier_p(Lisp_Object sym)275 haiku_valid_modifier_p (Lisp_Object sym)
276 {
277 return EQ (sym, Qcommand) || EQ (sym, Qshift)
278 || EQ (sym, Qcontrol) || EQ (sym, Qoption);
279 }
280
281 #define MODIFIER_OR(obj, def) (haiku_valid_modifier_p (obj) ? obj : def)
282
283 static void
haiku_add_modifier(int modifier,int toput,Lisp_Object qtem,int * modifiers)284 haiku_add_modifier (int modifier, int toput, Lisp_Object qtem, int *modifiers)
285 {
286 if ((modifier & HAIKU_MODIFIER_ALT && EQ (qtem, Qcommand))
287 || (modifier & HAIKU_MODIFIER_SHIFT && EQ (qtem, Qshift))
288 || (modifier & HAIKU_MODIFIER_CTRL && EQ (qtem, Qcontrol))
289 || (modifier & HAIKU_MODIFIER_SUPER && EQ (qtem, Qoption)))
290 *modifiers |= toput;
291 }
292
293 static int
haiku_modifiers_to_emacs(int haiku_key)294 haiku_modifiers_to_emacs (int haiku_key)
295 {
296 int modifiers = 0;
297 haiku_add_modifier (haiku_key, shift_modifier,
298 MODIFIER_OR (Vhaiku_shift_keysym, Qshift), &modifiers);
299 haiku_add_modifier (haiku_key, super_modifier,
300 MODIFIER_OR (Vhaiku_super_keysym, Qoption), &modifiers);
301 haiku_add_modifier (haiku_key, meta_modifier,
302 MODIFIER_OR (Vhaiku_meta_keysym, Qcommand), &modifiers);
303 haiku_add_modifier (haiku_key, ctrl_modifier,
304 MODIFIER_OR (Vhaiku_control_keysym, Qcontrol), &modifiers);
305 return modifiers;
306 }
307
308 #undef MODIFIER_OR
309
310 static void
haiku_rehighlight(void)311 haiku_rehighlight (void)
312 {
313 eassert (x_display_list && !x_display_list->next);
314
315 block_input ();
316
317 struct frame *old_hl = x_display_list->highlight_frame;
318
319 if (x_display_list->focused_frame)
320 {
321 x_display_list->highlight_frame
322 = ((FRAMEP (FRAME_FOCUS_FRAME (x_display_list->focused_frame)))
323 ? XFRAME (FRAME_FOCUS_FRAME (x_display_list->focused_frame))
324 : x_display_list->focused_frame);
325 if (!FRAME_LIVE_P (x_display_list->highlight_frame))
326 {
327 fset_focus_frame (x_display_list->focused_frame, Qnil);
328 x_display_list->highlight_frame = x_display_list->focused_frame;
329 }
330 }
331 else
332 x_display_list->highlight_frame = 0;
333
334 if (old_hl)
335 gui_update_cursor (old_hl, true);
336
337 if (x_display_list->highlight_frame)
338 gui_update_cursor (x_display_list->highlight_frame, true);
339 unblock_input ();
340 }
341
342 static void
haiku_frame_raise_lower(struct frame * f,bool raise_p)343 haiku_frame_raise_lower (struct frame *f, bool raise_p)
344 {
345 if (raise_p)
346 {
347 block_input ();
348 BWindow_activate (FRAME_HAIKU_WINDOW (f));
349 BWindow_sync (FRAME_HAIKU_WINDOW (f));
350 unblock_input ();
351 }
352 }
353
354 /* Unfortunately, NOACTIVATE is not implementable on Haiku. */
355 static void
haiku_focus_frame(struct frame * frame,bool noactivate)356 haiku_focus_frame (struct frame *frame, bool noactivate)
357 {
358 if (x_display_list->focused_frame != frame)
359 haiku_frame_raise_lower (frame, 1);
360 }
361
362 static void
haiku_new_focus_frame(struct frame * frame)363 haiku_new_focus_frame (struct frame *frame)
364 {
365 eassert (x_display_list && !x_display_list->next);
366
367 block_input ();
368 if (frame != x_display_list->focused_frame)
369 {
370 if (x_display_list->focused_frame &&
371 x_display_list->focused_frame->auto_lower)
372 haiku_frame_raise_lower (x_display_list->focused_frame, 0);
373
374 x_display_list->focused_frame = frame;
375
376 if (frame && frame->auto_raise)
377 haiku_frame_raise_lower (frame, 1);
378 }
379 unblock_input ();
380
381 haiku_rehighlight ();
382 }
383
384 static void
haiku_implicitly_set_name(struct frame * f,Lisp_Object arg,Lisp_Object oldval)385 haiku_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
386 {
387 haiku_set_name (f, arg, 0);
388 }
389
390 static void
haiku_query_frame_background_color(struct frame * f,Emacs_Color * bgcolor)391 haiku_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor)
392 {
393 haiku_query_color (FRAME_BACKGROUND_PIXEL (f), bgcolor);
394 }
395
396 static bool
haiku_defined_color(struct frame * f,const char * name,Emacs_Color * color,bool alloc,bool make_index)397 haiku_defined_color (struct frame *f,
398 const char *name,
399 Emacs_Color *color,
400 bool alloc,
401 bool make_index)
402 {
403 return !haiku_get_color (name, color);
404 }
405
406 /* Adapted from xterm `x_draw_box_rect'. */
407 static void
haiku_draw_box_rect(struct glyph_string * s,int left_x,int top_y,int right_x,int bottom_y,int hwidth,int vwidth,bool left_p,bool right_p,struct haiku_rect * clip_rect)408 haiku_draw_box_rect (struct glyph_string *s,
409 int left_x, int top_y, int right_x, int bottom_y, int hwidth,
410 int vwidth, bool left_p, bool right_p, struct haiku_rect *clip_rect)
411 {
412 void *view = FRAME_HAIKU_VIEW (s->f);
413 struct face *face = s->face;
414
415 BView_StartClip (view);
416 BView_SetHighColor (view, face->box_color);
417 if (clip_rect)
418 BView_ClipToRect (view, clip_rect->x, clip_rect->y, clip_rect->width,
419 clip_rect->height);
420 BView_FillRectangle (view, left_x, top_y, right_x - left_x + 1, hwidth);
421 if (left_p)
422 BView_FillRectangle (view, left_x, top_y, vwidth, bottom_y - top_y + 1);
423
424 BView_FillRectangle (view, left_x, bottom_y - hwidth + 1,
425 right_x - left_x + 1, hwidth);
426 if (right_p)
427 BView_FillRectangle (view, right_x - vwidth + 1,
428 top_y, vwidth, bottom_y - top_y + 1);
429 BView_EndClip (view);
430 }
431
432 static void
haiku_calculate_relief_colors(struct glyph_string * s,uint32_t * rgbout_w,uint32_t * rgbout_b,uint32_t * rgbout_c)433 haiku_calculate_relief_colors (struct glyph_string *s,
434 uint32_t *rgbout_w, uint32_t *rgbout_b,
435 uint32_t *rgbout_c)
436 {
437 struct face *face = s->face;
438
439 prepare_face_for_display (s->f, s->face);
440
441 uint32_t rgbin = face->use_box_color_for_shadows_p
442 ? face->box_color : face->background;
443
444 if (s->hl == DRAW_CURSOR)
445 rgbin = FRAME_CURSOR_COLOR (s->f).pixel;
446
447 double h, cs, l;
448 rgb_color_hsl (rgbin, &h, &cs, &l);
449
450 hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 0.6), rgbout_b);
451 hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 1.2), rgbout_w);
452 hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 1.8), rgbout_c);
453 }
454
455 static void
haiku_draw_relief_rect(struct glyph_string * s,int left_x,int top_y,int right_x,int bottom_y,int hwidth,int vwidth,bool raised_p,bool top_p,bool bot_p,bool left_p,bool right_p,struct haiku_rect * clip_rect,bool fancy_p)456 haiku_draw_relief_rect (struct glyph_string *s,
457 int left_x, int top_y, int right_x, int bottom_y,
458 int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p,
459 bool left_p, bool right_p,
460 struct haiku_rect *clip_rect, bool fancy_p)
461 {
462 uint32_t color_white;
463 uint32_t color_black;
464 uint32_t color_corner;
465
466 haiku_calculate_relief_colors (s, &color_white, &color_black,
467 &color_corner);
468
469 void *view = FRAME_HAIKU_VIEW (s->f);
470 BView_StartClip (view);
471
472 BView_SetHighColor (view, raised_p ? color_white : color_black);
473 if (clip_rect)
474 BView_ClipToRect (view, clip_rect->x, clip_rect->y, clip_rect->width,
475 clip_rect->height);
476 if (top_p)
477 BView_FillRectangle (view, left_x, top_y, right_x - left_x + 1, hwidth);
478 if (left_p)
479 BView_FillRectangle (view, left_x, top_y, vwidth, bottom_y - top_y + 1);
480 BView_SetHighColor (view, !raised_p ? color_white : color_black);
481
482 if (bot_p)
483 BView_FillRectangle (view, left_x, bottom_y - hwidth + 1,
484 right_x - left_x + 1, hwidth);
485 if (right_p)
486 BView_FillRectangle (view, right_x - vwidth + 1, top_y,
487 vwidth, bottom_y - top_y + 1);
488
489 /* Draw the triangle for the bottom-left corner. */
490 if (bot_p && left_p)
491 {
492 BView_SetHighColor (view, raised_p ? color_white : color_black);
493 BView_FillTriangle (view, left_x, bottom_y - hwidth, left_x + vwidth,
494 bottom_y - hwidth, left_x, bottom_y);
495 }
496
497 /* Now draw the triangle for the top-right corner. */
498 if (top_p && right_p)
499 {
500 BView_SetHighColor (view, raised_p ? color_white : color_black);
501 BView_FillTriangle (view, right_x - vwidth, top_y,
502 right_x, top_y,
503 right_x - vwidth, top_y + hwidth);
504 }
505
506 /* If (h/v)width is > 1, we draw the outer-most line on each side in the
507 black relief color. */
508
509 BView_SetHighColor (view, color_black);
510
511 if (hwidth > 1 && top_p)
512 BView_StrokeLine (view, left_x, top_y, right_x, top_y);
513 if (hwidth > 1 && bot_p)
514 BView_StrokeLine (view, left_x, bottom_y, right_x, bottom_y);
515 if (vwidth > 1 && left_p)
516 BView_StrokeLine (view, left_x, top_y, left_x, bottom_y);
517 if (vwidth > 1 && right_p)
518 BView_StrokeLine (view, right_x, top_y, right_x, bottom_y);
519
520 BView_SetHighColor (view, color_corner);
521
522 /* Omit corner pixels. */
523 if (hwidth > 1 || vwidth > 1)
524 {
525 if (left_p && top_p)
526 BView_FillRectangle (view, left_x, top_y, 1, 1);
527 if (left_p && bot_p)
528 BView_FillRectangle (view, left_x, bottom_y, 1, 1);
529 if (right_p && top_p)
530 BView_FillRectangle (view, right_x, top_y, 1, 1);
531 if (right_p && bot_p)
532 BView_FillRectangle (view, right_x, bottom_y, 1, 1);
533 }
534
535 BView_EndClip (view);
536 }
537
538 static void
haiku_draw_underwave(struct glyph_string * s,int width,int x)539 haiku_draw_underwave (struct glyph_string *s, int width, int x)
540 {
541 int wave_height = 3, wave_length = 2;
542 int y, dx, dy, odd, xmax;
543 dx = wave_length;
544 dy = wave_height - 1;
545 y = s->ybase - wave_height + 3;
546
547 float ax, ay, bx, by;
548 xmax = x + width;
549
550 void *view = FRAME_HAIKU_VIEW (s->f);
551
552 BView_StartClip (view);
553 BView_ClipToRect (view, x, y, width, wave_height);
554 ax = x - ((int) (x) % dx) + (float) 0.5;
555 bx = ax + dx;
556 odd = (int) (ax / dx) % 2;
557 ay = by = y + 0.5;
558
559 if (odd)
560 ay += dy;
561 else
562 by += dy;
563
564 while (ax <= xmax)
565 {
566 BView_StrokeLine (view, ax, ay, bx, by);
567 ax = bx, ay = by;
568 bx += dx, by = y + 0.5 + odd * dy;
569 odd = !odd;
570 }
571 BView_EndClip (view);
572 }
573
574 static void
haiku_draw_text_decoration(struct glyph_string * s,struct face * face,uint8_t dcol,int width,int x)575 haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
576 uint8_t dcol, int width, int x)
577 {
578 if (s->for_overlaps)
579 return;
580
581 void *view = FRAME_HAIKU_VIEW (s->f);
582 BView_draw_lock (view);
583 BView_StartClip (view);
584
585 if (face->underline)
586 {
587 if (s->hl == DRAW_CURSOR)
588 BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
589 else if (!face->underline_defaulted_p)
590 BView_SetHighColor (view, face->underline_color);
591 else
592 BView_SetHighColor (view, dcol);
593
594 if (face->underline == FACE_UNDER_WAVE)
595 haiku_draw_underwave (s, width, x);
596 else if (face->underline == FACE_UNDER_LINE)
597 {
598 unsigned long thickness, position;
599 int y;
600
601 if (s->prev && s->prev && s->prev->hl == DRAW_MOUSE_FACE)
602 {
603 struct face *prev_face = s->prev->face;
604
605 if (prev_face && prev_face->underline == FACE_UNDER_LINE)
606 {
607 /* We use the same underline style as the previous one. */
608 thickness = s->prev->underline_thickness;
609 position = s->prev->underline_position;
610 }
611 else
612 goto calculate_underline_metrics;
613 }
614 else
615 {
616 calculate_underline_metrics:;
617 struct font *font = font_for_underline_metrics (s);
618 unsigned long minimum_offset;
619 bool underline_at_descent_line;
620 bool use_underline_position_properties;
621 Lisp_Object val = (WINDOW_BUFFER_LOCAL_VALUE
622 (Qunderline_minimum_offset, s->w));
623
624 if (FIXNUMP (val))
625 minimum_offset = max (0, XFIXNUM (val));
626 else
627 minimum_offset = 1;
628
629 val = (WINDOW_BUFFER_LOCAL_VALUE
630 (Qx_underline_at_descent_line, s->w));
631 underline_at_descent_line
632 = !(NILP (val) || EQ (val, Qunbound));
633
634 val = (WINDOW_BUFFER_LOCAL_VALUE
635 (Qx_use_underline_position_properties, s->w));
636 use_underline_position_properties
637 = !(NILP (val) || EQ (val, Qunbound));
638
639 /* Get the underline thickness. Default is 1 pixel. */
640 if (font && font->underline_thickness > 0)
641 thickness = font->underline_thickness;
642 else
643 thickness = 1;
644 if (underline_at_descent_line)
645 position = (s->height - thickness) - (s->ybase - s->y);
646 else
647 {
648 /* Get the underline position. This is the
649 recommended vertical offset in pixels from
650 the baseline to the top of the underline.
651 This is a signed value according to the
652 specs, and its default is
653
654 ROUND ((maximum descent) / 2), with
655 ROUND(x) = floor (x + 0.5) */
656
657 if (use_underline_position_properties
658 && font && font->underline_position >= 0)
659 position = font->underline_position;
660 else if (font)
661 position = (font->descent + 1) / 2;
662 else
663 position = minimum_offset;
664 }
665 position = max (position, minimum_offset);
666 }
667 /* Check the sanity of thickness and position. We should
668 avoid drawing underline out of the current line area. */
669 if (s->y + s->height <= s->ybase + position)
670 position = (s->height - 1) - (s->ybase - s->y);
671 if (s->y + s->height < s->ybase + position + thickness)
672 thickness = (s->y + s->height) - (s->ybase + position);
673 s->underline_thickness = thickness;
674 s->underline_position = position;
675 y = s->ybase + position;
676
677 BView_FillRectangle (view, s->x, y, s->width, thickness);
678 }
679 }
680
681 if (face->overline_p)
682 {
683 unsigned long dy = 0, h = 1;
684 if (s->hl == DRAW_CURSOR)
685 BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
686 else if (!face->overline_color_defaulted_p)
687 BView_SetHighColor (view, face->overline_color);
688 else
689 BView_SetHighColor (view, dcol);
690
691 BView_FillRectangle (view, s->x, s->y + dy, s->width, h);
692 }
693
694 if (face->strike_through_p)
695 {
696 /* Y-coordinate and height of the glyph string's first
697 glyph. We cannot use s->y and s->height because those
698 could be larger if there are taller display elements
699 (e.g., characters displayed with a larger font) in the
700 same glyph row. */
701 int glyph_y = s->ybase - s->first_glyph->ascent;
702 int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
703 /* Strike-through width and offset from the glyph string's
704 top edge. */
705 unsigned long h = 1;
706 unsigned long dy = (glyph_height - h) / 2;
707
708 if (s->hl == DRAW_CURSOR)
709 BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
710 else if (!face->strike_through_color_defaulted_p)
711 BView_SetHighColor (view, face->strike_through_color);
712 else
713 BView_SetHighColor (view, dcol);
714
715 BView_FillRectangle (view, s->x, glyph_y + dy, s->width, h);
716 }
717
718 BView_EndClip (view);
719 BView_draw_unlock (view);
720 }
721
722 static void
haiku_draw_string_box(struct glyph_string * s,int clip_p)723 haiku_draw_string_box (struct glyph_string *s, int clip_p)
724 {
725 int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
726 bool raised_p, left_p, right_p;
727 struct glyph *last_glyph;
728 struct haiku_rect clip_rect;
729
730 struct face *face = s->face;
731
732 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
733 ? WINDOW_RIGHT_EDGE_X (s->w)
734 : window_box_right (s->w, s->area));
735
736 /* The glyph that may have a right box line. For static
737 compositions and images, the right-box flag is on the first glyph
738 of the glyph string; for other types it's on the last glyph. */
739 if (s->cmp || s->img)
740 last_glyph = s->first_glyph;
741 else if (s->first_glyph->type == COMPOSITE_GLYPH
742 && s->first_glyph->u.cmp.automatic)
743 {
744 /* For automatic compositions, we need to look up the last glyph
745 in the composition. */
746 struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area];
747 struct glyph *g = s->first_glyph;
748 for (last_glyph = g++;
749 g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id
750 && g->slice.cmp.to < s->cmp_to;
751 last_glyph = g++)
752 ;
753 }
754 else
755 last_glyph = s->first_glyph + s->nchars - 1;
756
757 vwidth = eabs (face->box_vertical_line_width);
758 hwidth = eabs (face->box_horizontal_line_width);
759 raised_p = face->box == FACE_RAISED_BOX;
760 left_x = s->x;
761 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
762 ? last_x - 1
763 : min (last_x, s->x + s->background_width) - 1);
764
765 top_y = s->y;
766 bottom_y = top_y + s->height - 1;
767
768 left_p = (s->first_glyph->left_box_line_p
769 || (s->hl == DRAW_MOUSE_FACE
770 && (s->prev == NULL
771 || s->prev->hl != s->hl)));
772 right_p = (last_glyph->right_box_line_p
773 || (s->hl == DRAW_MOUSE_FACE
774 && (s->next == NULL
775 || s->next->hl != s->hl)));
776
777 get_glyph_string_clip_rect (s, &clip_rect);
778
779 if (face->box == FACE_SIMPLE_BOX)
780 haiku_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
781 vwidth, left_p, right_p, &clip_rect);
782 else
783 haiku_draw_relief_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
784 vwidth, raised_p, true, true, left_p, right_p,
785 &clip_rect, 1);
786
787 if (clip_p)
788 {
789 void *view = FRAME_HAIKU_VIEW (s->f);
790
791 haiku_draw_text_decoration (s, face, face->foreground, s->width, s->x);
792 BView_ClipToInverseRect (view, left_x, top_y, right_x - left_x + 1, hwidth);
793 if (left_p)
794 BView_ClipToInverseRect (view, left_x, top_y, vwidth, bottom_y - top_y + 1);
795 BView_ClipToInverseRect (view, left_x, bottom_y - hwidth + 1,
796 right_x - left_x + 1, hwidth);
797 if (right_p)
798 BView_ClipToInverseRect (view, right_x - vwidth + 1,
799 top_y, vwidth, bottom_y - top_y + 1);
800 }
801 }
802
803 static void
haiku_draw_plain_background(struct glyph_string * s,struct face * face,int box_line_hwidth,int box_line_vwidth)804 haiku_draw_plain_background (struct glyph_string *s, struct face *face,
805 int box_line_hwidth, int box_line_vwidth)
806 {
807 void *view = FRAME_HAIKU_VIEW (s->f);
808 BView_StartClip (view);
809 if (s->hl == DRAW_CURSOR)
810 BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
811 else
812 BView_SetHighColor (view, face->background_defaulted_p ?
813 FRAME_BACKGROUND_PIXEL (s->f) :
814 face->background);
815
816 BView_FillRectangle (view, s->x,
817 s->y + box_line_hwidth,
818 s->background_width,
819 s->height - 2 * box_line_hwidth);
820 BView_EndClip (view);
821 }
822
823 static void
haiku_draw_stipple_background(struct glyph_string * s,struct face * face,int box_line_hwidth,int box_line_vwidth)824 haiku_draw_stipple_background (struct glyph_string *s, struct face *face,
825 int box_line_hwidth, int box_line_vwidth)
826 {
827 }
828
829 static void
haiku_maybe_draw_background(struct glyph_string * s,int force_p)830 haiku_maybe_draw_background (struct glyph_string *s, int force_p)
831 {
832 if ((s->first_glyph->type != IMAGE_GLYPH) && !s->background_filled_p)
833 {
834 struct face *face = s->face;
835 int box_line_width = max (face->box_horizontal_line_width, 0);
836 int box_vline_width = max (face->box_vertical_line_width, 0);
837
838 if (FONT_HEIGHT (s->font) < s->height - 2 * box_vline_width
839 || FONT_TOO_HIGH (s->font)
840 || s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
841 {
842 if (!face->stipple)
843 haiku_draw_plain_background (s, face, box_line_width,
844 box_vline_width);
845 else
846 haiku_draw_stipple_background (s, face, box_line_width,
847 box_vline_width);
848 s->background_filled_p = 1;
849 }
850 }
851 }
852
853 static void
haiku_mouse_face_colors(struct glyph_string * s,uint32_t * fg,uint32_t * bg)854 haiku_mouse_face_colors (struct glyph_string *s, uint32_t *fg,
855 uint32_t *bg)
856 {
857 int face_id;
858 struct face *face;
859
860 /* What face has to be used last for the mouse face? */
861 face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
862 face = FACE_FROM_ID_OR_NULL (s->f, face_id);
863 if (face == NULL)
864 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
865
866 if (s->first_glyph->type == CHAR_GLYPH)
867 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
868 else
869 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
870
871 face = FACE_FROM_ID (s->f, face_id);
872 prepare_face_for_display (s->f, s->face);
873
874 if (fg)
875 *fg = face->foreground;
876 if (bg)
877 *bg = face->background;
878 }
879
880 static void
haiku_draw_glyph_string_foreground(struct glyph_string * s)881 haiku_draw_glyph_string_foreground (struct glyph_string *s)
882 {
883 struct face *face = s->face;
884
885 int i, x;
886 if (face->box != FACE_NO_BOX
887 && s->first_glyph->left_box_line_p)
888 x = s->x + max (face->box_vertical_line_width, 0);
889 else
890 x = s->x;
891
892 void *view = FRAME_HAIKU_VIEW (s->f);
893
894 if (s->font_not_found_p)
895 {
896 BView_StartClip (view);
897 if (s->hl == DRAW_CURSOR)
898 BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
899 else
900 BView_SetHighColor (view, face->foreground);
901 for (i = 0; i < s->nchars; ++i)
902 {
903 struct glyph *g = s->first_glyph + i;
904 BView_StrokeRectangle (view, x, s->y, g->pixel_width,
905 s->height);
906 x += g->pixel_width;
907 }
908 BView_EndClip (view);
909 }
910 else
911 {
912 struct font *ft = s->font;
913 int off = ft->baseline_offset;
914 int y;
915
916 if (ft->vertical_centering)
917 off = VCENTER_BASELINE_OFFSET (ft, s->f) - off;
918 y = s->ybase - off;
919 if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR))
920 ft->driver->draw (s, 0, s->nchars, x, y, false);
921 else
922 ft->driver->draw (s, 0, s->nchars, x, y, true);
923
924 if (face->overstrike)
925 ft->driver->draw (s, 0, s->nchars, x + 1, y, false);
926 }
927 }
928
929 static void
haiku_draw_glyphless_glyph_string_foreground(struct glyph_string * s)930 haiku_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
931 {
932 struct glyph *glyph = s->first_glyph;
933 unsigned char2b[8];
934 int x, i, j;
935 struct face *face = s->face;
936
937 /* If first glyph of S has a left box line, start drawing the text
938 of S to the right of that box line. */
939 if (face && face->box != FACE_NO_BOX
940 && s->first_glyph->left_box_line_p)
941 x = s->x + max (face->box_vertical_line_width, 0);
942 else
943 x = s->x;
944
945 s->char2b = char2b;
946
947 for (i = 0; i < s->nchars; i++, glyph++)
948 {
949 #ifdef GCC_LINT
950 enum { PACIFY_GCC_BUG_81401 = 1 };
951 #else
952 enum { PACIFY_GCC_BUG_81401 = 0 };
953 #endif
954 char buf[7 + PACIFY_GCC_BUG_81401];
955 char *str = NULL;
956 int len = glyph->u.glyphless.len;
957
958 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
959 {
960 if (len > 0
961 && CHAR_TABLE_P (Vglyphless_char_display)
962 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
963 >= 1))
964 {
965 Lisp_Object acronym
966 = (! glyph->u.glyphless.for_no_font
967 ? CHAR_TABLE_REF (Vglyphless_char_display,
968 glyph->u.glyphless.ch)
969 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
970 if (STRINGP (acronym))
971 str = SSDATA (acronym);
972 }
973 }
974 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
975 {
976 unsigned int ch = glyph->u.glyphless.ch;
977 eassume (ch <= MAX_CHAR);
978 sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
979 str = buf;
980 }
981
982 if (str)
983 {
984 int upper_len = (len + 1) / 2;
985
986 /* It is assured that all LEN characters in STR is ASCII. */
987 for (j = 0; j < len; j++)
988 char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
989
990 s->font->driver->draw (s, 0, upper_len,
991 x + glyph->slice.glyphless.upper_xoff,
992 s->ybase + glyph->slice.glyphless.upper_yoff,
993 false);
994 s->font->driver->draw (s, upper_len, len,
995 x + glyph->slice.glyphless.lower_xoff,
996 s->ybase + glyph->slice.glyphless.lower_yoff,
997 false);
998 }
999 BView_StartClip (FRAME_HAIKU_VIEW (s->f));
1000 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
1001 BView_FillRectangle (FRAME_HAIKU_VIEW (s->f),
1002 x, s->ybase - glyph->ascent,
1003 glyph->pixel_width - 1,
1004 glyph->ascent + glyph->descent - 1);
1005 BView_EndClip (FRAME_HAIKU_VIEW (s->f));
1006 x += glyph->pixel_width;
1007 }
1008 }
1009
1010 static void
haiku_draw_stretch_glyph_string(struct glyph_string * s)1011 haiku_draw_stretch_glyph_string (struct glyph_string *s)
1012 {
1013 eassert (s->first_glyph->type == STRETCH_GLYPH);
1014
1015 struct face *face = s->face;
1016
1017 if (s->hl == DRAW_CURSOR && !x_stretch_cursor_p)
1018 {
1019 int width, background_width = s->background_width;
1020 int x = s->x;
1021
1022 if (!s->row->reversed_p)
1023 {
1024 int left_x = window_box_left_offset (s->w, TEXT_AREA);
1025
1026 if (x < left_x)
1027 {
1028 background_width -= left_x - x;
1029 x = left_x;
1030 }
1031 }
1032 else
1033 {
1034 /* In R2L rows, draw the cursor on the right edge of the
1035 stretch glyph. */
1036 int right_x = window_box_right (s->w, TEXT_AREA);
1037 if (x + background_width > right_x)
1038 background_width -= x - right_x;
1039 x += background_width;
1040 }
1041
1042 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
1043 if (s->row->reversed_p)
1044 x -= width;
1045
1046 void *view = FRAME_HAIKU_VIEW (s->f);
1047 BView_StartClip (view);
1048 BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
1049 BView_FillRectangle (view, x, s->y, width, s->height);
1050 BView_EndClip (view);
1051
1052 if (width < background_width)
1053 {
1054 if (!s->row->reversed_p)
1055 x += width;
1056 else
1057 x = s->x;
1058
1059 int y = s->y;
1060 int w = background_width - width, h = s->height;
1061
1062 if (!face->stipple)
1063 {
1064 uint32_t bkg;
1065 if (s->hl == DRAW_MOUSE_FACE || (s->hl == DRAW_CURSOR
1066 && s->row->mouse_face_p
1067 && cursor_in_mouse_face_p (s->w)))
1068 haiku_mouse_face_colors (s, NULL, &bkg);
1069 else
1070 bkg = face->background;
1071
1072 BView_StartClip (view);
1073 BView_SetHighColor (view, bkg);
1074 BView_FillRectangle (view, x, y, w, h);
1075 BView_EndClip (view);
1076 }
1077 }
1078 }
1079 else if (!s->background_filled_p)
1080 {
1081 int background_width = s->background_width;
1082 int x = s->x, text_left_x = window_box_left (s->w, TEXT_AREA);
1083
1084 /* Don't draw into left fringe or scrollbar area except for
1085 header line and mode line. */
1086 if (s->area == TEXT_AREA
1087 && x < text_left_x && !s->row->mode_line_p)
1088 {
1089 background_width -= text_left_x - x;
1090 x = text_left_x;
1091 }
1092
1093 if (background_width > 0)
1094 {
1095 void *view = FRAME_HAIKU_VIEW (s->f);
1096 BView_StartClip (view);
1097 uint32_t bkg;
1098 if (s->hl == DRAW_MOUSE_FACE)
1099 haiku_mouse_face_colors (s, NULL, &bkg);
1100 else if (s->hl == DRAW_CURSOR)
1101 bkg = FRAME_CURSOR_COLOR (s->f).pixel;
1102 else
1103 bkg = s->face->background;
1104
1105 BView_SetHighColor (view, bkg);
1106 BView_FillRectangle (view, x, s->y, background_width, s->height);
1107 BView_EndClip (view);
1108 }
1109 }
1110 s->background_filled_p = 1;
1111 }
1112
1113 static void
haiku_start_clip(struct glyph_string * s)1114 haiku_start_clip (struct glyph_string *s)
1115 {
1116 void *view = FRAME_HAIKU_VIEW (s->f);
1117 BView_draw_lock (view);
1118 BView_StartClip (view);
1119 }
1120
1121 static void
haiku_end_clip(struct glyph_string * s)1122 haiku_end_clip (struct glyph_string *s)
1123 {
1124 void *view = FRAME_HAIKU_VIEW (s->f);
1125 BView_EndClip (view);
1126 BView_draw_unlock (view);
1127 }
1128
1129 static void
haiku_clip_to_row(struct window * w,struct glyph_row * row,enum glyph_row_area area)1130 haiku_clip_to_row (struct window *w, struct glyph_row *row,
1131 enum glyph_row_area area)
1132 {
1133 struct frame *f = WINDOW_XFRAME (w);
1134 int window_x, window_y, window_width;
1135 int x, y, width, height;
1136
1137 window_box (w, area, &window_x, &window_y, &window_width, 0);
1138
1139 x = window_x;
1140 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
1141 y = max (y, window_y);
1142 width = window_width;
1143 height = row->visible_height;
1144
1145 BView_ClipToRect (FRAME_HAIKU_VIEW (f), x, y, width, height);
1146 }
1147
1148 static void
haiku_update_begin(struct frame * f)1149 haiku_update_begin (struct frame *f)
1150 {
1151 }
1152
1153 static void
haiku_update_end(struct frame * f)1154 haiku_update_end (struct frame *f)
1155 {
1156 MOUSE_HL_INFO (f)->mouse_face_defer = false;
1157 flush_frame (f);
1158 }
1159
1160 static void
haiku_draw_composite_glyph_string_foreground(struct glyph_string * s)1161 haiku_draw_composite_glyph_string_foreground (struct glyph_string *s)
1162 {
1163 int i, j, x;
1164 struct font *font = s->font;
1165 void *view = FRAME_HAIKU_VIEW (s->f);
1166 struct face *face = s->face;
1167
1168 /* If first glyph of S has a left box line, start drawing the text
1169 of S to the right of that box line. */
1170 if (face && face->box != FACE_NO_BOX
1171 && s->first_glyph->left_box_line_p)
1172 x = s->x + max (face->box_vertical_line_width, 0);
1173 else
1174 x = s->x;
1175
1176 /* S is a glyph string for a composition. S->cmp_from is the index
1177 of the first character drawn for glyphs of this composition.
1178 S->cmp_from == 0 means we are drawing the very first character of
1179 this composition. */
1180
1181 /* Draw a rectangle for the composition if the font for the very
1182 first character of the composition could not be loaded. */
1183
1184 if (s->font_not_found_p && !s->cmp_from)
1185 {
1186 BView_StartClip (view);
1187 if (s->hl == DRAW_CURSOR)
1188 BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
1189 else
1190 BView_SetHighColor (view, s->face->foreground);
1191 BView_StrokeRectangle (view, s->x, s->y, s->width - 1, s->height - 1);
1192 BView_EndClip (view);
1193 }
1194 else if (!s->first_glyph->u.cmp.automatic)
1195 {
1196 int y = s->ybase;
1197
1198 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1199 /* TAB in a composition means display glyphs with padding
1200 space on the left or right. */
1201 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1202 {
1203 int xx = x + s->cmp->offsets[j * 2];
1204 int yy = y - s->cmp->offsets[j * 2 + 1];
1205
1206 font->driver->draw (s, j, j + 1, xx, yy, false);
1207 if (face->overstrike)
1208 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
1209 }
1210 }
1211 else
1212 {
1213 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1214 Lisp_Object glyph;
1215 int y = s->ybase;
1216 int width = 0;
1217
1218 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1219 {
1220 glyph = LGSTRING_GLYPH (gstring, i);
1221 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1222 width += LGLYPH_WIDTH (glyph);
1223 else
1224 {
1225 int xoff, yoff, wadjust;
1226
1227 if (j < i)
1228 {
1229 font->driver->draw (s, j, i, x, y, false);
1230 if (s->face->overstrike)
1231 font->driver->draw (s, j, i, x + 1, y, false);
1232 x += width;
1233 }
1234 xoff = LGLYPH_XOFF (glyph);
1235 yoff = LGLYPH_YOFF (glyph);
1236 wadjust = LGLYPH_WADJUST (glyph);
1237 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
1238 if (face->overstrike)
1239 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
1240 false);
1241 x += wadjust;
1242 j = i + 1;
1243 width = 0;
1244 }
1245 }
1246 if (j < i)
1247 {
1248 font->driver->draw (s, j, i, x, y, false);
1249 if (face->overstrike)
1250 font->driver->draw (s, j, i, x + 1, y, false);
1251 }
1252 }
1253 }
1254
1255 static void
haiku_draw_image_relief(struct glyph_string * s)1256 haiku_draw_image_relief (struct glyph_string *s)
1257 {
1258 int x1, y1, thick;
1259 bool raised_p, top_p, bot_p, left_p, right_p;
1260 int extra_x, extra_y;
1261 struct haiku_rect r;
1262 int x = s->x;
1263 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1264
1265 struct face *face = s->face;
1266
1267 /* If first glyph of S has a left box line, start drawing it to the
1268 right of that line. */
1269 if (face->box != FACE_NO_BOX
1270 && s->first_glyph->left_box_line_p
1271 && s->slice.x == 0)
1272 x += max (face->box_vertical_line_width, 0);
1273
1274 /* If there is a margin around the image, adjust x- and y-position
1275 by that margin. */
1276 if (s->slice.x == 0)
1277 x += s->img->hmargin;
1278 if (s->slice.y == 0)
1279 y += s->img->vmargin;
1280
1281 if (s->hl == DRAW_IMAGE_SUNKEN
1282 || s->hl == DRAW_IMAGE_RAISED)
1283 {
1284 if (s->face->id == TAB_BAR_FACE_ID)
1285 thick = (tab_bar_button_relief < 0
1286 ? DEFAULT_TAB_BAR_BUTTON_RELIEF
1287 : min (tab_bar_button_relief, 1000000));
1288 else
1289 thick = (tool_bar_button_relief < 0
1290 ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
1291 : min (tool_bar_button_relief, 1000000));
1292 raised_p = s->hl == DRAW_IMAGE_RAISED;
1293 }
1294 else
1295 {
1296 thick = eabs (s->img->relief);
1297 raised_p = s->img->relief > 0;
1298 }
1299
1300 x1 = x + s->slice.width - 1;
1301 y1 = y + s->slice.height - 1;
1302
1303 extra_x = extra_y = 0;
1304
1305 if (s->face->id == TAB_BAR_FACE_ID)
1306 {
1307 if (CONSP (Vtab_bar_button_margin)
1308 && FIXNUMP (XCAR (Vtab_bar_button_margin))
1309 && FIXNUMP (XCDR (Vtab_bar_button_margin)))
1310 {
1311 extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick;
1312 extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick;
1313 }
1314 else if (FIXNUMP (Vtab_bar_button_margin))
1315 extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick;
1316 }
1317
1318 if (s->face->id == TOOL_BAR_FACE_ID)
1319 {
1320 if (CONSP (Vtool_bar_button_margin)
1321 && FIXNUMP (XCAR (Vtool_bar_button_margin))
1322 && FIXNUMP (XCDR (Vtool_bar_button_margin)))
1323 {
1324 extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
1325 extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
1326 }
1327 else if (FIXNUMP (Vtool_bar_button_margin))
1328 extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
1329 }
1330
1331 top_p = bot_p = left_p = right_p = 0;
1332
1333 if (s->slice.x == 0)
1334 x -= thick + extra_x, left_p = 1;
1335 if (s->slice.y == 0)
1336 y -= thick + extra_y, top_p = 1;
1337 if (s->slice.x + s->slice.width == s->img->width)
1338 x1 += thick + extra_x, right_p = 1;
1339 if (s->slice.y + s->slice.height == s->img->height)
1340 y1 += thick + extra_y, bot_p = 1;
1341
1342 get_glyph_string_clip_rect (s, &r);
1343 haiku_draw_relief_rect (s, x, y, x1, y1, thick, thick, raised_p,
1344 top_p, bot_p, left_p, right_p, &r, 0);
1345 }
1346
1347 static void
haiku_draw_image_glyph_string(struct glyph_string * s)1348 haiku_draw_image_glyph_string (struct glyph_string *s)
1349 {
1350 struct face *face = s->face;
1351
1352 int box_line_hwidth = max (face->box_vertical_line_width, 0);
1353 int box_line_vwidth = max (face->box_horizontal_line_width, 0);
1354
1355 int x, y;
1356 int height, width;
1357
1358 height = s->height;
1359 if (s->slice.y == 0)
1360 height -= box_line_vwidth;
1361 if (s->slice.y + s->slice.height >= s->img->height)
1362 height -= box_line_vwidth;
1363
1364 width = s->background_width;
1365 x = s->x;
1366 if (s->first_glyph->left_box_line_p
1367 && s->slice.x == 0)
1368 {
1369 x += box_line_hwidth;
1370 width -= box_line_hwidth;
1371 }
1372
1373 y = s->y;
1374 if (s->slice.y == 0)
1375 y += box_line_vwidth;
1376
1377 void *view = FRAME_HAIKU_VIEW (s->f);
1378 void *bitmap = s->img->pixmap;
1379
1380 s->stippled_p = face->stipple != 0;
1381
1382 BView_draw_lock (view);
1383 BView_StartClip (view);
1384 BView_SetHighColor (view, face->background);
1385 BView_FillRectangle (view, x, y, width, height);
1386 BView_EndClip (view);
1387 BView_draw_unlock (view);
1388
1389 if (bitmap)
1390 {
1391 struct haiku_rect nr;
1392 Emacs_Rectangle cr, ir, r;
1393
1394 get_glyph_string_clip_rect (s, &nr);
1395 CONVERT_TO_EMACS_RECT (cr, nr);
1396 x = s->x;
1397 y = s->ybase - image_ascent (s->img, face, &s->slice);
1398
1399 if (s->slice.x == 0)
1400 x += s->img->hmargin;
1401 if (s->slice.y == 0)
1402 y += s->img->vmargin;
1403
1404 if (face->box != FACE_NO_BOX
1405 && s->first_glyph->left_box_line_p
1406 && s->slice.x == 0)
1407 x += max (face->box_vertical_line_width, 0);
1408
1409 ir.x = x;
1410 ir.y = y;
1411 ir.width = s->slice.width;
1412 ir.height = s->slice.height;
1413 r = ir;
1414
1415 void *mask = s->img->mask;
1416
1417 if (gui_intersect_rectangles (&cr, &ir, &r))
1418 {
1419 BView_draw_lock (view);
1420 BView_StartClip (view);
1421
1422 haiku_clip_to_string (s);
1423 if (s->img->have_be_transforms_p)
1424 {
1425 bitmap = BBitmap_transform_bitmap (bitmap,
1426 s->img->mask,
1427 face->background,
1428 s->img->be_rotate,
1429 s->img->width,
1430 s->img->height);
1431 mask = NULL;
1432 }
1433
1434 BView_DrawBitmap (view, bitmap,
1435 s->slice.x + r.x - x,
1436 s->slice.y + r.y - y,
1437 r.width, r.height,
1438 r.x, r.y, r.width, r.height);
1439 if (mask)
1440 {
1441 BView_DrawMask (mask, view,
1442 s->slice.x + r.x - x,
1443 s->slice.y + r.y - y,
1444 r.width, r.height,
1445 r.x, r.y, r.width, r.height,
1446 face->background);
1447 }
1448
1449 if (s->img->have_be_transforms_p)
1450 BBitmap_free (bitmap);
1451 BView_EndClip (view);
1452 BView_draw_unlock (view);
1453 }
1454
1455 if (s->hl == DRAW_CURSOR)
1456 {
1457 BView_draw_lock (view);
1458 BView_StartClip (view);
1459 BView_SetPenSize (view, 1);
1460 BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
1461 BView_StrokeRectangle (view, r.x, r.y, r.width, r.height);
1462 BView_EndClip (view);
1463 BView_draw_unlock (view);
1464 }
1465 }
1466
1467 if (s->img->relief
1468 || s->hl == DRAW_IMAGE_RAISED
1469 || s->hl == DRAW_IMAGE_SUNKEN)
1470 haiku_draw_image_relief (s);
1471 }
1472
1473 static void
haiku_draw_glyph_string(struct glyph_string * s)1474 haiku_draw_glyph_string (struct glyph_string *s)
1475 {
1476 block_input ();
1477 prepare_face_for_display (s->f, s->face);
1478
1479 struct face *face = s->face;
1480 if (face != s->face)
1481 prepare_face_for_display (s->f, face);
1482
1483 if (s->next && s->right_overhang && !s->for_overlaps)
1484 {
1485 int width;
1486 struct glyph_string *next;
1487
1488 for (width = 0, next = s->next;
1489 next && width < s->right_overhang;
1490 width += next->width, next = next->next)
1491 if (next->first_glyph->type != IMAGE_GLYPH)
1492 {
1493 prepare_face_for_display (s->f, s->next->face);
1494 haiku_start_clip (s->next);
1495 haiku_clip_to_string (s->next);
1496 if (next->first_glyph->type != STRETCH_GLYPH)
1497 haiku_maybe_draw_background (s->next, 1);
1498 else
1499 haiku_draw_stretch_glyph_string (s->next);
1500 next->num_clips = 0;
1501 haiku_end_clip (s);
1502 }
1503 }
1504
1505 haiku_start_clip (s);
1506
1507 int box_filled_p = 0;
1508
1509 if (!s->for_overlaps && face->box != FACE_NO_BOX
1510 && (s->first_glyph->type == CHAR_GLYPH
1511 || s->first_glyph->type == COMPOSITE_GLYPH))
1512 {
1513 haiku_clip_to_string (s);
1514 haiku_maybe_draw_background (s, 1);
1515 box_filled_p = 1;
1516 haiku_draw_string_box (s, 0);
1517 }
1518 else if (!s->clip_head && !s->clip_tail &&
1519 ((s->prev && s->left_overhang && s->prev->hl != s->hl) ||
1520 (s->next && s->right_overhang && s->next->hl != s->hl)))
1521 haiku_clip_to_string_exactly (s, s);
1522 else
1523 haiku_clip_to_string (s);
1524
1525 if (s->for_overlaps)
1526 s->background_filled_p = 1;
1527
1528 switch (s->first_glyph->type)
1529 {
1530 case COMPOSITE_GLYPH:
1531 if (s->for_overlaps || (s->cmp_from > 0
1532 && ! s->first_glyph->u.cmp.automatic))
1533 s->background_filled_p = 1;
1534 else
1535 haiku_maybe_draw_background (s, 1);
1536 haiku_draw_composite_glyph_string_foreground (s);
1537 break;
1538 case CHAR_GLYPH:
1539 if (s->for_overlaps)
1540 s->background_filled_p = 1;
1541 else
1542 haiku_maybe_draw_background (s, 0);
1543 haiku_draw_glyph_string_foreground (s);
1544 break;
1545 case STRETCH_GLYPH:
1546 haiku_draw_stretch_glyph_string (s);
1547 break;
1548 case IMAGE_GLYPH:
1549 haiku_draw_image_glyph_string (s);
1550 break;
1551 case GLYPHLESS_GLYPH:
1552 if (s->for_overlaps)
1553 s->background_filled_p = 1;
1554 else
1555 haiku_maybe_draw_background (s, 1);
1556 haiku_draw_glyphless_glyph_string_foreground (s);
1557 break;
1558 }
1559
1560 if (!box_filled_p && face->box != FACE_NO_BOX)
1561 haiku_draw_string_box (s, 1);
1562 else
1563 haiku_draw_text_decoration (s, face, face->foreground, s->width, s->x);
1564
1565 if (!s->for_overlaps)
1566 {
1567 if (s->prev)
1568 {
1569 struct glyph_string *prev;
1570
1571 for (prev = s->prev; prev; prev = prev->prev)
1572 if (prev->hl != s->hl
1573 && prev->x + prev->width + prev->right_overhang > s->x)
1574 {
1575 /* As prev was drawn while clipped to its own area, we
1576 must draw the right_overhang part using s->hl now. */
1577 enum draw_glyphs_face save = prev->hl;
1578 struct face *save_face = prev->face;
1579
1580 prev->hl = s->hl;
1581 prev->face = s->face;
1582 haiku_start_clip (s);
1583 haiku_clip_to_string_exactly (s, prev);
1584 if (prev->first_glyph->type == CHAR_GLYPH)
1585 haiku_draw_glyph_string_foreground (prev);
1586 else
1587 haiku_draw_composite_glyph_string_foreground (prev);
1588 haiku_end_clip (s);
1589 prev->hl = save;
1590 prev->face = save_face;
1591 prev->num_clips = 0;
1592 }
1593 }
1594
1595 if (s->next)
1596 {
1597 struct glyph_string *next;
1598
1599 for (next = s->next; next; next = next->next)
1600 if (next->hl != s->hl
1601 && next->x - next->left_overhang < s->x + s->width)
1602 {
1603 /* As next will be drawn while clipped to its own area,
1604 we must draw the left_overhang part using s->hl now. */
1605 enum draw_glyphs_face save = next->hl;
1606 struct face *save_face = next->face;
1607
1608 next->hl = s->hl;
1609 next->face = s->face;
1610 haiku_start_clip (s);
1611 haiku_clip_to_string_exactly (s, next);
1612 if (next->first_glyph->type == CHAR_GLYPH)
1613 haiku_draw_glyph_string_foreground (next);
1614 else
1615 haiku_draw_composite_glyph_string_foreground (next);
1616 haiku_end_clip (s);
1617
1618 next->background_filled_p = 0;
1619 next->hl = save;
1620 next->face = save_face;
1621 next->clip_head = next;
1622 next->num_clips = 0;
1623 }
1624 }
1625 }
1626 s->num_clips = 0;
1627 haiku_end_clip (s);
1628 unblock_input ();
1629 }
1630
1631 static void
haiku_after_update_window_line(struct window * w,struct glyph_row * desired_row)1632 haiku_after_update_window_line (struct window *w,
1633 struct glyph_row *desired_row)
1634 {
1635 eassert (w);
1636 struct frame *f;
1637 int width, height;
1638
1639 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1640 desired_row->redraw_fringe_bitmaps_p = true;
1641
1642 if (windows_or_buffers_changed
1643 && desired_row->full_width_p
1644 && (f = XFRAME (w->frame),
1645 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1646 width != 0)
1647 && (height = desired_row->visible_height,
1648 height > 0))
1649 {
1650 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1651 int face_id =
1652 !NILP (Vface_remapping_alist)
1653 ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
1654 : INTERNAL_BORDER_FACE_ID;
1655 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
1656
1657 block_input ();
1658 if (face)
1659 {
1660 void *view = FRAME_HAIKU_VIEW (f);
1661 BView_draw_lock (view);
1662 BView_StartClip (view);
1663 BView_SetHighColor (view, face->background_defaulted_p ?
1664 FRAME_BACKGROUND_PIXEL (f) : face->background);
1665 BView_FillRectangle (view, 0, y, width, height);
1666 BView_FillRectangle (view, FRAME_PIXEL_WIDTH (f) - width,
1667 y, width, height);
1668 BView_EndClip (view);
1669 BView_draw_unlock (view);
1670 }
1671 else
1672 {
1673 haiku_clear_frame_area (f, 0, y, width, height);
1674 haiku_clear_frame_area (f, FRAME_PIXEL_WIDTH (f) - width,
1675 y, width, height);
1676 }
1677 unblock_input ();
1678 }
1679 }
1680
1681 static void
haiku_set_window_size(struct frame * f,bool change_gravity,int width,int height)1682 haiku_set_window_size (struct frame *f, bool change_gravity,
1683 int width, int height)
1684 {
1685 haiku_update_size_hints (f);
1686
1687 if (FRAME_HAIKU_WINDOW (f))
1688 {
1689 block_input ();
1690 BWindow_resize (FRAME_HAIKU_WINDOW (f), width, height);
1691 unblock_input ();
1692 }
1693 }
1694
1695 static void
haiku_draw_window_cursor(struct window * w,struct glyph_row * glyph_row,int x,int y,enum text_cursor_kinds cursor_type,int cursor_width,bool on_p,bool active_p)1696 haiku_draw_window_cursor (struct window *w,
1697 struct glyph_row *glyph_row,
1698 int x, int y,
1699 enum text_cursor_kinds cursor_type,
1700 int cursor_width, bool on_p, bool active_p)
1701 {
1702 struct frame *f = XFRAME (WINDOW_FRAME (w));
1703
1704 struct glyph *phys_cursor_glyph;
1705 struct glyph *cursor_glyph;
1706
1707 void *view = FRAME_HAIKU_VIEW (f);
1708
1709 int fx, fy, h, cursor_height;
1710
1711 if (!on_p)
1712 return;
1713
1714 if (cursor_type == NO_CURSOR)
1715 {
1716 w->phys_cursor_width = 0;
1717 return;
1718 }
1719
1720 w->phys_cursor_on_p = true;
1721 w->phys_cursor_type = cursor_type;
1722
1723 phys_cursor_glyph = get_phys_cursor_glyph (w);
1724
1725 if (!phys_cursor_glyph)
1726 {
1727 if (glyph_row->exact_window_width_line_p
1728 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
1729 {
1730 glyph_row->cursor_in_fringe_p = 1;
1731 draw_fringe_bitmap (w, glyph_row, 0);
1732 }
1733 return;
1734 }
1735
1736 get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h);
1737
1738 if (cursor_type == BAR_CURSOR)
1739 {
1740 if (cursor_width < 1)
1741 cursor_width = max (FRAME_CURSOR_WIDTH (f), 1);
1742 if (cursor_width < w->phys_cursor_width)
1743 w->phys_cursor_width = cursor_width;
1744 }
1745 else if (cursor_type == HBAR_CURSOR)
1746 {
1747 cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width;
1748 if (cursor_height > glyph_row->height)
1749 cursor_height = glyph_row->height;
1750 if (h > cursor_height)
1751 fy += h - cursor_height;
1752 h = cursor_height;
1753 }
1754
1755 BView_draw_lock (view);
1756 BView_StartClip (view);
1757 BView_SetHighColor (view, FRAME_CURSOR_COLOR (f).pixel);
1758 haiku_clip_to_row (w, glyph_row, TEXT_AREA);
1759
1760 switch (cursor_type)
1761 {
1762 default:
1763 case DEFAULT_CURSOR:
1764 case NO_CURSOR:
1765 break;
1766 case HBAR_CURSOR:
1767 BView_FillRectangle (view, fx, fy, w->phys_cursor_width, h);
1768 break;
1769 case BAR_CURSOR:
1770 cursor_glyph = get_phys_cursor_glyph (w);
1771 if (cursor_glyph->resolved_level & 1)
1772 BView_FillRectangle (view, fx + cursor_glyph->pixel_width - w->phys_cursor_width,
1773 fy, w->phys_cursor_width, h);
1774 else
1775 BView_FillRectangle (view, fx, fy, w->phys_cursor_width, h);
1776 break;
1777 case HOLLOW_BOX_CURSOR:
1778 if (phys_cursor_glyph->type != IMAGE_GLYPH)
1779 {
1780 BView_SetPenSize (view, 1);
1781 BView_StrokeRectangle (view, fx, fy, w->phys_cursor_width, h);
1782 }
1783 else
1784 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
1785 break;
1786 case FILLED_BOX_CURSOR:
1787 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
1788 }
1789 BView_EndClip (view);
1790 BView_draw_unlock (view);
1791 }
1792
1793 static void
haiku_show_hourglass(struct frame * f)1794 haiku_show_hourglass (struct frame *f)
1795 {
1796 if (FRAME_OUTPUT_DATA (f)->hourglass_p)
1797 return;
1798
1799 block_input ();
1800 FRAME_OUTPUT_DATA (f)->hourglass_p = 1;
1801
1802 if (FRAME_HAIKU_VIEW (f))
1803 BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
1804 FRAME_OUTPUT_DATA (f)->hourglass_cursor);
1805 unblock_input ();
1806 }
1807
1808 static void
haiku_hide_hourglass(struct frame * f)1809 haiku_hide_hourglass (struct frame *f)
1810 {
1811 if (!FRAME_OUTPUT_DATA (f)->hourglass_p)
1812 return;
1813
1814 block_input ();
1815 FRAME_OUTPUT_DATA (f)->hourglass_p = 0;
1816
1817 if (FRAME_HAIKU_VIEW (f))
1818 BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
1819 FRAME_OUTPUT_DATA (f)->current_cursor);
1820 unblock_input ();
1821 }
1822
1823 static void
haiku_compute_glyph_string_overhangs(struct glyph_string * s)1824 haiku_compute_glyph_string_overhangs (struct glyph_string *s)
1825 {
1826 if (s->cmp == NULL
1827 && (s->first_glyph->type == CHAR_GLYPH
1828 || s->first_glyph->type == COMPOSITE_GLYPH))
1829 {
1830 struct font_metrics metrics;
1831
1832 if (s->first_glyph->type == CHAR_GLYPH)
1833 {
1834 struct font *font = s->font;
1835 font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
1836 }
1837 else
1838 {
1839 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1840
1841 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
1842 }
1843 s->right_overhang = (metrics.rbearing > metrics.width
1844 ? metrics.rbearing - metrics.width : 0);
1845 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
1846 }
1847 else if (s->cmp)
1848 {
1849 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1850 s->left_overhang = - s->cmp->lbearing;
1851 }
1852 }
1853
1854 static void
haiku_draw_vertical_window_border(struct window * w,int x,int y_0,int y_1)1855 haiku_draw_vertical_window_border (struct window *w,
1856 int x, int y_0, int y_1)
1857 {
1858 struct frame *f = XFRAME (WINDOW_FRAME (w));
1859 struct face *face;
1860
1861 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
1862 void *view = FRAME_HAIKU_VIEW (f);
1863 BView_draw_lock (view);
1864 BView_StartClip (view);
1865 if (face)
1866 BView_SetHighColor (view, face->foreground);
1867 BView_StrokeLine (view, x, y_0, x, y_1);
1868 BView_EndClip (view);
1869 BView_draw_unlock (view);
1870 }
1871
1872 static void
haiku_set_scroll_bar_default_width(struct frame * f)1873 haiku_set_scroll_bar_default_width (struct frame *f)
1874 {
1875 int unit = FRAME_COLUMN_WIDTH (f);
1876 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = BScrollBar_default_size (0) + 1;
1877 FRAME_CONFIG_SCROLL_BAR_COLS (f) =
1878 (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
1879 }
1880
1881 static void
haiku_set_scroll_bar_default_height(struct frame * f)1882 haiku_set_scroll_bar_default_height (struct frame *f)
1883 {
1884 int height = FRAME_LINE_HEIGHT (f);
1885 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = BScrollBar_default_size (1) + 1;
1886 FRAME_CONFIG_SCROLL_BAR_LINES (f) =
1887 (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + height - 1) / height;
1888 }
1889
1890 static void
haiku_draw_window_divider(struct window * w,int x0,int x1,int y0,int y1)1891 haiku_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
1892 {
1893 struct frame *f = XFRAME (WINDOW_FRAME (w));
1894 struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
1895 struct face *face_first
1896 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
1897 struct face *face_last
1898 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
1899 unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
1900 unsigned long color_first = (face_first
1901 ? face_first->foreground
1902 : FRAME_FOREGROUND_PIXEL (f));
1903 unsigned long color_last = (face_last
1904 ? face_last->foreground
1905 : FRAME_FOREGROUND_PIXEL (f));
1906 void *view = FRAME_HAIKU_VIEW (f);
1907
1908 BView_draw_lock (view);
1909 BView_StartClip (view);
1910
1911 if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
1912 /* A vertical divider, at least three pixels wide: Draw first and
1913 last pixels differently. */
1914 {
1915 BView_SetHighColor (view, color_first);
1916 BView_StrokeLine (view, x0, y0, x0, y1 - 1);
1917 BView_SetHighColor (view, color);
1918 BView_FillRectangle (view, x0 + 1, y0, x1 - x0 - 2, y1 - y0);
1919 BView_SetHighColor (view, color_last);
1920 BView_StrokeLine (view, x1 - 1, y0, x1 - 1, y1 - 1);
1921 }
1922 else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
1923 /* A horizontal divider, at least three pixels high: Draw first and
1924 last pixels differently. */
1925 {
1926 BView_SetHighColor (view, color_first);
1927 BView_StrokeLine (f, x0, y0, x1 - 1, y0);
1928 BView_SetHighColor (view, color);
1929 BView_FillRectangle (view, x0, y0 + 1, x1 - x0, y1 - y0 - 2);
1930 BView_SetHighColor (view, color_last);
1931 BView_StrokeLine (view, x0, y1, x1 - 1, y1);
1932 }
1933 else
1934 {
1935 BView_SetHighColor (view, color);
1936 BView_FillRectangleAbs (view, x0, y0, x1, y1);
1937 }
1938 BView_EndClip (view);
1939 BView_draw_unlock (view);
1940 }
1941
1942 static void
haiku_condemn_scroll_bars(struct frame * frame)1943 haiku_condemn_scroll_bars (struct frame *frame)
1944 {
1945 if (!NILP (FRAME_SCROLL_BARS (frame)))
1946 {
1947 if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
1948 {
1949 /* Prepend scrollbars to already condemned ones. */
1950 Lisp_Object last = FRAME_SCROLL_BARS (frame);
1951
1952 while (!NILP (XSCROLL_BAR (last)->next))
1953 last = XSCROLL_BAR (last)->next;
1954
1955 XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
1956 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
1957 }
1958
1959 fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
1960 fset_scroll_bars (frame, Qnil);
1961 }
1962 }
1963
1964 static void
haiku_redeem_scroll_bar(struct window * w)1965 haiku_redeem_scroll_bar (struct window *w)
1966 {
1967 struct scroll_bar *bar;
1968 Lisp_Object barobj;
1969 struct frame *f;
1970
1971 if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
1972 {
1973 bar = XSCROLL_BAR (w->vertical_scroll_bar);
1974 /* Unlink it from the condemned list. */
1975 f = XFRAME (WINDOW_FRAME (w));
1976 if (NILP (bar->prev))
1977 {
1978 /* If the prev pointer is nil, it must be the first in one of
1979 the lists. */
1980 if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
1981 /* It's not condemned. Everything's fine. */
1982 goto horizontal;
1983 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
1984 w->vertical_scroll_bar))
1985 fset_condemned_scroll_bars (f, bar->next);
1986 else
1987 /* If its prev pointer is nil, it must be at the front of
1988 one or the other! */
1989 emacs_abort ();
1990 }
1991 else
1992 XSCROLL_BAR (bar->prev)->next = bar->next;
1993
1994 if (! NILP (bar->next))
1995 XSCROLL_BAR (bar->next)->prev = bar->prev;
1996
1997 bar->next = FRAME_SCROLL_BARS (f);
1998 bar->prev = Qnil;
1999 XSETVECTOR (barobj, bar);
2000 fset_scroll_bars (f, barobj);
2001 if (! NILP (bar->next))
2002 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2003 }
2004 horizontal:
2005 if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
2006 {
2007 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
2008 /* Unlink it from the condemned list. */
2009 f = XFRAME (WINDOW_FRAME (w));
2010 if (NILP (bar->prev))
2011 {
2012 /* If the prev pointer is nil, it must be the first in one of
2013 the lists. */
2014 if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
2015 /* It's not condemned. Everything's fine. */
2016 return;
2017 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2018 w->horizontal_scroll_bar))
2019 fset_condemned_scroll_bars (f, bar->next);
2020 else
2021 /* If its prev pointer is nil, it must be at the front of
2022 one or the other! */
2023 emacs_abort ();
2024 }
2025 else
2026 XSCROLL_BAR (bar->prev)->next = bar->next;
2027
2028 if (! NILP (bar->next))
2029 XSCROLL_BAR (bar->next)->prev = bar->prev;
2030
2031 bar->next = FRAME_SCROLL_BARS (f);
2032 bar->prev = Qnil;
2033 XSETVECTOR (barobj, bar);
2034 fset_scroll_bars (f, barobj);
2035 if (! NILP (bar->next))
2036 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2037 }
2038 }
2039
2040 static void
haiku_judge_scroll_bars(struct frame * f)2041 haiku_judge_scroll_bars (struct frame *f)
2042 {
2043 Lisp_Object bar, next;
2044
2045 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2046
2047 /* Clear out the condemned list now so we won't try to process any
2048 more events on the hapless scroll bars. */
2049 fset_condemned_scroll_bars (f, Qnil);
2050
2051 for (; ! NILP (bar); bar = next)
2052 {
2053 struct scroll_bar *b = XSCROLL_BAR (bar);
2054
2055 haiku_scroll_bar_remove (b);
2056
2057 next = b->next;
2058 b->next = b->prev = Qnil;
2059 }
2060
2061 /* Now there should be no references to the condemned scroll bars,
2062 and they should get garbage-collected. */
2063 }
2064
2065 static struct scroll_bar *
haiku_scroll_bar_create(struct window * w,int left,int top,int width,int height,bool horizontal_p)2066 haiku_scroll_bar_create (struct window *w, int left, int top,
2067 int width, int height, bool horizontal_p)
2068 {
2069 struct frame *f = XFRAME (WINDOW_FRAME (w));
2070 Lisp_Object barobj;
2071
2072 void *sb = NULL;
2073 void *vw = FRAME_HAIKU_VIEW (f);
2074
2075 block_input ();
2076 struct scroll_bar *bar
2077 = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER);
2078
2079 XSETWINDOW (bar->window, w);
2080 bar->top = top;
2081 bar->left = left;
2082 bar->width = width;
2083 bar->height = height;
2084 bar->position = 0;
2085 bar->total = 0;
2086 bar->dragging = 0;
2087 bar->update = -1;
2088 bar->horizontal = horizontal_p;
2089
2090 sb = BScrollBar_make_for_view (vw, horizontal_p,
2091 left, top, left + width - 1,
2092 top + height - 1, bar);
2093
2094 BView_publish_scroll_bar (vw, left, top, width, height);
2095
2096 bar->next = FRAME_SCROLL_BARS (f);
2097 bar->prev = Qnil;
2098 bar->scroll_bar = sb;
2099 XSETVECTOR (barobj, bar);
2100 fset_scroll_bars (f, barobj);
2101
2102 if (!NILP (bar->next))
2103 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2104
2105 unblock_input ();
2106 return bar;
2107 }
2108
2109 static void
haiku_set_horizontal_scroll_bar(struct window * w,int portion,int whole,int position)2110 haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
2111 {
2112 eassert (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w));
2113 Lisp_Object barobj;
2114 struct scroll_bar *bar;
2115 int top, height, left, width;
2116 int window_x, window_width;
2117
2118 /* Get window dimensions. */
2119 window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
2120 left = window_x;
2121 width = window_width;
2122 top = WINDOW_SCROLL_BAR_AREA_Y (w);
2123 height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
2124
2125 block_input ();
2126
2127 if (NILP (w->horizontal_scroll_bar))
2128 {
2129 bar = haiku_scroll_bar_create (w, left, top, width, height, true);
2130 BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
2131 bar->update = position;
2132 bar->position = position;
2133 bar->total = whole;
2134 }
2135 else
2136 {
2137 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
2138
2139 if (bar->left != left || bar->top != top ||
2140 bar->width != width || bar->height != height)
2141 {
2142 void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w));
2143 BView_forget_scroll_bar (view, bar->left, bar->top,
2144 bar->width, bar->height);
2145 BView_move_frame (bar->scroll_bar, left, top,
2146 left + width - 1, top + height - 1);
2147 BView_publish_scroll_bar (view, left, top, width, height);
2148 bar->left = left;
2149 bar->top = top;
2150 bar->width = width;
2151 bar->height = height;
2152 }
2153
2154 if (!bar->dragging)
2155 {
2156 BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
2157 BView_invalidate (bar->scroll_bar);
2158 }
2159 }
2160 bar->position = position;
2161 bar->total = whole;
2162 XSETVECTOR (barobj, bar);
2163 wset_horizontal_scroll_bar (w, barobj);
2164 unblock_input ();
2165 }
2166
2167 static void
haiku_set_vertical_scroll_bar(struct window * w,int portion,int whole,int position)2168 haiku_set_vertical_scroll_bar (struct window *w,
2169 int portion, int whole, int position)
2170 {
2171 eassert (WINDOW_HAS_VERTICAL_SCROLL_BAR (w));
2172 Lisp_Object barobj;
2173 struct scroll_bar *bar;
2174 int top, height, left, width;
2175 int window_y, window_height;
2176
2177 /* Get window dimensions. */
2178 window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
2179 top = window_y;
2180 height = window_height;
2181
2182 /* Compute the left edge and the width of the scroll bar area. */
2183 left = WINDOW_SCROLL_BAR_AREA_X (w);
2184 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2185 block_input ();
2186
2187 if (NILP (w->vertical_scroll_bar))
2188 {
2189 bar = haiku_scroll_bar_create (w, left, top, width, height, false);
2190 BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
2191 bar->position = position;
2192 bar->total = whole;
2193 }
2194 else
2195 {
2196 bar = XSCROLL_BAR (w->vertical_scroll_bar);
2197
2198 if (bar->left != left || bar->top != top ||
2199 bar->width != width || bar->height != height)
2200 {
2201 void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w));
2202 BView_forget_scroll_bar (view, bar->left, bar->top,
2203 bar->width, bar->height);
2204 BView_move_frame (bar->scroll_bar, left, top,
2205 left + width - 1, top + height - 1);
2206 flush_frame (WINDOW_XFRAME (w));
2207 BView_publish_scroll_bar (view, left, top, width, height);
2208 bar->left = left;
2209 bar->top = top;
2210 bar->width = width;
2211 bar->height = height;
2212 }
2213
2214 if (!bar->dragging)
2215 {
2216 BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
2217 bar->update = position;
2218 BView_invalidate (bar->scroll_bar);
2219 }
2220 }
2221
2222 bar->position = position;
2223 bar->total = whole;
2224
2225 XSETVECTOR (barobj, bar);
2226 wset_vertical_scroll_bar (w, barobj);
2227 unblock_input ();
2228 }
2229
2230 static void
haiku_draw_fringe_bitmap(struct window * w,struct glyph_row * row,struct draw_fringe_bitmap_params * p)2231 haiku_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2232 struct draw_fringe_bitmap_params *p)
2233 {
2234 void *view = FRAME_HAIKU_VIEW (XFRAME (WINDOW_FRAME (w)));
2235 struct face *face = p->face;
2236
2237 BView_draw_lock (view);
2238 BView_StartClip (view);
2239
2240 haiku_clip_to_row (w, row, ANY_AREA);
2241 if (p->bx >= 0 && !p->overlay_p)
2242 {
2243 BView_SetHighColor (view, face->background);
2244 BView_FillRectangle (view, p->bx, p->by, p->nx, p->ny);
2245 }
2246
2247 if (p->which && p->which < fringe_bitmap_fillptr)
2248 {
2249 void *bitmap = fringe_bmps[p->which];
2250
2251 uint32_t col;
2252
2253 if (!p->cursor_p)
2254 col = face->foreground;
2255 else if (p->overlay_p)
2256 col = face->background;
2257 else
2258 col = FRAME_CURSOR_COLOR (XFRAME (WINDOW_FRAME (w))).pixel;
2259
2260 if (!p->overlay_p)
2261 {
2262 BView_SetHighColor (view, face->background);
2263 BView_FillRectangle (view, p->x, p->y, p->wd, p->h);
2264 }
2265
2266 BView_SetLowColor (view, col);
2267 BView_DrawBitmapWithEraseOp (view, bitmap, p->x, p->y, p->wd, p->h);
2268 }
2269 BView_EndClip (view);
2270 BView_draw_unlock (view);
2271 }
2272
2273 static void
haiku_define_fringe_bitmap(int which,unsigned short * bits,int h,int wd)2274 haiku_define_fringe_bitmap (int which, unsigned short *bits,
2275 int h, int wd)
2276 {
2277 if (which >= fringe_bitmap_fillptr)
2278 {
2279 int i = fringe_bitmap_fillptr;
2280 fringe_bitmap_fillptr = which + 20;
2281 fringe_bmps = !i ? xmalloc (fringe_bitmap_fillptr * sizeof (void *)) :
2282 xrealloc (fringe_bmps, fringe_bitmap_fillptr * sizeof (void *));
2283
2284 while (i < fringe_bitmap_fillptr)
2285 fringe_bmps[i++] = NULL;
2286 }
2287
2288 fringe_bmps[which] = BBitmap_new (wd, h, 1);
2289 BBitmap_import_mono_bits (fringe_bmps[which], bits, wd, h);
2290 }
2291
2292 static void
haiku_destroy_fringe_bitmap(int which)2293 haiku_destroy_fringe_bitmap (int which)
2294 {
2295 if (which >= fringe_bitmap_fillptr)
2296 return;
2297
2298 if (fringe_bmps[which])
2299 BBitmap_free (fringe_bmps[which]);
2300 fringe_bmps[which] = NULL;
2301 }
2302
2303 static void
haiku_scroll_run(struct window * w,struct run * run)2304 haiku_scroll_run (struct window *w, struct run *run)
2305 {
2306 struct frame *f = XFRAME (w->frame);
2307 void *view = FRAME_HAIKU_VIEW (f);
2308 int x, y, width, height, from_y, to_y, bottom_y;
2309 window_box (w, ANY_AREA, &x, &y, &width, &height);
2310
2311 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2312 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2313 bottom_y = y + height;
2314
2315 if (to_y < from_y)
2316 {
2317 /* Scrolling up. Make sure we don't copy part of the mode
2318 line at the bottom. */
2319 if (from_y + run->height > bottom_y)
2320 height = bottom_y - from_y;
2321 else
2322 height = run->height;
2323 }
2324 else
2325 {
2326 /* Scrolling down. Make sure we don't copy over the mode line.
2327 at the bottom. */
2328 if (to_y + run->height > bottom_y)
2329 height = bottom_y - to_y;
2330 else
2331 height = run->height;
2332 }
2333
2334 if (!height)
2335 return;
2336
2337 block_input ();
2338 gui_clear_cursor (w);
2339 BView_draw_lock (view);
2340 #ifdef USE_BE_CAIRO
2341 if (EmacsView_double_buffered_p (view))
2342 {
2343 #endif
2344 BView_StartClip (view);
2345 BView_CopyBits (view, x, from_y, width, height,
2346 x, to_y, width, height);
2347 BView_EndClip (view);
2348 #ifdef USE_BE_CAIRO
2349 }
2350 else
2351 {
2352 EmacsWindow_begin_cr_critical_section (FRAME_HAIKU_WINDOW (f));
2353 cairo_surface_t *surface = FRAME_CR_SURFACE (f);
2354 cairo_surface_t *s
2355 = cairo_surface_create_similar (surface,
2356 cairo_surface_get_content (surface),
2357 width, height);
2358 cairo_t *cr = cairo_create (s);
2359 if (surface)
2360 {
2361 cairo_set_source_surface (cr, surface, -x, -from_y);
2362 cairo_paint (cr);
2363 cairo_destroy (cr);
2364
2365 cr = haiku_begin_cr_clip (f, NULL);
2366 cairo_save (cr);
2367 cairo_set_source_surface (cr, s, x, to_y);
2368 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
2369 cairo_rectangle (cr, x, to_y, width, height);
2370 cairo_fill (cr);
2371 cairo_restore (cr);
2372 cairo_surface_destroy (s);
2373 haiku_end_cr_clip (cr);
2374 }
2375 EmacsWindow_end_cr_critical_section (FRAME_HAIKU_WINDOW (f));
2376 }
2377 #endif
2378 BView_draw_unlock (view);
2379
2380 unblock_input ();
2381 }
2382
2383 static void
haiku_mouse_position(struct frame ** fp,int insist,Lisp_Object * bar_window,enum scroll_bar_part * part,Lisp_Object * x,Lisp_Object * y,Time * timestamp)2384 haiku_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
2385 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
2386 Time *timestamp)
2387 {
2388 if (!fp)
2389 return;
2390
2391 block_input ();
2392 Lisp_Object frame, tail;
2393 struct frame *f1 = NULL;
2394 FOR_EACH_FRAME (tail, frame)
2395 XFRAME (frame)->mouse_moved = false;
2396
2397 if (gui_mouse_grabbed (x_display_list) && !EQ (track_mouse, Qdropping))
2398 f1 = x_display_list->last_mouse_frame;
2399
2400 if (!f1 || FRAME_TOOLTIP_P (f1))
2401 f1 = ((EQ (track_mouse, Qdropping) && gui_mouse_grabbed (x_display_list))
2402 ? x_display_list->last_mouse_frame
2403 : NULL);
2404
2405 if (!f1 && insist > 0)
2406 f1 = SELECTED_FRAME ();
2407
2408 if (!f1 || (!FRAME_HAIKU_P (f1) && (insist > 0)))
2409 FOR_EACH_FRAME (tail, frame)
2410 if (FRAME_HAIKU_P (XFRAME (frame)) &&
2411 !FRAME_TOOLTIP_P (XFRAME (frame)))
2412 f1 = XFRAME (frame);
2413
2414 if (FRAME_TOOLTIP_P (f1))
2415 f1 = NULL;
2416
2417 if (f1 && FRAME_HAIKU_P (f1))
2418 {
2419 int sx, sy;
2420 void *view = FRAME_HAIKU_VIEW (f1);
2421 if (view)
2422 {
2423 BView_get_mouse (view, &sx, &sy);
2424
2425 remember_mouse_glyph (f1, sx, sy, &x_display_list->last_mouse_glyph);
2426 x_display_list->last_mouse_glyph_frame = f1;
2427
2428 *bar_window = Qnil;
2429 *part = scroll_bar_above_handle;
2430 *fp = f1;
2431 *timestamp = x_display_list->last_mouse_movement_time;
2432 XSETINT (*x, sx);
2433 XSETINT (*y, sy);
2434 }
2435 }
2436
2437 unblock_input ();
2438 }
2439
2440 static void
haiku_flush(struct frame * f)2441 haiku_flush (struct frame *f)
2442 {
2443 if (FRAME_VISIBLE_P (f))
2444 BWindow_Flush (FRAME_HAIKU_WINDOW (f));
2445 }
2446
2447 static void
haiku_define_frame_cursor(struct frame * f,Emacs_Cursor cursor)2448 haiku_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
2449 {
2450 if (f->tooltip)
2451 return;
2452 block_input ();
2453 if (!f->pointer_invisible && FRAME_HAIKU_VIEW (f)
2454 && !FRAME_OUTPUT_DATA (f)->hourglass_p)
2455 BView_set_view_cursor (FRAME_HAIKU_VIEW (f), cursor);
2456 unblock_input ();
2457 FRAME_OUTPUT_DATA (f)->current_cursor = cursor;
2458 }
2459
2460 static void
haiku_update_window_end(struct window * w,bool cursor_on_p,bool mouse_face_overwritten_p)2461 haiku_update_window_end (struct window *w, bool cursor_on_p,
2462 bool mouse_face_overwritten_p)
2463 {
2464
2465 }
2466
2467 static void
haiku_default_font_parameter(struct frame * f,Lisp_Object parms)2468 haiku_default_font_parameter (struct frame *f, Lisp_Object parms)
2469 {
2470 struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2471 Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
2472 RES_TYPE_STRING);
2473 Lisp_Object font = Qnil;
2474 if (EQ (font_param, Qunbound))
2475 font_param = Qnil;
2476
2477 if (NILP (font_param))
2478 {
2479 /* System font should take precedence over X resources. We suggest this
2480 regardless of font-use-system-font because .emacs may not have been
2481 read yet. */
2482 struct haiku_font_pattern ptn;
2483 ptn.specified = 0;
2484
2485 if (f->tooltip)
2486 BFont_populate_plain_family (&ptn);
2487 else
2488 BFont_populate_fixed_family (&ptn);
2489
2490 if (ptn.specified & FSPEC_FAMILY)
2491 font = font_open_by_name (f, build_unibyte_string (ptn.family));
2492 }
2493
2494 if (NILP (font))
2495 font = !NILP (font_param) ? font_param
2496 : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font",
2497 RES_TYPE_STRING);
2498
2499 if (! FONTP (font) && ! STRINGP (font))
2500 {
2501 const char **names = (const char *[]) { "monospace-12",
2502 "Noto Sans Mono-12",
2503 "Source Code Pro-12",
2504 NULL };
2505 int i;
2506
2507 for (i = 0; names[i]; i++)
2508 {
2509 font
2510 = font_open_by_name (f, build_unibyte_string (names[i]));
2511 if (!NILP (font))
2512 break;
2513 }
2514 if (NILP (font))
2515 error ("No suitable font was found");
2516 }
2517 else if (!NILP (font_param))
2518 {
2519 /* Remember the explicit font parameter, so we can re-apply it
2520 after we've applied the `default' face settings. */
2521 AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
2522 gui_set_frame_parameters (f, arg);
2523 }
2524
2525 gui_default_parameter (f, parms, Qfont, font, "font", "Font",
2526 RES_TYPE_STRING);
2527 }
2528
2529 static struct redisplay_interface haiku_redisplay_interface =
2530 {
2531 haiku_frame_parm_handlers,
2532 gui_produce_glyphs,
2533 gui_write_glyphs,
2534 gui_insert_glyphs,
2535 gui_clear_end_of_line,
2536 haiku_scroll_run,
2537 haiku_after_update_window_line,
2538 NULL,
2539 haiku_update_window_end,
2540 haiku_flush,
2541 gui_clear_window_mouse_face,
2542 gui_get_glyph_overhangs,
2543 gui_fix_overlapping_area,
2544 haiku_draw_fringe_bitmap,
2545 haiku_define_fringe_bitmap,
2546 haiku_destroy_fringe_bitmap,
2547 haiku_compute_glyph_string_overhangs,
2548 haiku_draw_glyph_string,
2549 haiku_define_frame_cursor,
2550 haiku_clear_frame_area,
2551 haiku_clear_under_internal_border,
2552 haiku_draw_window_cursor,
2553 haiku_draw_vertical_window_border,
2554 haiku_draw_window_divider,
2555 0, /* shift glyphs for insert */
2556 haiku_show_hourglass,
2557 haiku_hide_hourglass,
2558 haiku_default_font_parameter,
2559 };
2560
2561 static void
haiku_make_fullscreen_consistent(struct frame * f)2562 haiku_make_fullscreen_consistent (struct frame *f)
2563 {
2564 Lisp_Object lval = get_frame_param (f, Qfullscreen);
2565
2566 if (!EQ (lval, Qmaximized) && FRAME_OUTPUT_DATA (f)->zoomed_p)
2567 lval = Qmaximized;
2568 else if (EQ (lval, Qmaximized) && !FRAME_OUTPUT_DATA (f)->zoomed_p)
2569 lval = Qnil;
2570
2571 store_frame_param (f, Qfullscreen, lval);
2572 }
2573
2574 static void
flush_dirty_back_buffers(void)2575 flush_dirty_back_buffers (void)
2576 {
2577 block_input ();
2578 Lisp_Object tail, frame;
2579 FOR_EACH_FRAME (tail, frame)
2580 {
2581 struct frame *f = XFRAME (frame);
2582 if (FRAME_LIVE_P (f) &&
2583 FRAME_HAIKU_P (f) &&
2584 FRAME_HAIKU_WINDOW (f) &&
2585 !FRAME_GARBAGED_P (f) &&
2586 !buffer_flipping_blocked_p () &&
2587 FRAME_DIRTY_P (f))
2588 haiku_flip_buffers (f);
2589 }
2590 unblock_input ();
2591 }
2592
2593 static int
haiku_read_socket(struct terminal * terminal,struct input_event * hold_quit)2594 haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
2595 {
2596 block_input ();
2597 int message_count = 0;
2598 static void *buf = NULL;
2599 ssize_t b_size;
2600 struct unhandled_event *unhandled_events = NULL;
2601 int button_or_motion_p;
2602 int need_flush = 0;
2603
2604 if (!buf)
2605 buf = xmalloc (200);
2606 haiku_read_size (&b_size);
2607 while (b_size >= 0)
2608 {
2609 enum haiku_event_type type;
2610 struct input_event inev, inev2;
2611
2612 if (b_size > 200)
2613 emacs_abort ();
2614
2615 EVENT_INIT (inev);
2616 EVENT_INIT (inev2);
2617 inev.kind = NO_EVENT;
2618 inev2.kind = NO_EVENT;
2619 inev.arg = Qnil;
2620 inev2.arg = Qnil;
2621
2622 button_or_motion_p = 0;
2623
2624 haiku_read (&type, buf, b_size);
2625
2626 switch (type)
2627 {
2628 case QUIT_REQUESTED:
2629 {
2630 struct haiku_quit_requested_event *b = buf;
2631 struct frame *f = haiku_window_to_frame (b->window);
2632
2633 if (!f)
2634 continue;
2635
2636 inev.kind = DELETE_WINDOW_EVENT;
2637 XSETFRAME (inev.frame_or_window, f);
2638 break;
2639 }
2640 case FRAME_RESIZED:
2641 {
2642 struct haiku_resize_event *b = buf;
2643 struct frame *f = haiku_window_to_frame (b->window);
2644
2645 if (!f)
2646 continue;
2647
2648 int width = lrint (b->px_widthf);
2649 int height = lrint (b->px_heightf);
2650
2651 BView_draw_lock (FRAME_HAIKU_VIEW (f));
2652 BView_resize_to (FRAME_HAIKU_VIEW (f), width, height);
2653 BView_draw_unlock (FRAME_HAIKU_VIEW (f));
2654 if (width != FRAME_PIXEL_WIDTH (f)
2655 || height != FRAME_PIXEL_HEIGHT (f)
2656 || (f->new_size_p
2657 && ((f->new_width >= 0 && width != f->new_width)
2658 || (f->new_height >= 0 && height != f->new_height))))
2659 {
2660 change_frame_size (f, width, height, false, true, false);
2661 SET_FRAME_GARBAGED (f);
2662 cancel_mouse_face (f);
2663 haiku_clear_under_internal_border (f);
2664 }
2665
2666 if (FRAME_OUTPUT_DATA (f)->pending_zoom_width != width ||
2667 FRAME_OUTPUT_DATA (f)->pending_zoom_height != height)
2668 {
2669 FRAME_OUTPUT_DATA (f)->zoomed_p = 0;
2670 haiku_make_fullscreen_consistent (f);
2671 }
2672 else
2673 {
2674 FRAME_OUTPUT_DATA (f)->zoomed_p = 1;
2675 FRAME_OUTPUT_DATA (f)->pending_zoom_width = INT_MIN;
2676 FRAME_OUTPUT_DATA (f)->pending_zoom_height = INT_MIN;
2677 }
2678 break;
2679 }
2680 case FRAME_EXPOSED:
2681 {
2682 struct haiku_expose_event *b = buf;
2683 struct frame *f = haiku_window_to_frame (b->window);
2684
2685 if (!f)
2686 continue;
2687
2688 expose_frame (f, b->x, b->y, b->width, b->height);
2689
2690 haiku_clear_under_internal_border (f);
2691 break;
2692 }
2693 case KEY_DOWN:
2694 {
2695 struct haiku_key_event *b = buf;
2696 struct frame *f = haiku_window_to_frame (b->window);
2697 int non_ascii_p;
2698 if (!f)
2699 continue;
2700
2701 inev.code = b->unraw_mb_char;
2702
2703 BMapKey (b->kc, &non_ascii_p, &inev.code);
2704
2705 if (non_ascii_p)
2706 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
2707 else
2708 inev.kind = inev.code > 127 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT :
2709 ASCII_KEYSTROKE_EVENT;
2710
2711 inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
2712 XSETFRAME (inev.frame_or_window, f);
2713 break;
2714 }
2715 case ACTIVATION:
2716 {
2717 struct haiku_activation_event *b = buf;
2718 struct frame *f = haiku_window_to_frame (b->window);
2719
2720 if (!f)
2721 continue;
2722
2723 if ((x_display_list->focus_event_frame != f && b->activated_p) ||
2724 (x_display_list->focus_event_frame == f && !b->activated_p))
2725 {
2726 haiku_new_focus_frame (b->activated_p ? f : NULL);
2727 if (b->activated_p)
2728 x_display_list->focus_event_frame = f;
2729 else
2730 x_display_list->focus_event_frame = NULL;
2731 inev.kind = b->activated_p ? FOCUS_IN_EVENT : FOCUS_OUT_EVENT;
2732 XSETFRAME (inev.frame_or_window, f);
2733 }
2734
2735 break;
2736 }
2737 case MOUSE_MOTION:
2738 {
2739 struct haiku_mouse_motion_event *b = buf;
2740 struct frame *f = haiku_window_to_frame (b->window);
2741
2742 if (!f)
2743 continue;
2744
2745 Lisp_Object frame;
2746 XSETFRAME (frame, f);
2747
2748 x_display_list->last_mouse_movement_time = time (NULL);
2749 button_or_motion_p = 1;
2750
2751 if (b->just_exited_p)
2752 {
2753 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
2754 if (f == hlinfo->mouse_face_mouse_frame)
2755 {
2756 /* If we move outside the frame, then we're
2757 certainly no longer on any text in the frame. */
2758 clear_mouse_face (hlinfo);
2759 hlinfo->mouse_face_mouse_frame = 0;
2760 }
2761
2762 haiku_new_focus_frame (x_display_list->focused_frame);
2763 help_echo_string = Qnil;
2764 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
2765 }
2766 else
2767 {
2768 struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2769 struct haiku_rect r = dpyinfo->last_mouse_glyph;
2770
2771 dpyinfo->last_mouse_motion_x = b->x;
2772 dpyinfo->last_mouse_motion_y = b->y;
2773 dpyinfo->last_mouse_motion_frame = f;
2774
2775 previous_help_echo_string = help_echo_string;
2776 help_echo_string = Qnil;
2777
2778 if (f != dpyinfo->last_mouse_glyph_frame
2779 || b->x < r.x || b->x >= r.x + r.width
2780 || b->y < r.y || b->y >= r.y + r.height)
2781 {
2782 f->mouse_moved = true;
2783 dpyinfo->last_mouse_scroll_bar = NULL;
2784 note_mouse_highlight (f, b->x, b->y);
2785 remember_mouse_glyph (f, b->x, b->y,
2786 &FRAME_DISPLAY_INFO (f)->last_mouse_glyph);
2787 dpyinfo->last_mouse_glyph_frame = f;
2788 gen_help_event (help_echo_string, frame, help_echo_window,
2789 help_echo_object, help_echo_pos);
2790 }
2791
2792 if (MOUSE_HL_INFO (f)->mouse_face_hidden)
2793 {
2794 MOUSE_HL_INFO (f)->mouse_face_hidden = 0;
2795 clear_mouse_face (MOUSE_HL_INFO (f));
2796 }
2797
2798 if (!NILP (Vmouse_autoselect_window))
2799 {
2800 static Lisp_Object last_mouse_window;
2801 Lisp_Object window = window_from_coordinates (f, b->x, b->y, 0, 0, 0);
2802
2803 if (WINDOWP (window)
2804 && !EQ (window, last_mouse_window)
2805 && !EQ (window, selected_window)
2806 && (!NILP (focus_follows_mouse)
2807 || (EQ (XWINDOW (window)->frame,
2808 XWINDOW (selected_window)->frame))))
2809 {
2810 inev.kind = SELECT_WINDOW_EVENT;
2811 inev.frame_or_window = window;
2812 }
2813
2814 last_mouse_window = window;
2815 }
2816 }
2817 break;
2818 }
2819 case BUTTON_UP:
2820 case BUTTON_DOWN:
2821 {
2822 struct haiku_button_event *b = buf;
2823 struct frame *f = haiku_window_to_frame (b->window);
2824 Lisp_Object tab_bar_arg = Qnil;
2825 int tab_bar_p = 0, tool_bar_p = 0;
2826
2827 if (!f)
2828 continue;
2829
2830 struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2831
2832 inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
2833
2834 x_display_list->last_mouse_glyph_frame = 0;
2835 x_display_list->last_mouse_movement_time = time (NULL);
2836 button_or_motion_p = 1;
2837
2838 /* Is this in the tab-bar? */
2839 if (WINDOWP (f->tab_bar_window)
2840 && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
2841 {
2842 Lisp_Object window;
2843 int x = b->x;
2844 int y = b->y;
2845
2846 window = window_from_coordinates (f, x, y, 0, true, true);
2847 tab_bar_p = EQ (window, f->tab_bar_window);
2848
2849 if (tab_bar_p)
2850 {
2851 tab_bar_arg = handle_tab_bar_click
2852 (f, x, y, type == BUTTON_DOWN, inev.modifiers);
2853 need_flush = 1;
2854 }
2855 }
2856
2857 if (WINDOWP (f->tool_bar_window)
2858 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
2859 {
2860 Lisp_Object window;
2861 int x = b->x;
2862 int y = b->y;
2863
2864 window = window_from_coordinates (f, x, y, 0, true, true);
2865 tool_bar_p = EQ (window, f->tool_bar_window);
2866
2867 if (tool_bar_p)
2868 {
2869 handle_tool_bar_click
2870 (f, x, y, type == BUTTON_DOWN, inev.modifiers);
2871 need_flush = 1;
2872 }
2873 }
2874
2875 if (type == BUTTON_UP)
2876 {
2877 inev.modifiers |= up_modifier;
2878 dpyinfo->grabbed &= ~(1 << b->btn_no);
2879 }
2880 else
2881 {
2882 inev.modifiers |= down_modifier;
2883 dpyinfo->last_mouse_frame = f;
2884 dpyinfo->grabbed |= (1 << b->btn_no);
2885 if (f && !tab_bar_p)
2886 f->last_tab_bar_item = -1;
2887 if (f && !tool_bar_p)
2888 f->last_tool_bar_item = -1;
2889 }
2890
2891 if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
2892 inev.kind = MOUSE_CLICK_EVENT;
2893 inev.arg = tab_bar_arg;
2894 inev.code = b->btn_no;
2895
2896 f->mouse_moved = false;
2897
2898 XSETINT (inev.x, b->x);
2899 XSETINT (inev.y, b->y);
2900
2901 XSETFRAME (inev.frame_or_window, f);
2902 break;
2903 }
2904 case ICONIFICATION:
2905 {
2906 struct haiku_iconification_event *b = buf;
2907 struct frame *f = haiku_window_to_frame (b->window);
2908
2909 if (!f)
2910 continue;
2911
2912 if (!b->iconified_p)
2913 {
2914 SET_FRAME_VISIBLE (f, 1);
2915 SET_FRAME_ICONIFIED (f, 0);
2916 inev.kind = DEICONIFY_EVENT;
2917
2918
2919 /* Haiku doesn't expose frames on deiconification, but
2920 if we are double-buffered, the previous screen
2921 contents should have been preserved. */
2922 if (!EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)))
2923 {
2924 SET_FRAME_GARBAGED (f);
2925 expose_frame (f, 0, 0, 0, 0);
2926 }
2927 }
2928 else
2929 {
2930 SET_FRAME_VISIBLE (f, 0);
2931 SET_FRAME_ICONIFIED (f, 1);
2932 inev.kind = ICONIFY_EVENT;
2933 }
2934
2935 XSETFRAME (inev.frame_or_window, f);
2936 break;
2937 }
2938 case MOVE_EVENT:
2939 {
2940 struct haiku_move_event *b = buf;
2941 struct frame *f = haiku_window_to_frame (b->window);
2942
2943 if (!f)
2944 continue;
2945
2946 if (FRAME_OUTPUT_DATA (f)->pending_zoom_x != b->x ||
2947 FRAME_OUTPUT_DATA (f)->pending_zoom_y != b->y)
2948 FRAME_OUTPUT_DATA (f)->zoomed_p = 0;
2949 else
2950 {
2951 FRAME_OUTPUT_DATA (f)->zoomed_p = 1;
2952 FRAME_OUTPUT_DATA (f)->pending_zoom_x = INT_MIN;
2953 FRAME_OUTPUT_DATA (f)->pending_zoom_y = INT_MIN;
2954 }
2955
2956 if (FRAME_PARENT_FRAME (f))
2957 haiku_coords_from_parent (f, &b->x, &b->y);
2958
2959 if (b->x != f->left_pos || b->y != f->top_pos)
2960 {
2961 inev.kind = MOVE_FRAME_EVENT;
2962
2963 XSETINT (inev.x, b->x);
2964 XSETINT (inev.y, b->y);
2965
2966 f->left_pos = b->x;
2967 f->top_pos = b->y;
2968
2969 struct frame *p;
2970
2971 if ((p = FRAME_PARENT_FRAME (f)))
2972 {
2973 void *window = FRAME_HAIKU_WINDOW (p);
2974 EmacsWindow_move_weak_child (window, b->window, b->x, b->y);
2975 }
2976
2977 XSETFRAME (inev.frame_or_window, f);
2978 }
2979
2980 haiku_make_fullscreen_consistent (f);
2981 break;
2982 }
2983 case SCROLL_BAR_VALUE_EVENT:
2984 {
2985 struct haiku_scroll_bar_value_event *b = buf;
2986 struct scroll_bar *bar = b->scroll_bar;
2987
2988 struct window *w = XWINDOW (bar->window);
2989
2990 if (bar->update != -1)
2991 {
2992 bar->update = -1;
2993 break;
2994 }
2995
2996 if (bar->position != b->position)
2997 {
2998 inev.kind = bar->horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT :
2999 SCROLL_BAR_CLICK_EVENT;
3000 inev.part = bar->horizontal ?
3001 scroll_bar_horizontal_handle : scroll_bar_handle;
3002
3003 XSETINT (inev.x, b->position);
3004 XSETINT (inev.y, bar->total);
3005 XSETWINDOW (inev.frame_or_window, w);
3006 }
3007 break;
3008 }
3009 case SCROLL_BAR_DRAG_EVENT:
3010 {
3011 struct haiku_scroll_bar_drag_event *b = buf;
3012 struct scroll_bar *bar = b->scroll_bar;
3013
3014 bar->dragging = b->dragging_p;
3015 if (!b->dragging_p && bar->horizontal)
3016 set_horizontal_scroll_bar (XWINDOW (bar->window));
3017 else if (!b->dragging_p)
3018 set_vertical_scroll_bar (XWINDOW (bar->window));
3019 break;
3020 }
3021 case WHEEL_MOVE_EVENT:
3022 {
3023 struct haiku_wheel_move_event *b = buf;
3024 struct frame *f = haiku_window_to_frame (b->window);
3025 int x, y;
3026 static float px = 0.0f, py = 0.0f;
3027
3028 if (!f)
3029 continue;
3030 BView_get_mouse (FRAME_HAIKU_VIEW (f), &x, &y);
3031
3032 inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
3033
3034 inev2.modifiers = inev.modifiers;
3035
3036 if (signbit (px) != signbit (b->delta_x))
3037 px = 0;
3038
3039 if (signbit (py) != signbit (b->delta_y))
3040 py = 0;
3041
3042 px += (b->delta_x
3043 * powf (FRAME_PIXEL_HEIGHT (f), 2.0f / 3.0f));
3044 py += (b->delta_y
3045 * powf (FRAME_PIXEL_HEIGHT (f), 2.0f / 3.0f));
3046
3047 if (fabsf (py) >= FRAME_LINE_HEIGHT (f)
3048 || fabsf (px) >= FRAME_COLUMN_WIDTH (f)
3049 || !mwheel_coalesce_scroll_events)
3050 {
3051 inev.kind = (fabsf (px) > fabsf (py)
3052 ? HORIZ_WHEEL_EVENT
3053 : WHEEL_EVENT);
3054 inev.code = 0;
3055
3056 XSETINT (inev.x, x);
3057 XSETINT (inev.y, y);
3058 inev.arg = list3 (Qnil, make_float (-px),
3059 make_float (-py));
3060 XSETFRAME (inev.frame_or_window, f);
3061
3062 inev.modifiers |= (signbit (inev.kind == HORIZ_WHEEL_EVENT
3063 ? px : py)
3064 ? up_modifier
3065 : down_modifier);
3066 py = 0.0f;
3067 px = 0.0f;
3068 }
3069
3070 break;
3071 }
3072
3073 case MENU_BAR_RESIZE:
3074 {
3075 struct haiku_menu_bar_resize_event *b = buf;
3076 struct frame *f = haiku_window_to_frame (b->window);
3077
3078 if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
3079 continue;
3080
3081 int old_height = FRAME_MENU_BAR_HEIGHT (f);
3082
3083 FRAME_MENU_BAR_HEIGHT (f) = b->height + 1;
3084 FRAME_MENU_BAR_LINES (f) =
3085 (b->height + FRAME_LINE_HEIGHT (f)) / FRAME_LINE_HEIGHT (f);
3086
3087 if (old_height != b->height)
3088 {
3089 adjust_frame_size (f, -1, -1, 3, true, Qmenu_bar_lines);
3090 haiku_clear_under_internal_border (f);
3091 }
3092 break;
3093 }
3094 case MENU_BAR_OPEN:
3095 case MENU_BAR_CLOSE:
3096 {
3097 struct haiku_menu_bar_state_event *b = buf;
3098 struct frame *f = haiku_window_to_frame (b->window);
3099
3100 if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
3101 continue;
3102
3103 if (type == MENU_BAR_OPEN)
3104 {
3105 if (!FRAME_OUTPUT_DATA (f)->menu_up_to_date_p)
3106 {
3107 BView_draw_lock (FRAME_HAIKU_VIEW (f));
3108 /* This shouldn't be here, but nsmenu does it, so
3109 it should probably be safe. */
3110 int was_waiting_for_input_p = waiting_for_input;
3111 if (waiting_for_input)
3112 waiting_for_input = 0;
3113 set_frame_menubar (f, 1);
3114 waiting_for_input = was_waiting_for_input_p;
3115 BView_draw_unlock (FRAME_HAIKU_VIEW (f));
3116 }
3117 FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
3118 popup_activated_p += 1;
3119 }
3120 else
3121 {
3122 if (!popup_activated_p)
3123 emacs_abort ();
3124 if (FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
3125 {
3126 FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 0;
3127 popup_activated_p -= 1;
3128 }
3129 }
3130 break;
3131 }
3132 case MENU_BAR_SELECT_EVENT:
3133 {
3134 struct haiku_menu_bar_select_event *b = buf;
3135 struct frame *f = haiku_window_to_frame (b->window);
3136
3137 if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
3138 continue;
3139
3140 if (FRAME_OUTPUT_DATA (f)->menu_up_to_date_p)
3141 find_and_call_menu_selection (f, f->menu_bar_items_used,
3142 f->menu_bar_vector, b->ptr);
3143 break;
3144 }
3145 case FILE_PANEL_EVENT:
3146 {
3147 if (!popup_activated_p)
3148 continue;
3149
3150 struct unhandled_event *ev = xmalloc (sizeof *ev);
3151 ev->next = unhandled_events;
3152 ev->type = type;
3153 memcpy (&ev->buffer, buf, 200);
3154
3155 unhandled_events = ev;
3156 break;
3157 }
3158 case MENU_BAR_HELP_EVENT:
3159 {
3160 struct haiku_menu_bar_help_event *b = buf;
3161
3162 if (!popup_activated_p)
3163 continue;
3164
3165 struct frame *f = haiku_window_to_frame (b->window);
3166 if (!f || !FRAME_EXTERNAL_MENU_BAR (f) ||
3167 !FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
3168 continue;
3169
3170 run_menu_bar_help_event (f, b->mb_idx);
3171
3172 break;
3173 }
3174 case ZOOM_EVENT:
3175 {
3176 struct haiku_zoom_event *b = buf;
3177
3178 struct frame *f = haiku_window_to_frame (b->window);
3179
3180 if (!f)
3181 continue;
3182
3183 FRAME_OUTPUT_DATA (f)->pending_zoom_height = b->height;
3184 FRAME_OUTPUT_DATA (f)->pending_zoom_width = b->width;
3185 FRAME_OUTPUT_DATA (f)->pending_zoom_x = b->x;
3186 FRAME_OUTPUT_DATA (f)->pending_zoom_y = b->y;
3187
3188 FRAME_OUTPUT_DATA (f)->zoomed_p = 1;
3189 haiku_make_fullscreen_consistent (f);
3190 break;
3191 }
3192 case REFS_EVENT:
3193 {
3194 struct haiku_refs_event *b = buf;
3195 struct frame *f = haiku_window_to_frame (b->window);
3196
3197 if (!f)
3198 continue;
3199
3200 inev.kind = DRAG_N_DROP_EVENT;
3201 inev.arg = build_string_from_utf8 (b->ref);
3202
3203 XSETINT (inev.x, b->x);
3204 XSETINT (inev.y, b->y);
3205 XSETFRAME (inev.frame_or_window, f);
3206
3207 /* There should be no problem with calling free here.
3208 free on Haiku is thread-safe. */
3209 free (b->ref);
3210 break;
3211 }
3212 case APP_QUIT_REQUESTED_EVENT:
3213 case KEY_UP:
3214 default:
3215 break;
3216 }
3217
3218 haiku_read_size (&b_size);
3219
3220 if (inev.kind != NO_EVENT)
3221 {
3222 if (inev.kind != HELP_EVENT)
3223 inev.timestamp = (button_or_motion_p
3224 ? x_display_list->last_mouse_movement_time
3225 : time (NULL));
3226 kbd_buffer_store_event_hold (&inev, hold_quit);
3227 ++message_count;
3228 }
3229
3230 if (inev2.kind != NO_EVENT)
3231 {
3232 if (inev2.kind != HELP_EVENT)
3233 inev2.timestamp = (button_or_motion_p
3234 ? x_display_list->last_mouse_movement_time
3235 : time (NULL));
3236 kbd_buffer_store_event_hold (&inev2, hold_quit);
3237 ++message_count;
3238 }
3239 }
3240
3241 for (struct unhandled_event *ev = unhandled_events; ev;)
3242 {
3243 haiku_write_without_signal (ev->type, &ev->buffer);
3244 struct unhandled_event *old = ev;
3245 ev = old->next;
3246 xfree (old);
3247 }
3248
3249 if (need_flush)
3250 flush_dirty_back_buffers ();
3251
3252 unblock_input ();
3253 return message_count;
3254 }
3255
3256 static void
haiku_frame_rehighlight(struct frame * frame)3257 haiku_frame_rehighlight (struct frame *frame)
3258 {
3259 haiku_rehighlight ();
3260 }
3261
3262 static void
haiku_delete_window(struct frame * f)3263 haiku_delete_window (struct frame *f)
3264 {
3265 check_window_system (f);
3266 haiku_free_frame_resources (f);
3267 }
3268
3269 static void
haiku_free_pixmap(struct frame * f,Emacs_Pixmap pixmap)3270 haiku_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
3271 {
3272 BBitmap_free (pixmap);
3273 }
3274
3275 static void
haiku_beep(struct frame * f)3276 haiku_beep (struct frame *f)
3277 {
3278 if (visible_bell)
3279 {
3280 void *view = FRAME_HAIKU_VIEW (f);
3281 if (view)
3282 {
3283 block_input ();
3284 BView_draw_lock (view);
3285 if (!EmacsView_double_buffered_p (view))
3286 {
3287 BView_SetHighColorForVisibleBell (view, FRAME_FOREGROUND_PIXEL (f));
3288 BView_FillRectangleForVisibleBell (view, 0, 0, FRAME_PIXEL_WIDTH (f),
3289 FRAME_PIXEL_HEIGHT (f));
3290 SET_FRAME_GARBAGED (f);
3291 expose_frame (f, 0, 0, 0, 0);
3292 }
3293 else
3294 {
3295 EmacsView_do_visible_bell (view, FRAME_FOREGROUND_PIXEL (f));
3296 haiku_flip_buffers (f);
3297 }
3298 BView_draw_unlock (view);
3299 unblock_input ();
3300 }
3301 }
3302 else
3303 haiku_ring_bell ();
3304 }
3305
3306 static void
haiku_toggle_invisible_pointer(struct frame * f,bool invisible_p)3307 haiku_toggle_invisible_pointer (struct frame *f, bool invisible_p)
3308 {
3309 void *view = FRAME_HAIKU_VIEW (f);
3310
3311 if (view)
3312 {
3313 block_input ();
3314 BView_set_view_cursor (view, invisible_p ?
3315 FRAME_OUTPUT_DATA (f)->no_cursor :
3316 FRAME_OUTPUT_DATA (f)->current_cursor);
3317 f->pointer_invisible = invisible_p;
3318 unblock_input ();
3319 }
3320 }
3321
3322 static void
haiku_fullscreen(struct frame * f)3323 haiku_fullscreen (struct frame *f)
3324 {
3325 if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
3326 {
3327 EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 0);
3328 BWindow_zoom (FRAME_HAIKU_WINDOW (f));
3329 }
3330 else if (f->want_fullscreen == FULLSCREEN_BOTH)
3331 EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 1);
3332 else if (f->want_fullscreen == FULLSCREEN_NONE)
3333 {
3334 EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 0);
3335 EmacsWindow_unzoom (FRAME_HAIKU_WINDOW (f));
3336 }
3337
3338 f->want_fullscreen = FULLSCREEN_NONE;
3339
3340 haiku_update_size_hints (f);
3341 }
3342
3343 static struct terminal *
haiku_create_terminal(struct haiku_display_info * dpyinfo)3344 haiku_create_terminal (struct haiku_display_info *dpyinfo)
3345 {
3346 struct terminal *terminal;
3347
3348 terminal = create_terminal (output_haiku, &haiku_redisplay_interface);
3349
3350 terminal->display_info.haiku = dpyinfo;
3351 dpyinfo->terminal = terminal;
3352 terminal->kboard = allocate_kboard (Qhaiku);
3353
3354 terminal->iconify_frame_hook = haiku_iconify_frame;
3355 terminal->focus_frame_hook = haiku_focus_frame;
3356 terminal->ring_bell_hook = haiku_beep;
3357 terminal->popup_dialog_hook = haiku_popup_dialog;
3358 terminal->frame_visible_invisible_hook = haiku_set_frame_visible_invisible;
3359 terminal->set_frame_offset_hook = haiku_set_offset;
3360 terminal->delete_terminal_hook = haiku_delete_terminal;
3361 terminal->get_string_resource_hook = get_string_resource;
3362 terminal->set_new_font_hook = haiku_new_font;
3363 terminal->defined_color_hook = haiku_defined_color;
3364 terminal->set_window_size_hook = haiku_set_window_size;
3365 terminal->read_socket_hook = haiku_read_socket;
3366 terminal->implicit_set_name_hook = haiku_implicitly_set_name;
3367 terminal->mouse_position_hook = haiku_mouse_position;
3368 terminal->delete_frame_hook = haiku_delete_window;
3369 terminal->frame_up_to_date_hook = haiku_frame_up_to_date;
3370 terminal->buffer_flipping_unblocked_hook = haiku_buffer_flipping_unblocked_hook;
3371 terminal->clear_frame_hook = haiku_clear_frame;
3372 terminal->change_tab_bar_height_hook = haiku_change_tab_bar_height;
3373 terminal->change_tool_bar_height_hook = haiku_change_tool_bar_height;
3374 terminal->set_vertical_scroll_bar_hook = haiku_set_vertical_scroll_bar;
3375 terminal->set_horizontal_scroll_bar_hook = haiku_set_horizontal_scroll_bar;
3376 terminal->set_scroll_bar_default_height_hook = haiku_set_scroll_bar_default_height;
3377 terminal->set_scroll_bar_default_width_hook = haiku_set_scroll_bar_default_width;
3378 terminal->judge_scroll_bars_hook = haiku_judge_scroll_bars;
3379 terminal->condemn_scroll_bars_hook = haiku_condemn_scroll_bars;
3380 terminal->redeem_scroll_bar_hook = haiku_redeem_scroll_bar;
3381 terminal->update_begin_hook = haiku_update_begin;
3382 terminal->update_end_hook = haiku_update_end;
3383 terminal->frame_rehighlight_hook = haiku_frame_rehighlight;
3384 terminal->query_frame_background_color = haiku_query_frame_background_color;
3385 terminal->free_pixmap = haiku_free_pixmap;
3386 terminal->frame_raise_lower_hook = haiku_frame_raise_lower;
3387 terminal->menu_show_hook = haiku_menu_show;
3388 terminal->toggle_invisible_pointer_hook = haiku_toggle_invisible_pointer;
3389 terminal->fullscreen_hook = haiku_fullscreen;
3390
3391 return terminal;
3392 }
3393
3394 struct haiku_display_info *
haiku_term_init(void)3395 haiku_term_init (void)
3396 {
3397 struct haiku_display_info *dpyinfo;
3398 struct terminal *terminal;
3399
3400 Lisp_Object color_file, color_map;
3401
3402 block_input ();
3403 Fset_input_interrupt_mode (Qnil);
3404
3405 baud_rate = 19200;
3406
3407 dpyinfo = xzalloc (sizeof *dpyinfo);
3408
3409 haiku_io_init ();
3410
3411 if (port_application_to_emacs < B_OK)
3412 emacs_abort ();
3413
3414 color_file = Fexpand_file_name (build_string ("rgb.txt"),
3415 Fsymbol_value (intern ("data-directory")));
3416
3417 color_map = Fx_load_color_file (color_file);
3418 if (NILP (color_map))
3419 fatal ("Could not read %s.\n", SDATA (color_file));
3420
3421 dpyinfo->color_map = color_map;
3422
3423 dpyinfo->display = BApplication_setup ();
3424
3425 BScreen_res (&dpyinfo->resx, &dpyinfo->resy);
3426
3427 dpyinfo->next = x_display_list;
3428 dpyinfo->n_planes = be_get_display_planes ();
3429 x_display_list = dpyinfo;
3430
3431 terminal = haiku_create_terminal (dpyinfo);
3432 if (current_kboard == initial_kboard)
3433 current_kboard = terminal->kboard;
3434
3435 terminal->kboard->reference_count++;
3436 /* Never delete haiku displays -- there can only ever be one,
3437 anyhow. */
3438 terminal->reference_count++;
3439 terminal->name = xstrdup ("be");
3440
3441 dpyinfo->name_list_element = Fcons (build_string ("be"), Qnil);
3442 dpyinfo->smallest_font_height = 1;
3443 dpyinfo->smallest_char_width = 1;
3444
3445 gui_init_fringe (terminal->rif);
3446 unblock_input ();
3447
3448 return dpyinfo;
3449 }
3450
3451 void
put_xrm_resource(Lisp_Object name,Lisp_Object val)3452 put_xrm_resource (Lisp_Object name, Lisp_Object val)
3453 {
3454 eassert (STRINGP (name));
3455 eassert (STRINGP (val) || NILP (val));
3456
3457 Lisp_Object lval = assoc_no_quit (name, rdb);
3458 if (!NILP (lval))
3459 Fsetcdr (lval, val);
3460 else
3461 rdb = Fcons (Fcons (name, val), rdb);
3462 }
3463
3464 void
haiku_clear_under_internal_border(struct frame * f)3465 haiku_clear_under_internal_border (struct frame *f)
3466 {
3467 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
3468 {
3469 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
3470 int width = FRAME_PIXEL_WIDTH (f);
3471 int height = FRAME_PIXEL_HEIGHT (f);
3472 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
3473 int face_id =
3474 (FRAME_PARENT_FRAME (f)
3475 ? (!NILP (Vface_remapping_alist)
3476 ? lookup_basic_face (NULL, f, CHILD_FRAME_BORDER_FACE_ID)
3477 : CHILD_FRAME_BORDER_FACE_ID)
3478 : (!NILP (Vface_remapping_alist)
3479 ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
3480 : INTERNAL_BORDER_FACE_ID));
3481 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
3482 void *view = FRAME_HAIKU_VIEW (f);
3483 block_input ();
3484 BView_draw_lock (view);
3485 BView_StartClip (view);
3486 BView_ClipToRect (view, 0, 0, FRAME_PIXEL_WIDTH (f),
3487 FRAME_PIXEL_HEIGHT (f));
3488
3489 if (face)
3490 BView_SetHighColor (view, face->background);
3491 else
3492 BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (f));
3493
3494 BView_FillRectangle (view, 0, margin, width, border);
3495 BView_FillRectangle (view, 0, 0, border, height);
3496 BView_FillRectangle (view, 0, margin, width, border);
3497 BView_FillRectangle (view, width - border, 0, border, height);
3498 BView_FillRectangle (view, 0, height - border, width, border);
3499 BView_EndClip (view);
3500 BView_draw_unlock (view);
3501 unblock_input ();
3502 }
3503 }
3504
3505 void
mark_haiku_display(void)3506 mark_haiku_display (void)
3507 {
3508 if (x_display_list)
3509 mark_object (x_display_list->color_map);
3510 }
3511
3512 void
haiku_scroll_bar_remove(struct scroll_bar * bar)3513 haiku_scroll_bar_remove (struct scroll_bar *bar)
3514 {
3515 block_input ();
3516 void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (XWINDOW (bar->window)));
3517 BView_forget_scroll_bar (view, bar->left, bar->top, bar->width, bar->height);
3518 BScrollBar_delete (bar->scroll_bar);
3519 expose_frame (WINDOW_XFRAME (XWINDOW (bar->window)),
3520 bar->left, bar->top, bar->width, bar->height);
3521
3522 if (bar->horizontal)
3523 wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
3524 else
3525 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
3526
3527 unblock_input ();
3528 };
3529
3530 void
haiku_set_offset(struct frame * frame,int x,int y,int change_gravity)3531 haiku_set_offset (struct frame *frame, int x, int y,
3532 int change_gravity)
3533 {
3534 if (change_gravity > 0)
3535 {
3536 frame->top_pos = y;
3537 frame->left_pos = x;
3538 frame->size_hint_flags &= ~ (XNegative | YNegative);
3539 if (x < 0)
3540 frame->size_hint_flags |= XNegative;
3541 if (y < 0)
3542 frame->size_hint_flags |= YNegative;
3543 frame->win_gravity = NorthWestGravity;
3544 }
3545
3546 haiku_update_size_hints (frame);
3547
3548 block_input ();
3549 if (change_gravity)
3550 BWindow_set_offset (FRAME_HAIKU_WINDOW (frame), x, y);
3551 unblock_input ();
3552 }
3553
3554 #ifdef USE_BE_CAIRO
3555 cairo_t *
haiku_begin_cr_clip(struct frame * f,struct glyph_string * s)3556 haiku_begin_cr_clip (struct frame *f, struct glyph_string *s)
3557 {
3558 cairo_surface_t *surface = FRAME_CR_SURFACE (f);
3559 if (!surface)
3560 return NULL;
3561
3562 cairo_t *context = cairo_create (surface);
3563 return context;
3564 }
3565
3566 void
haiku_end_cr_clip(cairo_t * cr)3567 haiku_end_cr_clip (cairo_t *cr)
3568 {
3569 cairo_destroy (cr);
3570 }
3571 #endif
3572
3573 void
syms_of_haikuterm(void)3574 syms_of_haikuterm (void)
3575 {
3576 DEFVAR_BOOL ("haiku-initialized", haiku_initialized,
3577 doc: /* Non-nil if the Haiku terminal backend has been initialized. */);
3578
3579 DEFVAR_BOOL ("x-use-underline-position-properties",
3580 x_use_underline_position_properties,
3581 doc: /* SKIP: real doc in xterm.c. */);
3582 x_use_underline_position_properties = 1;
3583
3584 DEFVAR_BOOL ("x-underline-at-descent-line",
3585 x_underline_at_descent_line,
3586 doc: /* SKIP: real doc in xterm.c. */);
3587 x_underline_at_descent_line = 0;
3588
3589 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
3590 doc: /* SKIP: real doc in xterm.c. */);
3591 Vx_toolkit_scroll_bars = Qt;
3592
3593 DEFVAR_BOOL ("haiku-debug-on-fatal-error", haiku_debug_on_fatal_error,
3594 doc: /* If non-nil, Emacs will launch the system debugger upon a fatal error. */);
3595 haiku_debug_on_fatal_error = 1;
3596
3597 DEFSYM (Qshift, "shift");
3598 DEFSYM (Qcontrol, "control");
3599 DEFSYM (Qoption, "option");
3600 DEFSYM (Qcommand, "command");
3601
3602 DEFVAR_LISP ("haiku-meta-keysym", Vhaiku_meta_keysym,
3603 doc: /* Which key Emacs uses as the meta modifier.
3604 This is either one of the symbols `shift', `control', `command', and
3605 `option', or nil, in which case it is treated as `command'.
3606
3607 Setting it to any other value is equivalent to `command'. */);
3608 Vhaiku_meta_keysym = Qnil;
3609
3610 DEFVAR_LISP ("haiku-control-keysym", Vhaiku_control_keysym,
3611 doc: /* Which key Emacs uses as the control modifier.
3612 This is either one of the symbols `shift', `control', `command', and
3613 `option', or nil, in which case it is treated as `control'.
3614
3615 Setting it to any other value is equivalent to `control'. */);
3616 Vhaiku_control_keysym = Qnil;
3617
3618 DEFVAR_LISP ("haiku-super-keysym", Vhaiku_super_keysym,
3619 doc: /* Which key Emacs uses as the super modifier.
3620 This is either one of the symbols `shift', `control', `command', and
3621 `option', or nil, in which case it is treated as `option'.
3622
3623 Setting it to any other value is equivalent to `option'. */);
3624 Vhaiku_super_keysym = Qnil;
3625
3626 DEFVAR_LISP ("haiku-shift-keysym", Vhaiku_shift_keysym,
3627 doc: /* Which key Emacs uses as the shift modifier.
3628 This is either one of the symbols `shift', `control', `command', and
3629 `option', or nil, in which case it is treated as `shift'.
3630
3631 Setting it to any other value is equivalent to `shift'. */);
3632 Vhaiku_shift_keysym = Qnil;
3633
3634
3635 DEFSYM (Qx_use_underline_position_properties,
3636 "x-use-underline-position-properties");
3637
3638 DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
3639
3640 rdb = Qnil;
3641 staticpro (&rdb);
3642
3643 Fprovide (Qhaiku, Qnil);
3644 #ifdef USE_BE_CAIRO
3645 Fprovide (intern_c_string ("cairo"), Qnil);
3646 #endif
3647 }
3648