Fix project-find-regexp in remote projects
[emacs.git] / src / haikuterm.c
blobc194a348df373f8db30a5033e0a0fa9a34a38b90
1 /* Haiku window system support
2 Copyright (C) 2021-2024 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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.
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.
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/>. */
19 #include <config.h>
21 #include "dispextern.h"
22 #include "frame.h"
23 #include "lisp.h"
24 #include "haikugui.h"
25 #include "keyboard.h"
26 #include "haikuterm.h"
27 #include "blockinput.h"
28 #include "termchar.h"
29 #include "termhooks.h"
30 #include "menu.h"
31 #include "buffer.h"
32 #include "haiku_support.h"
33 #include "thread.h"
34 #include "window.h"
35 #include "haikuselect.h"
37 #include <math.h>
38 #include <stdlib.h>
40 #ifdef USE_BE_CAIRO
41 #include <cairo.h>
42 #endif
44 /* Minimum and maximum values used for Haiku scroll bars. */
45 #define BE_SB_MAX 12000000
47 /* The single Haiku display (if any). */
48 struct haiku_display_info *x_display_list;
50 /* This is used to determine when to evict the font lookup cache,
51 which we do every 50 updates. */
52 static int up_to_date_count;
54 /* List of defined fringe bitmaps. */
55 static void **fringe_bmps;
57 /* The amount of fringe bitmaps in that list. */
58 static int max_fringe_bmp;
60 /* Alist of resources to their values. */
61 static Lisp_Object rdb;
63 /* Non-zero means that a HELP_EVENT has been generated since Emacs
64 start. */
65 static bool any_help_event_p;
67 char *
68 get_keysym_name (int keysym)
70 static char value[16];
71 sprintf (value, "%d", keysym);
72 return value;
75 static struct frame *
76 haiku_window_to_frame (void *window)
78 Lisp_Object tail, tem;
79 struct frame *f;
81 FOR_EACH_FRAME (tail, tem)
83 f = XFRAME (tem);
84 if (!FRAME_HAIKU_P (f))
85 continue;
87 eassert (FRAME_DISPLAY_INFO (f) == x_display_list);
89 if (FRAME_HAIKU_WINDOW (f) == window)
90 return f;
93 return 0;
96 static void
97 haiku_coords_from_parent (struct frame *f, int *x, int *y)
99 struct frame *p = FRAME_PARENT_FRAME (f);
101 *x -= FRAME_OUTPUT_DATA (p)->frame_x;
102 *y -= FRAME_OUTPUT_DATA (p)->frame_y;
105 static void
106 haiku_toolkit_position (struct frame *f, int x, int y,
107 bool *menu_bar_p, bool *tool_bar_p)
109 if (FRAME_OUTPUT_DATA (f)->menubar)
110 *menu_bar_p = (x >= 0 && x < FRAME_PIXEL_WIDTH (f)
111 && y >= 0 && y < FRAME_MENU_BAR_HEIGHT (f));
114 static void
115 haiku_delete_terminal (struct terminal *terminal)
117 error ("The Haiku terminal cannot be deleted");
120 static const char *
121 haiku_get_string_resource (void *ignored, const char *name,
122 const char *class)
124 const char *native;
126 if (!name)
127 return NULL;
129 Lisp_Object lval = assoc_no_quit (build_string (name), rdb);
131 if (!NILP (lval))
132 return SSDATA (XCDR (lval));
134 if ((native = be_find_setting (name)))
135 return native;
137 return NULL;
140 static void
141 haiku_update_size_hints (struct frame *f)
143 if (f->tooltip)
144 return;
146 block_input ();
147 BWindow_set_size_alignment (FRAME_HAIKU_WINDOW (f),
148 (frame_resize_pixelwise
149 ? 1 : FRAME_COLUMN_WIDTH (f)),
150 (frame_resize_pixelwise
151 ? 1 : FRAME_LINE_HEIGHT (f)));
152 unblock_input ();
155 static void
156 haiku_clip_to_string (struct glyph_string *s)
158 struct haiku_rect r[2];
159 int n = get_glyph_string_clip_rects (s, (struct haiku_rect *) &r, 2);
161 if (n)
163 /* If n[FOO].width is 0, it means to not draw at all, so set the
164 clipping to some impossible value. */
165 if (r[0].width <= 0)
166 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f),
167 FRAME_PIXEL_WIDTH (s->f),
168 FRAME_PIXEL_HEIGHT (s->f),
169 10, 10);
170 else
172 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f), r[0].x,
173 r[0].y, r[0].width, r[0].height);
174 BView_invalidate_region (FRAME_HAIKU_DRAWABLE (s->f), r[0].x,
175 r[0].y, r[0].width, r[0].height);
179 if (n > 1)
181 /* If n[FOO].width is 0, it means to not draw at all, so set the
182 clipping to some impossible value. */
183 if (r[1].width <= 0)
184 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f),
185 FRAME_PIXEL_WIDTH (s->f),
186 FRAME_PIXEL_HEIGHT (s->f),
187 10, 10);
188 else
190 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f), r[1].x, r[1].y,
191 r[1].width, r[1].height);
192 BView_invalidate_region (FRAME_HAIKU_DRAWABLE (s->f), r[1].x,
193 r[1].y, r[1].width, r[1].height);
198 static void
199 haiku_clip_to_string_exactly (struct glyph_string *s, struct glyph_string *dst)
201 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f), s->x, s->y,
202 s->width, s->height);
203 BView_invalidate_region (FRAME_HAIKU_DRAWABLE (s->f), s->x,
204 s->y, s->width, s->height);
207 static void
208 haiku_flip_buffers (struct frame *f)
210 void *view = FRAME_OUTPUT_DATA (f)->view;
211 block_input ();
213 BView_draw_lock (view, false, 0, 0, 0, 0);
214 FRAME_DIRTY_P (f) = 0;
215 EmacsView_flip_and_blit (view);
216 BView_draw_unlock (view);
218 unblock_input ();
221 static void
222 haiku_frame_up_to_date (struct frame *f)
224 block_input ();
225 FRAME_MOUSE_UPDATE (f);
226 if (FRAME_DIRTY_P (f) && !buffer_flipping_blocked_p ())
227 haiku_flip_buffers (f);
229 up_to_date_count++;
230 if (up_to_date_count == 50)
232 be_evict_font_cache ();
233 up_to_date_count = 0;
236 /* Mark the frame as complete. */
237 FRAME_COMPLETE_P (f) = true;
238 unblock_input ();
241 static void
242 haiku_buffer_flipping_unblocked_hook (struct frame *f)
244 if (FRAME_DIRTY_P (f))
245 haiku_flip_buffers (f);
248 static void
249 haiku_clear_frame_area (struct frame *f, int x, int y,
250 int width, int height)
252 void *vw = FRAME_HAIKU_DRAWABLE (f);
253 block_input ();
254 BView_draw_lock (vw, true, x, y, width, height);
255 BView_StartClip (vw);
256 BView_ClipToRect (vw, x, y, width, height);
257 BView_SetHighColor (vw, FRAME_BACKGROUND_PIXEL (f));
258 BView_FillRectangle (vw, x, y, width, height);
259 BView_EndClip (vw);
260 BView_draw_unlock (vw);
261 unblock_input ();
264 static void
265 haiku_clear_frame (struct frame *f)
267 void *view = FRAME_HAIKU_DRAWABLE (f);
269 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
271 FRAME_COMPLETE_P (f) = false;
273 block_input ();
274 BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
275 FRAME_PIXEL_HEIGHT (f));
276 BView_StartClip (view);
277 BView_ClipToRect (view, 0, 0, FRAME_PIXEL_WIDTH (f),
278 FRAME_PIXEL_HEIGHT (f));
279 BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (f));
280 BView_FillRectangle (view, 0, 0, FRAME_PIXEL_WIDTH (f) ,
281 FRAME_PIXEL_HEIGHT (f));
282 BView_EndClip (view);
283 BView_draw_unlock (view);
284 unblock_input ();
287 /* Give frame F the font FONT-OBJECT as its default font. The return
288 value is FONT-OBJECT. FONTSET is an ID of the fontset for the
289 frame. If it is negative, generate a new fontset from
290 FONT-OBJECT. */
292 static Lisp_Object
293 haiku_new_font (struct frame *f, Lisp_Object font_object, int fontset)
295 struct font *font;
296 int ascent, descent, unit;
298 font = XFONT_OBJECT (font_object);
300 if (fontset < 0)
301 fontset = fontset_from_font (font_object);
303 FRAME_FONTSET (f) = fontset;
305 if (FRAME_FONT (f) == font)
306 return font_object;
308 FRAME_FONT (f) = font;
309 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
310 FRAME_COLUMN_WIDTH (f) = font->average_width;
312 get_font_ascent_descent (font, &ascent, &descent);
313 FRAME_LINE_HEIGHT (f) = ascent + descent;
314 FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
316 unit = FRAME_COLUMN_WIDTH (f);
317 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
318 FRAME_CONFIG_SCROLL_BAR_COLS (f)
319 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
320 else
321 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
323 if (FRAME_HAIKU_WINDOW (f) && !FRAME_TOOLTIP_P (f))
324 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
325 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f),
326 3, false, Qfont);
328 return font_object;
331 static int
332 haiku_valid_modifier_p (Lisp_Object sym)
334 return EQ (sym, Qcommand) || EQ (sym, Qshift)
335 || EQ (sym, Qcontrol) || EQ (sym, Qoption);
338 #define MODIFIER_OR(obj, def) (haiku_valid_modifier_p (obj) ? obj : def)
340 static void
341 haiku_add_modifier (int modifier, int toput, Lisp_Object qtem, int *modifiers)
343 if ((modifier & HAIKU_MODIFIER_ALT && EQ (qtem, Qcommand))
344 || (modifier & HAIKU_MODIFIER_SHIFT && EQ (qtem, Qshift))
345 || (modifier & HAIKU_MODIFIER_CTRL && EQ (qtem, Qcontrol))
346 || (modifier & HAIKU_MODIFIER_SUPER && EQ (qtem, Qoption)))
347 *modifiers |= toput;
350 static int
351 haiku_modifiers_to_emacs (int haiku_key)
353 int modifiers = 0;
354 haiku_add_modifier (haiku_key, shift_modifier,
355 MODIFIER_OR (Vhaiku_shift_keysym, Qshift), &modifiers);
356 haiku_add_modifier (haiku_key, super_modifier,
357 MODIFIER_OR (Vhaiku_super_keysym, Qoption), &modifiers);
358 haiku_add_modifier (haiku_key, meta_modifier,
359 MODIFIER_OR (Vhaiku_meta_keysym, Qcommand), &modifiers);
360 haiku_add_modifier (haiku_key, ctrl_modifier,
361 MODIFIER_OR (Vhaiku_control_keysym, Qcontrol), &modifiers);
362 return modifiers;
365 #undef MODIFIER_OR
367 static void
368 haiku_rehighlight (void)
370 eassert (x_display_list && !x_display_list->next);
372 block_input ();
374 struct frame *old_hl = x_display_list->highlight_frame;
376 if (x_display_list->focused_frame)
378 x_display_list->highlight_frame
379 = ((FRAMEP (FRAME_FOCUS_FRAME (x_display_list->focused_frame)))
380 ? XFRAME (FRAME_FOCUS_FRAME (x_display_list->focused_frame))
381 : x_display_list->focused_frame);
382 if (!FRAME_LIVE_P (x_display_list->highlight_frame))
384 fset_focus_frame (x_display_list->focused_frame, Qnil);
385 x_display_list->highlight_frame = x_display_list->focused_frame;
388 else
389 x_display_list->highlight_frame = 0;
391 if (old_hl)
392 gui_update_cursor (old_hl, true);
394 if (x_display_list->highlight_frame)
395 gui_update_cursor (x_display_list->highlight_frame, true);
396 unblock_input ();
399 static void
400 haiku_frame_raise_lower (struct frame *f, bool raise_p)
402 if (raise_p)
404 block_input ();
405 BWindow_activate (FRAME_HAIKU_WINDOW (f));
406 BWindow_sync (FRAME_HAIKU_WINDOW (f));
407 unblock_input ();
409 else
411 block_input ();
412 BWindow_send_behind (FRAME_HAIKU_WINDOW (f), NULL);
413 BWindow_sync (FRAME_HAIKU_WINDOW (f));
414 unblock_input ();
418 static struct frame *
419 haiku_mouse_or_wdesc_frame (void *window, bool accept_tooltip)
421 struct frame *lm_f = (gui_mouse_grabbed (x_display_list)
422 ? x_display_list->last_mouse_frame
423 : NULL);
425 if (lm_f && !EQ (track_mouse, Qdropping)
426 && !EQ (track_mouse, Qdrag_source))
427 return lm_f;
428 else
430 struct frame *w_f = haiku_window_to_frame (window);
432 /* Do not return a tooltip frame. */
433 if (!w_f || (FRAME_TOOLTIP_P (w_f) && !accept_tooltip))
434 return EQ (track_mouse, Qdropping) ? lm_f : NULL;
435 else
436 /* When dropping it would be probably nice to raise w_f
437 here. */
438 return w_f;
442 /* Set the thumb size and position of scroll bar BAR. We are
443 currently displaying PORTION out of a whole WHOLE, and our position
444 POSITION. */
446 static void
447 haiku_set_scroll_bar_thumb (struct scroll_bar *bar, int portion,
448 int position, int whole)
450 void *scroll_bar = bar->scroll_bar;
451 double top, shown, size, value;
453 if (scroll_bar_adjust_thumb_portion_p)
455 /* We use an estimate of 30 chars per line rather than the real
456 `portion' value. This has the disadvantage that the thumb
457 size is not very representative, but it makes our life a lot
458 easier. Otherwise, we have to constantly adjust the thumb
459 size, which we can't always do quickly enough: while
460 dragging, the size of the thumb might prevent the user from
461 dragging the thumb all the way to the end. */
462 portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
463 /* When the thumb is at the bottom, position == whole. So we
464 need to increase `whole' to make space for the thumb. */
465 whole += portion;
467 else
468 bar->page_size = 0;
470 if (whole <= 0)
471 top = 0, shown = 1;
472 else
474 top = (double) position / whole;
475 shown = (double) portion / whole;
478 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
479 is the scroll bar's maximum and MIN is the scroll bar's minimum
480 value. */
481 size = clip_to_bounds (1, shown * BE_SB_MAX, BE_SB_MAX);
483 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
484 value = top * BE_SB_MAX;
485 value = min (value, BE_SB_MAX - size);
487 if (!bar->dragging && scroll_bar_adjust_thumb_portion_p)
488 bar->page_size = size;
490 BView_scroll_bar_update (scroll_bar, lrint (size),
491 BE_SB_MAX, ceil (value),
492 (scroll_bar_adjust_thumb_portion_p
493 ? bar->dragging : bar->dragging ? -1 : 0),
494 !scroll_bar_adjust_thumb_portion_p);
497 static void
498 haiku_set_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion,
499 int position, int whole)
501 void *scroll_bar = bar->scroll_bar;
502 double size, value, shown, top;
504 shown = (double) portion / whole;
505 top = (double) position / whole;
507 size = shown * BE_SB_MAX;
508 value = top * BE_SB_MAX;
510 if (!bar->dragging)
511 bar->page_size = size;
513 BView_scroll_bar_update (scroll_bar, lrint (size), BE_SB_MAX,
514 ceil (value), bar->dragging ? -1 : 0, true);
517 static struct scroll_bar *
518 haiku_scroll_bar_from_widget (void *scroll_bar, void *window)
520 Lisp_Object tem;
521 struct frame *frame = haiku_window_to_frame (window);
523 if (!frame)
524 return NULL;
526 if (!scroll_bar)
527 return NULL;
529 if (!NILP (FRAME_SCROLL_BARS (frame)))
531 for (tem = FRAME_SCROLL_BARS (frame); !NILP (tem);
532 tem = XSCROLL_BAR (tem)->next)
534 if (XSCROLL_BAR (tem)->scroll_bar == scroll_bar)
535 return XSCROLL_BAR (tem);
539 return NULL;
542 /* Unfortunately, NOACTIVATE is not implementable on Haiku. */
543 static void
544 haiku_focus_frame (struct frame *frame, bool noactivate)
546 if (x_display_list->focused_frame != frame)
547 haiku_frame_raise_lower (frame, 1);
550 static void
551 haiku_new_focus_frame (struct frame *frame)
553 eassert (x_display_list && !x_display_list->next);
555 block_input ();
556 if (frame != x_display_list->focused_frame)
558 if (x_display_list->focused_frame &&
559 x_display_list->focused_frame->auto_lower)
560 haiku_frame_raise_lower (x_display_list->focused_frame, 0);
562 x_display_list->focused_frame = frame;
564 if (frame && frame->auto_raise && !popup_activated_p)
565 haiku_frame_raise_lower (frame, 1);
567 unblock_input ();
569 haiku_rehighlight ();
572 static void
573 haiku_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
575 haiku_set_name (f, arg, 0);
578 static void
579 haiku_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor)
581 haiku_query_color (FRAME_BACKGROUND_PIXEL (f), bgcolor);
584 static bool
585 haiku_defined_color (struct frame *f, const char *name,
586 Emacs_Color *color, bool alloc, bool make_index)
588 int rc;
590 rc = !haiku_get_color (name, color);
592 if (rc && f->gamma && alloc)
593 gamma_correct (f, color);
595 return rc;
598 /* Adapted from xterm `x_draw_box_rect'. */
599 static void
600 haiku_draw_box_rect (struct glyph_string *s, int left_x, int top_y,
601 int right_x, int bottom_y, int hwidth, int vwidth,
602 bool left_p, bool right_p, struct haiku_rect *clip_rect)
604 void *view = FRAME_HAIKU_DRAWABLE (s->f);
605 struct face *face = s->face;
607 BView_SetHighColor (view, face->box_color);
608 if (clip_rect)
609 BView_ClipToRect (view, clip_rect->x, clip_rect->y, clip_rect->width,
610 clip_rect->height);
611 BView_FillRectangle (view, left_x, top_y, right_x - left_x + 1, hwidth);
612 if (left_p)
613 BView_FillRectangle (view, left_x, top_y, vwidth, bottom_y - top_y + 1);
615 BView_FillRectangle (view, left_x, bottom_y - hwidth + 1,
616 right_x - left_x + 1, hwidth);
617 if (right_p)
618 BView_FillRectangle (view, right_x - vwidth + 1,
619 top_y, vwidth, bottom_y - top_y + 1);
622 static void
623 haiku_calculate_relief_colors (struct glyph_string *s, uint32_t *rgbout_w,
624 uint32_t *rgbout_b)
626 double h, cs, l;
627 uint32_t rgbin;
628 struct haiku_output *di;
630 if (s->face->use_box_color_for_shadows_p)
631 rgbin = s->face->box_color;
632 else if (s->first_glyph->type == IMAGE_GLYPH
633 && s->img->pixmap
634 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
635 rgbin = IMAGE_BACKGROUND (s->img, s->f, 0);
636 else
637 rgbin = s->face->background;
639 di = FRAME_OUTPUT_DATA (s->f);
641 if (s->hl == DRAW_CURSOR)
642 rgbin = FRAME_CURSOR_COLOR (s->f).pixel;
644 if (di->relief_background != rgbin)
646 di->relief_background = rgbin & 0xffffffff;
648 rgb_color_hsl (rgbin, &h, &cs, &l);
649 hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 0.6),
650 &di->black_relief_pixel);
651 hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 1.2),
652 &di->white_relief_pixel);
655 *rgbout_w = di->white_relief_pixel;
656 *rgbout_b = di->black_relief_pixel;
659 static void
660 haiku_draw_relief_rect (struct glyph_string *s, int left_x, int top_y,
661 int right_x, int bottom_y, int hwidth, int vwidth,
662 bool raised_p, bool top_p, bool bot_p, bool left_p,
663 bool right_p, struct haiku_rect *clip_rect)
665 uint32_t color_white, color_black;
666 void *view;
668 view = FRAME_HAIKU_DRAWABLE (s->f);
669 haiku_calculate_relief_colors (s, &color_white, &color_black);
671 BView_SetHighColor (view, raised_p ? color_white : color_black);
673 if (clip_rect)
675 BView_StartClip (view);
676 haiku_clip_to_string (s);
677 BView_ClipToRect (view, clip_rect->x, clip_rect->y,
678 clip_rect->width, clip_rect->height);
681 if (top_p)
682 BView_FillRectangle (view, left_x, top_y,
683 right_x - left_x + 1, hwidth);
685 if (left_p)
686 BView_FillRectangle (view, left_x, top_y,
687 vwidth, bottom_y - top_y + 1);
689 BView_SetHighColor (view, !raised_p ? color_white : color_black);
691 if (bot_p)
692 BView_FillRectangle (view, left_x, bottom_y - hwidth + 1,
693 right_x - left_x + 1, hwidth);
694 if (right_p)
695 BView_FillRectangle (view, right_x - vwidth + 1, top_y,
696 vwidth, bottom_y - top_y + 1);
698 /* Draw the triangle for the bottom-left corner. */
699 if (bot_p && left_p)
701 BView_SetHighColor (view, raised_p ? color_white : color_black);
702 BView_FillTriangle (view, left_x, bottom_y - hwidth, left_x + vwidth,
703 bottom_y - hwidth, left_x, bottom_y);
706 /* Now draw the triangle for the top-right corner. */
707 if (top_p && right_p)
709 BView_SetHighColor (view, raised_p ? color_white : color_black);
710 BView_FillTriangle (view, right_x - vwidth, top_y,
711 right_x, top_y,
712 right_x - vwidth, top_y + hwidth);
715 /* If (h/v)width is > 1, we draw the outer-most line on each side in the
716 black relief color. */
718 BView_SetHighColor (view, color_black);
720 if (hwidth > 1 && top_p)
721 BView_StrokeLine (view, left_x, top_y, right_x, top_y);
722 if (hwidth > 1 && bot_p)
723 BView_StrokeLine (view, left_x, bottom_y, right_x, bottom_y);
724 if (vwidth > 1 && left_p)
725 BView_StrokeLine (view, left_x, top_y, left_x, bottom_y);
726 if (vwidth > 1 && right_p)
727 BView_StrokeLine (view, right_x, top_y, right_x, bottom_y);
729 BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (s->f));
731 /* Omit corner pixels. */
732 if (hwidth > 1 && vwidth > 1)
734 if (left_p && top_p)
735 BView_FillRectangle (view, left_x, top_y, 1, 1);
736 if (left_p && bot_p)
737 BView_FillRectangle (view, left_x, bottom_y, 1, 1);
738 if (right_p && top_p)
739 BView_FillRectangle (view, right_x, top_y, 1, 1);
740 if (right_p && bot_p)
741 BView_FillRectangle (view, right_x, bottom_y, 1, 1);
744 if (clip_rect)
745 BView_EndClip (view);
748 static void
749 haiku_get_scale_factor (int *scale_x, int *scale_y)
751 struct haiku_display_info *dpyinfo = x_display_list;
753 if (dpyinfo->resx > 96)
754 *scale_x = floor (dpyinfo->resx / 96);
755 if (dpyinfo->resy > 96)
756 *scale_y = floor (dpyinfo->resy / 96);
759 static void
760 haiku_draw_underwave (struct glyph_string *s, int width, int x)
762 int wave_height, wave_length;
763 int y, dx, dy, odd, xmax, scale_x, scale_y;
764 float ax, ay, bx, by;
765 void *view;
767 scale_x = 1;
768 scale_y = 1;
769 haiku_get_scale_factor (&scale_x, &scale_y);
770 wave_height = 3 * scale_y;
771 wave_length = 2 * scale_x;
773 dx = wave_length;
774 dy = wave_height - 1;
775 y = s->ybase - wave_height + 3;
776 xmax = x + width;
777 view = FRAME_HAIKU_DRAWABLE (s->f);
779 BView_StartClip (view);
780 haiku_clip_to_string (s);
781 BView_ClipToRect (view, x, y, width, wave_height);
783 ax = x - ((int) (x) % dx) + (float) 0.5;
784 bx = ax + dx;
785 odd = (int) (ax / dx) % 2;
786 ay = by = y + 0.5;
788 if (odd)
789 ay += dy;
790 else
791 by += dy;
793 BView_SetPenSize (view, scale_y);
795 while (ax <= xmax)
797 BView_StrokeLine (view, ax, ay, bx, by);
798 ax = bx, ay = by;
799 bx += dx, by = y + 0.5 + odd * dy;
800 odd = !odd;
803 BView_SetPenSize (view, 1);
804 BView_EndClip (view);
807 /* Draw a dashed underline of thickness THICKNESS and width WIDTH onto F
808 at a vertical offset of OFFSET from the position of the glyph string
809 S, with each segment SEGMENT pixels in length. */
811 static void
812 haiku_draw_dash (struct frame *f, struct glyph_string *s, int width,
813 int segment, int offset, int thickness)
815 int y_center, which, length, x, doffset;
816 void *view;
818 /* Configure the thickness of the view's strokes. */
819 view = FRAME_HAIKU_VIEW (s->f);
820 BView_SetPenSize (view, thickness);
822 /* Offset the origin of the line by half the line width. */
823 y_center = s->ybase + offset + thickness / 2;
825 /* Remove redundant portions of OFFSET. */
826 doffset = s->x % (segment * 2);
828 /* Set which to the phase of the first dash that ought to be drawn and
829 length to its length. */
830 which = doffset < segment;
831 length = segment - (s->x % segment);
833 /* Begin drawing this dash. */
834 for (x = s->x; x < s->x + width; x += length, length = segment)
836 if (which)
837 BView_StrokeLine (view, x, y_center,
838 min (x + length - 1,
839 s->x + width - 1),
840 y_center);
842 which = !which;
846 /* Draw an underline of STYLE onto F at an offset of POSITION from the
847 baseline of the glyph string S, S->WIDTH in length, and THICKNESS in
848 height. */
850 static void
851 haiku_fill_underline (struct frame *f, struct glyph_string *s,
852 enum face_underline_type style, int position,
853 int thickness)
855 int segment;
856 void *view;
858 segment = thickness * 3;
859 view = FRAME_HAIKU_VIEW (f);
861 switch (style)
863 /* FACE_UNDERLINE_DOUBLE_LINE is treated identically to SINGLE, as
864 the second line will be filled by another invocation of this
865 function. */
866 case FACE_UNDERLINE_SINGLE:
867 case FACE_UNDERLINE_DOUBLE_LINE:
868 BView_FillRectangle (view, s->x, s->ybase + position,
869 s->width, thickness);
870 break;
872 case FACE_UNDERLINE_DOTS:
873 segment = thickness;
874 FALLTHROUGH;
876 case FACE_UNDERLINE_DASHES:
877 haiku_draw_dash (f, s, s->width, segment, position, thickness);
878 break;
880 case FACE_NO_UNDERLINE:
881 case FACE_UNDERLINE_WAVE:
882 default:
883 emacs_abort ();
887 static void
888 haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
889 int width, int x)
891 unsigned long cursor_color;
893 if (s->for_overlaps)
894 return;
896 if (s->hl == DRAW_CURSOR)
897 haiku_merge_cursor_foreground (s, &cursor_color, NULL);
899 void *view = FRAME_HAIKU_DRAWABLE (s->f);
901 if (face->underline)
903 if (s->hl == DRAW_CURSOR)
904 BView_SetHighColor (view, cursor_color);
905 else if (!face->underline_defaulted_p)
906 BView_SetHighColor (view, face->underline_color);
907 else
908 BView_SetHighColor (view, face->foreground);
910 if (face->underline == FACE_UNDERLINE_WAVE)
911 haiku_draw_underwave (s, width, x);
912 else if (face->underline >= FACE_UNDERLINE_SINGLE)
914 unsigned long thickness, position;
916 if (s->prev
917 && (s->prev->face->underline != FACE_UNDERLINE_WAVE
918 && s->prev->face->underline >= FACE_UNDERLINE_SINGLE)
919 && (s->prev->face->underline_at_descent_line_p
920 == s->face->underline_at_descent_line_p)
921 && (s->prev->face->underline_pixels_above_descent_line
922 == s->face->underline_pixels_above_descent_line))
924 /* We use the same underline style as the previous one. */
925 thickness = s->prev->underline_thickness;
926 position = s->prev->underline_position;
928 else
930 struct font *font = font_for_underline_metrics (s);
931 unsigned long minimum_offset;
932 bool underline_at_descent_line;
933 bool use_underline_position_properties;
934 Lisp_Object val = (WINDOW_BUFFER_LOCAL_VALUE
935 (Qunderline_minimum_offset, s->w));
937 if (FIXNUMP (val))
938 minimum_offset = max (0, XFIXNUM (val));
939 else
940 minimum_offset = 1;
942 val = (WINDOW_BUFFER_LOCAL_VALUE
943 (Qx_underline_at_descent_line, s->w));
944 underline_at_descent_line
945 = (!(NILP (val) || BASE_EQ (val, Qunbound))
946 || s->face->underline_at_descent_line_p);
948 val = (WINDOW_BUFFER_LOCAL_VALUE
949 (Qx_use_underline_position_properties, s->w));
950 use_underline_position_properties
951 = !(NILP (val) || BASE_EQ (val, Qunbound));
953 /* Get the underline thickness. Default is 1 pixel. */
954 if (font && font->underline_thickness > 0)
955 thickness = font->underline_thickness;
956 else
957 thickness = 1;
958 if (underline_at_descent_line)
959 position = ((s->height - thickness)
960 - (s->ybase - s->y)
961 - s->face->underline_pixels_above_descent_line);
962 else
964 /* Get the underline position. This is the
965 recommended vertical offset in pixels from
966 the baseline to the top of the underline.
967 This is a signed value according to the
968 specs, and its default is
970 ROUND ((maximum descent) / 2), with
971 ROUND(x) = floor (x + 0.5) */
973 if (use_underline_position_properties
974 && font && font->underline_position >= 0)
975 position = font->underline_position;
976 else if (font)
977 position = (font->descent + 1) / 2;
978 else
979 position = minimum_offset;
981 position = max (position, minimum_offset);
983 /* Check the sanity of thickness and position. We should
984 avoid drawing underline out of the current line area. */
985 if (s->y + s->height <= s->ybase + position)
986 position = (s->height - 1) - (s->ybase - s->y);
987 if (s->y + s->height < s->ybase + position + thickness)
988 thickness = (s->y + s->height) - (s->ybase + position);
989 s->underline_thickness = thickness;
990 s->underline_position = position;
992 haiku_fill_underline (s->f, s, s->face->underline,
993 position, thickness);
995 /* Place a second underline above the first if this was
996 requested in the face specification. */
998 if (s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
1000 /* Compute the position of the second underline. */
1001 position = position - thickness - 1;
1002 haiku_fill_underline (s->f, s, s->face->underline,
1003 position, thickness);
1008 if (face->overline_p)
1010 unsigned long dy = 0, h = 1;
1011 if (s->hl == DRAW_CURSOR)
1012 BView_SetHighColor (view, cursor_color);
1013 else if (!face->overline_color_defaulted_p)
1014 BView_SetHighColor (view, face->overline_color);
1015 else
1016 BView_SetHighColor (view, face->foreground);
1018 BView_FillRectangle (view, s->x, s->y + dy, s->width, h);
1021 if (face->strike_through_p)
1023 /* Y-coordinate and height of the glyph string's first
1024 glyph. We cannot use s->y and s->height because those
1025 could be larger if there are taller display elements
1026 (e.g., characters displayed with a larger font) in the
1027 same glyph row. */
1028 int glyph_y = s->ybase - s->first_glyph->ascent;
1029 int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
1030 /* Strike-through width and offset from the glyph string's
1031 top edge. */
1032 unsigned long h = 1;
1033 unsigned long dy = (glyph_height - h) / 2;
1035 if (s->hl == DRAW_CURSOR)
1036 BView_SetHighColor (view, cursor_color);
1037 else if (!face->strike_through_color_defaulted_p)
1038 BView_SetHighColor (view, face->strike_through_color);
1039 else
1040 BView_SetHighColor (view, face->foreground);
1042 BView_FillRectangle (view, s->x, glyph_y + dy, s->width, h);
1046 static void
1047 haiku_draw_string_box (struct glyph_string *s)
1049 int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
1050 bool raised_p, left_p, right_p;
1051 struct glyph *last_glyph;
1052 struct face *face = s->face;
1054 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
1055 ? WINDOW_RIGHT_EDGE_X (s->w)
1056 : window_box_right (s->w, s->area));
1058 /* The glyph that may have a right box line. For static
1059 compositions and images, the right-box flag is on the first glyph
1060 of the glyph string; for other types it's on the last glyph. */
1061 if (s->cmp || s->img)
1062 last_glyph = s->first_glyph;
1063 else if (s->first_glyph->type == COMPOSITE_GLYPH
1064 && s->first_glyph->u.cmp.automatic)
1066 /* For automatic compositions, we need to look up the last glyph
1067 in the composition. */
1068 struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area];
1069 struct glyph *g = s->first_glyph;
1070 for (last_glyph = g++;
1071 g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id
1072 && g->slice.cmp.to < s->cmp_to;
1073 last_glyph = g++)
1076 else
1077 last_glyph = s->first_glyph + s->nchars - 1;
1079 vwidth = eabs (face->box_vertical_line_width);
1080 hwidth = eabs (face->box_horizontal_line_width);
1081 raised_p = face->box == FACE_RAISED_BOX;
1082 left_x = s->x;
1083 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
1084 ? last_x - 1
1085 : min (last_x, s->x + s->background_width) - 1);
1087 top_y = s->y;
1088 bottom_y = top_y + s->height - 1;
1090 left_p = (s->first_glyph->left_box_line_p
1091 || (s->hl == DRAW_MOUSE_FACE
1092 && (s->prev == NULL
1093 || s->prev->hl != s->hl)));
1094 right_p = (last_glyph->right_box_line_p
1095 || (s->hl == DRAW_MOUSE_FACE
1096 && (s->next == NULL
1097 || s->next->hl != s->hl)));
1099 if (face->box == FACE_SIMPLE_BOX)
1100 haiku_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
1101 vwidth, left_p, right_p, NULL);
1102 else
1103 haiku_draw_relief_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
1104 vwidth, raised_p, true, true, left_p, right_p,
1105 NULL);
1108 static void
1109 haiku_draw_plain_background (struct glyph_string *s, struct face *face,
1110 int x, int y, int width, int height)
1112 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1113 unsigned long cursor_color;
1115 if (s->hl == DRAW_CURSOR)
1117 haiku_merge_cursor_foreground (s, NULL, &cursor_color);
1118 BView_SetHighColor (view, cursor_color);
1120 else
1121 BView_SetHighColor (view, face->background_defaulted_p ?
1122 FRAME_BACKGROUND_PIXEL (s->f) :
1123 face->background);
1125 BView_FillRectangle (view, x, y, width, height);
1128 static struct haiku_bitmap_record *
1129 haiku_get_bitmap_rec (struct frame *f, ptrdiff_t id)
1131 return &FRAME_DISPLAY_INFO (f)->bitmaps[id - 1];
1134 static void
1135 haiku_update_bitmap_rec (struct haiku_bitmap_record *rec,
1136 uint32_t new_foreground,
1137 uint32_t new_background)
1139 char *bits;
1140 int x, y, bytes_per_line;
1142 if (new_foreground == rec->stipple_foreground
1143 && new_background == rec->stipple_background)
1144 return;
1146 bits = rec->stipple_bits;
1147 bytes_per_line = (rec->width + 7) / 8;
1149 for (y = 0; y < rec->height; y++)
1151 for (x = 0; x < rec->width; x++)
1152 haiku_put_pixel (rec->img, x, y,
1153 ((bits[x / 8] >> (x % 8)) & 1
1154 ? new_foreground : new_background));
1156 bits += bytes_per_line;
1159 rec->stipple_foreground = new_foreground;
1160 rec->stipple_background = new_background;
1163 static void
1164 haiku_draw_stipple_background (struct glyph_string *s, struct face *face,
1165 int x, int y, int width, int height,
1166 bool explicit_colors_p,
1167 uint32 explicit_background,
1168 uint32 explicit_foreground)
1170 struct haiku_bitmap_record *rec;
1171 unsigned long foreground, background;
1172 void *view;
1174 view = FRAME_HAIKU_DRAWABLE (s->f);
1175 rec = haiku_get_bitmap_rec (s->f, s->face->stipple);
1177 if (explicit_colors_p)
1179 background = explicit_background;
1180 foreground = explicit_foreground;
1182 else if (s->hl == DRAW_CURSOR)
1183 haiku_merge_cursor_foreground (s, &foreground, &background);
1184 else
1186 foreground = s->face->foreground;
1187 background = s->face->background;
1190 haiku_update_bitmap_rec (rec, foreground, background);
1192 BView_StartClip (view);
1193 haiku_clip_to_string (s);
1194 BView_ClipToRect (view, x, y, width, height);
1195 BView_DrawBitmapTiled (view, rec->img, 0, 0, -1, -1,
1196 0, 0, x + width, y + height);
1197 BView_EndClip (view);
1200 void
1201 haiku_draw_background_rect (struct glyph_string *s, struct face *face,
1202 int x, int y, int width, int height)
1204 if (!s->stippled_p)
1205 haiku_draw_plain_background (s, face, x, y, width, height);
1206 else
1207 haiku_draw_stipple_background (s, face, x, y, width, height,
1208 false, 0, 0);
1211 static void
1212 haiku_maybe_draw_background (struct glyph_string *s, int force_p)
1214 if ((s->first_glyph->type != IMAGE_GLYPH) && !s->background_filled_p)
1216 struct face *face = s->face;
1217 int box_line_width = max (face->box_horizontal_line_width, 0);
1218 int box_vline_width = max (face->box_vertical_line_width, 0);
1220 if (FONT_HEIGHT (s->font) < s->height - 2 * box_vline_width
1221 || FONT_TOO_HIGH (s->font)
1222 || s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
1224 haiku_draw_background_rect (s, s->face, s->x, s->y + box_line_width,
1225 s->background_width,
1226 s->height - 2 * box_line_width);
1228 s->background_filled_p = 1;
1233 static void
1234 haiku_mouse_face_colors (struct glyph_string *s, uint32_t *fg,
1235 uint32_t *bg)
1237 int face_id;
1238 struct face *face;
1240 /* What face has to be used last for the mouse face? */
1241 face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
1242 face = FACE_FROM_ID_OR_NULL (s->f, face_id);
1243 if (face == NULL)
1244 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1246 if (s->first_glyph->type == CHAR_GLYPH)
1247 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
1248 else
1249 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
1251 face = FACE_FROM_ID (s->f, face_id);
1252 prepare_face_for_display (s->f, s->face);
1254 if (fg)
1255 *fg = face->foreground;
1256 if (bg)
1257 *bg = face->background;
1260 static void
1261 haiku_draw_glyph_string_foreground (struct glyph_string *s)
1263 struct face *face = s->face;
1265 int i, x;
1266 if (face->box != FACE_NO_BOX
1267 && s->first_glyph->left_box_line_p)
1268 x = s->x + max (face->box_vertical_line_width, 0);
1269 else
1270 x = s->x;
1272 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1274 if (s->font_not_found_p)
1276 if (s->hl == DRAW_CURSOR)
1277 BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
1278 else
1279 BView_SetHighColor (view, face->foreground);
1280 for (i = 0; i < s->nchars; ++i)
1282 struct glyph *g = s->first_glyph + i;
1284 BView_SetPenSize (view, 1);
1285 BView_StrokeRectangle (view, x, s->y, g->pixel_width,
1286 s->height);
1287 x += g->pixel_width;
1290 else
1292 struct font *ft = s->font;
1293 int off = ft->baseline_offset;
1294 int y;
1296 if (ft->vertical_centering)
1297 off = VCENTER_BASELINE_OFFSET (ft, s->f) - off;
1298 y = s->ybase - off;
1299 if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR))
1300 ft->driver->draw (s, 0, s->nchars, x, y, false);
1301 else
1302 ft->driver->draw (s, 0, s->nchars, x, y, true);
1304 if (face->overstrike)
1305 ft->driver->draw (s, 0, s->nchars, x + 1, y, false);
1309 static void
1310 haiku_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1312 struct glyph *glyph = s->first_glyph;
1313 static unsigned char2b[8];
1314 int x, i, j;
1315 struct face *face = s->face;
1316 unsigned long color;
1318 /* If first glyph of S has a left box line, start drawing the text
1319 of S to the right of that box line. */
1320 if (face && face->box != FACE_NO_BOX
1321 && s->first_glyph->left_box_line_p)
1322 x = s->x + max (face->box_vertical_line_width, 0);
1323 else
1324 x = s->x;
1326 s->char2b = char2b;
1328 for (i = 0; i < s->nchars; i++, glyph++)
1330 #ifdef GCC_LINT
1331 enum { PACIFY_GCC_BUG_81401 = 1 };
1332 #else
1333 enum { PACIFY_GCC_BUG_81401 = 0 };
1334 #endif
1335 char buf[7 + PACIFY_GCC_BUG_81401];
1336 char *str = NULL;
1337 int len = glyph->u.glyphless.len;
1339 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
1341 if (len > 0
1342 && CHAR_TABLE_P (Vglyphless_char_display)
1343 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
1344 >= 1))
1346 Lisp_Object acronym
1347 = (! glyph->u.glyphless.for_no_font
1348 ? CHAR_TABLE_REF (Vglyphless_char_display,
1349 glyph->u.glyphless.ch)
1350 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
1351 if (CONSP (acronym))
1352 acronym = XCAR (acronym);
1353 if (STRINGP (acronym))
1354 str = SSDATA (acronym);
1357 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
1359 unsigned int ch = glyph->u.glyphless.ch;
1360 eassume (ch <= MAX_CHAR);
1361 sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
1362 str = buf;
1365 if (str)
1367 int upper_len = (len + 1) / 2;
1369 /* It is assured that all LEN characters in STR is ASCII. */
1370 for (j = 0; j < len; j++)
1371 char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
1373 s->font->driver->draw (s, 0, upper_len,
1374 x + glyph->slice.glyphless.upper_xoff,
1375 s->ybase + glyph->slice.glyphless.upper_yoff,
1376 false);
1377 s->font->driver->draw (s, upper_len, len,
1378 x + glyph->slice.glyphless.lower_xoff,
1379 s->ybase + glyph->slice.glyphless.lower_yoff,
1380 false);
1383 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
1385 if (s->hl == DRAW_CURSOR)
1386 haiku_merge_cursor_foreground (s, NULL, &color);
1387 else
1388 color = s->face->foreground;
1390 BView_SetHighColor (FRAME_HAIKU_DRAWABLE (s->f), color);
1391 BView_SetPenSize (FRAME_HAIKU_DRAWABLE (s->f), 1);
1392 BView_StrokeRectangle (FRAME_HAIKU_DRAWABLE (s->f),
1393 x, s->ybase - glyph->ascent,
1394 glyph->pixel_width,
1395 glyph->ascent + glyph->descent);
1397 x += glyph->pixel_width;
1401 static void
1402 haiku_draw_stretch_glyph_string (struct glyph_string *s)
1404 struct face *face = s->face;
1405 uint32_t bkg;
1407 if (s->hl == DRAW_CURSOR && !x_stretch_cursor_p)
1409 int width, background_width = s->background_width;
1410 int x = s->x;
1412 if (!s->row->reversed_p)
1414 int left_x = window_box_left_offset (s->w, TEXT_AREA);
1416 if (x < left_x)
1418 background_width -= left_x - x;
1419 x = left_x;
1422 else
1424 /* In R2L rows, draw the cursor on the right edge of the
1425 stretch glyph. */
1426 int right_x = window_box_right (s->w, TEXT_AREA);
1427 if (x + background_width > right_x)
1428 background_width -= x - right_x;
1429 x += background_width;
1432 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
1433 if (s->row->reversed_p)
1434 x -= width;
1436 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1437 unsigned long cursor_color;
1439 haiku_merge_cursor_foreground (s, NULL, &cursor_color);
1440 BView_SetHighColor (view, cursor_color);
1441 BView_FillRectangle (view, x, s->y, width, s->height);
1443 if (width < background_width)
1445 if (!s->row->reversed_p)
1446 x += width;
1447 else
1448 x = s->x;
1450 int y = s->y;
1451 int w = background_width - width, h = s->height;
1453 /* Draw stipples manually because we want the background
1454 part of a stretch glyph to have a stipple even if the
1455 cursor is visible on top. */
1456 if (!face->stipple)
1458 if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w))
1459 haiku_mouse_face_colors (s, NULL, &bkg);
1460 else
1461 bkg = face->background;
1463 BView_SetHighColor (view, bkg);
1464 BView_FillRectangle (view, x, y, w, h);
1466 else
1468 if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w))
1469 haiku_mouse_face_colors (s, NULL, &bkg);
1470 else
1471 bkg = face->background;
1473 haiku_draw_stipple_background (s, s->face, x, y, w, h,
1474 true, bkg, face->foreground);
1478 else if (!s->background_filled_p)
1480 int background_width = s->background_width;
1481 int x = s->x, text_left_x = window_box_left (s->w, TEXT_AREA);
1483 /* Don't draw into left fringe or scrollbar area except for
1484 header line and mode line. */
1485 if (s->area == TEXT_AREA
1486 && x < text_left_x && !s->row->mode_line_p)
1488 background_width -= text_left_x - x;
1489 x = text_left_x;
1492 if (background_width > 0)
1493 haiku_draw_background_rect (s, s->face, x, s->y,
1494 background_width, s->height);
1496 s->background_filled_p = 1;
1499 static void
1500 haiku_start_clip (struct glyph_string *s)
1502 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1503 BView_StartClip (view);
1506 static void
1507 haiku_end_clip (struct glyph_string *s)
1509 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1510 BView_EndClip (view);
1513 static void
1514 haiku_clip_to_row (struct window *w, struct glyph_row *row,
1515 enum glyph_row_area area)
1517 struct frame *f = WINDOW_XFRAME (w);
1518 int window_x, window_y, window_width;
1519 int x, y, width, height;
1521 window_box (w, area, &window_x, &window_y, &window_width, 0);
1523 x = window_x;
1524 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
1525 y = max (y, window_y);
1526 width = window_width;
1527 height = row->visible_height;
1529 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (f), x, y, width, height);
1532 static void
1533 haiku_update_begin (struct frame *f)
1535 /* Mark the frame as incomplete so it is not flushed upon handling
1536 input. */
1537 FRAME_COMPLETE_P (f) = false;
1540 static void
1541 haiku_update_end (struct frame *f)
1543 MOUSE_HL_INFO (f)->mouse_face_defer = false;
1544 BWindow_Flush (FRAME_HAIKU_WINDOW (f));
1547 static void
1548 haiku_draw_composite_glyph_string_foreground (struct glyph_string *s)
1550 int i, j, x;
1551 struct font *font = s->font;
1552 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1553 struct face *face = s->face;
1555 /* If first glyph of S has a left box line, start drawing the text
1556 of S to the right of that box line. */
1557 if (face && face->box != FACE_NO_BOX
1558 && s->first_glyph->left_box_line_p)
1559 x = s->x + max (face->box_vertical_line_width, 0);
1560 else
1561 x = s->x;
1563 /* S is a glyph string for a composition. S->cmp_from is the index
1564 of the first character drawn for glyphs of this composition.
1565 S->cmp_from == 0 means we are drawing the very first character of
1566 this composition. */
1568 /* Draw a rectangle for the composition if the font for the very
1569 first character of the composition could not be loaded. */
1570 if (s->font_not_found_p && !s->cmp_from)
1572 if (s->hl == DRAW_CURSOR)
1573 BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
1574 else
1575 BView_SetHighColor (view, s->face->foreground);
1577 BView_SetPenSize (view, 1);
1578 BView_StrokeRectangle (view, s->x, s->y,
1579 s->width, s->height);
1581 else if (!s->first_glyph->u.cmp.automatic)
1583 int y = s->ybase;
1585 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1586 /* TAB in a composition means display glyphs with padding
1587 space on the left or right. */
1588 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1590 int xx = x + s->cmp->offsets[j * 2];
1591 int yy = y - s->cmp->offsets[j * 2 + 1];
1593 font->driver->draw (s, j, j + 1, xx, yy, false);
1594 if (face->overstrike)
1595 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
1598 else
1600 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1601 Lisp_Object glyph;
1602 int y = s->ybase;
1603 int width = 0;
1605 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1607 glyph = LGSTRING_GLYPH (gstring, i);
1608 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1609 width += LGLYPH_WIDTH (glyph);
1610 else
1612 int xoff, yoff, wadjust;
1614 if (j < i)
1616 font->driver->draw (s, j, i, x, y, false);
1617 if (s->face->overstrike)
1618 font->driver->draw (s, j, i, x + 1, y, false);
1619 x += width;
1621 xoff = LGLYPH_XOFF (glyph);
1622 yoff = LGLYPH_YOFF (glyph);
1623 wadjust = LGLYPH_WADJUST (glyph);
1624 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
1625 if (face->overstrike)
1626 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
1627 false);
1628 x += wadjust;
1629 j = i + 1;
1630 width = 0;
1633 if (j < i)
1635 font->driver->draw (s, j, i, x, y, false);
1636 if (face->overstrike)
1637 font->driver->draw (s, j, i, x + 1, y, false);
1642 static void
1643 haiku_draw_image_relief (struct glyph_string *s)
1645 int x1, y1, thick;
1646 bool raised_p, top_p, bot_p, left_p, right_p;
1647 int extra_x, extra_y;
1648 struct haiku_rect r;
1649 int x = s->x;
1650 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1652 struct face *face = s->face;
1654 /* If first glyph of S has a left box line, start drawing it to the
1655 right of that line. */
1656 if (face->box != FACE_NO_BOX
1657 && s->first_glyph->left_box_line_p
1658 && s->slice.x == 0)
1659 x += max (face->box_vertical_line_width, 0);
1661 /* If there is a margin around the image, adjust x- and y-position
1662 by that margin. */
1663 if (s->slice.x == 0)
1664 x += s->img->hmargin;
1665 if (s->slice.y == 0)
1666 y += s->img->vmargin;
1668 if (s->hl == DRAW_IMAGE_SUNKEN
1669 || s->hl == DRAW_IMAGE_RAISED)
1671 if (s->face->id == TAB_BAR_FACE_ID)
1672 thick = (tab_bar_button_relief < 0
1673 ? DEFAULT_TAB_BAR_BUTTON_RELIEF
1674 : min (tab_bar_button_relief, 1000000));
1675 else
1676 thick = (tool_bar_button_relief < 0
1677 ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
1678 : min (tool_bar_button_relief, 1000000));
1679 raised_p = s->hl == DRAW_IMAGE_RAISED;
1681 else
1683 thick = eabs (s->img->relief);
1684 raised_p = s->img->relief > 0;
1687 x1 = x + s->slice.width - 1;
1688 y1 = y + s->slice.height - 1;
1690 extra_x = extra_y = 0;
1692 if (s->face->id == TAB_BAR_FACE_ID)
1694 if (CONSP (Vtab_bar_button_margin)
1695 && FIXNUMP (XCAR (Vtab_bar_button_margin))
1696 && FIXNUMP (XCDR (Vtab_bar_button_margin)))
1698 extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick;
1699 extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick;
1701 else if (FIXNUMP (Vtab_bar_button_margin))
1702 extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick;
1705 if (s->face->id == TOOL_BAR_FACE_ID)
1707 if (CONSP (Vtool_bar_button_margin)
1708 && FIXNUMP (XCAR (Vtool_bar_button_margin))
1709 && FIXNUMP (XCDR (Vtool_bar_button_margin)))
1711 extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
1712 extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
1714 else if (FIXNUMP (Vtool_bar_button_margin))
1715 extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
1718 top_p = bot_p = left_p = right_p = 0;
1720 if (s->slice.x == 0)
1721 x -= thick + extra_x, left_p = 1;
1722 if (s->slice.y == 0)
1723 y -= thick + extra_y, top_p = 1;
1724 if (s->slice.x + s->slice.width == s->img->width)
1725 x1 += thick + extra_x, right_p = 1;
1726 if (s->slice.y + s->slice.height == s->img->height)
1727 y1 += thick + extra_y, bot_p = 1;
1729 get_glyph_string_clip_rect (s, &r);
1730 haiku_draw_relief_rect (s, x, y, x1, y1, thick, thick, raised_p,
1731 top_p, bot_p, left_p, right_p, &r);
1734 static void
1735 haiku_translate_transform (double (*transform)[3], double dx,
1736 double dy)
1738 transform[0][2] += dx;
1739 transform[1][2] += dy;
1742 static void
1743 haiku_draw_image_glyph_string (struct glyph_string *s)
1745 struct face *face = s->face;
1746 void *view, *bitmap, *mask;
1747 int box_line_hwidth = max (face->box_vertical_line_width, 0);
1748 int box_line_vwidth = max (face->box_horizontal_line_width, 0);
1749 int x, y, height, width, relief;
1750 struct haiku_rect nr;
1751 Emacs_Rectangle cr, ir, r;
1752 unsigned long background;
1753 double image_transform[3][3];
1755 height = s->height;
1756 if (s->slice.y == 0)
1757 height -= box_line_vwidth;
1758 if (s->slice.y + s->slice.height >= s->img->height)
1759 height -= box_line_vwidth;
1761 width = s->background_width;
1762 x = s->x;
1763 if (s->first_glyph->left_box_line_p
1764 && s->slice.x == 0)
1766 x += box_line_hwidth;
1767 width -= box_line_hwidth;
1770 y = s->y;
1771 if (s->slice.y == 0)
1772 y += box_line_vwidth;
1774 view = FRAME_HAIKU_DRAWABLE (s->f);
1775 bitmap = s->img->pixmap;
1777 s->stippled_p = face->stipple != 0;
1779 if (s->hl == DRAW_CURSOR)
1780 haiku_merge_cursor_foreground (s, NULL, &background);
1781 else
1782 background = face->background;
1784 haiku_draw_background_rect (s, face, x, y,
1785 width, height);
1787 if (bitmap)
1789 get_glyph_string_clip_rect (s, &nr);
1790 CONVERT_TO_EMACS_RECT (cr, nr);
1791 x = s->x;
1792 y = s->ybase - image_ascent (s->img, face, &s->slice);
1794 if (s->slice.x == 0)
1795 x += s->img->hmargin;
1796 if (s->slice.y == 0)
1797 y += s->img->vmargin;
1799 if (face->box != FACE_NO_BOX
1800 && s->first_glyph->left_box_line_p
1801 && s->slice.x == 0)
1802 x += max (face->box_vertical_line_width, 0);
1804 ir.x = x;
1805 ir.y = y;
1806 ir.width = s->slice.width;
1807 ir.height = s->slice.height;
1808 r = ir;
1810 mask = s->img->mask;
1812 if (gui_intersect_rectangles (&cr, &ir, &r))
1814 memcpy (&image_transform, &s->img->transform,
1815 sizeof image_transform);
1817 if (s->slice.x != x || s->slice.y != y
1818 || s->slice.width != s->img->width
1819 || s->slice.height != s->img->height)
1821 BView_StartClip (view);
1822 BView_ClipToRect (view, r.x, r.y, r.width, r.height);
1825 haiku_translate_transform (image_transform,
1826 x - s->slice.x,
1827 y - s->slice.y);
1829 be_apply_affine_transform (view,
1830 image_transform[0][0],
1831 image_transform[0][1],
1832 image_transform[0][2],
1833 image_transform[1][0],
1834 image_transform[1][1],
1835 image_transform[1][2]);
1837 if (!s->stippled_p || !mask)
1839 BView_DrawBitmap (view, bitmap, 0, 0,
1840 s->img->original_width,
1841 s->img->original_height,
1842 0, 0,
1843 s->img->original_width,
1844 s->img->original_height,
1845 s->img->use_bilinear_filtering);
1847 if (mask)
1848 be_draw_image_mask (mask, view, 0, 0,
1849 s->img->original_width,
1850 s->img->original_height,
1851 0, 0,
1852 s->img->original_width,
1853 s->img->original_height,
1854 background);
1856 else
1857 /* In order to make sure the stipple background remains
1858 visible, use the mask for the alpha channel of BITMAP
1859 and composite it onto the view instead. */
1860 be_draw_bitmap_with_mask (view, bitmap, mask, 0, 0,
1861 s->img->original_width,
1862 s->img->original_height,
1863 0, 0,
1864 s->img->original_width,
1865 s->img->original_height,
1866 s->img->use_bilinear_filtering);
1868 if (s->slice.x != x || s->slice.y != y
1869 || s->slice.width != s->img->width
1870 || s->slice.height != s->img->height)
1871 BView_EndClip (view);
1873 be_apply_affine_transform (view, 1, 0, 0, 0, 1, 0);
1876 if (!s->img->mask)
1878 /* When the image has a mask, we can expect that at
1879 least part of a mouse highlight or a block cursor will
1880 be visible. If the image doesn't have a mask, make
1881 a block cursor visible by drawing a rectangle around
1882 the image. I believe it's looking better if we do
1883 nothing here for mouse-face. */
1885 if (s->hl == DRAW_CURSOR)
1887 relief = eabs (s->img->relief);
1889 BView_SetPenSize (view, 1);
1890 BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
1891 BView_StrokeRectangle (view, x - relief, y - relief,
1892 s->slice.width + relief * 2,
1893 s->slice.height + relief * 2);
1898 if (s->img->relief
1899 || s->hl == DRAW_IMAGE_RAISED
1900 || s->hl == DRAW_IMAGE_SUNKEN)
1901 haiku_draw_image_relief (s);
1904 static void
1905 haiku_draw_glyph_string (struct glyph_string *s)
1907 void *view = FRAME_HAIKU_DRAWABLE (s->f);;
1908 struct face *face = s->face;
1910 block_input ();
1911 BView_draw_lock (view, false, 0, 0, 0, 0);
1912 prepare_face_for_display (s->f, s->face);
1914 s->stippled_p = s->hl != DRAW_CURSOR && face->stipple;
1916 if (s->next && s->right_overhang && !s->for_overlaps)
1918 int width;
1919 struct glyph_string *next;
1921 for (width = 0, next = s->next;
1922 next && width < s->right_overhang;
1923 width += next->width, next = next->next)
1924 if (next->first_glyph->type != IMAGE_GLYPH)
1926 prepare_face_for_display (s->f, next->face);
1927 next->stippled_p
1928 = next->hl != DRAW_CURSOR && next->face->stipple;
1930 haiku_start_clip (next);
1931 haiku_clip_to_string (next);
1932 if (next->first_glyph->type != STRETCH_GLYPH)
1933 haiku_maybe_draw_background (next, true);
1934 else
1935 haiku_draw_stretch_glyph_string (next);
1936 haiku_end_clip (s);
1940 haiku_start_clip (s);
1942 int box_filled_p = 0;
1944 if (!s->for_overlaps && face->box != FACE_NO_BOX
1945 && (s->first_glyph->type == CHAR_GLYPH
1946 || s->first_glyph->type == COMPOSITE_GLYPH))
1948 haiku_clip_to_string (s);
1949 haiku_maybe_draw_background (s, 1);
1950 box_filled_p = 1;
1951 haiku_draw_string_box (s);
1953 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
1954 && !s->clip_tail
1955 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
1956 || (s->next && s->next->hl != s->hl && s->right_overhang)))
1957 /* We must clip just this glyph. left_overhang part has already
1958 drawn when s->prev was drawn, and right_overhang part will be
1959 drawn later when s->next is drawn. */
1960 haiku_clip_to_string_exactly (s, s);
1961 else
1962 haiku_clip_to_string (s);
1964 if (s->for_overlaps)
1965 s->background_filled_p = 1;
1967 switch (s->first_glyph->type)
1969 case COMPOSITE_GLYPH:
1970 if (s->for_overlaps || (s->cmp_from > 0
1971 && ! s->first_glyph->u.cmp.automatic))
1972 s->background_filled_p = 1;
1973 else
1974 haiku_maybe_draw_background (s, 1);
1975 haiku_draw_composite_glyph_string_foreground (s);
1976 break;
1977 case CHAR_GLYPH:
1978 if (s->for_overlaps)
1979 s->background_filled_p = 1;
1980 else
1981 haiku_maybe_draw_background (s, 0);
1982 haiku_draw_glyph_string_foreground (s);
1983 break;
1984 case STRETCH_GLYPH:
1985 haiku_draw_stretch_glyph_string (s);
1986 break;
1987 case IMAGE_GLYPH:
1988 haiku_draw_image_glyph_string (s);
1989 break;
1990 case GLYPHLESS_GLYPH:
1991 if (s->for_overlaps)
1992 s->background_filled_p = 1;
1993 else
1994 haiku_maybe_draw_background (s, 1);
1995 haiku_draw_glyphless_glyph_string_foreground (s);
1996 break;
1997 default:
1998 emacs_abort ();
2001 if (!s->for_overlaps)
2003 if (!box_filled_p && face->box != FACE_NO_BOX)
2004 haiku_draw_string_box (s);
2005 else
2006 haiku_draw_text_decoration (s, face, s->width, s->x);
2008 if (s->prev)
2010 struct glyph_string *prev;
2012 for (prev = s->prev; prev; prev = prev->prev)
2013 if (prev->hl != s->hl
2014 && prev->x + prev->width + prev->right_overhang > s->x)
2016 /* As prev was drawn while clipped to its own area, we
2017 must draw the right_overhang part using s->hl now. */
2018 enum draw_glyphs_face save = prev->hl;
2020 prev->hl = s->hl;
2021 haiku_start_clip (s);
2022 haiku_clip_to_string (s);
2023 haiku_clip_to_string_exactly (s, prev);
2024 if (prev->first_glyph->type == CHAR_GLYPH)
2025 haiku_draw_glyph_string_foreground (prev);
2026 else
2027 haiku_draw_composite_glyph_string_foreground (prev);
2028 haiku_end_clip (s);
2029 prev->hl = save;
2033 if (s->next)
2035 struct glyph_string *next;
2037 for (next = s->next; next; next = next->next)
2038 if (next->hl != s->hl
2039 && next->x - next->left_overhang < s->x + s->width)
2041 /* As next will be drawn while clipped to its own area,
2042 we must draw the left_overhang part using s->hl now. */
2043 enum draw_glyphs_face save = next->hl;
2045 next->hl = s->hl;
2046 haiku_start_clip (s);
2047 haiku_clip_to_string (s);
2048 haiku_clip_to_string_exactly (s, next);
2049 if (next->first_glyph->type == CHAR_GLYPH)
2050 haiku_draw_glyph_string_foreground (next);
2051 else
2052 haiku_draw_composite_glyph_string_foreground (next);
2053 haiku_end_clip (s);
2055 next->hl = save;
2056 next->clip_head = s->next;
2061 haiku_end_clip (s);
2062 BView_draw_unlock (view);
2064 /* Set the stipple_p flag indicating whether or not a stipple was
2065 drawn in s->row. That is the case either when s is a stretch
2066 glyph string and s->face->stipple is not NULL, or when
2067 s->face->stipple exists and s->hl is not DRAW_CURSOR. */
2068 if (s->face->stipple
2069 && (s->first_glyph->type == STRETCH_GLYPH
2070 || s->hl != DRAW_CURSOR))
2071 s->row->stipple_p = true;
2073 unblock_input ();
2076 static void
2077 haiku_after_update_window_line (struct window *w,
2078 struct glyph_row *desired_row)
2080 eassert (w);
2081 struct frame *f;
2082 int width, height;
2084 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2085 desired_row->redraw_fringe_bitmaps_p = true;
2087 if (windows_or_buffers_changed
2088 && desired_row->full_width_p
2089 && (f = XFRAME (w->frame),
2090 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2091 width != 0)
2092 && (height = desired_row->visible_height,
2093 height > 0))
2095 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2096 int face_id =
2097 !NILP (Vface_remapping_alist)
2098 ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
2099 : INTERNAL_BORDER_FACE_ID;
2100 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2102 block_input ();
2103 if (face)
2105 void *view = FRAME_HAIKU_DRAWABLE (f);
2106 BView_draw_lock (view, false, 0, 0, 0, 0);
2107 BView_StartClip (view);
2108 BView_SetHighColor (view, (face->background_defaulted_p
2109 ? FRAME_BACKGROUND_PIXEL (f)
2110 : face->background));
2111 BView_FillRectangle (view, 0, y, width, height);
2112 BView_FillRectangle (view, FRAME_PIXEL_WIDTH (f) - width,
2113 y, width, height);
2114 BView_invalidate_region (FRAME_HAIKU_DRAWABLE (f),
2115 0, y, width, height);
2116 BView_invalidate_region (view, FRAME_PIXEL_WIDTH (f) - width,
2117 y, width, height);
2118 BView_EndClip (view);
2119 BView_draw_unlock (view);
2121 else
2123 haiku_clear_frame_area (f, 0, y, width, height);
2124 haiku_clear_frame_area (f, FRAME_PIXEL_WIDTH (f) - width,
2125 y, width, height);
2127 unblock_input ();
2131 static void
2132 haiku_set_window_size (struct frame *f, bool change_gravity,
2133 int width, int height)
2135 Lisp_Object frame;
2137 /* On X Windows, window managers typically disallow resizing a
2138 window when it is fullscreen. Do the same here. */
2140 XSETFRAME (frame, f);
2141 if (!NILP (Fframe_parameter (frame, Qfullscreen))
2142 /* Only do this if the fullscreen status has actually been
2143 applied. */
2144 && f->want_fullscreen == FULLSCREEN_NONE
2145 /* And if the configury during frame creation has been
2146 completed. Otherwise, there will be no valid "old size" to
2147 go back to. */
2148 && FRAME_OUTPUT_DATA (f)->configury_done)
2149 return;
2151 haiku_update_size_hints (f);
2153 if (FRAME_HAIKU_WINDOW (f))
2155 block_input ();
2156 BWindow_resize (FRAME_HAIKU_WINDOW (f),
2157 width, height);
2159 if (FRAME_VISIBLE_P (f)
2160 && (width != FRAME_PIXEL_WIDTH (f)
2161 || height != FRAME_PIXEL_HEIGHT (f)))
2162 haiku_wait_for_event (f, FRAME_RESIZED);
2163 unblock_input ();
2166 do_pending_window_change (false);
2169 static void
2170 haiku_draw_hollow_cursor (struct window *w, struct glyph_row *row)
2172 struct frame *f;
2173 int x, y, wd, h;
2174 struct glyph *cursor_glyph;
2175 uint32_t foreground;
2176 void *view;
2178 f = XFRAME (WINDOW_FRAME (w));
2179 view = FRAME_HAIKU_DRAWABLE (f);
2181 /* Get the glyph the cursor is on. If we can't tell because
2182 the current matrix is invalid or such, give up. */
2183 cursor_glyph = get_phys_cursor_glyph (w);
2184 if (cursor_glyph == NULL)
2185 return;
2187 /* Compute frame-relative coordinates for phys cursor. */
2188 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
2189 wd = w->phys_cursor_width;
2191 /* The foreground of cursor_gc is typically the same as the normal
2192 background color, which can cause the cursor box to be invisible. */
2193 foreground = FRAME_CURSOR_COLOR (f).pixel;
2195 /* When on R2L character, show cursor at the right edge of the
2196 glyph, unless the cursor box is as wide as the glyph or wider
2197 (the latter happens when x-stretch-cursor is non-nil). */
2198 if ((cursor_glyph->resolved_level & 1) != 0
2199 && cursor_glyph->pixel_width > wd)
2200 x += cursor_glyph->pixel_width - wd;
2202 /* Set clipping, draw the rectangle, and reset clipping again.
2203 This also marks the region as invalidated. */
2205 BView_draw_lock (view, true, x, y, wd, h);
2206 BView_StartClip (view);
2207 haiku_clip_to_row (w, row, TEXT_AREA);
2209 /* Now set the foreground color and pen size. */
2210 BView_SetHighColor (view, foreground);
2211 BView_SetPenSize (view, 1);
2213 /* Actually draw the rectangle. */
2214 BView_StrokeRectangle (view, x, y, wd, h);
2216 /* Reset clipping. */
2217 BView_EndClip (view);
2218 BView_draw_unlock (view);
2221 static void
2222 haiku_draw_bar_cursor (struct window *w, struct glyph_row *row,
2223 int width, enum text_cursor_kinds kind)
2225 struct frame *f;
2226 struct glyph *cursor_glyph;
2227 struct glyph_row *r;
2228 struct face *face;
2229 uint32_t foreground;
2230 void *view;
2231 int x, y, dummy_x, dummy_y, dummy_h;
2233 f = XFRAME (w->frame);
2235 /* If cursor is out of bounds, don't draw garbage. This can happen
2236 in mini-buffer windows when switching between echo area glyphs
2237 and mini-buffer. */
2238 cursor_glyph = get_phys_cursor_glyph (w);
2239 if (cursor_glyph == NULL)
2240 return;
2242 /* If on an image, draw like a normal cursor. That's usually better
2243 visible than drawing a bar, esp. if the image is large so that
2244 the bar might not be in the window. */
2245 if (cursor_glyph->type == IMAGE_GLYPH)
2247 r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
2248 draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
2250 else
2252 view = FRAME_HAIKU_DRAWABLE (f);
2253 face = FACE_FROM_ID (f, cursor_glyph->face_id);
2255 /* If the glyph's background equals the color we normally draw
2256 the bars cursor in, the bar cursor in its normal color is
2257 invisible. Use the glyph's foreground color instead in this
2258 case, on the assumption that the glyph's colors are chosen so
2259 that the glyph is legible. */
2260 if (face->background == FRAME_CURSOR_COLOR (f).pixel)
2261 foreground = face->foreground;
2262 else
2263 foreground = FRAME_CURSOR_COLOR (f).pixel;
2265 BView_draw_lock (view, false, 0, 0, 0, 0);
2266 BView_StartClip (view);
2267 BView_SetHighColor (view, foreground);
2268 haiku_clip_to_row (w, row, TEXT_AREA);
2270 if (kind == BAR_CURSOR)
2272 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
2273 y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
2275 if (width < 0)
2276 width = FRAME_CURSOR_WIDTH (f);
2277 width = min (cursor_glyph->pixel_width, width);
2279 w->phys_cursor_width = width;
2281 /* If the character under cursor is R2L, draw the bar cursor
2282 on the right of its glyph, rather than on the left. */
2283 if ((cursor_glyph->resolved_level & 1) != 0)
2284 x += cursor_glyph->pixel_width - width;
2286 BView_FillRectangle (view, x, y, width, row->height);
2287 BView_invalidate_region (view, x, y, width, row->height);
2289 else /* HBAR_CURSOR */
2291 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
2292 y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
2293 row->height - width);
2295 if (width < 0)
2296 width = row->height;
2298 width = min (row->height, width);
2300 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
2301 &dummy_y, &dummy_h);
2303 if ((cursor_glyph->resolved_level & 1) != 0
2304 && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
2305 x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
2307 BView_FillRectangle (view, x, y, w->phys_cursor_width - 1,
2308 width);
2309 BView_invalidate_region (view, x, y, w->phys_cursor_width - 1,
2310 width);
2313 BView_EndClip (view);
2314 BView_draw_unlock (view);
2318 static void
2319 haiku_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
2320 int x, int y, enum text_cursor_kinds cursor_type,
2321 int cursor_width, bool on_p, bool active_p)
2323 if (on_p)
2325 w->phys_cursor_type = cursor_type;
2326 w->phys_cursor_on_p = true;
2328 if (glyph_row->exact_window_width_line_p
2329 && (glyph_row->reversed_p
2330 ? (w->phys_cursor.hpos < 0)
2331 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
2333 glyph_row->cursor_in_fringe_p = true;
2334 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
2336 else
2338 switch (cursor_type)
2340 case HOLLOW_BOX_CURSOR:
2341 haiku_draw_hollow_cursor (w, glyph_row);
2342 break;
2344 case FILLED_BOX_CURSOR:
2345 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
2346 break;
2348 case BAR_CURSOR:
2349 haiku_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
2350 break;
2352 case HBAR_CURSOR:
2353 haiku_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
2354 break;
2356 case NO_CURSOR:
2357 w->phys_cursor_width = 0;
2358 break;
2360 default:
2361 emacs_abort ();
2367 static void
2368 haiku_show_hourglass (struct frame *f)
2370 if (FRAME_TOOLTIP_P (f)
2371 || FRAME_OUTPUT_DATA (f)->hourglass_p)
2372 return;
2374 block_input ();
2375 FRAME_OUTPUT_DATA (f)->hourglass_p = 1;
2377 if (FRAME_HAIKU_VIEW (f))
2378 BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
2379 FRAME_OUTPUT_DATA (f)->hourglass_cursor);
2380 unblock_input ();
2383 static void
2384 haiku_hide_hourglass (struct frame *f)
2386 if (FRAME_TOOLTIP_P (f)
2387 || !FRAME_OUTPUT_DATA (f)->hourglass_p)
2388 return;
2390 block_input ();
2391 FRAME_OUTPUT_DATA (f)->hourglass_p = 0;
2393 if (FRAME_HAIKU_VIEW (f))
2394 BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
2395 FRAME_OUTPUT_DATA (f)->current_cursor);
2396 unblock_input ();
2399 static void
2400 haiku_compute_glyph_string_overhangs (struct glyph_string *s)
2402 if (s->cmp == NULL
2403 && (s->first_glyph->type == CHAR_GLYPH
2404 || s->first_glyph->type == COMPOSITE_GLYPH))
2406 struct font_metrics metrics;
2408 if (s->first_glyph->type == CHAR_GLYPH)
2410 struct font *font = s->font;
2411 font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
2413 else
2415 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
2417 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
2419 s->right_overhang = (metrics.rbearing > metrics.width
2420 ? metrics.rbearing - metrics.width : 0);
2421 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
2423 else if (s->cmp)
2425 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
2426 s->left_overhang = - s->cmp->lbearing;
2430 static void
2431 haiku_draw_vertical_window_border (struct window *w,
2432 int x, int y_0, int y_1)
2434 struct frame *f = XFRAME (WINDOW_FRAME (w));
2435 struct face *face;
2437 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
2438 void *view = FRAME_HAIKU_DRAWABLE (f);
2439 BView_draw_lock (view, true, x, y_0, 1, y_1);
2440 BView_StartClip (view);
2441 if (face)
2442 BView_SetHighColor (view, face->foreground);
2443 BView_StrokeLine (view, x, y_0, x, y_1);
2444 BView_EndClip (view);
2445 BView_draw_unlock (view);
2448 static void
2449 haiku_set_scroll_bar_default_width (struct frame *f)
2451 int unit, size;
2453 unit = FRAME_COLUMN_WIDTH (f);
2454 size = BScrollBar_default_size (0) + 1;
2456 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = size;
2457 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (size + unit - 1) / unit;
2460 static void
2461 haiku_set_scroll_bar_default_height (struct frame *f)
2463 int height, size;
2465 height = FRAME_LINE_HEIGHT (f);
2466 size = BScrollBar_default_size (true) + 1;
2468 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = size;
2469 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (size + height - 1) / height;
2472 static void
2473 haiku_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
2475 struct frame *f = XFRAME (WINDOW_FRAME (w));
2476 struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
2477 struct face *face_first
2478 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
2479 struct face *face_last
2480 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
2481 unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
2482 unsigned long color_first = (face_first
2483 ? face_first->foreground
2484 : FRAME_FOREGROUND_PIXEL (f));
2485 unsigned long color_last = (face_last
2486 ? face_last->foreground
2487 : FRAME_FOREGROUND_PIXEL (f));
2488 void *view = FRAME_HAIKU_DRAWABLE (f);
2490 BView_draw_lock (view, true, x0, y0, x1 - x0 + 1, y1 - y0 + 1);
2491 BView_StartClip (view);
2493 if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
2494 /* A vertical divider, at least three pixels wide: Draw first and
2495 last pixels differently. */
2497 BView_SetHighColor (view, color_first);
2498 BView_StrokeLine (view, x0, y0, x0, y1 - 1);
2499 BView_SetHighColor (view, color);
2500 BView_FillRectangle (view, x0 + 1, y0, x1 - x0 - 2, y1 - y0);
2501 BView_SetHighColor (view, color_last);
2502 BView_StrokeLine (view, x1 - 1, y0, x1 - 1, y1 - 1);
2504 else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
2505 /* A horizontal divider, at least three pixels high: Draw first and
2506 last pixels differently. */
2508 BView_SetHighColor (view, color_first);
2509 BView_StrokeLine (view, x0, y0, x1 - 1, y0);
2510 BView_SetHighColor (view, color);
2511 BView_FillRectangle (view, x0, y0 + 1, x1 - x0, y1 - y0 - 2);
2512 BView_SetHighColor (view, color_last);
2513 BView_FillRectangle (view, x0, y1 - 1, x1 - x0, 1);
2515 else
2517 BView_SetHighColor (view, color);
2518 BView_FillRectangleAbs (view, x0, y0, x1, y1);
2520 BView_EndClip (view);
2521 BView_draw_unlock (view);
2524 static void
2525 haiku_condemn_scroll_bars (struct frame *frame)
2527 if (!NILP (FRAME_SCROLL_BARS (frame)))
2529 if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2531 /* Prepend scrollbars to already condemned ones. */
2532 Lisp_Object last = FRAME_SCROLL_BARS (frame);
2534 while (!NILP (XSCROLL_BAR (last)->next))
2535 last = XSCROLL_BAR (last)->next;
2537 XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
2538 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
2541 fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
2542 fset_scroll_bars (frame, Qnil);
2546 static void
2547 haiku_redeem_scroll_bar (struct window *w)
2549 struct scroll_bar *bar;
2550 Lisp_Object barobj;
2551 struct frame *f;
2553 if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
2555 bar = XSCROLL_BAR (w->vertical_scroll_bar);
2556 /* Unlink it from the condemned list. */
2557 f = XFRAME (WINDOW_FRAME (w));
2558 if (NILP (bar->prev))
2560 /* If the prev pointer is nil, it must be the first in one of
2561 the lists. */
2562 if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
2563 /* It's not condemned. Everything's fine. */
2564 goto horizontal;
2565 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2566 w->vertical_scroll_bar))
2567 fset_condemned_scroll_bars (f, bar->next);
2568 else
2569 /* If its prev pointer is nil, it must be at the front of
2570 one or the other! */
2571 emacs_abort ();
2573 else
2574 XSCROLL_BAR (bar->prev)->next = bar->next;
2576 if (! NILP (bar->next))
2577 XSCROLL_BAR (bar->next)->prev = bar->prev;
2579 bar->next = FRAME_SCROLL_BARS (f);
2580 bar->prev = Qnil;
2581 XSETVECTOR (barobj, bar);
2582 fset_scroll_bars (f, barobj);
2583 if (! NILP (bar->next))
2584 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2586 horizontal:
2587 if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
2589 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
2590 /* Unlink it from the condemned list. */
2591 f = XFRAME (WINDOW_FRAME (w));
2592 if (NILP (bar->prev))
2594 /* If the prev pointer is nil, it must be the first in one of
2595 the lists. */
2596 if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
2597 /* It's not condemned. Everything's fine. */
2598 return;
2599 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2600 w->horizontal_scroll_bar))
2601 fset_condemned_scroll_bars (f, bar->next);
2602 else
2603 /* If its prev pointer is nil, it must be at the front of
2604 one or the other! */
2605 emacs_abort ();
2607 else
2608 XSCROLL_BAR (bar->prev)->next = bar->next;
2610 if (! NILP (bar->next))
2611 XSCROLL_BAR (bar->next)->prev = bar->prev;
2613 bar->next = FRAME_SCROLL_BARS (f);
2614 bar->prev = Qnil;
2615 XSETVECTOR (barobj, bar);
2616 fset_scroll_bars (f, barobj);
2617 if (! NILP (bar->next))
2618 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2622 static void
2623 haiku_judge_scroll_bars (struct frame *f)
2625 Lisp_Object bar, next;
2627 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2629 /* Clear out the condemned list now so we won't try to process any
2630 more events on the hapless scroll bars. */
2631 fset_condemned_scroll_bars (f, Qnil);
2633 for (; ! NILP (bar); bar = next)
2635 struct scroll_bar *b = XSCROLL_BAR (bar);
2637 haiku_scroll_bar_remove (b);
2639 next = b->next;
2640 b->next = b->prev = Qnil;
2643 /* Now there should be no references to the condemned scroll bars,
2644 and they should get garbage-collected. */
2647 static struct scroll_bar *
2648 haiku_scroll_bar_create (struct window *w, int left, int top,
2649 int width, int height, bool horizontal_p)
2651 struct frame *f;
2652 Lisp_Object barobj;
2653 struct scroll_bar *bar;
2654 void *scroll_bar;
2655 void *view;
2657 f = XFRAME (WINDOW_FRAME (w));
2658 view = FRAME_HAIKU_DRAWABLE (f);
2660 block_input ();
2661 bar = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER);
2663 XSETWINDOW (bar->window, w);
2664 bar->top = top;
2665 bar->left = left;
2666 bar->width = width;
2667 bar->height = height;
2668 bar->position = 0;
2669 bar->total = 0;
2670 bar->dragging = 0;
2671 bar->update = -1;
2672 bar->horizontal = horizontal_p;
2674 scroll_bar = be_make_scroll_bar_for_view (view, horizontal_p,
2675 left, top, left + width - 1,
2676 top + height - 1);
2677 BView_publish_scroll_bar (view, left, top, width, height);
2679 bar->next = FRAME_SCROLL_BARS (f);
2680 bar->prev = Qnil;
2681 bar->scroll_bar = scroll_bar;
2682 XSETVECTOR (barobj, bar);
2683 fset_scroll_bars (f, barobj);
2685 if (!NILP (bar->next))
2686 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2688 unblock_input ();
2689 return bar;
2692 static void
2693 haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
2695 Lisp_Object barobj;
2696 struct scroll_bar *bar;
2697 int top, height, left, width;
2698 int window_x, window_width;
2699 void *view;
2701 eassert (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w));
2702 /* Get window dimensions. */
2703 window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
2704 left = window_x;
2705 width = window_width;
2706 top = WINDOW_SCROLL_BAR_AREA_Y (w);
2707 height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
2708 view = FRAME_HAIKU_DRAWABLE (WINDOW_XFRAME (w));
2710 block_input ();
2712 if (NILP (w->horizontal_scroll_bar))
2714 bar = haiku_scroll_bar_create (w, left, top, width, height, true);
2715 bar->update = position;
2716 bar->position = position;
2717 bar->total = whole;
2719 else
2721 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
2723 if (bar->left != left || bar->top != top
2724 || bar->width != width || bar->height != height)
2726 BView_forget_scroll_bar (view, bar->left, bar->top,
2727 bar->width, bar->height);
2728 BView_move_frame (bar->scroll_bar, left, top,
2729 left + width - 1, top + height - 1);
2730 BView_publish_scroll_bar (view, left, top, width, height);
2732 bar->left = left;
2733 bar->top = top;
2734 bar->width = width;
2735 bar->height = height;
2739 haiku_set_horizontal_scroll_bar_thumb (bar, portion, position, whole);
2740 bar->position = position;
2741 bar->total = whole;
2742 XSETVECTOR (barobj, bar);
2743 wset_horizontal_scroll_bar (w, barobj);
2744 unblock_input ();
2747 static void
2748 haiku_set_vertical_scroll_bar (struct window *w, int portion, int whole, int position)
2750 Lisp_Object barobj;
2751 struct scroll_bar *bar;
2752 int top, height, left, width;
2753 int window_y, window_height;
2754 void *view;
2756 eassert (WINDOW_HAS_VERTICAL_SCROLL_BAR (w));
2758 /* Get window dimensions. */
2759 window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
2760 top = window_y;
2761 height = window_height;
2763 /* Compute the left edge and the width of the scroll bar area. */
2764 left = WINDOW_SCROLL_BAR_AREA_X (w);
2765 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2767 view = FRAME_HAIKU_DRAWABLE (WINDOW_XFRAME (w));
2769 block_input ();
2770 if (NILP (w->vertical_scroll_bar))
2772 bar = haiku_scroll_bar_create (w, left, top, width, height, false);
2773 bar->position = position;
2774 bar->total = whole;
2776 else
2778 bar = XSCROLL_BAR (w->vertical_scroll_bar);
2780 if (bar->left != left || bar->top != top
2781 || bar->width != width || bar->height != height)
2783 BView_forget_scroll_bar (view, bar->left, bar->top,
2784 bar->width, bar->height);
2785 BView_move_frame (bar->scroll_bar, left, top,
2786 left + width - 1, top + height - 1);
2787 BView_publish_scroll_bar (view, left, top, width, height);
2789 bar->left = left;
2790 bar->top = top;
2791 bar->width = width;
2792 bar->height = height;
2796 haiku_set_scroll_bar_thumb (bar, portion, position, whole);
2797 bar->position = position;
2798 bar->total = whole;
2800 XSETVECTOR (barobj, bar);
2801 wset_vertical_scroll_bar (w, barobj);
2802 unblock_input ();
2805 static void
2806 haiku_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2807 struct draw_fringe_bitmap_params *p)
2809 struct face *face;
2810 struct frame *f;
2811 struct haiku_bitmap_record *rec;
2812 void *view, *bitmap;
2813 uint32 col;
2815 f = XFRAME (WINDOW_FRAME (w));
2816 view = FRAME_HAIKU_DRAWABLE (f);
2817 face = p->face;
2819 block_input ();
2820 BView_draw_lock (view, true, 0, 0, 0, 0);
2821 BView_StartClip (view);
2823 if (p->wd && p->h)
2824 BView_invalidate_region (view, p->x, p->y, p->wd, p->h);
2826 haiku_clip_to_row (w, row, ANY_AREA);
2828 if (p->bx >= 0 && !p->overlay_p)
2830 BView_invalidate_region (view, p->bx, p->by, p->nx, p->ny);
2832 if (!face->stipple)
2834 BView_SetHighColor (view, face->background);
2835 BView_FillRectangle (view, p->bx, p->by, p->nx, p->ny);
2837 else
2839 rec = haiku_get_bitmap_rec (f, face->stipple);
2840 haiku_update_bitmap_rec (rec, face->foreground,
2841 face->background);
2843 BView_StartClip (view);
2844 haiku_clip_to_row (w, row, ANY_AREA);
2845 BView_ClipToRect (view, p->bx, p->by, p->nx, p->ny);
2846 BView_DrawBitmapTiled (view, rec->img, 0, 0, -1, -1,
2847 0, 0, FRAME_PIXEL_WIDTH (f),
2848 FRAME_PIXEL_HEIGHT (f));
2849 BView_EndClip (view);
2851 row->stipple_p = true;
2855 if (p->which
2856 && p->which < max_fringe_bmp
2857 && p->which < max_used_fringe_bitmap)
2859 bitmap = fringe_bmps[p->which];
2861 if (!bitmap)
2863 /* This fringe bitmap is known to fringe.c, but lacks the
2864 BBitmap which shadows that bitmap. This is typical to
2865 define-fringe-bitmap being called when the selected frame
2866 was not a GUI frame, for example, when packages that
2867 define fringe bitmaps are loaded by a daemon Emacs.
2868 Create the missing pattern now. */
2869 gui_define_fringe_bitmap (WINDOW_XFRAME (w), p->which);
2870 bitmap = fringe_bmps[p->which];
2873 if (!p->cursor_p)
2874 col = face->foreground;
2875 else if (p->overlay_p)
2876 col = face->background;
2877 else
2878 col = FRAME_CURSOR_COLOR (XFRAME (WINDOW_FRAME (w))).pixel;
2880 if (!p->overlay_p)
2882 BView_SetHighColor (view, face->background);
2883 BView_FillRectangle (view, p->x, p->y, p->wd, p->h);
2886 BView_SetLowColor (view, col);
2887 BView_DrawBitmapWithEraseOp (view, bitmap, p->x, p->y, p->wd, p->h);
2889 BView_EndClip (view);
2890 BView_draw_unlock (view);
2891 unblock_input ();
2894 static void
2895 haiku_define_fringe_bitmap (int which, unsigned short *bits,
2896 int h, int wd)
2898 if (which >= max_fringe_bmp)
2900 int i = max_fringe_bmp;
2901 max_fringe_bmp = which + 20;
2902 fringe_bmps = !i ? xmalloc (max_fringe_bmp * sizeof (void *)) :
2903 xrealloc (fringe_bmps, max_fringe_bmp * sizeof (void *));
2905 while (i < max_fringe_bmp)
2906 fringe_bmps[i++] = NULL;
2909 block_input ();
2910 fringe_bmps[which] = BBitmap_new (wd, h, 1);
2911 if (!fringe_bmps[which])
2912 memory_full (SIZE_MAX);
2913 BBitmap_import_fringe_bitmap (fringe_bmps[which], bits, wd, h);
2914 unblock_input ();
2917 static void
2918 haiku_destroy_fringe_bitmap (int which)
2920 if (which >= max_fringe_bmp)
2921 return;
2923 if (fringe_bmps[which])
2924 BBitmap_free (fringe_bmps[which]);
2925 fringe_bmps[which] = NULL;
2928 static void
2929 haiku_scroll_run (struct window *w, struct run *run)
2931 struct frame *f = XFRAME (w->frame);
2932 void *view = FRAME_HAIKU_DRAWABLE (f);
2933 int x, y, width, height, from_y, to_y, bottom_y;
2934 window_box (w, ANY_AREA, &x, &y, &width, &height);
2936 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2937 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2938 bottom_y = y + height;
2940 if (to_y < from_y)
2942 /* Scrolling up. Make sure we don't copy part of the mode
2943 line at the bottom. */
2944 if (from_y + run->height > bottom_y)
2945 height = bottom_y - from_y;
2946 else
2947 height = run->height;
2949 else
2951 /* Scrolling down. Make sure we don't copy over the mode line.
2952 at the bottom. */
2953 if (to_y + run->height > bottom_y)
2954 height = bottom_y - to_y;
2955 else
2956 height = run->height;
2959 block_input ();
2960 gui_clear_cursor (w);
2962 BView_draw_lock (view, true, x, to_y, width, height);
2963 BView_StartClip (view);
2964 BView_CopyBits (view, x, from_y, width, height,
2965 x, to_y, width, height);
2966 BView_EndClip (view);
2967 BView_draw_unlock (view);
2969 unblock_input ();
2972 /* Haiku doesn't provide any way to get the frame actually underneath
2973 the pointer, so we typically return dpyinfo->last_mouse_frame if
2974 the display is grabbed and `track-mouse' is not `dropping' or
2975 `drag-source'; failing that, we return the selected frame, and
2976 finally a random window system frame (as long as `track-mouse' is
2977 not `drag-source') if that didn't work either. */
2978 static void
2979 haiku_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
2980 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
2981 Time *timestamp)
2983 Lisp_Object frame, tail;
2984 struct frame *f1;
2985 int screen_x, screen_y;
2986 void *view;
2988 if (!fp)
2989 return;
2991 f1 = NULL;
2992 block_input ();
2994 FOR_EACH_FRAME (tail, frame)
2996 if (FRAME_HAIKU_P (XFRAME (frame)))
2997 XFRAME (frame)->mouse_moved = false;
3000 if (gui_mouse_grabbed (x_display_list)
3001 && !EQ (track_mouse, Qdropping)
3002 && !EQ (track_mouse, Qdrag_source))
3003 f1 = x_display_list->last_mouse_frame;
3004 else
3005 f1 = x_display_list->last_mouse_motion_frame;
3007 if (!f1 && FRAME_HAIKU_P (SELECTED_FRAME ()))
3008 f1 = SELECTED_FRAME ();
3010 if (!f1 || (!FRAME_HAIKU_P (f1) && (insist > 0)))
3011 FOR_EACH_FRAME (tail, frame)
3012 if (FRAME_HAIKU_P (XFRAME (frame)) &&
3013 !FRAME_TOOLTIP_P (XFRAME (frame)))
3014 f1 = XFRAME (frame);
3016 if (f1 && FRAME_TOOLTIP_P (f1))
3017 f1 = NULL;
3019 if (f1 && FRAME_HAIKU_P (f1))
3021 view = FRAME_HAIKU_VIEW (f1);
3023 if (view)
3025 BView_get_mouse (view, &screen_x, &screen_y);
3026 remember_mouse_glyph (f1, screen_x, screen_y,
3027 &x_display_list->last_mouse_glyph);
3028 x_display_list->last_mouse_glyph_frame = f1;
3030 *bar_window = Qnil;
3031 *part = scroll_bar_nowhere;
3033 /* If track-mouse is `drag-source' and the mouse pointer is
3034 certain to not be actually under the chosen frame, return
3035 NULL in FP to at least try being consistent with X. */
3036 if (EQ (track_mouse, Qdrag_source)
3037 && (screen_x < 0 || screen_y < 0
3038 || screen_x >= FRAME_PIXEL_WIDTH (f1)
3039 || screen_y >= FRAME_PIXEL_HEIGHT (f1)))
3040 *fp = NULL;
3041 else
3042 *fp = f1;
3044 *timestamp = x_display_list->last_mouse_movement_time;
3045 XSETINT (*x, screen_x);
3046 XSETINT (*y, screen_y);
3050 unblock_input ();
3053 static void
3054 haiku_flush (struct frame *f)
3056 /* This is needed for tooltip frames to work properly with double
3057 buffering. */
3058 if (FRAME_DIRTY_P (f) && !buffer_flipping_blocked_p ())
3059 haiku_flip_buffers (f);
3061 /* The frame is complete again as its contents were just
3062 flushed. */
3063 FRAME_COMPLETE_P (f) = true;
3065 if (FRAME_VISIBLE_P (f) && !FRAME_TOOLTIP_P (f))
3066 BWindow_Flush (FRAME_HAIKU_WINDOW (f));
3069 static void
3070 haiku_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
3072 if (FRAME_TOOLTIP_P (f))
3073 return;
3075 block_input ();
3076 if (!f->pointer_invisible && FRAME_HAIKU_VIEW (f)
3077 && !FRAME_OUTPUT_DATA (f)->hourglass_p)
3078 BView_set_view_cursor (FRAME_HAIKU_VIEW (f), cursor);
3079 unblock_input ();
3080 FRAME_OUTPUT_DATA (f)->current_cursor = cursor;
3083 static void
3084 haiku_default_font_parameter (struct frame *f, Lisp_Object parms)
3086 struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3087 Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
3088 RES_TYPE_STRING);
3089 Lisp_Object font = Qnil;
3090 if (BASE_EQ (font_param, Qunbound))
3091 font_param = Qnil;
3093 if (NILP (font_param))
3094 /* System font should take precedence over X resources. We
3095 suggest this regardless of font-use-system-font because .emacs
3096 may not have been read yet. Returning a font-spec is Haiku
3097 specific behavior. */
3098 font = font_open_by_spec (f, Ffont_get_system_font ());
3100 if (NILP (font))
3101 font = (!NILP (font_param)
3102 ? font_param
3103 : gui_display_get_arg (dpyinfo, parms, Qfont,
3104 "font", "Font",
3105 RES_TYPE_STRING));
3107 if (! FONTP (font) && ! STRINGP (font))
3109 const char **names = (const char *[]) { "monospace-12",
3110 "Noto Sans Mono-12",
3111 "Source Code Pro-12",
3112 NULL };
3113 int i;
3115 for (i = 0; names[i]; i++)
3117 font
3118 = font_open_by_name (f, build_unibyte_string (names[i]));
3119 if (!NILP (font))
3120 break;
3122 if (NILP (font))
3123 error ("No suitable font was found");
3126 gui_default_parameter (f, parms, Qfont, font, "font", "Font",
3127 RES_TYPE_STRING);
3130 static struct redisplay_interface haiku_redisplay_interface =
3132 haiku_frame_parm_handlers,
3133 gui_produce_glyphs,
3134 gui_write_glyphs,
3135 gui_insert_glyphs,
3136 gui_clear_end_of_line,
3137 haiku_scroll_run,
3138 haiku_after_update_window_line,
3139 NULL, /* update_window_begin */
3140 NULL, /* update_window_end */
3141 haiku_flush,
3142 gui_clear_window_mouse_face,
3143 gui_get_glyph_overhangs,
3144 gui_fix_overlapping_area,
3145 haiku_draw_fringe_bitmap,
3146 haiku_define_fringe_bitmap,
3147 haiku_destroy_fringe_bitmap,
3148 haiku_compute_glyph_string_overhangs,
3149 haiku_draw_glyph_string,
3150 haiku_define_frame_cursor,
3151 haiku_clear_frame_area,
3152 haiku_clear_under_internal_border,
3153 haiku_draw_window_cursor,
3154 haiku_draw_vertical_window_border,
3155 haiku_draw_window_divider,
3156 NULL, /* shift glyphs for insert */
3157 haiku_show_hourglass,
3158 haiku_hide_hourglass,
3159 haiku_default_font_parameter,
3162 static void
3163 haiku_make_fullscreen_consistent (struct frame *f)
3165 Lisp_Object lval;
3166 struct haiku_output *output;
3168 output = FRAME_OUTPUT_DATA (f);
3170 if (output->fullscreen_mode == FULLSCREEN_MODE_BOTH)
3171 lval = Qfullboth;
3172 else if (output->fullscreen_mode == FULLSCREEN_MODE_WIDTH)
3173 lval = Qfullwidth;
3174 else if (output->fullscreen_mode == FULLSCREEN_MODE_HEIGHT)
3175 lval = Qfullheight;
3176 else if (output->fullscreen_mode == FULLSCREEN_MODE_MAXIMIZED)
3177 lval = Qmaximized;
3178 else
3179 lval = Qnil;
3181 store_frame_param (f, Qfullscreen, lval);
3184 static void
3185 haiku_flush_dirty_back_buffer_on (struct frame *f)
3187 if (FRAME_GARBAGED_P (f)
3188 || buffer_flipping_blocked_p ()
3189 /* If the frame is not already up to date, do not flush buffers
3190 on input, as that will result in flicker. */
3191 || !FRAME_COMPLETE_P (f)
3192 || !FRAME_DIRTY_P (f))
3193 return;
3195 haiku_flip_buffers (f);
3198 /* N.B. that support for TYPE must be explicitly added to
3199 haiku_read_socket. */
3200 void
3201 haiku_wait_for_event (struct frame *f, int type)
3203 int input_blocked_to;
3204 object_wait_info info;
3205 specpdl_ref depth;
3207 input_blocked_to = interrupt_input_blocked;
3208 info.object = port_application_to_emacs;
3209 info.type = B_OBJECT_TYPE_PORT;
3210 info.events = B_EVENT_READ;
3212 depth = SPECPDL_INDEX ();
3213 specbind (Qinhibit_quit, Qt);
3215 FRAME_OUTPUT_DATA (f)->wait_for_event_type = type;
3217 while (FRAME_OUTPUT_DATA (f)->wait_for_event_type == type)
3219 if (wait_for_objects (&info, 1) < B_OK)
3220 continue;
3222 pending_signals = true;
3223 /* This will call the read_socket_hook. */
3224 totally_unblock_input ();
3225 interrupt_input_blocked = input_blocked_to;
3226 info.events = B_EVENT_READ;
3229 unbind_to (depth, Qnil);
3232 static int
3233 haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
3235 int message_count;
3236 void *buf;
3237 ssize_t b_size;
3238 int button_or_motion_p, do_help;
3239 enum haiku_event_type type;
3240 struct input_event inev, inev2;
3241 struct frame *mouse_frame;
3243 message_count = 0;
3244 button_or_motion_p = 0;
3245 do_help = 0;
3247 buf = alloca (200);
3249 block_input ();
3250 haiku_read_size (&b_size, false);
3251 while (b_size >= 0)
3253 if (b_size > 200)
3254 emacs_abort ();
3256 EVENT_INIT (inev);
3257 EVENT_INIT (inev2);
3258 inev.kind = NO_EVENT;
3259 inev2.kind = NO_EVENT;
3260 inev.arg = Qnil;
3261 inev2.arg = Qnil;
3263 button_or_motion_p = 0;
3264 haiku_read (&type, buf, b_size);
3266 switch (type)
3268 case QUIT_REQUESTED:
3270 struct haiku_quit_requested_event *b = buf;
3271 struct frame *f = haiku_window_to_frame (b->window);
3273 if (!f)
3274 continue;
3276 inev.kind = DELETE_WINDOW_EVENT;
3277 XSETFRAME (inev.frame_or_window, f);
3278 break;
3280 case FRAME_RESIZED:
3282 struct haiku_resize_event *b = buf;
3283 struct frame *f = haiku_window_to_frame (b->window);
3285 if (!f)
3286 continue;
3288 int width = lrint (b->width);
3289 int height = lrint (b->height);
3291 if (FRAME_OUTPUT_DATA (f)->wait_for_event_type
3292 == FRAME_RESIZED)
3293 FRAME_OUTPUT_DATA (f)->wait_for_event_type = -1;
3295 if (FRAME_TOOLTIP_P (f))
3297 if (FRAME_PIXEL_WIDTH (f) != width
3298 || FRAME_PIXEL_HEIGHT (f) != height)
3299 SET_FRAME_GARBAGED (f);
3301 FRAME_PIXEL_WIDTH (f) = width;
3302 FRAME_PIXEL_HEIGHT (f) = height;
3304 haiku_clear_under_internal_border (f);
3306 /* Flush the frame and flip buffers here. It is
3307 necessary for tooltips displayed inside menus, as
3308 redisplay cannot happen. */
3309 haiku_flush (f);
3310 continue;
3313 BView_draw_lock (FRAME_HAIKU_DRAWABLE (f), false, 0, 0, 0, 0);
3314 BView_resize_to (FRAME_HAIKU_DRAWABLE (f), width, height);
3315 BView_draw_unlock (FRAME_HAIKU_DRAWABLE (f));
3317 if (width != FRAME_PIXEL_WIDTH (f)
3318 || height != FRAME_PIXEL_HEIGHT (f)
3319 || (f->new_size_p
3320 && ((f->new_width >= 0 && width != f->new_width)
3321 || (f->new_height >= 0 && height != f->new_height))))
3323 change_frame_size (f, width, height, false, true, false);
3324 SET_FRAME_GARBAGED (f);
3325 cancel_mouse_face (f);
3326 haiku_clear_under_internal_border (f);
3329 break;
3331 case FRAME_EXPOSED:
3333 struct haiku_expose_event *b = buf;
3334 struct frame *f = haiku_window_to_frame (b->window);
3336 if (!f)
3337 continue;
3339 expose_frame (f, b->x, b->y, b->width, b->height);
3340 haiku_clear_under_internal_border (f);
3341 break;
3343 case KEY_DOWN:
3345 struct haiku_key_event *b = buf;
3346 Mouse_HLInfo *hlinfo = &x_display_list->mouse_highlight;
3347 struct frame *f = haiku_window_to_frame (b->window);
3349 if (!f)
3350 continue;
3352 /* If mouse-highlight is an integer, input clears out
3353 mouse highlighting. */
3354 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
3355 && (f == 0
3356 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
3357 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window)))
3359 mouse_frame = hlinfo->mouse_face_mouse_frame;
3361 clear_mouse_face (hlinfo);
3362 hlinfo->mouse_face_hidden = true;
3364 if (mouse_frame)
3365 haiku_flush_dirty_back_buffer_on (mouse_frame);
3368 inev.code = b->keysym ? b->keysym : b->multibyte_char;
3370 if (b->keysym)
3371 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
3372 else
3373 inev.kind = inev.code > 127 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT :
3374 ASCII_KEYSTROKE_EVENT;
3376 inev.timestamp = b->time / 1000;
3377 inev.modifiers = (haiku_modifiers_to_emacs (b->modifiers)
3378 | (extra_keyboard_modifiers
3379 & (meta_modifier
3380 | hyper_modifier
3381 | ctrl_modifier
3382 | alt_modifier
3383 | shift_modifier)));
3385 XSETFRAME (inev.frame_or_window, f);
3386 break;
3388 case ACTIVATION:
3390 struct haiku_activation_event *b = buf;
3391 struct frame *f = haiku_window_to_frame (b->window);
3393 if (!f)
3394 continue;
3396 if ((x_display_list->focus_event_frame != f && b->activated_p)
3397 || (x_display_list->focus_event_frame == f && !b->activated_p))
3399 haiku_new_focus_frame (b->activated_p ? f : NULL);
3400 if (b->activated_p)
3401 x_display_list->focus_event_frame = f;
3402 else
3403 x_display_list->focus_event_frame = NULL;
3404 inev.kind = b->activated_p ? FOCUS_IN_EVENT : FOCUS_OUT_EVENT;
3405 XSETFRAME (inev.frame_or_window, f);
3408 break;
3410 case MENU_BAR_LEFT:
3412 struct haiku_menu_bar_left_event *b = buf;
3413 struct frame *f = haiku_window_to_frame (b->window);
3415 if (!f)
3416 continue;
3418 if (b->y > 0 && b->y <= FRAME_PIXEL_HEIGHT (f)
3419 && b->x > 0 && b->x <= FRAME_PIXEL_WIDTH (f))
3420 break;
3422 if (f->auto_lower && !popup_activated_p)
3423 haiku_frame_raise_lower (f, 0);
3425 break;
3427 case MOUSE_MOTION:
3429 struct haiku_mouse_motion_event *b = buf;
3430 struct frame *f = haiku_mouse_or_wdesc_frame (b->window, true);
3431 Mouse_HLInfo *hlinfo = &x_display_list->mouse_highlight;
3432 Lisp_Object frame;
3434 if (!f)
3435 continue;
3437 if (FRAME_TOOLTIP_P (f))
3439 /* Dismiss the tooltip if the mouse moves onto a
3440 tooltip frame (except when drag-and-drop is in
3441 progress and we are trying to move the tooltip
3442 along with the mouse pointer). FIXME: for some
3443 reason we don't get leave notification events for
3444 this. */
3446 if (any_help_event_p
3447 && !(be_drag_and_drop_in_progress ()
3448 && haiku_dnd_follow_tooltip)
3449 && !((EQ (track_mouse, Qdrag_source)
3450 || EQ (track_mouse, Qdropping))
3451 && gui_mouse_grabbed (x_display_list)))
3452 do_help = -1;
3453 break;
3456 XSETFRAME (frame, f);
3458 x_display_list->last_mouse_movement_time = b->time / 1000;
3459 button_or_motion_p = 1;
3461 if (hlinfo->mouse_face_hidden)
3463 hlinfo->mouse_face_hidden = false;
3464 clear_mouse_face (hlinfo);
3465 haiku_flush_dirty_back_buffer_on (f);
3468 if (b->just_exited_p)
3470 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
3472 if (f == hlinfo->mouse_face_mouse_frame)
3474 /* If we move outside the frame, then we're
3475 certainly no longer on any text in the frame. */
3476 clear_mouse_face (hlinfo);
3477 hlinfo->mouse_face_mouse_frame = 0;
3479 haiku_flush_dirty_back_buffer_on (f);
3482 if (f == x_display_list->last_mouse_glyph_frame)
3483 x_display_list->last_mouse_glyph_frame = NULL;
3485 if (f->auto_lower && !popup_activated_p
3486 /* Don't do this if the mouse entered a scroll bar. */
3487 && !BView_inside_scroll_bar (FRAME_HAIKU_VIEW (f),
3488 b->x, b->y))
3490 /* If we're leaving towards the menu bar, don't
3491 auto-lower here, and wait for a exit
3492 notification from the menu bar instead. */
3493 if (b->x > FRAME_PIXEL_WIDTH (f)
3494 || b->y >= FRAME_MENU_BAR_HEIGHT (f)
3495 || b->x < 0
3496 || b->y < 0)
3497 haiku_frame_raise_lower (f, 0);
3500 haiku_new_focus_frame (x_display_list->focused_frame);
3502 if (any_help_event_p
3503 && !((EQ (track_mouse, Qdrag_source)
3504 || EQ (track_mouse, Qdropping))
3505 && gui_mouse_grabbed (x_display_list)))
3506 do_help = -1;
3508 else
3510 struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3511 struct haiku_rect r = dpyinfo->last_mouse_glyph;
3513 /* For an unknown reason Haiku sends phantom motion events when a
3514 tooltip frame is visible. FIXME */
3515 if (FRAMEP (tip_frame)
3516 && FRAME_LIVE_P (XFRAME (tip_frame))
3517 && FRAME_VISIBLE_P (XFRAME (tip_frame))
3518 && f == dpyinfo->last_mouse_motion_frame
3519 && b->x == dpyinfo->last_mouse_motion_x
3520 && b->y == dpyinfo->last_mouse_motion_y)
3521 continue;
3523 dpyinfo->last_mouse_motion_x = b->x;
3524 dpyinfo->last_mouse_motion_y = b->y;
3525 dpyinfo->last_mouse_motion_frame = f;
3527 previous_help_echo_string = help_echo_string;
3528 help_echo_string = Qnil;
3530 /* A crossing event might be sent out-of-order with
3531 regard to motion events from other windows, such as
3532 when the mouse pointer rapidly moves from an
3533 undecorated child frame to its parent. This can
3534 cause a failure to clear the mouse face on the
3535 former if an event for the latter is read by Emacs
3536 first and ends up showing the mouse face there.
3538 Work around the problem by clearing the mouse face
3539 now if it is currently shown on a different
3540 frame. */
3542 if (hlinfo->mouse_face_hidden
3543 || (f != hlinfo->mouse_face_mouse_frame
3544 && !NILP (hlinfo->mouse_face_window)))
3546 hlinfo->mouse_face_hidden = 0;
3547 clear_mouse_face (hlinfo);
3550 if (f != dpyinfo->last_mouse_glyph_frame
3551 || b->x < r.x || b->x >= r.x + r.width
3552 || b->y < r.y || b->y >= r.y + r.height)
3554 f->mouse_moved = true;
3555 note_mouse_highlight (f, b->x, b->y);
3556 remember_mouse_glyph (f, b->x, b->y,
3557 &FRAME_DISPLAY_INFO (f)->last_mouse_glyph);
3558 dpyinfo->last_mouse_glyph_frame = f;
3560 else
3561 help_echo_string = previous_help_echo_string;
3563 if (!NILP (Vmouse_autoselect_window))
3565 static Lisp_Object last_mouse_window;
3566 Lisp_Object window = window_from_coordinates (f, b->x, b->y, 0, 0, 0, 0);
3568 if (WINDOWP (window)
3569 && !EQ (window, last_mouse_window)
3570 && !EQ (window, selected_window)
3571 && !popup_activated_p
3572 && !MINI_WINDOW_P (XWINDOW (selected_window))
3573 && (!NILP (focus_follows_mouse)
3574 || f == SELECTED_FRAME ()))
3576 inev2.kind = SELECT_WINDOW_EVENT;
3577 inev2.frame_or_window = window;
3580 last_mouse_window = window;
3583 if (f->auto_raise)
3585 if (!BWindow_is_active (FRAME_HAIKU_WINDOW (f)))
3586 haiku_frame_raise_lower (f, 1);
3589 if (!NILP (help_echo_string)
3590 || !NILP (previous_help_echo_string))
3591 do_help = 1;
3593 if (b->dnd_message)
3595 /* It doesn't make sense to show tooltips when
3596 another program is dragging stuff over us. */
3598 if (any_help_event_p || do_help)
3599 do_help = -1;
3601 if (!be_drag_and_drop_in_progress ())
3603 inev.kind = DRAG_N_DROP_EVENT;
3604 inev.arg = Qlambda;
3606 XSETINT (inev.x, b->x);
3607 XSETINT (inev.y, b->y);
3608 XSETFRAME (inev.frame_or_window, f);
3610 else
3611 haiku_note_drag_motion ();
3613 break;
3617 if (FRAME_DIRTY_P (f))
3618 haiku_flush_dirty_back_buffer_on (f);
3619 break;
3621 case BUTTON_UP:
3622 case BUTTON_DOWN:
3624 struct haiku_button_event *b = buf;
3625 struct frame *f = haiku_mouse_or_wdesc_frame (b->window, false);
3626 Lisp_Object tab_bar_arg = Qnil;
3627 int tab_bar_p = 0, tool_bar_p = 0;
3628 bool up_okay_p = false;
3629 struct scroll_bar *bar;
3631 if (popup_activated_p || !f)
3632 continue;
3634 inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
3635 bar = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
3637 x_display_list->last_mouse_glyph_frame = 0;
3638 x_display_list->last_mouse_movement_time = b->time / 1000;
3639 button_or_motion_p = 1;
3641 /* Is this in the tab-bar? */
3642 if (WINDOWP (f->tab_bar_window)
3643 && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
3645 Lisp_Object window;
3646 int x = b->x;
3647 int y = b->y;
3649 window = window_from_coordinates (f, x, y, 0, true, true, true);
3650 tab_bar_p = EQ (window, f->tab_bar_window);
3652 if (tab_bar_p)
3654 tab_bar_arg = handle_tab_bar_click
3655 (f, x, y, type == BUTTON_DOWN, inev.modifiers);
3656 haiku_flush_dirty_back_buffer_on (f);
3660 if (WINDOWP (f->tool_bar_window)
3661 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
3663 Lisp_Object window;
3664 int x = b->x;
3665 int y = b->y;
3667 window = window_from_coordinates (f, x, y, 0, true, true, true);
3668 tool_bar_p = (EQ (window, f->tool_bar_window)
3669 && (type != BUTTON_UP
3670 || f->last_tool_bar_item != -1));
3672 if (tool_bar_p)
3674 handle_tool_bar_click
3675 (f, x, y, type == BUTTON_DOWN, inev.modifiers);
3676 haiku_flush_dirty_back_buffer_on (f);
3680 if (type == BUTTON_UP)
3682 inev.modifiers |= up_modifier;
3683 up_okay_p = (x_display_list->grabbed & (1 << b->btn_no));
3684 x_display_list->grabbed &= ~(1 << b->btn_no);
3686 else
3688 up_okay_p = true;
3689 inev.modifiers |= down_modifier;
3690 x_display_list->last_mouse_frame = f;
3691 x_display_list->grabbed |= (1 << b->btn_no);
3692 if (f && !tab_bar_p)
3693 f->last_tab_bar_item = -1;
3694 if (f && !tool_bar_p)
3695 f->last_tool_bar_item = -1;
3698 if (bar)
3700 inev.kind = (bar->horizontal
3701 ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
3702 : SCROLL_BAR_CLICK_EVENT);
3703 inev.part = (bar->horizontal
3704 ? scroll_bar_horizontal_handle
3705 : scroll_bar_handle);
3707 else if (up_okay_p
3708 && !(tab_bar_p && NILP (tab_bar_arg))
3709 && !tool_bar_p)
3710 inev.kind = MOUSE_CLICK_EVENT;
3712 inev.arg = tab_bar_arg;
3713 inev.code = b->btn_no;
3715 f->mouse_moved = false;
3717 if (bar)
3719 if (bar->horizontal)
3721 XSETINT (inev.x, min (max (0, b->x - bar->left),
3722 bar->width));
3723 XSETINT (inev.y, bar->width);
3725 else
3727 XSETINT (inev.x, min (max (0, b->y - bar->top),
3728 bar->height));
3729 XSETINT (inev.y, bar->height);
3732 inev.frame_or_window = bar->window;
3734 else
3736 XSETINT (inev.x, b->x);
3737 XSETINT (inev.y, b->y);
3738 XSETFRAME (inev.frame_or_window, f);
3741 break;
3743 case ICONIFICATION:
3745 struct haiku_iconification_event *b = buf;
3746 struct frame *f = haiku_window_to_frame (b->window);
3748 if (!f)
3749 continue;
3751 if (!b->iconified_p)
3753 SET_FRAME_VISIBLE (f, 1);
3754 SET_FRAME_ICONIFIED (f, 0);
3755 inev.kind = DEICONIFY_EVENT;
3757 /* Haiku doesn't expose frames on deiconification, but
3758 if we are double-buffered, the previous screen
3759 contents should have been preserved. */
3760 if (!EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)))
3762 SET_FRAME_GARBAGED (f);
3763 expose_frame (f, 0, 0, 0, 0);
3766 else
3768 SET_FRAME_VISIBLE (f, 0);
3769 SET_FRAME_ICONIFIED (f, 1);
3770 inev.kind = ICONIFY_EVENT;
3773 XSETFRAME (inev.frame_or_window, f);
3774 break;
3776 case MOVE_EVENT:
3778 struct haiku_move_event *b = buf;
3779 struct frame *f = haiku_window_to_frame (b->window);
3780 int top, left;
3781 struct frame *p;
3783 if (!f)
3784 continue;
3786 FRAME_OUTPUT_DATA (f)->frame_x = b->x;
3787 FRAME_OUTPUT_DATA (f)->frame_y = b->y;
3789 if (FRAME_PARENT_FRAME (f))
3790 haiku_coords_from_parent (f, &b->x, &b->y);
3792 left = b->x - b->decorator_width;
3793 top = b->y - b->decorator_height;
3795 if (left != f->left_pos || top != f->top_pos)
3797 inev.kind = MOVE_FRAME_EVENT;
3799 XSETINT (inev.x, left);
3800 XSETINT (inev.y, top);
3802 f->left_pos = left;
3803 f->top_pos = top;
3805 p = FRAME_PARENT_FRAME (f);
3807 if (p)
3808 EmacsWindow_move_weak_child (FRAME_HAIKU_WINDOW (p),
3809 b->window, left, top);
3811 XSETFRAME (inev.frame_or_window, f);
3814 haiku_make_fullscreen_consistent (f);
3815 break;
3817 case SCROLL_BAR_VALUE_EVENT:
3819 struct haiku_scroll_bar_value_event *b = buf;
3820 struct scroll_bar *bar
3821 = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
3822 int portion, whole;
3824 if (!bar)
3825 continue;
3827 struct window *w = XWINDOW (bar->window);
3829 if (bar->update != -1)
3831 bar->update = -1;
3832 break;
3835 if (bar->position != b->position)
3837 inev.kind = (bar->horizontal
3838 ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT :
3839 SCROLL_BAR_CLICK_EVENT);
3840 inev.part = (bar->horizontal
3841 ? scroll_bar_horizontal_handle
3842 : scroll_bar_handle);
3844 if (bar->horizontal)
3846 portion = bar->total * ((float) b->position
3847 / BE_SB_MAX);
3848 whole = (bar->total
3849 * ((float) (BE_SB_MAX - bar->page_size)
3850 / BE_SB_MAX));
3851 portion = min (portion, whole);
3853 else
3855 whole = BE_SB_MAX - bar->page_size;
3856 portion = min (b->position, whole);
3859 XSETINT (inev.x, portion);
3860 XSETINT (inev.y, whole);
3861 XSETWINDOW (inev.frame_or_window, w);
3863 break;
3865 case SCROLL_BAR_PART_EVENT:
3867 struct haiku_scroll_bar_part_event *b = buf;
3868 struct scroll_bar *bar
3869 = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
3871 if (!bar)
3872 continue;
3874 inev.kind = (bar->horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
3875 : SCROLL_BAR_CLICK_EVENT);
3877 bar->dragging = 0;
3879 switch (b->part)
3881 case HAIKU_SCROLL_BAR_UP_BUTTON:
3882 inev.part = (bar->horizontal
3883 ? scroll_bar_left_arrow
3884 : scroll_bar_up_arrow);
3885 break;
3886 case HAIKU_SCROLL_BAR_DOWN_BUTTON:
3887 inev.part = (bar->horizontal
3888 ? scroll_bar_right_arrow
3889 : scroll_bar_down_arrow);
3890 break;
3893 XSETINT (inev.x, 0);
3894 XSETINT (inev.y, 0);
3895 inev.frame_or_window = bar->window;
3897 break;
3899 case SCROLL_BAR_DRAG_EVENT:
3901 struct haiku_scroll_bar_drag_event *b = buf;
3902 struct scroll_bar *bar
3903 = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
3905 if (!bar)
3906 continue;
3908 bar->dragging = b->dragging_p;
3909 if (!b->dragging_p && bar->horizontal)
3910 set_horizontal_scroll_bar (XWINDOW (bar->window));
3911 else if (!b->dragging_p)
3912 set_vertical_scroll_bar (XWINDOW (bar->window));
3913 break;
3915 case WHEEL_MOVE_EVENT:
3917 struct haiku_wheel_move_event *b = buf;
3918 struct frame *f = haiku_window_to_frame (b->window);
3919 int x, y, scroll_width, scroll_height;
3920 static float px = 0.0f, py = 0.0f;
3921 Lisp_Object wheel_window;
3923 if (!f)
3924 continue;
3926 BView_get_mouse (FRAME_HAIKU_VIEW (f), &x, &y);
3928 wheel_window = window_from_coordinates (f, x, y, 0, false, false, false);
3930 if (NILP (wheel_window))
3932 scroll_width = FRAME_PIXEL_WIDTH (f);
3933 scroll_height = FRAME_PIXEL_HEIGHT (f);
3935 else
3937 scroll_width = XWINDOW (wheel_window)->pixel_width;
3938 scroll_height = XWINDOW (wheel_window)->pixel_height;
3941 inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
3943 inev2.modifiers = inev.modifiers;
3945 if (signbit (px) != signbit (b->delta_x))
3946 px = 0;
3948 if (signbit (py) != signbit (b->delta_y))
3949 py = 0;
3951 px += (b->delta_x
3952 * powf (scroll_width, 2.0f / 3.0f));
3953 py += (b->delta_y
3954 * powf (scroll_height, 2.0f / 3.0f));
3956 if (fabsf (py) >= FRAME_LINE_HEIGHT (f)
3957 || fabsf (px) >= FRAME_COLUMN_WIDTH (f)
3958 || !mwheel_coalesce_scroll_events)
3960 inev.kind = (fabsf (px) > fabsf (py)
3961 ? HORIZ_WHEEL_EVENT
3962 : WHEEL_EVENT);
3963 inev.code = 0;
3965 XSETINT (inev.x, x);
3966 XSETINT (inev.y, y);
3967 inev.arg = list3 (Qnil, make_float (-px),
3968 make_float (-py));
3969 XSETFRAME (inev.frame_or_window, f);
3971 inev.modifiers |= (signbit (inev.kind == HORIZ_WHEEL_EVENT
3972 ? px : py)
3973 ? up_modifier
3974 : down_modifier);
3975 py = 0.0f;
3976 px = 0.0f;
3978 if (be_drag_and_drop_in_progress ())
3979 haiku_note_drag_wheel (&inev);
3982 break;
3984 case MENU_BAR_RESIZE:
3986 struct haiku_menu_bar_resize_event *b = buf;
3987 struct frame *f = haiku_window_to_frame (b->window);
3989 if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
3990 continue;
3992 if (FRAME_OUTPUT_DATA (f)->wait_for_event_type
3993 == MENU_BAR_RESIZE)
3994 FRAME_OUTPUT_DATA (f)->wait_for_event_type = -1;
3996 int old_height = FRAME_MENU_BAR_HEIGHT (f);
3998 FRAME_MENU_BAR_HEIGHT (f) = b->height;
3999 FRAME_MENU_BAR_LINES (f)
4000 = (b->height + FRAME_LINE_HEIGHT (f)) / FRAME_LINE_HEIGHT (f);
4002 if (old_height != b->height)
4004 adjust_frame_size (f, -1, -1, 3, true, Qmenu_bar_lines);
4005 haiku_clear_under_internal_border (f);
4007 break;
4009 case MENU_BAR_CLICK:
4011 struct haiku_menu_bar_click_event *b = buf;
4012 struct frame *f = haiku_window_to_frame (b->window);
4014 if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
4015 continue;
4017 if (!FRAME_OUTPUT_DATA (f)->saved_menu_event)
4018 FRAME_OUTPUT_DATA (f)->saved_menu_event = xmalloc (sizeof *b);
4019 *FRAME_OUTPUT_DATA (f)->saved_menu_event = *b;
4020 inev.kind = MENU_BAR_ACTIVATE_EVENT;
4021 XSETFRAME (inev.frame_or_window, f);
4022 break;
4024 case MENU_BAR_OPEN:
4025 case MENU_BAR_CLOSE:
4027 struct haiku_menu_bar_state_event *b = buf;
4028 struct frame *f = haiku_window_to_frame (b->window);
4030 if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
4031 continue;
4033 if (type == MENU_BAR_OPEN)
4035 FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
4036 popup_activated_p += 1;
4038 else
4040 if (!popup_activated_p)
4041 emacs_abort ();
4043 if (FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
4045 FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 0;
4046 popup_activated_p -= 1;
4049 break;
4051 case MENU_BAR_SELECT_EVENT:
4053 struct haiku_menu_bar_select_event *b = buf;
4054 struct frame *f = haiku_window_to_frame (b->window);
4056 if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
4057 continue;
4059 find_and_call_menu_selection (f, f->menu_bar_items_used,
4060 f->menu_bar_vector, b->ptr);
4061 break;
4063 case MENU_BAR_HELP_EVENT:
4065 struct haiku_menu_bar_help_event *b = buf;
4067 if (!popup_activated_p)
4068 continue;
4070 struct frame *f = haiku_window_to_frame (b->window);
4071 if (!f || !FRAME_EXTERNAL_MENU_BAR (f)
4072 || !FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
4073 continue;
4075 run_menu_bar_help_event (f, b->mb_idx);
4076 break;
4078 case ZOOM_EVENT:
4080 struct haiku_zoom_event *b = buf;
4081 struct frame *f = haiku_window_to_frame (b->window);
4083 if (!f)
4084 continue;
4086 if (b->fullscreen_mode == FULLSCREEN_MODE_MAXIMIZED)
4087 f->want_fullscreen = FULLSCREEN_NONE;
4088 else
4089 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
4091 FRAME_TERMINAL (f)->fullscreen_hook (f);
4092 break;
4094 case DRAG_AND_DROP_EVENT:
4096 struct haiku_drag_and_drop_event *b = buf;
4097 struct frame *f = haiku_window_to_frame (b->window);
4099 if (!f)
4101 BMessage_delete (b->message);
4102 continue;
4105 inev.kind = DRAG_N_DROP_EVENT;
4106 inev.arg = haiku_message_to_lisp (b->message);
4108 XSETINT (inev.x, b->x);
4109 XSETINT (inev.y, b->y);
4110 XSETFRAME (inev.frame_or_window, f);
4112 BMessage_delete (b->message);
4113 break;
4115 case SCREEN_CHANGED_EVENT:
4117 struct haiku_screen_changed_event *b = buf;
4119 inev.kind = MONITORS_CHANGED_EVENT;
4120 XSETTERMINAL (inev.arg, x_display_list->terminal);
4121 inev.timestamp = b->when / 1000;
4122 break;
4124 case CLIPBOARD_CHANGED_EVENT:
4125 be_handle_clipboard_changed_message ();
4126 break;
4127 case APP_QUIT_REQUESTED_EVENT:
4128 inev.kind = SAVE_SESSION_EVENT;
4129 inev.arg = Qt;
4130 break;
4131 case FONT_CHANGE_EVENT:
4132 /* This generates CONFIG_CHANGED_EVENTs, which are then
4133 handled in Lisp. */
4134 haiku_handle_font_change_event (buf, &inev);
4135 break;
4137 case NOTIFICATION_CLICK_EVENT:
4138 /* This code doesn't function, but the why is unknown. */
4139 #if 0
4141 struct haiku_notification_click_event *b = buf;
4143 inev.kind = NOTIFICATION_CLICKED_EVENT;
4144 inev.arg = make_int (b->id);
4145 break;
4147 #endif /* 0 */
4149 case KEY_UP:
4150 case DUMMY_EVENT:
4151 default:
4152 break;
4155 haiku_read_size (&b_size, false);
4157 if (inev.kind != NO_EVENT)
4159 if (inev.kind != HELP_EVENT && !inev.timestamp)
4160 inev.timestamp = (button_or_motion_p
4161 ? x_display_list->last_mouse_movement_time
4162 : system_time () / 1000);
4163 kbd_buffer_store_event_hold (&inev, hold_quit);
4164 ++message_count;
4167 if (inev2.kind != NO_EVENT)
4169 if (inev2.kind != HELP_EVENT && !inev.timestamp)
4170 inev2.timestamp = (button_or_motion_p
4171 ? x_display_list->last_mouse_movement_time
4172 : system_time () / 1000);
4173 kbd_buffer_store_event_hold (&inev2, hold_quit);
4174 ++message_count;
4178 if (do_help && !(hold_quit && hold_quit->kind != NO_EVENT))
4180 Lisp_Object help_frame = Qnil;
4182 if (x_display_list->last_mouse_frame)
4183 XSETFRAME (help_frame,
4184 x_display_list->last_mouse_frame);
4186 if (do_help > 0)
4188 any_help_event_p = true;
4189 gen_help_event (help_echo_string, help_frame,
4190 help_echo_window, help_echo_object,
4191 help_echo_pos);
4193 else
4195 help_echo_string = Qnil;
4196 gen_help_event (Qnil, help_frame, Qnil, Qnil, 0);
4200 unblock_input ();
4202 return message_count;
4205 static Lisp_Object
4206 haiku_get_focus_frame (struct frame *f)
4208 Lisp_Object lisp_focus;
4209 struct frame *focus;
4211 focus = FRAME_DISPLAY_INFO (f)->focused_frame;
4213 if (!focus)
4214 return Qnil;
4216 XSETFRAME (lisp_focus, focus);
4217 return lisp_focus;
4220 static void
4221 haiku_frame_rehighlight (struct frame *frame)
4223 haiku_rehighlight ();
4226 static void
4227 haiku_delete_window (struct frame *f)
4229 check_window_system (f);
4230 haiku_free_frame_resources (f);
4233 static void
4234 haiku_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
4236 BBitmap_free (pixmap);
4239 static void
4240 haiku_flash (struct frame *f)
4242 /* Get the height not including a menu bar widget. */
4243 int height = FRAME_PIXEL_HEIGHT (f);
4244 /* Height of each line to flash. */
4245 int flash_height = FRAME_LINE_HEIGHT (f);
4246 /* These will be the left and right margins of the rectangles. */
4247 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4248 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4249 int width = flash_right - flash_left;
4250 void *view = FRAME_HAIKU_DRAWABLE (f);
4251 object_wait_info info;
4252 bigtime_t wakeup;
4254 info.object = port_application_to_emacs;
4255 info.type = B_OBJECT_TYPE_PORT;
4256 info.events = B_EVENT_READ;
4257 wakeup = system_time () + 150000;
4259 BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
4260 FRAME_PIXEL_HEIGHT (f));
4261 BView_StartClip (view);
4262 /* If window is tall, flash top and bottom line. */
4263 if (height > 3 * FRAME_LINE_HEIGHT (f))
4265 BView_InvertRect (view, flash_left,
4266 (FRAME_INTERNAL_BORDER_WIDTH (f)
4267 + FRAME_TOP_MARGIN_HEIGHT (f)),
4268 width, flash_height);
4270 BView_InvertRect (view, flash_left,
4271 (height - flash_height
4272 - FRAME_INTERNAL_BORDER_WIDTH (f)
4273 - FRAME_BOTTOM_MARGIN_HEIGHT (f)),
4274 width, flash_height);
4276 else
4277 /* If it is short, flash it all. */
4278 BView_InvertRect (view, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4279 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4280 BView_EndClip (view);
4281 BView_draw_unlock (view);
4283 flush_frame (f);
4285 if (EmacsView_double_buffered_p (view))
4286 haiku_flip_buffers (f);
4288 /* Keep waiting until past the time wakeup or any input gets
4289 available. */
4290 while (!detect_input_pending ())
4292 /* Break if result would not be positive. */
4293 if (wakeup < system_time ())
4294 break;
4296 /* Try to wait that long--but we might wake up sooner. */
4297 wait_for_objects_etc (&info, 1, B_ABSOLUTE_TIMEOUT, wakeup);
4299 if (info.events & B_EVENT_READ)
4300 break;
4302 info.events = B_EVENT_READ;
4305 BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
4306 FRAME_PIXEL_HEIGHT (f));
4307 BView_StartClip (view);
4308 /* If window is tall, flash top and bottom line. */
4309 if (height > 3 * FRAME_LINE_HEIGHT (f))
4311 BView_InvertRect (view, flash_left,
4312 (FRAME_INTERNAL_BORDER_WIDTH (f)
4313 + FRAME_TOP_MARGIN_HEIGHT (f)),
4314 width, flash_height);
4316 BView_InvertRect (view, flash_left,
4317 (height - flash_height
4318 - FRAME_INTERNAL_BORDER_WIDTH (f)
4319 - FRAME_BOTTOM_MARGIN_HEIGHT (f)),
4320 width, flash_height);
4322 else
4323 /* If it is short, flash it all. */
4324 BView_InvertRect (view, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4325 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4326 BView_EndClip (view);
4327 BView_draw_unlock (view);
4329 flush_frame (f);
4330 if (EmacsView_double_buffered_p (view))
4331 haiku_flip_buffers (f);
4334 static void
4335 haiku_beep (struct frame *f)
4337 if (visible_bell)
4339 void *view = FRAME_HAIKU_VIEW (f);
4340 if (view)
4342 block_input ();
4343 haiku_flash (f);
4344 unblock_input ();
4347 else
4348 haiku_ring_bell ();
4351 static void
4352 haiku_toggle_invisible_pointer (struct frame *f, bool invisible_p)
4354 void *view = FRAME_HAIKU_VIEW (f);
4356 if (view && !FRAME_TOOLTIP_P (f))
4358 block_input ();
4359 BView_set_view_cursor (view, (invisible_p
4360 ? FRAME_OUTPUT_DATA (f)->no_cursor
4361 : FRAME_OUTPUT_DATA (f)->current_cursor));
4362 f->pointer_invisible = invisible_p;
4363 unblock_input ();
4367 static void
4368 haiku_fullscreen (struct frame *f)
4370 enum haiku_fullscreen_mode mode;
4372 /* When FRAME_OUTPUT_DATA (f)->configury_done is false, the frame is
4373 being created, and its regular width and height have not yet been
4374 set. This function will be called again by haiku_create_frame,
4375 so do nothing. */
4376 if (!FRAME_OUTPUT_DATA (f)->configury_done)
4377 return;
4379 if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
4380 mode = FULLSCREEN_MODE_MAXIMIZED;
4381 else if (f->want_fullscreen == FULLSCREEN_BOTH)
4382 mode = FULLSCREEN_MODE_BOTH;
4383 else if (f->want_fullscreen == FULLSCREEN_WIDTH)
4384 mode = FULLSCREEN_MODE_WIDTH;
4385 else if (f->want_fullscreen == FULLSCREEN_HEIGHT)
4386 mode = FULLSCREEN_MODE_HEIGHT;
4387 else
4388 mode = FULLSCREEN_MODE_NONE;
4390 f->want_fullscreen = FULLSCREEN_NONE;
4391 be_set_window_fullscreen_mode (FRAME_HAIKU_WINDOW (f), mode);
4392 FRAME_OUTPUT_DATA (f)->fullscreen_mode = mode;
4394 haiku_update_size_hints (f);
4395 haiku_make_fullscreen_consistent (f);
4398 static struct terminal *
4399 haiku_create_terminal (struct haiku_display_info *dpyinfo)
4401 struct terminal *terminal;
4403 terminal = create_terminal (output_haiku, &haiku_redisplay_interface);
4405 terminal->display_info.haiku = dpyinfo;
4406 dpyinfo->terminal = terminal;
4407 terminal->kboard = allocate_kboard (Qhaiku);
4409 terminal->iconify_frame_hook = haiku_iconify_frame;
4410 terminal->focus_frame_hook = haiku_focus_frame;
4411 terminal->ring_bell_hook = haiku_beep;
4412 terminal->popup_dialog_hook = haiku_popup_dialog;
4413 terminal->frame_visible_invisible_hook = haiku_set_frame_visible_invisible;
4414 terminal->set_frame_offset_hook = haiku_set_offset;
4415 terminal->delete_terminal_hook = haiku_delete_terminal;
4416 terminal->get_string_resource_hook = haiku_get_string_resource;
4417 terminal->set_new_font_hook = haiku_new_font;
4418 terminal->defined_color_hook = haiku_defined_color;
4419 terminal->set_window_size_hook = haiku_set_window_size;
4420 terminal->read_socket_hook = haiku_read_socket;
4421 terminal->implicit_set_name_hook = haiku_implicitly_set_name;
4422 terminal->mouse_position_hook = haiku_mouse_position;
4423 terminal->delete_frame_hook = haiku_delete_window;
4424 terminal->frame_up_to_date_hook = haiku_frame_up_to_date;
4425 terminal->buffer_flipping_unblocked_hook = haiku_buffer_flipping_unblocked_hook;
4426 terminal->clear_frame_hook = haiku_clear_frame;
4427 terminal->change_tab_bar_height_hook = haiku_change_tab_bar_height;
4428 terminal->change_tool_bar_height_hook = haiku_change_tool_bar_height;
4429 terminal->set_vertical_scroll_bar_hook = haiku_set_vertical_scroll_bar;
4430 terminal->set_horizontal_scroll_bar_hook = haiku_set_horizontal_scroll_bar;
4431 terminal->set_scroll_bar_default_height_hook = haiku_set_scroll_bar_default_height;
4432 terminal->set_scroll_bar_default_width_hook = haiku_set_scroll_bar_default_width;
4433 terminal->judge_scroll_bars_hook = haiku_judge_scroll_bars;
4434 terminal->condemn_scroll_bars_hook = haiku_condemn_scroll_bars;
4435 terminal->redeem_scroll_bar_hook = haiku_redeem_scroll_bar;
4436 terminal->update_begin_hook = haiku_update_begin;
4437 terminal->update_end_hook = haiku_update_end;
4438 terminal->frame_rehighlight_hook = haiku_frame_rehighlight;
4439 terminal->query_frame_background_color = haiku_query_frame_background_color;
4440 terminal->free_pixmap = haiku_free_pixmap;
4441 terminal->frame_raise_lower_hook = haiku_frame_raise_lower;
4442 terminal->menu_show_hook = haiku_menu_show;
4443 terminal->toggle_invisible_pointer_hook = haiku_toggle_invisible_pointer;
4444 terminal->fullscreen_hook = haiku_fullscreen;
4445 terminal->toolkit_position_hook = haiku_toolkit_position;
4446 terminal->activate_menubar_hook = haiku_activate_menubar;
4447 terminal->get_focus_frame = haiku_get_focus_frame;
4449 return terminal;
4452 struct haiku_display_info *
4453 haiku_term_init (void)
4455 struct haiku_display_info *dpyinfo;
4456 struct terminal *terminal;
4457 Lisp_Object color_file, color_map, system_name;
4458 ptrdiff_t nbytes;
4459 void *name_buffer;
4461 block_input ();
4463 Fset_input_interrupt_mode (Qt);
4464 baud_rate = 19200;
4465 dpyinfo = xzalloc (sizeof *dpyinfo);
4466 haiku_io_init ();
4468 if (port_application_to_emacs < B_OK
4469 || port_emacs_to_session_manager < B_OK)
4470 emacs_abort ();
4472 color_file = Fexpand_file_name (build_string ("rgb.txt"),
4473 Fsymbol_value (Qdata_directory));
4474 color_map = Fx_load_color_file (color_file);
4476 if (NILP (color_map))
4477 fatal ("Could not read %s.\n", SDATA (color_file));
4479 dpyinfo->color_map = color_map;
4480 dpyinfo->display = BApplication_setup ();
4481 dpyinfo->next = x_display_list;
4482 dpyinfo->n_planes = be_get_display_planes ();
4483 be_get_display_resolution (&dpyinfo->resx, &dpyinfo->resy);
4485 x_display_list = dpyinfo;
4487 terminal = haiku_create_terminal (dpyinfo);
4488 if (current_kboard == initial_kboard)
4489 current_kboard = terminal->kboard;
4491 terminal->kboard->reference_count++;
4492 /* Never delete haiku displays -- there can only ever be one,
4493 anyhow. */
4494 terminal->reference_count++;
4495 terminal->name = xstrdup ("be");
4497 dpyinfo->name_list_element = Fcons (build_string ("be"), Qnil);
4498 dpyinfo->smallest_font_height = 1;
4499 dpyinfo->smallest_char_width = 1;
4501 gui_init_fringe (terminal->rif);
4503 #define ASSIGN_CURSOR(cursor, cursor_id) \
4504 (dpyinfo->cursor = be_create_cursor_from_id (cursor_id))
4505 ASSIGN_CURSOR (text_cursor, CURSOR_ID_I_BEAM);
4506 ASSIGN_CURSOR (nontext_cursor, CURSOR_ID_SYSTEM_DEFAULT);
4507 ASSIGN_CURSOR (modeline_cursor, CURSOR_ID_CONTEXT_MENU);
4508 ASSIGN_CURSOR (hand_cursor, CURSOR_ID_GRAB);
4509 ASSIGN_CURSOR (hourglass_cursor, CURSOR_ID_PROGRESS);
4510 ASSIGN_CURSOR (horizontal_drag_cursor, CURSOR_ID_RESIZE_EAST_WEST);
4511 ASSIGN_CURSOR (vertical_drag_cursor, CURSOR_ID_RESIZE_NORTH_SOUTH);
4512 ASSIGN_CURSOR (left_edge_cursor, CURSOR_ID_RESIZE_WEST);
4513 ASSIGN_CURSOR (top_left_corner_cursor, CURSOR_ID_RESIZE_NORTH_WEST);
4514 ASSIGN_CURSOR (top_edge_cursor, CURSOR_ID_RESIZE_NORTH);
4515 ASSIGN_CURSOR (top_right_corner_cursor, CURSOR_ID_RESIZE_NORTH_EAST);
4516 ASSIGN_CURSOR (right_edge_cursor, CURSOR_ID_RESIZE_EAST);
4517 ASSIGN_CURSOR (bottom_right_corner_cursor, CURSOR_ID_RESIZE_SOUTH_EAST);
4518 ASSIGN_CURSOR (bottom_edge_cursor, CURSOR_ID_RESIZE_SOUTH);
4519 ASSIGN_CURSOR (bottom_left_corner_cursor, CURSOR_ID_RESIZE_SOUTH_WEST);
4520 ASSIGN_CURSOR (no_cursor, CURSOR_ID_NO_CURSOR);
4521 #undef ASSIGN_CURSOR
4523 system_name = Fsystem_name ();
4525 if (STRINGP (system_name))
4527 nbytes = sizeof "GNU Emacs" + sizeof " at ";
4529 if (ckd_add (&nbytes, nbytes, SBYTES (system_name)))
4530 memory_full (SIZE_MAX);
4532 name_buffer = alloca (nbytes);
4533 sprintf (name_buffer, "%s%s%s", "GNU Emacs",
4534 " at ", SDATA (system_name));
4535 dpyinfo->default_name = build_string (name_buffer);
4537 else
4538 dpyinfo->default_name = build_string ("GNU Emacs");
4540 haiku_start_watching_selections ();
4542 /* Start listening for font configuration changes. */
4543 be_listen_font_settings ();
4544 unblock_input ();
4546 return dpyinfo;
4549 void
4550 put_xrm_resource (Lisp_Object name, Lisp_Object val)
4552 eassert (STRINGP (name));
4553 eassert (STRINGP (val) || NILP (val));
4555 Lisp_Object lval = assoc_no_quit (name, rdb);
4556 if (!NILP (lval))
4557 Fsetcdr (lval, val);
4558 else
4559 rdb = Fcons (Fcons (name, val), rdb);
4562 void
4563 haiku_clear_under_internal_border (struct frame *f)
4565 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
4566 /* This is needed because tooltip frames set up the internal
4567 border before init_frame_faces. */
4568 && FRAME_FACE_CACHE (f))
4570 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
4571 int width = FRAME_PIXEL_WIDTH (f);
4572 int height = FRAME_PIXEL_HEIGHT (f);
4573 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
4574 int bottom_margin = FRAME_BOTTOM_MARGIN_HEIGHT (f);
4575 int face_id = (FRAME_PARENT_FRAME (f)
4576 ? (!NILP (Vface_remapping_alist)
4577 ? lookup_basic_face (NULL, f,
4578 CHILD_FRAME_BORDER_FACE_ID)
4579 : CHILD_FRAME_BORDER_FACE_ID)
4580 : (!NILP (Vface_remapping_alist)
4581 ? lookup_basic_face (NULL, f,
4582 INTERNAL_BORDER_FACE_ID)
4583 : INTERNAL_BORDER_FACE_ID));
4584 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
4585 void *view = FRAME_HAIKU_DRAWABLE (f);
4587 block_input ();
4588 BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
4589 FRAME_PIXEL_HEIGHT (f));
4590 BView_StartClip (view);
4591 BView_ClipToRect (view, 0, 0, FRAME_PIXEL_WIDTH (f),
4592 FRAME_PIXEL_HEIGHT (f));
4594 if (face)
4595 BView_SetHighColor (view, face->background);
4596 else
4597 BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (f));
4599 BView_FillRectangle (view, 0, margin, width, border);
4600 BView_FillRectangle (view, 0, 0, border, height);
4601 BView_FillRectangle (view, 0, margin, width, border);
4602 BView_FillRectangle (view, width - border, 0, border, height);
4603 BView_FillRectangle (view, 0, height - bottom_margin - border,
4604 width, border);
4605 BView_EndClip (view);
4606 BView_draw_unlock (view);
4607 unblock_input ();
4611 void
4612 mark_haiku_display (void)
4614 if (x_display_list)
4616 mark_object (x_display_list->color_map);
4617 mark_object (x_display_list->default_name);
4621 void
4622 haiku_scroll_bar_remove (struct scroll_bar *bar)
4624 void *view;
4625 struct frame *f;
4627 f = WINDOW_XFRAME (XWINDOW (bar->window));
4628 view = FRAME_HAIKU_DRAWABLE (f);
4630 block_input ();
4631 BView_forget_scroll_bar (view, bar->left, bar->top,
4632 bar->width, bar->height);
4633 BScrollBar_delete (bar->scroll_bar);
4634 expose_frame (WINDOW_XFRAME (XWINDOW (bar->window)),
4635 bar->left, bar->top, bar->width, bar->height);
4637 if (bar->horizontal)
4638 wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
4639 else
4640 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
4641 unblock_input ();
4644 void
4645 haiku_set_offset (struct frame *frame, int x, int y,
4646 int change_gravity)
4648 Lisp_Object lframe;
4650 /* Don't allow moving a fullscreen frame: the semantics of that are
4651 unclear. */
4653 XSETFRAME (lframe, frame);
4654 if (EQ (Fframe_parameter (lframe, Qfullscreen), Qfullboth)
4655 /* Only do this if the fullscreen status has actually been
4656 applied. */
4657 && frame->want_fullscreen == FULLSCREEN_NONE
4658 /* And if the configury during frame creation has been
4659 completed. Otherwise, there will be no valid "old position"
4660 to go back to. */
4661 && FRAME_OUTPUT_DATA (frame)->configury_done)
4662 return;
4664 if (change_gravity > 0)
4666 frame->top_pos = y;
4667 frame->left_pos = x;
4668 frame->size_hint_flags &= ~ (XNegative | YNegative);
4669 if (x < 0)
4670 frame->size_hint_flags |= XNegative;
4671 if (y < 0)
4672 frame->size_hint_flags |= YNegative;
4673 frame->win_gravity = NorthWestGravity;
4676 haiku_update_size_hints (frame);
4678 block_input ();
4679 if (change_gravity)
4680 BWindow_set_offset (FRAME_HAIKU_WINDOW (frame), x, y);
4681 unblock_input ();
4684 #ifdef USE_BE_CAIRO
4685 cairo_t *
4686 haiku_begin_cr_clip (struct frame *f, struct glyph_string *s)
4688 cairo_t *cr = FRAME_CR_CONTEXT (f);
4690 if (!cr)
4691 return NULL;
4693 cairo_save (cr);
4694 return cr;
4697 void
4698 haiku_end_cr_clip (cairo_t *cr)
4700 if (!cr)
4701 return;
4703 cairo_restore (cr);
4705 #endif
4707 void
4708 haiku_merge_cursor_foreground (struct glyph_string *s,
4709 unsigned long *foreground_out,
4710 unsigned long *background_out)
4712 unsigned long background = FRAME_CURSOR_COLOR (s->f).pixel;
4713 unsigned long foreground = s->face->background;
4715 if (background == foreground)
4716 foreground = s->face->background;
4717 if (background == foreground)
4718 foreground = FRAME_OUTPUT_DATA (s->f)->cursor_fg;
4719 if (background == foreground)
4720 foreground = s->face->foreground;
4722 if (background == s->face->background
4723 && foreground == s->face->foreground)
4725 background = s->face->foreground;
4726 foreground = s->face->background;
4729 if (foreground_out)
4730 *foreground_out = foreground;
4731 if (background_out)
4732 *background_out = background;
4735 void
4736 syms_of_haikuterm (void)
4738 DEFVAR_BOOL ("haiku-initialized", haiku_initialized,
4739 doc: /* Non-nil if the Haiku terminal backend has been initialized. */);
4741 DEFVAR_BOOL ("x-use-underline-position-properties",
4742 x_use_underline_position_properties,
4743 doc: /* SKIP: real doc in xterm.c. */);
4744 x_use_underline_position_properties = 1;
4746 DEFVAR_BOOL ("x-underline-at-descent-line",
4747 x_underline_at_descent_line,
4748 doc: /* SKIP: real doc in xterm.c. */);
4749 x_underline_at_descent_line = 0;
4751 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
4752 doc: /* SKIP: real doc in xterm.c. */);
4753 Vx_toolkit_scroll_bars = Qt;
4755 DEFVAR_BOOL ("haiku-debug-on-fatal-error", haiku_debug_on_fatal_error,
4756 doc: /* If non-nil, Emacs will launch the system debugger upon a fatal error. */);
4757 haiku_debug_on_fatal_error = 1;
4759 DEFSYM (Qshift, "shift");
4760 DEFSYM (Qcontrol, "control");
4761 DEFSYM (Qoption, "option");
4762 DEFSYM (Qcommand, "command");
4764 DEFSYM (Qdata_directory, "data-directory");
4766 DEFVAR_LISP ("haiku-meta-keysym", Vhaiku_meta_keysym,
4767 doc: /* Which key Emacs uses as the meta modifier.
4768 This is either one of the symbols `shift', `control', `command', and
4769 `option', or nil, in which case it is treated as `command'.
4771 Setting it to any other value is equivalent to `command'. */);
4772 Vhaiku_meta_keysym = Qnil;
4774 DEFVAR_LISP ("haiku-control-keysym", Vhaiku_control_keysym,
4775 doc: /* Which key Emacs uses as the control modifier.
4776 This is either one of the symbols `shift', `control', `command', and
4777 `option', or nil, in which case it is treated as `control'.
4779 Setting it to any other value is equivalent to `control'. */);
4780 Vhaiku_control_keysym = Qnil;
4782 DEFVAR_LISP ("haiku-super-keysym", Vhaiku_super_keysym,
4783 doc: /* Which key Emacs uses as the super modifier.
4784 This is either one of the symbols `shift', `control', `command', and
4785 `option', or nil, in which case it is treated as `option'.
4787 Setting it to any other value is equivalent to `option'. */);
4788 Vhaiku_super_keysym = Qnil;
4790 DEFVAR_LISP ("haiku-shift-keysym", Vhaiku_shift_keysym,
4791 doc: /* Which key Emacs uses as the shift modifier.
4792 This is either one of the symbols `shift', `control', `command', and
4793 `option', or nil, in which case it is treated as `shift'.
4795 Setting it to any other value is equivalent to `shift'. */);
4796 Vhaiku_shift_keysym = Qnil;
4798 DEFSYM (Qx_use_underline_position_properties,
4799 "x-use-underline-position-properties");
4801 DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
4803 rdb = Qnil;
4804 staticpro (&rdb);
4806 Fprovide (Qhaiku, Qnil);
4807 #ifdef USE_BE_CAIRO
4808 Fprovide (intern_c_string ("cairo"), Qnil);
4809 #endif