rofi  1.7.3
scrollbar.c
Go to the documentation of this file.
1 /*
2  * rofi
3  *
4  * MIT/X11 License
5  * Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  */
27 
28 #include "widgets/scrollbar.h"
29 #include "widgets/icon.h"
30 #include "widgets/listview.h"
31 #include "widgets/textbox.h"
32 #include <glib.h>
33 #include <xkbcommon/xkbcommon.h>
34 
35 #include "theme.h"
36 
38 #define DEFAULT_SCROLLBAR_WIDTH 8
39 
40 static void scrollbar_draw(widget *, cairo_t *);
41 static void scrollbar_free(widget *);
42 
44  G_GNUC_UNUSED const int width) {
45  // Want height we are.
46  return wid->h;
47 }
48 
49 // TODO
50 // This should behave more like a real scrollbar.
51 guint scrollbar_scroll_get_line(const scrollbar *sb, int y) {
52  y -= sb->widget.border.top.base.distance;
53  if (y < 0) {
54  return 0;
55  }
56 
57  if (y > sb->widget.h) {
58  return sb->length - 1;
59  }
60 
61  short r =
62  (sb->length * sb->widget.h) / ((double)(sb->length + sb->pos_length));
63  short handle = sb->widget.h - r;
64  double sec = ((r) / (double)(sb->length - 1));
65  short half_handle = handle / 2;
66  y -= half_handle;
67  y = MIN(MAX(0, y), sb->widget.h - 2 * half_handle);
68 
69  unsigned int sel = ((y) / sec);
70  return MIN(sel, sb->length - 1);
71 }
72 
73 static void scrollbar_scroll(scrollbar *sb, int y) {
76 }
77 
80  G_GNUC_UNUSED gint x, gint y,
81  G_GNUC_UNUSED void *user_data) {
82  scrollbar *sb = (scrollbar *)wid;
83  switch (action) {
84  case MOUSE_CLICK_DOWN:
86  case MOUSE_CLICK_UP:
87  scrollbar_scroll(sb, y);
89  case MOUSE_DCLICK_DOWN:
90  case MOUSE_DCLICK_UP:
91  break;
92  }
93  return FALSE;
94 }
95 
96 static gboolean scrollbar_motion_notify(widget *wid, G_GNUC_UNUSED gint x,
97  gint y) {
98  scrollbar *sb = (scrollbar *)wid;
99  scrollbar_scroll(sb, y);
100  return TRUE;
101 }
102 
103 scrollbar *scrollbar_create(widget *parent, const char *name) {
104  scrollbar *sb = g_malloc0(sizeof(scrollbar));
105  widget_init(WIDGET(sb), parent, WIDGET_TYPE_SCROLLBAR, name);
106  sb->widget.x = 0;
107  sb->widget.y = 0;
108  sb->width = rofi_theme_get_distance(WIDGET(sb), "handle-width",
111  sb->widget.w = widget_padding_get_padding_width(WIDGET(sb)) + width;
113 
114  sb->widget.draw = scrollbar_draw;
115  sb->widget.free = scrollbar_free;
119 
120  sb->length = 10;
121  sb->pos = 0;
122  sb->pos_length = 4;
123 
124  return sb;
125 }
126 
127 static void scrollbar_free(widget *wid) {
128  scrollbar *sb = (scrollbar *)wid;
129  g_free(sb);
130 }
131 
132 void scrollbar_set_max_value(scrollbar *sb, unsigned int max) {
133  if (sb != NULL) {
134  sb->length = MAX(1u, max);
135  }
136 }
137 
138 void scrollbar_set_handle(scrollbar *sb, unsigned int pos) {
139  if (sb != NULL) {
140  sb->pos = MIN(sb->length, pos);
141  }
142 }
143 
144 void scrollbar_set_handle_length(scrollbar *sb, unsigned int pos_length) {
145  if (sb != NULL) {
146  sb->pos_length = MIN(sb->length, MAX(1u, pos_length));
147  }
148 }
149 
162 static void scrollbar_draw(widget *wid, cairo_t *draw) {
163  scrollbar *sb = (scrollbar *)wid;
164  unsigned int wh = widget_padding_get_remaining_height(wid);
165  // Calculate position and size.
166  unsigned int r = (sb->length * wh) / ((double)(sb->length + sb->pos_length));
167  unsigned int handle = wid->h - r;
168  double sec = ((r) / (double)(sb->length - 1));
169  unsigned int height = handle;
170  unsigned int y = sb->pos * sec;
171  // Set max pos.
172  y = MIN(y, wh - handle);
173  // Never go out of bar.
174  height = MAX(2, height);
175  // Cap length;
176  rofi_theme_get_color(WIDGET(sb), "handle-color", draw);
177 
178  cairo_rectangle(draw, widget_padding_get_left(wid),
179  widget_padding_get_top(wid) + y,
181  cairo_fill(draw);
182 }
MouseBindingMouseDefaultAction
Definition: keyb.h:166
@ MOUSE_CLICK_DOWN
Definition: keyb.h:167
@ MOUSE_DCLICK_UP
Definition: keyb.h:170
@ MOUSE_CLICK_UP
Definition: keyb.h:168
@ MOUSE_DCLICK_DOWN
Definition: keyb.h:169
void scrollbar_set_max_value(scrollbar *sb, unsigned int max)
Definition: scrollbar.c:132
scrollbar * scrollbar_create(widget *parent, const char *name)
Definition: scrollbar.c:103
guint scrollbar_scroll_get_line(const scrollbar *sb, int y)
Definition: scrollbar.c:51
void scrollbar_set_handle(scrollbar *sb, unsigned int pos)
Definition: scrollbar.c:138
void scrollbar_set_handle_length(scrollbar *sb, unsigned int pos_length)
Definition: scrollbar.c:144
void listview_set_selected(listview *lv, unsigned int selected)
Definition: listview.c:544
#define WIDGET(a)
Definition: widget.h:119
WidgetTriggerActionResult
Definition: widget.h:76
@ WIDGET_TYPE_SCROLLBAR
Definition: widget.h:66
@ WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_END
Definition: widget.h:84
@ WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_BEGIN
Definition: widget.h:82
@ ROFI_ORIENTATION_HORIZONTAL
Definition: rofi-types.h:139
static void scrollbar_free(widget *)
Definition: scrollbar.c:127
static void scrollbar_scroll(scrollbar *sb, int y)
Definition: scrollbar.c:73
static int scrollbar_get_desired_height(widget *wid, G_GNUC_UNUSED const int width)
Definition: scrollbar.c:43
static void scrollbar_draw(widget *, cairo_t *)
Definition: scrollbar.c:162
#define DEFAULT_SCROLLBAR_WIDTH
Definition: scrollbar.c:38
static gboolean scrollbar_motion_notify(widget *wid, G_GNUC_UNUSED gint x, gint y)
Definition: scrollbar.c:96
static WidgetTriggerActionResult scrollbar_trigger_action(widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x, gint y, G_GNUC_UNUSED void *user_data)
Definition: scrollbar.c:79
RofiDistanceUnit base
Definition: rofi-types.h:129
RofiDistance top
Definition: rofi-types.h:206
RofiDistance width
Definition: scrollbar.h:48
unsigned int pos_length
Definition: scrollbar.h:47
unsigned int length
Definition: scrollbar.h:45
unsigned int pos
Definition: scrollbar.h:46
widget widget
Definition: scrollbar.h:44
void(* free)(struct _widget *widget)
RofiPadding border
widget_trigger_action_cb trigger_action
int(* get_desired_height)(struct _widget *, const int width)
struct _widget * parent
void(* draw)(struct _widget *widget, cairo_t *draw)
gboolean(* motion_notify)(struct _widget *, gint x, gint y)
RofiDistance rofi_theme_get_distance(const widget *widget, const char *property, int def)
Definition: theme.c:865
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
Definition: theme.c:1403
void rofi_theme_get_color(const widget *widget, const char *property, cairo_t *d)
Definition: theme.c:1055
int widget_padding_get_remaining_width(const widget *wid)
Definition: widget.c:617
void widget_init(widget *wid, widget *parent, WidgetType type, const char *name)
Definition: widget.c:34
int widget_padding_get_padding_width(const widget *wid)
Definition: widget.c:635
int widget_padding_get_left(const widget *wid)
Definition: widget.c:574
int widget_padding_get_padding_height(const widget *wid)
Definition: widget.c:629
int widget_padding_get_top(const widget *wid)
Definition: widget.c:596
int widget_padding_get_remaining_height(const widget *wid)
Definition: widget.c:623