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/>. */
21 #include "dispextern.h"
26 #include "haikuterm.h"
27 #include "blockinput.h"
29 #include "termhooks.h"
32 #include "haiku_support.h"
35 #include "haikuselect.h"
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
65 static bool any_help_event_p
;
68 get_keysym_name (int keysym
)
70 static char value
[16];
71 sprintf (value
, "%d", keysym
);
76 haiku_window_to_frame (void *window
)
78 Lisp_Object tail
, tem
;
81 FOR_EACH_FRAME (tail
, tem
)
84 if (!FRAME_HAIKU_P (f
))
87 eassert (FRAME_DISPLAY_INFO (f
) == x_display_list
);
89 if (FRAME_HAIKU_WINDOW (f
) == window
)
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
;
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
));
115 haiku_delete_terminal (struct terminal
*terminal
)
117 error ("The Haiku terminal cannot be deleted");
121 haiku_get_string_resource (void *ignored
, const char *name
,
129 Lisp_Object lval
= assoc_no_quit (build_string (name
), rdb
);
132 return SSDATA (XCDR (lval
));
134 if ((native
= be_find_setting (name
)))
141 haiku_update_size_hints (struct frame
*f
)
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
)));
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);
163 /* If n[FOO].width is 0, it means to not draw at all, so set the
164 clipping to some impossible value. */
166 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s
->f
),
167 FRAME_PIXEL_WIDTH (s
->f
),
168 FRAME_PIXEL_HEIGHT (s
->f
),
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
);
181 /* If n[FOO].width is 0, it means to not draw at all, so set the
182 clipping to some impossible value. */
184 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s
->f
),
185 FRAME_PIXEL_WIDTH (s
->f
),
186 FRAME_PIXEL_HEIGHT (s
->f
),
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
);
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
);
208 haiku_flip_buffers (struct frame
*f
)
210 void *view
= FRAME_OUTPUT_DATA (f
)->view
;
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
);
222 haiku_frame_up_to_date (struct frame
*f
)
225 FRAME_MOUSE_UPDATE (f
);
226 if (FRAME_DIRTY_P (f
) && !buffer_flipping_blocked_p ())
227 haiku_flip_buffers (f
);
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;
242 haiku_buffer_flipping_unblocked_hook (struct frame
*f
)
244 if (FRAME_DIRTY_P (f
))
245 haiku_flip_buffers (f
);
249 haiku_clear_frame_area (struct frame
*f
, int x
, int y
,
250 int width
, int height
)
252 void *vw
= FRAME_HAIKU_DRAWABLE (f
);
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
);
260 BView_draw_unlock (vw
);
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;
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
);
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
293 haiku_new_font (struct frame
*f
, Lisp_Object font_object
, int fontset
)
296 int ascent
, descent
, unit
;
298 font
= XFONT_OBJECT (font_object
);
301 fontset
= fontset_from_font (font_object
);
303 FRAME_FONTSET (f
) = fontset
;
305 if (FRAME_FONT (f
) == font
)
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
;
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
),
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)
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
)))
351 haiku_modifiers_to_emacs (int haiku_key
)
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
);
368 haiku_rehighlight (void)
370 eassert (x_display_list
&& !x_display_list
->next
);
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
;
389 x_display_list
->highlight_frame
= 0;
392 gui_update_cursor (old_hl
, true);
394 if (x_display_list
->highlight_frame
)
395 gui_update_cursor (x_display_list
->highlight_frame
, true);
400 haiku_frame_raise_lower (struct frame
*f
, bool raise_p
)
405 BWindow_activate (FRAME_HAIKU_WINDOW (f
));
406 BWindow_sync (FRAME_HAIKU_WINDOW (f
));
412 BWindow_send_behind (FRAME_HAIKU_WINDOW (f
), NULL
);
413 BWindow_sync (FRAME_HAIKU_WINDOW (f
));
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
425 if (lm_f
&& !EQ (track_mouse
, Qdropping
)
426 && !EQ (track_mouse
, Qdrag_source
))
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
;
436 /* When dropping it would be probably nice to raise 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
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. */
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
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
);
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
;
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
)
521 struct frame
*frame
= haiku_window_to_frame (window
);
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
);
542 /* Unfortunately, NOACTIVATE is not implementable on Haiku. */
544 haiku_focus_frame (struct frame
*frame
, bool noactivate
)
546 if (x_display_list
->focused_frame
!= frame
)
547 haiku_frame_raise_lower (frame
, 1);
551 haiku_new_focus_frame (struct frame
*frame
)
553 eassert (x_display_list
&& !x_display_list
->next
);
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);
569 haiku_rehighlight ();
573 haiku_implicitly_set_name (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
575 haiku_set_name (f
, arg
, 0);
579 haiku_query_frame_background_color (struct frame
*f
, Emacs_Color
*bgcolor
)
581 haiku_query_color (FRAME_BACKGROUND_PIXEL (f
), bgcolor
);
585 haiku_defined_color (struct frame
*f
, const char *name
,
586 Emacs_Color
*color
, bool alloc
, bool make_index
)
590 rc
= !haiku_get_color (name
, color
);
592 if (rc
&& f
->gamma
&& alloc
)
593 gamma_correct (f
, color
);
598 /* Adapted from xterm `x_draw_box_rect'. */
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
);
609 BView_ClipToRect (view
, clip_rect
->x
, clip_rect
->y
, clip_rect
->width
,
611 BView_FillRectangle (view
, left_x
, top_y
, right_x
- left_x
+ 1, hwidth
);
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
);
618 BView_FillRectangle (view
, right_x
- vwidth
+ 1,
619 top_y
, vwidth
, bottom_y
- top_y
+ 1);
623 haiku_calculate_relief_colors (struct glyph_string
*s
, uint32_t *rgbout_w
,
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
634 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
635 rgbin
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
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
;
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
;
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
);
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
);
682 BView_FillRectangle (view
, left_x
, top_y
,
683 right_x
- left_x
+ 1, hwidth
);
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
);
692 BView_FillRectangle (view
, left_x
, bottom_y
- hwidth
+ 1,
693 right_x
- left_x
+ 1, hwidth
);
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. */
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
,
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)
735 BView_FillRectangle (view
, left_x
, top_y
, 1, 1);
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);
745 BView_EndClip (view
);
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);
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
;
769 haiku_get_scale_factor (&scale_x
, &scale_y
);
770 wave_height
= 3 * scale_y
;
771 wave_length
= 2 * scale_x
;
774 dy
= wave_height
- 1;
775 y
= s
->ybase
- wave_height
+ 3;
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;
785 odd
= (int) (ax
/ dx
) % 2;
793 BView_SetPenSize (view
, scale_y
);
797 BView_StrokeLine (view
, ax
, ay
, bx
, by
);
799 bx
+= dx
, by
= y
+ 0.5 + odd
* dy
;
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. */
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
;
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
)
837 BView_StrokeLine (view
, x
, y_center
,
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
851 haiku_fill_underline (struct frame
*f
, struct glyph_string
*s
,
852 enum face_underline_type style
, int position
,
858 segment
= thickness
* 3;
859 view
= FRAME_HAIKU_VIEW (f
);
863 /* FACE_UNDERLINE_DOUBLE_LINE is treated identically to SINGLE, as
864 the second line will be filled by another invocation of this
866 case FACE_UNDERLINE_SINGLE
:
867 case FACE_UNDERLINE_DOUBLE_LINE
:
868 BView_FillRectangle (view
, s
->x
, s
->ybase
+ position
,
869 s
->width
, thickness
);
872 case FACE_UNDERLINE_DOTS
:
876 case FACE_UNDERLINE_DASHES
:
877 haiku_draw_dash (f
, s
, s
->width
, segment
, position
, thickness
);
880 case FACE_NO_UNDERLINE
:
881 case FACE_UNDERLINE_WAVE
:
888 haiku_draw_text_decoration (struct glyph_string
*s
, struct face
*face
,
891 unsigned long cursor_color
;
896 if (s
->hl
== DRAW_CURSOR
)
897 haiku_merge_cursor_foreground (s
, &cursor_color
, NULL
);
899 void *view
= FRAME_HAIKU_DRAWABLE (s
->f
);
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
);
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
;
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
;
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
));
938 minimum_offset
= max (0, XFIXNUM (val
));
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
;
958 if (underline_at_descent_line
)
959 position
= ((s
->height
- thickness
)
961 - s
->face
->underline_pixels_above_descent_line
);
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
;
977 position
= (font
->descent
+ 1) / 2;
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
);
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
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
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
);
1040 BView_SetHighColor (view
, face
->foreground
);
1042 BView_FillRectangle (view
, s
->x
, glyph_y
+ dy
, s
->width
, h
);
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
;
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
;
1083 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
1085 : min (last_x
, s
->x
+ s
->background_width
) - 1);
1088 bottom_y
= top_y
+ s
->height
- 1;
1090 left_p
= (s
->first_glyph
->left_box_line_p
1091 || (s
->hl
== DRAW_MOUSE_FACE
1093 || s
->prev
->hl
!= s
->hl
)));
1094 right_p
= (last_glyph
->right_box_line_p
1095 || (s
->hl
== DRAW_MOUSE_FACE
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
);
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
,
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
);
1121 BView_SetHighColor (view
, face
->background_defaulted_p
?
1122 FRAME_BACKGROUND_PIXEL (s
->f
) :
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];
1135 haiku_update_bitmap_rec (struct haiku_bitmap_record
*rec
,
1136 uint32_t new_foreground
,
1137 uint32_t new_background
)
1140 int x
, y
, bytes_per_line
;
1142 if (new_foreground
== rec
->stipple_foreground
1143 && new_background
== rec
->stipple_background
)
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
;
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
;
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
);
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
);
1201 haiku_draw_background_rect (struct glyph_string
*s
, struct face
*face
,
1202 int x
, int y
, int width
, int height
)
1205 haiku_draw_plain_background (s
, face
, x
, y
, width
, height
);
1207 haiku_draw_stipple_background (s
, face
, x
, y
, width
, height
,
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;
1234 haiku_mouse_face_colors (struct glyph_string
*s
, uint32_t *fg
,
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
);
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
);
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
);
1255 *fg
= face
->foreground
;
1257 *bg
= face
->background
;
1261 haiku_draw_glyph_string_foreground (struct glyph_string
*s
)
1263 struct face
*face
= s
->face
;
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);
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
);
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
,
1287 x
+= g
->pixel_width
;
1292 struct font
*ft
= s
->font
;
1293 int off
= ft
->baseline_offset
;
1296 if (ft
->vertical_centering
)
1297 off
= VCENTER_BASELINE_OFFSET (ft
, s
->f
) - 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);
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);
1310 haiku_draw_glyphless_glyph_string_foreground (struct glyph_string
*s
)
1312 struct glyph
*glyph
= s
->first_glyph
;
1313 static unsigned char2b
[8];
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);
1328 for (i
= 0; i
< s
->nchars
; i
++, glyph
++)
1331 enum { PACIFY_GCC_BUG_81401
= 1 };
1333 enum { PACIFY_GCC_BUG_81401
= 0 };
1335 char buf
[7 + PACIFY_GCC_BUG_81401
];
1337 int len
= glyph
->u
.glyphless
.len
;
1339 if (glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_ACRONYM
)
1342 && CHAR_TABLE_P (Vglyphless_char_display
)
1343 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display
))
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
);
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
,
1377 s
->font
->driver
->draw (s
, upper_len
, len
,
1378 x
+ glyph
->slice
.glyphless
.lower_xoff
,
1379 s
->ybase
+ glyph
->slice
.glyphless
.lower_yoff
,
1383 if (glyph
->u
.glyphless
.method
!= GLYPHLESS_DISPLAY_THIN_SPACE
)
1385 if (s
->hl
== DRAW_CURSOR
)
1386 haiku_merge_cursor_foreground (s
, NULL
, &color
);
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
,
1395 glyph
->ascent
+ glyph
->descent
);
1397 x
+= glyph
->pixel_width
;
1402 haiku_draw_stretch_glyph_string (struct glyph_string
*s
)
1404 struct face
*face
= s
->face
;
1407 if (s
->hl
== DRAW_CURSOR
&& !x_stretch_cursor_p
)
1409 int width
, background_width
= s
->background_width
;
1412 if (!s
->row
->reversed_p
)
1414 int left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
1418 background_width
-= left_x
- x
;
1424 /* In R2L rows, draw the cursor on the right edge of the
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
)
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
)
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. */
1458 if (s
->row
->mouse_face_p
&& cursor_in_mouse_face_p (s
->w
))
1459 haiku_mouse_face_colors (s
, NULL
, &bkg
);
1461 bkg
= face
->background
;
1463 BView_SetHighColor (view
, bkg
);
1464 BView_FillRectangle (view
, x
, y
, w
, h
);
1468 if (s
->row
->mouse_face_p
&& cursor_in_mouse_face_p (s
->w
))
1469 haiku_mouse_face_colors (s
, NULL
, &bkg
);
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
;
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;
1500 haiku_start_clip (struct glyph_string
*s
)
1502 void *view
= FRAME_HAIKU_DRAWABLE (s
->f
);
1503 BView_StartClip (view
);
1507 haiku_end_clip (struct glyph_string
*s
)
1509 void *view
= FRAME_HAIKU_DRAWABLE (s
->f
);
1510 BView_EndClip (view
);
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);
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
);
1533 haiku_update_begin (struct frame
*f
)
1535 /* Mark the frame as incomplete so it is not flushed upon handling
1537 FRAME_COMPLETE_P (f
) = false;
1541 haiku_update_end (struct frame
*f
)
1543 MOUSE_HL_INFO (f
)->mouse_face_defer
= false;
1544 BWindow_Flush (FRAME_HAIKU_WINDOW (f
));
1548 haiku_draw_composite_glyph_string_foreground (struct glyph_string
*s
)
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);
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
);
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
)
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);
1600 Lisp_Object gstring
= composition_gstring_from_id (s
->cmp_id
);
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
);
1612 int xoff
, yoff
, wadjust
;
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);
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
,
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);
1643 haiku_draw_image_relief (struct glyph_string
*s
)
1646 bool raised_p
, top_p
, bot_p
, left_p
, right_p
;
1647 int extra_x
, extra_y
;
1648 struct haiku_rect r
;
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
1659 x
+= max (face
->box_vertical_line_width
, 0);
1661 /* If there is a margin around the image, adjust x- and y-position
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));
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
;
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
);
1735 haiku_translate_transform (double (*transform
)[3], double dx
,
1738 transform
[0][2] += dx
;
1739 transform
[1][2] += dy
;
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];
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
;
1763 if (s
->first_glyph
->left_box_line_p
1766 x
+= box_line_hwidth
;
1767 width
-= box_line_hwidth
;
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
);
1782 background
= face
->background
;
1784 haiku_draw_background_rect (s
, face
, x
, y
,
1789 get_glyph_string_clip_rect (s
, &nr
);
1790 CONVERT_TO_EMACS_RECT (cr
, nr
);
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
1802 x
+= max (face
->box_vertical_line_width
, 0);
1806 ir
.width
= s
->slice
.width
;
1807 ir
.height
= s
->slice
.height
;
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
,
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
,
1843 s
->img
->original_width
,
1844 s
->img
->original_height
,
1845 s
->img
->use_bilinear_filtering
);
1848 be_draw_image_mask (mask
, view
, 0, 0,
1849 s
->img
->original_width
,
1850 s
->img
->original_height
,
1852 s
->img
->original_width
,
1853 s
->img
->original_height
,
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
,
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);
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);
1899 || s
->hl
== DRAW_IMAGE_RAISED
1900 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1901 haiku_draw_image_relief (s
);
1905 haiku_draw_glyph_string (struct glyph_string
*s
)
1907 void *view
= FRAME_HAIKU_DRAWABLE (s
->f
);;
1908 struct face
*face
= s
->face
;
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
)
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
);
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);
1935 haiku_draw_stretch_glyph_string (next
);
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);
1951 haiku_draw_string_box (s
);
1953 else if (!s
->clip_head
/* draw_glyphs didn't specify a clip mask. */
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
);
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;
1974 haiku_maybe_draw_background (s
, 1);
1975 haiku_draw_composite_glyph_string_foreground (s
);
1978 if (s
->for_overlaps
)
1979 s
->background_filled_p
= 1;
1981 haiku_maybe_draw_background (s
, 0);
1982 haiku_draw_glyph_string_foreground (s
);
1985 haiku_draw_stretch_glyph_string (s
);
1988 haiku_draw_image_glyph_string (s
);
1990 case GLYPHLESS_GLYPH
:
1991 if (s
->for_overlaps
)
1992 s
->background_filled_p
= 1;
1994 haiku_maybe_draw_background (s
, 1);
1995 haiku_draw_glyphless_glyph_string_foreground (s
);
2001 if (!s
->for_overlaps
)
2003 if (!box_filled_p
&& face
->box
!= FACE_NO_BOX
)
2004 haiku_draw_string_box (s
);
2006 haiku_draw_text_decoration (s
, face
, s
->width
, s
->x
);
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
;
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
);
2027 haiku_draw_composite_glyph_string_foreground (prev
);
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
;
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
);
2052 haiku_draw_composite_glyph_string_foreground (next
);
2056 next
->clip_head
= s
->next
;
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;
2077 haiku_after_update_window_line (struct window
*w
,
2078 struct glyph_row
*desired_row
)
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
),
2092 && (height
= desired_row
->visible_height
,
2095 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
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
);
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
,
2114 BView_invalidate_region (FRAME_HAIKU_DRAWABLE (f
),
2115 0, y
, width
, height
);
2116 BView_invalidate_region (view
, FRAME_PIXEL_WIDTH (f
) - width
,
2118 BView_EndClip (view
);
2119 BView_draw_unlock (view
);
2123 haiku_clear_frame_area (f
, 0, y
, width
, height
);
2124 haiku_clear_frame_area (f
, FRAME_PIXEL_WIDTH (f
) - width
,
2132 haiku_set_window_size (struct frame
*f
, bool change_gravity
,
2133 int width
, int height
)
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
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
2148 && FRAME_OUTPUT_DATA (f
)->configury_done
)
2151 haiku_update_size_hints (f
);
2153 if (FRAME_HAIKU_WINDOW (f
))
2156 BWindow_resize (FRAME_HAIKU_WINDOW (f
),
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
);
2166 do_pending_window_change (false);
2170 haiku_draw_hollow_cursor (struct window
*w
, struct glyph_row
*row
)
2174 struct glyph
*cursor_glyph
;
2175 uint32_t foreground
;
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
)
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
);
2222 haiku_draw_bar_cursor (struct window
*w
, struct glyph_row
*row
,
2223 int width
, enum text_cursor_kinds kind
)
2226 struct glyph
*cursor_glyph
;
2227 struct glyph_row
*r
;
2229 uint32_t foreground
;
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
2238 cursor_glyph
= get_phys_cursor_glyph (w
);
2239 if (cursor_glyph
== NULL
)
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
);
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
;
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
);
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
);
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,
2309 BView_invalidate_region (view
, x
, y
, w
->phys_cursor_width
- 1,
2313 BView_EndClip (view
);
2314 BView_draw_unlock (view
);
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
)
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
);
2338 switch (cursor_type
)
2340 case HOLLOW_BOX_CURSOR
:
2341 haiku_draw_hollow_cursor (w
, glyph_row
);
2344 case FILLED_BOX_CURSOR
:
2345 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
2349 haiku_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
2353 haiku_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
2357 w
->phys_cursor_width
= 0;
2368 haiku_show_hourglass (struct frame
*f
)
2370 if (FRAME_TOOLTIP_P (f
)
2371 || FRAME_OUTPUT_DATA (f
)->hourglass_p
)
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
);
2384 haiku_hide_hourglass (struct frame
*f
)
2386 if (FRAME_TOOLTIP_P (f
)
2387 || !FRAME_OUTPUT_DATA (f
)->hourglass_p
)
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
);
2400 haiku_compute_glyph_string_overhangs (struct glyph_string
*s
)
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
);
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;
2425 s
->right_overhang
= s
->cmp
->rbearing
- s
->cmp
->pixel_width
;
2426 s
->left_overhang
= - s
->cmp
->lbearing
;
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
));
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
);
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
);
2449 haiku_set_scroll_bar_default_width (struct frame
*f
)
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
;
2461 haiku_set_scroll_bar_default_height (struct frame
*f
)
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
;
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);
2517 BView_SetHighColor (view
, color
);
2518 BView_FillRectangleAbs (view
, x0
, y0
, x1
, y1
);
2520 BView_EndClip (view
);
2521 BView_draw_unlock (view
);
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
);
2547 haiku_redeem_scroll_bar (struct window
*w
)
2549 struct scroll_bar
*bar
;
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
2562 if (EQ (FRAME_SCROLL_BARS (f
), w
->vertical_scroll_bar
))
2563 /* It's not condemned. Everything's fine. */
2565 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2566 w
->vertical_scroll_bar
))
2567 fset_condemned_scroll_bars (f
, bar
->next
);
2569 /* If its prev pointer is nil, it must be at the front of
2570 one or the other! */
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
);
2581 XSETVECTOR (barobj
, bar
);
2582 fset_scroll_bars (f
, barobj
);
2583 if (! NILP (bar
->next
))
2584 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
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
2596 if (EQ (FRAME_SCROLL_BARS (f
), w
->horizontal_scroll_bar
))
2597 /* It's not condemned. Everything's fine. */
2599 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2600 w
->horizontal_scroll_bar
))
2601 fset_condemned_scroll_bars (f
, bar
->next
);
2603 /* If its prev pointer is nil, it must be at the front of
2604 one or the other! */
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
);
2615 XSETVECTOR (barobj
, bar
);
2616 fset_scroll_bars (f
, barobj
);
2617 if (! NILP (bar
->next
))
2618 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
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
);
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
)
2653 struct scroll_bar
*bar
;
2657 f
= XFRAME (WINDOW_FRAME (w
));
2658 view
= FRAME_HAIKU_DRAWABLE (f
);
2661 bar
= ALLOCATE_PSEUDOVECTOR (struct scroll_bar
, prev
, PVEC_OTHER
);
2663 XSETWINDOW (bar
->window
, w
);
2667 bar
->height
= height
;
2672 bar
->horizontal
= horizontal_p
;
2674 scroll_bar
= be_make_scroll_bar_for_view (view
, horizontal_p
,
2675 left
, top
, left
+ width
- 1,
2677 BView_publish_scroll_bar (view
, left
, top
, width
, height
);
2679 bar
->next
= FRAME_SCROLL_BARS (f
);
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
);
2693 haiku_set_horizontal_scroll_bar (struct window
*w
, int portion
, int whole
, int position
)
2696 struct scroll_bar
*bar
;
2697 int top
, height
, left
, width
;
2698 int window_x
, window_width
;
2701 eassert (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w
));
2702 /* Get window dimensions. */
2703 window_box (w
, ANY_AREA
, &window_x
, 0, &window_width
, 0);
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
));
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
;
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
);
2735 bar
->height
= height
;
2739 haiku_set_horizontal_scroll_bar_thumb (bar
, portion
, position
, whole
);
2740 bar
->position
= position
;
2742 XSETVECTOR (barobj
, bar
);
2743 wset_horizontal_scroll_bar (w
, barobj
);
2748 haiku_set_vertical_scroll_bar (struct window
*w
, int portion
, int whole
, int position
)
2751 struct scroll_bar
*bar
;
2752 int top
, height
, left
, width
;
2753 int window_y
, window_height
;
2756 eassert (WINDOW_HAS_VERTICAL_SCROLL_BAR (w
));
2758 /* Get window dimensions. */
2759 window_box (w
, ANY_AREA
, 0, &window_y
, 0, &window_height
);
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
));
2770 if (NILP (w
->vertical_scroll_bar
))
2772 bar
= haiku_scroll_bar_create (w
, left
, top
, width
, height
, false);
2773 bar
->position
= position
;
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
);
2792 bar
->height
= height
;
2796 haiku_set_scroll_bar_thumb (bar
, portion
, position
, whole
);
2797 bar
->position
= position
;
2800 XSETVECTOR (barobj
, bar
);
2801 wset_vertical_scroll_bar (w
, barobj
);
2806 haiku_draw_fringe_bitmap (struct window
*w
, struct glyph_row
*row
,
2807 struct draw_fringe_bitmap_params
*p
)
2811 struct haiku_bitmap_record
*rec
;
2812 void *view
, *bitmap
;
2815 f
= XFRAME (WINDOW_FRAME (w
));
2816 view
= FRAME_HAIKU_DRAWABLE (f
);
2820 BView_draw_lock (view
, true, 0, 0, 0, 0);
2821 BView_StartClip (view
);
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
);
2834 BView_SetHighColor (view
, face
->background
);
2835 BView_FillRectangle (view
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2839 rec
= haiku_get_bitmap_rec (f
, face
->stipple
);
2840 haiku_update_bitmap_rec (rec
, face
->foreground
,
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;
2856 && p
->which
< max_fringe_bmp
2857 && p
->which
< max_used_fringe_bitmap
)
2859 bitmap
= fringe_bmps
[p
->which
];
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
];
2874 col
= face
->foreground
;
2875 else if (p
->overlay_p
)
2876 col
= face
->background
;
2878 col
= FRAME_CURSOR_COLOR (XFRAME (WINDOW_FRAME (w
))).pixel
;
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
);
2895 haiku_define_fringe_bitmap (int which
, unsigned short *bits
,
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
;
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
);
2918 haiku_destroy_fringe_bitmap (int which
)
2920 if (which
>= max_fringe_bmp
)
2923 if (fringe_bmps
[which
])
2924 BBitmap_free (fringe_bmps
[which
]);
2925 fringe_bmps
[which
] = NULL
;
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
;
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
;
2947 height
= run
->height
;
2951 /* Scrolling down. Make sure we don't copy over the mode line.
2953 if (to_y
+ run
->height
> bottom_y
)
2954 height
= bottom_y
- to_y
;
2956 height
= run
->height
;
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
);
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. */
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
,
2983 Lisp_Object frame
, tail
;
2985 int screen_x
, screen_y
;
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
;
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
))
3019 if (f1
&& FRAME_HAIKU_P (f1
))
3021 view
= FRAME_HAIKU_VIEW (f1
);
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
;
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
)))
3044 *timestamp
= x_display_list
->last_mouse_movement_time
;
3045 XSETINT (*x
, screen_x
);
3046 XSETINT (*y
, screen_y
);
3054 haiku_flush (struct frame
*f
)
3056 /* This is needed for tooltip frames to work properly with double
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
3063 FRAME_COMPLETE_P (f
) = true;
3065 if (FRAME_VISIBLE_P (f
) && !FRAME_TOOLTIP_P (f
))
3066 BWindow_Flush (FRAME_HAIKU_WINDOW (f
));
3070 haiku_define_frame_cursor (struct frame
*f
, Emacs_Cursor cursor
)
3072 if (FRAME_TOOLTIP_P (f
))
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
);
3080 FRAME_OUTPUT_DATA (f
)->current_cursor
= cursor
;
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
,
3089 Lisp_Object font
= Qnil
;
3090 if (BASE_EQ (font_param
, Qunbound
))
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 ());
3101 font
= (!NILP (font_param
)
3103 : gui_display_get_arg (dpyinfo
, parms
, Qfont
,
3107 if (! FONTP (font
) && ! STRINGP (font
))
3109 const char **names
= (const char *[]) { "monospace-12",
3110 "Noto Sans Mono-12",
3111 "Source Code Pro-12",
3115 for (i
= 0; names
[i
]; i
++)
3118 = font_open_by_name (f
, build_unibyte_string (names
[i
]));
3123 error ("No suitable font was found");
3126 gui_default_parameter (f
, parms
, Qfont
, font
, "font", "Font",
3130 static struct redisplay_interface haiku_redisplay_interface
=
3132 haiku_frame_parm_handlers
,
3136 gui_clear_end_of_line
,
3138 haiku_after_update_window_line
,
3139 NULL
, /* update_window_begin */
3140 NULL
, /* update_window_end */
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
,
3163 haiku_make_fullscreen_consistent (struct frame
*f
)
3166 struct haiku_output
*output
;
3168 output
= FRAME_OUTPUT_DATA (f
);
3170 if (output
->fullscreen_mode
== FULLSCREEN_MODE_BOTH
)
3172 else if (output
->fullscreen_mode
== FULLSCREEN_MODE_WIDTH
)
3174 else if (output
->fullscreen_mode
== FULLSCREEN_MODE_HEIGHT
)
3176 else if (output
->fullscreen_mode
== FULLSCREEN_MODE_MAXIMIZED
)
3181 store_frame_param (f
, Qfullscreen
, lval
);
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
))
3195 haiku_flip_buffers (f
);
3198 /* N.B. that support for TYPE must be explicitly added to
3199 haiku_read_socket. */
3201 haiku_wait_for_event (struct frame
*f
, int type
)
3203 int input_blocked_to
;
3204 object_wait_info info
;
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
)
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
);
3233 haiku_read_socket (struct terminal
*terminal
, struct input_event
*hold_quit
)
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
;
3244 button_or_motion_p
= 0;
3250 haiku_read_size (&b_size
, false);
3258 inev
.kind
= NO_EVENT
;
3259 inev2
.kind
= NO_EVENT
;
3263 button_or_motion_p
= 0;
3264 haiku_read (&type
, buf
, b_size
);
3268 case QUIT_REQUESTED
:
3270 struct haiku_quit_requested_event
*b
= buf
;
3271 struct frame
*f
= haiku_window_to_frame (b
->window
);
3276 inev
.kind
= DELETE_WINDOW_EVENT
;
3277 XSETFRAME (inev
.frame_or_window
, f
);
3282 struct haiku_resize_event
*b
= buf
;
3283 struct frame
*f
= haiku_window_to_frame (b
->window
);
3288 int width
= lrint (b
->width
);
3289 int height
= lrint (b
->height
);
3291 if (FRAME_OUTPUT_DATA (f
)->wait_for_event_type
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. */
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
)
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
);
3333 struct haiku_expose_event
*b
= buf
;
3334 struct frame
*f
= haiku_window_to_frame (b
->window
);
3339 expose_frame (f
, b
->x
, b
->y
, b
->width
, b
->height
);
3340 haiku_clear_under_internal_border (f
);
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
);
3352 /* If mouse-highlight is an integer, input clears out
3353 mouse highlighting. */
3354 if (!hlinfo
->mouse_face_hidden
&& FIXNUMP (Vmouse_highlight
)
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;
3365 haiku_flush_dirty_back_buffer_on (mouse_frame
);
3368 inev
.code
= b
->keysym
? b
->keysym
: b
->multibyte_char
;
3371 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
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
3383 | shift_modifier
)));
3385 XSETFRAME (inev
.frame_or_window
, f
);
3390 struct haiku_activation_event
*b
= buf
;
3391 struct frame
*f
= haiku_window_to_frame (b
->window
);
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
);
3401 x_display_list
->focus_event_frame
= f
;
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
);
3412 struct haiku_menu_bar_left_event
*b
= buf
;
3413 struct frame
*f
= haiku_window_to_frame (b
->window
);
3418 if (b
->y
> 0 && b
->y
<= FRAME_PIXEL_HEIGHT (f
)
3419 && b
->x
> 0 && b
->x
<= FRAME_PIXEL_WIDTH (f
))
3422 if (f
->auto_lower
&& !popup_activated_p
)
3423 haiku_frame_raise_lower (f
, 0);
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
;
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
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
)))
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
),
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
)
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
)))
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
)
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
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
;
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
;
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
))
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
)
3601 if (!be_drag_and_drop_in_progress ())
3603 inev
.kind
= DRAG_N_DROP_EVENT
;
3606 XSETINT (inev
.x
, b
->x
);
3607 XSETINT (inev
.y
, b
->y
);
3608 XSETFRAME (inev
.frame_or_window
, f
);
3611 haiku_note_drag_motion ();
3617 if (FRAME_DIRTY_P (f
))
3618 haiku_flush_dirty_back_buffer_on (f
);
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
)
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
)))
3649 window
= window_from_coordinates (f
, x
, y
, 0, true, true, true);
3650 tab_bar_p
= EQ (window
, f
->tab_bar_window
);
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
)))
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));
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
);
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;
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
);
3708 && !(tab_bar_p
&& NILP (tab_bar_arg
))
3710 inev
.kind
= MOUSE_CLICK_EVENT
;
3712 inev
.arg
= tab_bar_arg
;
3713 inev
.code
= b
->btn_no
;
3715 f
->mouse_moved
= false;
3719 if (bar
->horizontal
)
3721 XSETINT (inev
.x
, min (max (0, b
->x
- bar
->left
),
3723 XSETINT (inev
.y
, bar
->width
);
3727 XSETINT (inev
.x
, min (max (0, b
->y
- bar
->top
),
3729 XSETINT (inev
.y
, bar
->height
);
3732 inev
.frame_or_window
= bar
->window
;
3736 XSETINT (inev
.x
, b
->x
);
3737 XSETINT (inev
.y
, b
->y
);
3738 XSETFRAME (inev
.frame_or_window
, f
);
3745 struct haiku_iconification_event
*b
= buf
;
3746 struct frame
*f
= haiku_window_to_frame (b
->window
);
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);
3768 SET_FRAME_VISIBLE (f
, 0);
3769 SET_FRAME_ICONIFIED (f
, 1);
3770 inev
.kind
= ICONIFY_EVENT
;
3773 XSETFRAME (inev
.frame_or_window
, f
);
3778 struct haiku_move_event
*b
= buf
;
3779 struct frame
*f
= haiku_window_to_frame (b
->window
);
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
);
3805 p
= FRAME_PARENT_FRAME (f
);
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
);
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
);
3827 struct window
*w
= XWINDOW (bar
->window
);
3829 if (bar
->update
!= -1)
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
3849 * ((float) (BE_SB_MAX
- bar
->page_size
)
3851 portion
= min (portion
, whole
);
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
);
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
);
3874 inev
.kind
= (bar
->horizontal
? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
3875 : SCROLL_BAR_CLICK_EVENT
);
3881 case HAIKU_SCROLL_BAR_UP_BUTTON
:
3882 inev
.part
= (bar
->horizontal
3883 ? scroll_bar_left_arrow
3884 : scroll_bar_up_arrow
);
3886 case HAIKU_SCROLL_BAR_DOWN_BUTTON
:
3887 inev
.part
= (bar
->horizontal
3888 ? scroll_bar_right_arrow
3889 : scroll_bar_down_arrow
);
3893 XSETINT (inev
.x
, 0);
3894 XSETINT (inev
.y
, 0);
3895 inev
.frame_or_window
= bar
->window
;
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
);
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
));
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
;
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
);
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
))
3948 if (signbit (py
) != signbit (b
->delta_y
))
3952 * powf (scroll_width
, 2.0f
/ 3.0f
));
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
)
3965 XSETINT (inev
.x
, x
);
3966 XSETINT (inev
.y
, y
);
3967 inev
.arg
= list3 (Qnil
, make_float (-px
),
3969 XSETFRAME (inev
.frame_or_window
, f
);
3971 inev
.modifiers
|= (signbit (inev
.kind
== HORIZ_WHEEL_EVENT
3978 if (be_drag_and_drop_in_progress ())
3979 haiku_note_drag_wheel (&inev
);
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
))
3992 if (FRAME_OUTPUT_DATA (f
)->wait_for_event_type
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
);
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
))
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
);
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
))
4033 if (type
== MENU_BAR_OPEN
)
4035 FRAME_OUTPUT_DATA (f
)->menu_bar_open_p
= 1;
4036 popup_activated_p
+= 1;
4040 if (!popup_activated_p
)
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;
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
))
4059 find_and_call_menu_selection (f
, f
->menu_bar_items_used
,
4060 f
->menu_bar_vector
, b
->ptr
);
4063 case MENU_BAR_HELP_EVENT
:
4065 struct haiku_menu_bar_help_event
*b
= buf
;
4067 if (!popup_activated_p
)
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
)
4075 run_menu_bar_help_event (f
, b
->mb_idx
);
4080 struct haiku_zoom_event
*b
= buf
;
4081 struct frame
*f
= haiku_window_to_frame (b
->window
);
4086 if (b
->fullscreen_mode
== FULLSCREEN_MODE_MAXIMIZED
)
4087 f
->want_fullscreen
= FULLSCREEN_NONE
;
4089 f
->want_fullscreen
= FULLSCREEN_MAXIMIZED
;
4091 FRAME_TERMINAL (f
)->fullscreen_hook (f
);
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
);
4101 BMessage_delete (b
->message
);
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
);
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;
4124 case CLIPBOARD_CHANGED_EVENT
:
4125 be_handle_clipboard_changed_message ();
4127 case APP_QUIT_REQUESTED_EVENT
:
4128 inev
.kind
= SAVE_SESSION_EVENT
;
4131 case FONT_CHANGE_EVENT
:
4132 /* This generates CONFIG_CHANGED_EVENTs, which are then
4134 haiku_handle_font_change_event (buf
, &inev
);
4137 case NOTIFICATION_CLICK_EVENT
:
4138 /* This code doesn't function, but the why is unknown. */
4141 struct haiku_notification_click_event
*b
= buf
;
4143 inev
.kind
= NOTIFICATION_CLICKED_EVENT
;
4144 inev
.arg
= make_int (b
->id
);
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
);
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
);
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
);
4188 any_help_event_p
= true;
4189 gen_help_event (help_echo_string
, help_frame
,
4190 help_echo_window
, help_echo_object
,
4195 help_echo_string
= Qnil
;
4196 gen_help_event (Qnil
, help_frame
, Qnil
, Qnil
, 0);
4202 return message_count
;
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
;
4216 XSETFRAME (lisp_focus
, focus
);
4221 haiku_frame_rehighlight (struct frame
*frame
)
4223 haiku_rehighlight ();
4227 haiku_delete_window (struct frame
*f
)
4229 check_window_system (f
);
4230 haiku_free_frame_resources (f
);
4234 haiku_free_pixmap (struct frame
*f
, Emacs_Pixmap pixmap
)
4236 BBitmap_free (pixmap
);
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
;
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
);
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
);
4285 if (EmacsView_double_buffered_p (view
))
4286 haiku_flip_buffers (f
);
4288 /* Keep waiting until past the time wakeup or any input gets
4290 while (!detect_input_pending ())
4292 /* Break if result would not be positive. */
4293 if (wakeup
< system_time ())
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
)
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
);
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
);
4330 if (EmacsView_double_buffered_p (view
))
4331 haiku_flip_buffers (f
);
4335 haiku_beep (struct frame
*f
)
4339 void *view
= FRAME_HAIKU_VIEW (f
);
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
))
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
;
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,
4376 if (!FRAME_OUTPUT_DATA (f
)->configury_done
)
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
;
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
;
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
;
4463 Fset_input_interrupt_mode (Qt
);
4465 dpyinfo
= xzalloc (sizeof *dpyinfo
);
4468 if (port_application_to_emacs
< B_OK
4469 || port_emacs_to_session_manager
< B_OK
)
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,
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
);
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 ();
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
);
4557 Fsetcdr (lval
, val
);
4559 rdb
= Fcons (Fcons (name
, val
), rdb
);
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
);
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
));
4595 BView_SetHighColor (view
, face
->background
);
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
,
4605 BView_EndClip (view
);
4606 BView_draw_unlock (view
);
4612 mark_haiku_display (void)
4616 mark_object (x_display_list
->color_map
);
4617 mark_object (x_display_list
->default_name
);
4622 haiku_scroll_bar_remove (struct scroll_bar
*bar
)
4627 f
= WINDOW_XFRAME (XWINDOW (bar
->window
));
4628 view
= FRAME_HAIKU_DRAWABLE (f
);
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
);
4640 wset_vertical_scroll_bar (XWINDOW (bar
->window
), Qnil
);
4645 haiku_set_offset (struct frame
*frame
, int x
, int y
,
4650 /* Don't allow moving a fullscreen frame: the semantics of that are
4653 XSETFRAME (lframe
, frame
);
4654 if (EQ (Fframe_parameter (lframe
, Qfullscreen
), Qfullboth
)
4655 /* Only do this if the fullscreen status has actually been
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"
4661 && FRAME_OUTPUT_DATA (frame
)->configury_done
)
4664 if (change_gravity
> 0)
4667 frame
->left_pos
= x
;
4668 frame
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4670 frame
->size_hint_flags
|= XNegative
;
4672 frame
->size_hint_flags
|= YNegative
;
4673 frame
->win_gravity
= NorthWestGravity
;
4676 haiku_update_size_hints (frame
);
4680 BWindow_set_offset (FRAME_HAIKU_WINDOW (frame
), x
, y
);
4686 haiku_begin_cr_clip (struct frame
*f
, struct glyph_string
*s
)
4688 cairo_t
*cr
= FRAME_CR_CONTEXT (f
);
4698 haiku_end_cr_clip (cairo_t
*cr
)
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
;
4730 *foreground_out
= foreground
;
4732 *background_out
= background
;
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");
4806 Fprovide (Qhaiku
, Qnil
);
4808 Fprovide (intern_c_string ("cairo"), Qnil
);