From 974c44414a1bd3dced0f77ce65c60a41e0f25a1a Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 26 Feb 2022 06:56:31 +0000 Subject: [PATCH] Improve scroll bar button handling on Haiku * src/haiku_io.c (haiku_len): Add `SCROLL_BAR_PART_EVENT'. * src/haiku_support.cc (class EmacsScrollBar): New fields `dragging' and `current_state', along with `old_value' and `current_part'. (EmacsScrollBar): Set horizontal flag to `horizontal_p'. (MessageReceived): Set old_value when receiving SCROLL_BAR_UPDATE message. (ValueChanged): Don't allow scroll bar values to change while dragging. (MouseUp, MouseDown): Calculate button under mouse and act accordingly. * src/haiku_support.h (enum haiku_event_type): New event `SCROLL_BAR_PART_EVENT'. (enum haiku_scroll_bar_part): New enumerator. (struct haiku_scroll_bar_part_event): New struct. * src/haikuterm.c (haiku_read_socket): Handle SCROLL_BAR_PART_EVENTs. --- src/haiku_io.c | 2 + src/haiku_support.cc | 121 +++++++++++++++++++++++++++++++++++++++++++ src/haiku_support.h | 13 +++++ src/haikuterm.c | 26 ++++++++++ 4 files changed, 162 insertions(+) diff --git a/src/haiku_io.c b/src/haiku_io.c index cade69f3387..ff684df4337 100644 --- a/src/haiku_io.c +++ b/src/haiku_io.c @@ -98,6 +98,8 @@ haiku_len (enum haiku_event_type type) return sizeof (struct haiku_dummy_event); case MENU_BAR_LEFT: return sizeof (struct haiku_menu_bar_left_event); + case SCROLL_BAR_PART_EVENT: + return sizeof (struct haiku_scroll_bar_part_event); } emacs_abort (); diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 43b996b7959..ab33e38dc70 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -1558,6 +1558,10 @@ class EmacsScrollBar : public BScrollBar { public: void *scroll_bar; + int dragging = 0; + bool horizontal; + enum haiku_scroll_bar_part current_part; + float old_value; EmacsScrollBar (int x, int y, int x1, int y1, bool horizontal_p) : BScrollBar (BRect (x, y, x1, y1), NULL, NULL, 0, 0, horizontal_p ? @@ -1565,6 +1569,7 @@ public: { BView *vw = (BView *) this; vw->SetResizingMode (B_FOLLOW_NONE); + horizontal = horizontal_p; } void @@ -1572,6 +1577,7 @@ public: { if (msg->what == SCROLL_BAR_UPDATE) { + old_value = msg->GetInt32 ("emacs:units", 0); this->SetRange (0, msg->GetInt32 ("emacs:range", 0)); this->SetValue (msg->GetInt32 ("emacs:units", 0)); } @@ -1583,20 +1589,133 @@ public: ValueChanged (float new_value) { struct haiku_scroll_bar_value_event rq; + struct haiku_scroll_bar_part_event part; + + if (dragging) + { + if (new_value != old_value) + { + if (dragging > 1) + { + SetValue (old_value); + + part.scroll_bar = scroll_bar; + part.part = current_part; + haiku_write (SCROLL_BAR_PART_EVENT, &part); + } + else + dragging++; + } + + return; + } + rq.scroll_bar = scroll_bar; rq.position = new_value; haiku_write (SCROLL_BAR_VALUE_EVENT, &rq); } + BRegion + ButtonRegionFor (enum haiku_scroll_bar_part button) + { + BRegion region; + BRect bounds; + BRect rect; + float button_size; + scroll_bar_info info; + + get_scroll_bar_info (&info); + + bounds = Bounds (); + bounds.InsetBy (0.0, 0.0); + + if (horizontal) + button_size = bounds.Height () + 1.0f; + else + button_size = bounds.Width () + 1.0f; + + rect = BRect (bounds.left, bounds.top, + bounds.left + button_size - 1.0f, + bounds.top + button_size - 1.0f); + + if (button == HAIKU_SCROLL_BAR_UP_BUTTON) + { + if (!horizontal) + { + region.Include (rect); + if (info.double_arrows) + region.Include (rect.OffsetToCopy (bounds.left, + bounds.bottom - 2 * button_size + 1)); + } + else + { + region.Include (rect); + if (info.double_arrows) + region.Include (rect.OffsetToCopy (bounds.right - 2 * button_size, + bounds.top)); + } + } + else + { + if (!horizontal) + { + region.Include (rect.OffsetToCopy (bounds.left, bounds.bottom - button_size)); + + if (info.double_arrows) + region.Include (rect.OffsetByCopy (0.0, button_size)); + } + else + { + region.Include (rect.OffsetToCopy (bounds.right - button_size, bounds.top)); + + if (info.double_arrows) + region.Include (rect.OffsetByCopy (button_size, 0.0)); + } + } + + return region; + } + void MouseDown (BPoint pt) { struct haiku_scroll_bar_drag_event rq; + struct haiku_scroll_bar_part_event part; + BRegion r; + + r = ButtonRegionFor (HAIKU_SCROLL_BAR_UP_BUTTON); + + if (r.Contains (pt)) + { + part.scroll_bar = scroll_bar; + part.part = HAIKU_SCROLL_BAR_UP_BUTTON; + dragging = 1; + current_part = HAIKU_SCROLL_BAR_UP_BUTTON; + + haiku_write (SCROLL_BAR_PART_EVENT, &part); + goto out; + } + + r = ButtonRegionFor (HAIKU_SCROLL_BAR_DOWN_BUTTON); + + if (r.Contains (pt)) + { + part.scroll_bar = scroll_bar; + part.part = HAIKU_SCROLL_BAR_DOWN_BUTTON; + dragging = 1; + current_part = HAIKU_SCROLL_BAR_DOWN_BUTTON; + + haiku_write (SCROLL_BAR_PART_EVENT, &part); + goto out; + } + rq.dragging_p = 1; rq.scroll_bar = scroll_bar; haiku_write (SCROLL_BAR_DRAG_EVENT, &rq); + + out: BScrollBar::MouseDown (pt); } @@ -1608,6 +1727,8 @@ public: rq.scroll_bar = scroll_bar; haiku_write (SCROLL_BAR_DRAG_EVENT, &rq); + dragging = false; + BScrollBar::MouseUp (pt); } diff --git a/src/haiku_support.h b/src/haiku_support.h index 4de71075c0e..714cb18ae79 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -76,6 +76,7 @@ enum haiku_event_type ICONIFICATION, MOVE_EVENT, SCROLL_BAR_VALUE_EVENT, + SCROLL_BAR_PART_EVENT, SCROLL_BAR_DRAG_EVENT, WHEEL_MOVE_EVENT, MENU_BAR_RESIZE, @@ -304,6 +305,18 @@ struct haiku_scroll_bar_drag_event int dragging_p; }; +enum haiku_scroll_bar_part + { + HAIKU_SCROLL_BAR_UP_BUTTON, + HAIKU_SCROLL_BAR_DOWN_BUTTON + }; + +struct haiku_scroll_bar_part_event +{ + void *scroll_bar; + enum haiku_scroll_bar_part part; +}; + struct haiku_menu_bar_resize_event { void *window; diff --git a/src/haikuterm.c b/src/haikuterm.c index 5e2259e49a8..badc3f5801d 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -3150,6 +3150,32 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) } break; } + case SCROLL_BAR_PART_EVENT: + { + struct haiku_scroll_bar_part_event *b = buf; + struct scroll_bar *bar = b->scroll_bar; + + inev.kind = (bar->horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT + : SCROLL_BAR_CLICK_EVENT); + + bar->dragging = 0; + + switch (b->part) + { + case HAIKU_SCROLL_BAR_UP_BUTTON: + inev.part = scroll_bar_up_arrow; + break; + case HAIKU_SCROLL_BAR_DOWN_BUTTON: + inev.part = scroll_bar_down_arrow; + break; + } + + XSETINT (inev.x, 0); + XSETINT (inev.y, 0); + inev.frame_or_window = bar->window; + + break; + } case SCROLL_BAR_DRAG_EVENT: { struct haiku_scroll_bar_drag_event *b = buf; -- 2.39.5