vw->SetResizingMode (B_FOLLOW_NONE);
horizontal = horizontal_p;
get_scroll_bar_info (&info);
+ SetSteps (5000, 10000);
}
void
MessageReceived (BMessage *msg)
{
+ int32 portion, range;
+
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));
+ portion = msg->GetInt32 ("emacs:portion", 0);
+ range = msg->GetInt32 ("emacs:range", 0);
+
+ if (!msg->GetBool ("emacs:dragging", false))
+ {
+ this->SetRange (0, range);
+ this->SetValue (old_value);
+ this->SetProportion ((float) portion / range);
+ }
}
BScrollBar::MessageReceived (msg);
return;
}
- rq.scroll_bar = this;
- rq.window = Window ();
- rq.position = new_value;
+ if (new_value != old_value)
+ {
+ rq.scroll_bar = this;
+ rq.window = Window ();
+ rq.position = new_value;
+ old_value = new_value;
- haiku_write (SCROLL_BAR_VALUE_EVENT, &rq);
+ haiku_write (SCROLL_BAR_VALUE_EVENT, &rq);
+ }
}
BRegion
}
void
-BView_scroll_bar_update (void *sb, int portion, int whole, int position)
+BView_scroll_bar_update (void *sb, int portion, int whole, int position,
+ bool dragging)
{
BScrollBar *bar = (BScrollBar *) sb;
BMessage msg = BMessage (SCROLL_BAR_UPDATE);
BMessenger mr = BMessenger (bar);
msg.AddInt32 ("emacs:range", whole);
msg.AddInt32 ("emacs:units", position);
+ msg.AddInt32 ("emacs:portion", portion);
+ msg.AddBool ("emacs:dragging", dragging);
mr.SendMessage (&msg);
}
#include <cairo.h>
#endif
+/* Minimum and maximum values used for Haiku scroll bars. */
+#define BE_SB_MAX 10000000
+
struct haiku_display_info *x_display_list = NULL;
extern frame_parm_handler haiku_frame_parm_handlers[];
}
}
+/* Set the thumb size and position of scroll bar BAR. We are
+ currently displaying PORTION out of a whole WHOLE, and our position
+ POSITION. */
+
+static void
+haiku_set_scroll_bar_thumb (struct scroll_bar *bar, int portion,
+ int position, int whole)
+{
+ void *scroll_bar = bar->scroll_bar;
+ float top, shown;
+ int size, value;
+
+ if (scroll_bar_adjust_thumb_portion_p)
+ {
+ /* We use an estimate of 30 chars per line rather than the real
+ `portion' value. This has the disadvantage that the thumb
+ size is not very representative, but it makes our life a lot
+ easier. Otherwise, we have to constantly adjust the thumb
+ size, which we can't always do quickly enough: while
+ dragging, the size of the thumb might prevent the user from
+ dragging the thumb all the way to the end. */
+ portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
+ /* When the thumb is at the bottom, position == whole. So we
+ need to increase `whole' to make space for the thumb. */
+ whole += portion;
+ }
+
+ if (whole <= 0)
+ top = 0, shown = 1;
+ else
+ {
+ top = (float) position / whole;
+ shown = (float) portion / whole;
+ }
+
+ /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
+ is the scroll bar's maximum and MIN is the scroll bar's minimum
+ value. */
+ size = clip_to_bounds (1, shown * BE_SB_MAX, BE_SB_MAX);
+
+ /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
+ value = top * BE_SB_MAX;
+ value = min (value, BE_SB_MAX - size);
+
+ if (!bar->dragging)
+ bar->page_size = size;
+
+ BView_scroll_bar_update (scroll_bar, size, BE_SB_MAX, value,
+ bar->dragging);
+}
+
+static void
+haiku_set_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion,
+ int position, int whole)
+{
+ void *scroll_bar = bar->scroll_bar;
+ float shown, top;
+ int size, value;
+
+ shown = (float) portion / whole;
+ top = (float) position / (whole - portion);
+
+ size = clip_to_bounds (1, shown * BE_SB_MAX, BE_SB_MAX);
+ value = clip_to_bounds (0, top * (BE_SB_MAX - size), BE_SB_MAX - size);
+
+ if (!bar->dragging)
+ bar->page_size = size;
+
+ BView_scroll_bar_update (scroll_bar, shown, BE_SB_MAX, value,
+ bar->dragging);
+}
+
static struct scroll_bar *
haiku_scroll_bar_from_widget (void *scroll_bar, void *window)
{
if (NILP (w->horizontal_scroll_bar))
{
bar = haiku_scroll_bar_create (w, left, top, width, height, true);
- BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
bar->update = position;
bar->position = position;
bar->total = whole;
bar->width = width;
bar->height = height;
}
-
- if (!bar->dragging)
- {
- BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
- BView_invalidate (bar->scroll_bar);
- }
}
+
+ haiku_set_horizontal_scroll_bar_thumb (bar, portion, position, whole);
bar->position = position;
bar->total = whole;
XSETVECTOR (barobj, bar);
if (NILP (w->vertical_scroll_bar))
{
bar = haiku_scroll_bar_create (w, left, top, width, height, false);
- BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
bar->position = position;
bar->total = whole;
}
bar->width = width;
bar->height = height;
}
-
- if (!bar->dragging)
- {
- BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
- bar->update = position;
- BView_invalidate (bar->scroll_bar);
- }
}
+ haiku_set_scroll_bar_thumb (bar, portion, position, whole);
bar->position = position;
bar->total = whole;
struct haiku_scroll_bar_value_event *b = buf;
struct scroll_bar *bar
= haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
+ int portion, whole;
if (!bar)
continue;
if (bar->position != b->position)
{
- inev.kind = bar->horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT :
- SCROLL_BAR_CLICK_EVENT;
+ inev.kind = (bar->horizontal
+ ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT :
+ SCROLL_BAR_CLICK_EVENT);
inev.part = bar->horizontal ?
scroll_bar_horizontal_handle : scroll_bar_handle;
- XSETINT (inev.x, b->position);
- XSETINT (inev.y, bar->total);
+ if (bar->horizontal)
+ {
+ portion = bar->total * ((float) b->position
+ / BE_SB_MAX);
+ whole = (bar->total
+ * ((float) (BE_SB_MAX - bar->page_size)
+ / BE_SB_MAX));
+ portion = min (portion, whole);
+ }
+ else
+ {
+ whole = BE_SB_MAX - bar->page_size;
+ portion = min (b->position, whole);
+ }
+
+ XSETINT (inev.x, portion);
+ XSETINT (inev.y, whole);
XSETWINDOW (inev.frame_or_window, w);
}
break;