From 4c6a4281a41ca2b3ab76339292aac24d8470efe5 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 12 Feb 2022 04:42:42 +0000 Subject: [PATCH] Implement visual bell on Haiku like on X * src/haiku_draw_support.cc (BView_FillRectangleForVisibleBell): Delete function. (BView_InvertRect): New function. * src/haiku_support.cc (class EmacsView): Delete field `visible_bell_color' and visible bell related methods. (EmacsView_do_visible_bell): Delete function. * src/haiku_support.h: Update prototypes. * src/haikuterm.c (haiku_flash): Implement using `BView_InvertRect'. (haiku_beep): Use `haiku_flash' instead. --- src/haiku_draw_support.cc | 7 ++- src/haiku_support.cc | 39 -------------- src/haiku_support.h | 10 ++-- src/haikuterm.c | 104 ++++++++++++++++++++++++++++++++------ 4 files changed, 95 insertions(+), 65 deletions(-) diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc index 270a619b89b..f8df298958f 100644 --- a/src/haiku_draw_support.cc +++ b/src/haiku_draw_support.cc @@ -479,10 +479,9 @@ BView_SetHighColorForVisibleBell (void *view, uint32_t color) } void -BView_FillRectangleForVisibleBell (void *view, int x, int y, int width, int height) +BView_InvertRect (void *view, int x, int y, int width, int height) { - BView *vw = (BView *) view; - BRect rect = BRect (x, y, x + width - 1, y + height - 1); + BView *vw = get_view (view); - vw->FillRect (rect); + vw->InvertRect (BRect (x, y, x + width - 1, y + height - 1)); } diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 71aa323b07f..28bf2ac8b6d 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -1174,7 +1174,6 @@ public: class EmacsView : public BView { public: - uint32_t visible_bell_color = 0; uint32_t previous_buttons = 0; int looper_locked_count = 0; BRegion sb_region; @@ -1313,30 +1312,12 @@ public: } } - void - Pulse (void) - { - visible_bell_color = 0; - SetFlags (Flags () & ~B_PULSE_NEEDED); - Window ()->SetPulseRate (0); - Invalidate (); - } - void Draw (BRect expose_bounds) { struct haiku_expose_event rq; EmacsWindow *w = (EmacsWindow *) Window (); - if (visible_bell_color > 0) - { - PushState (); - BView_SetHighColorForVisibleBell (this, visible_bell_color); - FillRect (Frame ()); - PopState (); - return; - } - if (w->shown_flag && offscreen_draw_view) { PushState (); @@ -1372,18 +1353,6 @@ public: } } - void - DoVisibleBell (uint32_t color) - { - if (!LockLooper ()) - gui_abort ("Failed to lock looper during visible bell"); - visible_bell_color = color | (255 << 24); - SetFlags (Flags () | B_PULSE_NEEDED); - Window ()->SetPulseRate (100 * 1000); - Invalidate (); - UnlockLooper (); - } - void FlipBuffers (void) { @@ -3054,14 +3023,6 @@ be_app_quit (void) } } -/* Temporarily fill VIEW with COLOR. */ -void -EmacsView_do_visible_bell (void *view, uint32_t color) -{ - EmacsView *vw = (EmacsView *) view; - vw->DoVisibleBell (color); -} - /* Zoom WINDOW. */ void BWindow_zoom (void *window) diff --git a/src/haiku_support.h b/src/haiku_support.h index 369a4b6bb45..e50d347009f 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -472,10 +472,6 @@ extern "C" extern void BView_SetHighColorForVisibleBell (void *view, uint32_t color); - extern void - BView_FillRectangleForVisibleBell (void *view, int x, int y, int width, - int height); - extern void BView_SetLowColor (void *view, uint32_t color); @@ -538,6 +534,9 @@ extern "C" int vx, int vy, int vwidth, int vheight, uint32_t color); + extern void + BView_InvertRect (void *view, int x, int y, int width, int height); + extern void * BBitmap_transform_bitmap (void *bitmap, void *mask, uint32_t m_color, double rot, int desw, int desh); @@ -794,9 +793,6 @@ extern "C" extern void c_unbind_to_nil_from_cxx (ptrdiff_t idx); - extern void - EmacsView_do_visible_bell (void *view, uint32_t color); - extern void BWindow_zoom (void *window); diff --git a/src/haikuterm.c b/src/haikuterm.c index 117d8df2e56..3de215bc88b 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -3380,6 +3380,94 @@ haiku_free_pixmap (struct frame *f, Emacs_Pixmap pixmap) BBitmap_free (pixmap); } +static void +haiku_flash (struct frame *f) +{ + /* Get the height not including a menu bar widget. */ + int height = FRAME_PIXEL_HEIGHT (f); + /* Height of each line to flash. */ + int flash_height = FRAME_LINE_HEIGHT (f); + /* These will be the left and right margins of the rectangles. */ + int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f); + int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f); + int width = flash_right - flash_left; + void *view = FRAME_HAIKU_VIEW (f); + struct timespec delay, wakeup, current, timeout; + + delay = make_timespec (0, 150 * 1000 * 1000); + wakeup = timespec_add (current_timespec (), delay); + + BView_draw_lock (view); + BView_StartClip (view); + /* If window is tall, flash top and bottom line. */ + if (height > 3 * FRAME_LINE_HEIGHT (f)) + { + BView_InvertRect (view, flash_left, + (FRAME_INTERNAL_BORDER_WIDTH (f) + + FRAME_TOP_MARGIN_HEIGHT (f)), + width, flash_height); + + BView_InvertRect (view, flash_left, + (height - flash_height + - FRAME_INTERNAL_BORDER_WIDTH (f)), + width, flash_height); + } + else + /* If it is short, flash it all. */ + BView_InvertRect (view, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), + width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); + BView_EndClip (view); + BView_draw_unlock (view); + + flush_frame (f); + + if (EmacsView_double_buffered_p (view)) + haiku_flip_buffers (f); + + /* Keep waiting until past the time wakeup or any input gets + available. */ + while (!detect_input_pending ()) + { + current = current_timespec (); + + /* Break if result would not be positive. */ + if (timespec_cmp (wakeup, current) <= 0) + break; + + /* How long `select' should wait. */ + timeout = make_timespec (0, 10 * 1000 * 1000); + + /* Try to wait that long--but we might wake up sooner. */ + pselect (0, NULL, NULL, NULL, &timeout, NULL); + } + + BView_draw_lock (view); + BView_StartClip (view); + /* If window is tall, flash top and bottom line. */ + if (height > 3 * FRAME_LINE_HEIGHT (f)) + { + BView_InvertRect (view, flash_left, + (FRAME_INTERNAL_BORDER_WIDTH (f) + + FRAME_TOP_MARGIN_HEIGHT (f)), + width, flash_height); + + BView_InvertRect (view, flash_left, + (height - flash_height + - FRAME_INTERNAL_BORDER_WIDTH (f)), + width, flash_height); + } + else + /* If it is short, flash it all. */ + BView_InvertRect (view, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), + width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); + BView_EndClip (view); + BView_draw_unlock (view); + + flush_frame (f); + if (EmacsView_double_buffered_p (view)) + haiku_flip_buffers (f); +} + static void haiku_beep (struct frame *f) { @@ -3389,21 +3477,7 @@ haiku_beep (struct frame *f) if (view) { block_input (); - BView_draw_lock (view); - if (!EmacsView_double_buffered_p (view)) - { - BView_SetHighColorForVisibleBell (view, FRAME_FOREGROUND_PIXEL (f)); - BView_FillRectangleForVisibleBell (view, 0, 0, FRAME_PIXEL_WIDTH (f), - FRAME_PIXEL_HEIGHT (f)); - SET_FRAME_GARBAGED (f); - expose_frame (f, 0, 0, 0, 0); - } - else - { - EmacsView_do_visible_bell (view, FRAME_FOREGROUND_PIXEL (f)); - haiku_flip_buffers (f); - } - BView_draw_unlock (view); + haiku_flash (f); unblock_input (); } } -- 2.39.5