]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow dragging scroll bar for overscroll on Haiku
authorPo Lu <luangruo@yahoo.com>
Sun, 13 Mar 2022 06:41:58 +0000 (06:41 +0000)
committerPo Lu <luangruo@yahoo.com>
Sun, 13 Mar 2022 06:45:46 +0000 (06:45 +0000)
* src/haiku_support.cc (class EmacsScrollBar): New fields
`in_overscroll', `can_overscroll', `last_overscroll',
`last_reported_overscroll_value' and `max_value'.
(ValueChanged): Make very sure extraneous value are not
generated.
(MouseUp): Clear overscroll if enabled.
(MouseMoved): If overscroll is enabled and dragging downwards
fails to dislodge the maximum value, enable overscrolling.
(BView_scroll_bar_update): New parameter `can_overscroll'
* src/haiku_support.h: Update prototypes.
* src/haikuterm.c (haiku_set_scroll_bar_thumb)
(haiku_set_horizontal_scroll_bar_thumb): Adjust parameters to
scroll bar update functions.
(haiku_read_socket): Take ceiling of bar position if
horizontal.

src/haiku_support.cc
src/haiku_support.h
src/haikuterm.c

index 6b33245f64c09a8f841c4affc5c68732af3e36a0..ecd93dd226a85bd7e04dc0e01b3d7ee75fb6f76b 100644 (file)
@@ -1565,6 +1565,11 @@ public:
 
   /* True if button events should be passed to the parent.  */
   bool handle_button = false;
+  bool in_overscroll = false;
+  bool can_overscroll = false;
+  BPoint last_overscroll;
+  int last_reported_overscroll_value;
+  int max_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 ?
@@ -1580,23 +1585,54 @@ public:
   void
   MessageReceived (BMessage *msg)
   {
-    int32 portion, range;
+    int32 portion, range, dragging, value;
     float proportion;
 
     if (msg->what == SCROLL_BAR_UPDATE)
       {
-       old_value = msg->GetInt32 ("emacs:units", 0);
        portion = msg->GetInt32 ("emacs:portion", 0);
        range = msg->GetInt32 ("emacs:range", 0);
+       dragging = msg->GetInt32 ("emacs:dragging", 0);
        proportion = (float) portion / range;
+       value = msg->GetInt32 ("emacs:units", 0);
+       can_overscroll = msg->GetBool ("emacs:overscroll", false);
+       value = std::max (0, value);
 
-       if (!msg->GetBool ("emacs:dragging", false))
+       if (dragging != 1)
          {
-           /* Unlike on Motif, PORTION isn't included in the total
-              range of the scroll bar.  */
-           this->SetRange (0, range - portion);
-           this->SetValue (old_value);
-           this->SetProportion (proportion);
+           if (in_overscroll || dragging != -1)
+             {
+               /* Set the value to the smallest possible one.
+                  Otherwise, the call to SetRange could lead to
+                  spurious updates.  */
+               old_value = 0;
+               SetValue (0);
+
+               /* Unlike on Motif, PORTION isn't included in the total
+                  range of the scroll bar.  */
+
+               SetRange (0, range - portion);
+               SetProportion (proportion);
+               max_value = range - portion;
+
+               if (in_overscroll || value > max_value)
+                 value = max_value;
+
+               old_value = roundf (value);
+               SetValue (old_value);
+             }
+           else
+             {
+               value = Value ();
+
+               old_value = 0;
+               SetValue (0);
+               SetRange (0, range - portion);
+               SetProportion (proportion);
+               old_value = value;
+               SetValue (value);
+               max_value = range - portion;
+             }
          }
       }
 
@@ -1609,6 +1645,8 @@ public:
     struct haiku_scroll_bar_value_event rq;
     struct haiku_scroll_bar_part_event part;
 
+    new_value = Value ();
+
     if (dragging)
       {
        if (new_value != old_value)
@@ -1781,6 +1819,8 @@ public:
     struct haiku_scroll_bar_drag_event rq;
     BView *parent;
 
+    in_overscroll = false;
+
     if (handle_button)
       {
        handle_button = false;
@@ -1804,7 +1844,13 @@ public:
   MouseMoved (BPoint point, uint32 transit, const BMessage *msg)
   {
     struct haiku_menu_bar_left_event rq;
+    struct haiku_scroll_bar_value_event value_event;
+    int range, diff, value, trough_size;
+    BRect bounds;
     BPoint conv;
+    uint32 buttons;
+
+    GetMouse (NULL, &buttons, false);
 
     if (transit == B_EXITED_VIEW)
       {
@@ -1821,6 +1867,61 @@ public:
          }
       }
 
+    if (in_overscroll)
+      {
+       diff = point.y - last_overscroll.y;
+
+       if (diff < 0)
+         {
+           in_overscroll = false;
+           goto allow;
+         }
+
+       range = max_value;
+       bounds = Bounds ();
+       bounds.InsetBy (1.0, 1.0);
+       value = Value ();
+       trough_size = BE_RECT_HEIGHT (bounds);
+       trough_size -= BE_RECT_WIDTH (bounds) / 2;
+       if (info.double_arrows)
+         trough_size -= BE_RECT_WIDTH (bounds) / 2;
+
+       value += ((double) range / trough_size) * diff * 2;
+
+       if (value != last_reported_overscroll_value)
+         {
+           last_reported_overscroll_value = value;
+           last_overscroll = point;
+
+           value_event.scroll_bar = this;
+           value_event.window = Window ();
+           value_event.position = value;
+
+           haiku_write (SCROLL_BAR_VALUE_EVENT, &value_event);
+           return;
+         }
+      }
+    else if (can_overscroll && (buttons == B_PRIMARY_MOUSE_BUTTON))
+      {
+       value = Value ();
+
+       if (value >= max_value)
+         {
+           BScrollBar::MouseMoved (point, transit, msg);
+
+           if (value == Value () && Proportion () < 1.0f)
+             {
+               in_overscroll = true;
+               last_overscroll = point;
+               last_reported_overscroll_value = value;
+
+               MouseMoved (point, transit, msg);
+               return;
+             }
+         }
+      }
+
+  allow:
     BScrollBar::MouseMoved (point, transit, msg);
   }
 };
@@ -2314,9 +2415,13 @@ BView_move_frame (void *view, int x, int y, int x1, int y1)
   vw->UnlockLooper ();
 }
 
+/* DRAGGING can either be 0 (which means to update everything), 1
+   (which means to update nothing), or -1 (which means to update only
+   the thumb size and range).  */
+
 void
 BView_scroll_bar_update (void *sb, int portion, int whole, int position,
-                        bool dragging)
+                        int dragging, bool can_overscroll)
 {
   BScrollBar *bar = (BScrollBar *) sb;
   BMessage msg = BMessage (SCROLL_BAR_UPDATE);
@@ -2324,7 +2429,8 @@ BView_scroll_bar_update (void *sb, int portion, int whole, int position,
   msg.AddInt32 ("emacs:range", whole);
   msg.AddInt32 ("emacs:units", position);
   msg.AddInt32 ("emacs:portion", portion);
-  msg.AddBool ("emacs:dragging", dragging);
+  msg.AddInt32 ("emacs:dragging", dragging);
+  msg.AddBool ("emacs:overscroll", can_overscroll);
 
   mr.SendMessage (&msg);
 }
index e7c55d4d75896946701f73953be9a706864fb34f..8b21fafad73431154d777d6ed6ab0377e4449e6b 100644 (file)
@@ -629,7 +629,7 @@ extern "C"
 
   extern void
   BView_scroll_bar_update (void *sb, int portion, int whole, int position,
-                          bool dragging);
+                          int dragging, bool can_overscroll);
 
   extern int
   BScrollBar_default_size (int horizontal_p);
index cd0dcb083422ac2b0717f970a3c01501d44aa395..c98ab13e1a90c43c5b97fd4c4a45f1766175cb9a 100644 (file)
@@ -485,7 +485,10 @@ haiku_set_scroll_bar_thumb (struct scroll_bar *bar, int portion,
     }
 
   BView_scroll_bar_update (scroll_bar, lrint (size),
-                          BE_SB_MAX, ceil (value), bar->dragging);
+                          BE_SB_MAX, ceil (value),
+                          (scroll_bar_adjust_thumb_portion_p
+                           ? bar->dragging : bar->dragging ? -1 : 0),
+                          !scroll_bar_adjust_thumb_portion_p);
 }
 
 static void
@@ -505,7 +508,7 @@ haiku_set_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion,
     bar->page_size = size;
 
   BView_scroll_bar_update (scroll_bar, lrint (size), BE_SB_MAX,
-                          ceil (value), bar->dragging);
+                          ceil (value), bar->dragging, false);
 }
 
 static struct scroll_bar *
@@ -3282,8 +3285,8 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
 
                if (bar->horizontal)
                  {
-                   portion = bar->total * ((float) b->position
-                                           / BE_SB_MAX);
+                   portion = bar->total * ceil ((double) b->position
+                                                / BE_SB_MAX);
                    whole = (bar->total
                             * ((float) (BE_SB_MAX - bar->page_size)
                                / BE_SB_MAX));