rofi 2.1.0
scrollbar.c
Go to the documentation of this file.
1/*
2 * rofi
3 *
4 * MIT/X11 License
5 * Copyright © 2013-2023 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
34#include "theme.h"
35
36#include <math.h>
37
39#define DEFAULT_SCROLLBAR_WIDTH 8
40
41static void scrollbar_draw(widget *, cairo_t *);
42static void scrollbar_free(widget *);
43
45 G_GNUC_UNUSED const int width) {
46 // Want height we are.
47 return wid->h;
48}
49
50// TODO
51// This should behave more like a real scrollbar.
52guint scrollbar_scroll_get_line(const scrollbar *sb, int y) {
53 y -= sb->widget.border.top.base.distance;
54 if (y < 0) {
55 return 0;
56 }
57
58 if (y > sb->widget.h) {
59 return sb->length - 1;
60 }
61
62 short r =
63 (sb->length * sb->widget.h) / ((double)(sb->length + sb->pos_length));
64 short handle = sb->widget.h - r;
65 double sec = ((r) / (double)(sb->length - 1));
66 short half_handle = handle / 2;
67 y -= half_handle;
68 y = MIN(MAX(0, y), sb->widget.h - 2 * half_handle);
69
70 unsigned int sel = round((y) / sec);
71 return MIN(sel, sb->length - 1);
72}
73
78
81 G_GNUC_UNUSED gint x, gint y,
82 G_GNUC_UNUSED void *user_data) {
83 scrollbar *sb = (scrollbar *)wid;
84 switch (action) {
87 case MOUSE_CLICK_UP:
88 scrollbar_scroll(sb, y);
91 case MOUSE_DCLICK_UP:
92 break;
93 }
94 return FALSE;
95}
96
97static gboolean scrollbar_motion_notify(widget *wid, G_GNUC_UNUSED gint x,
98 gint y) {
99 scrollbar *sb = (scrollbar *)wid;
100 scrollbar_scroll(sb, y);
101 return TRUE;
102}
103
104scrollbar *scrollbar_create(widget *parent, const char *name) {
105 scrollbar *sb = g_malloc0(sizeof(scrollbar));
106 widget_init(WIDGET(sb), parent, WIDGET_TYPE_SCROLLBAR, name);
107 sb->widget.x = 0;
108 sb->widget.y = 0;
109 sb->width = rofi_theme_get_distance(WIDGET(sb), "handle-width",
114
120
121 sb->length = 10;
122 sb->pos = 0;
123 sb->pos_length = 4;
124
125 return sb;
126}
127
128static void scrollbar_free(widget *wid) {
129 scrollbar *sb = (scrollbar *)wid;
130 g_free(sb);
131}
132
133void scrollbar_set_max_value(scrollbar *sb, unsigned int max) {
134 if (sb != NULL) {
135 sb->length = MAX(1u, max);
136 }
137}
138
139void scrollbar_set_handle(scrollbar *sb, unsigned int pos) {
140 if (sb != NULL) {
141 sb->pos = MIN(sb->length, pos);
142 }
143}
144
145void scrollbar_set_handle_length(scrollbar *sb, unsigned int pos_length) {
146 if (sb != NULL) {
147 sb->pos_length = MIN(sb->length, MAX(1u, pos_length));
148 }
149}
150
163static void scrollbar_draw(widget *wid, cairo_t *draw) {
164 scrollbar *sb = (scrollbar *)wid;
166 // Calculate position and size.
167 double r = (sb->length * wh) / ((double)(sb->length + sb->pos_length));
168 unsigned int handle = wid->h - r;
169 double sec = ((r) / (double)(sb->length - 1));
170 unsigned int height = handle;
171 unsigned int y = sb->pos * sec;
172 // Set max pos.
173 y = MIN(y, wh - handle);
174 // Never go out of bar.
175 height = MAX(2, height);
176 // Cap length;
177 rofi_theme_get_color(WIDGET(sb), "handle-color", draw);
178
179 if (rofi_theme_get_boolean(WIDGET(sb), "handle-rounded-corners", FALSE)) {
180 float x = widget_padding_get_left(wid);
181 float width = widget_padding_get_remaining_width(wid);
182
183 float radius = ((width < height) ? width : height) /
184 2; // Limit radius to prevent overlap
185
186 // Draw rounded rectangle
187 cairo_new_sub_path(draw);
188 cairo_arc(draw, x + width - radius, y + radius, radius, -G_PI_2, 0);
189 cairo_arc(draw, x + width - radius, y + height - radius, radius, 0, G_PI_2);
190 cairo_arc(draw, x + radius, y + height - radius, radius, G_PI_2, G_PI);
191 cairo_arc(draw, x + radius, y + radius, radius, G_PI, 1.5 * G_PI);
192 cairo_close_path(draw);
193
194 cairo_fill(draw);
195 } else {
196 cairo_rectangle(draw, widget_padding_get_left(wid),
197 widget_padding_get_top(wid) + y,
199 cairo_fill(draw);
200 }
201}
MouseBindingMouseDefaultAction
Definition keyb.h:176
@ MOUSE_CLICK_DOWN
Definition keyb.h:177
@ MOUSE_DCLICK_UP
Definition keyb.h:180
@ MOUSE_CLICK_UP
Definition keyb.h:178
@ MOUSE_DCLICK_DOWN
Definition keyb.h:179
void scrollbar_set_max_value(scrollbar *sb, unsigned int max)
Definition scrollbar.c:133
struct _scrollbar scrollbar
scrollbar * scrollbar_create(widget *parent, const char *name)
Definition scrollbar.c:104
guint scrollbar_scroll_get_line(const scrollbar *sb, int y)
Definition scrollbar.c:52
void scrollbar_set_handle(scrollbar *sb, unsigned int pos)
Definition scrollbar.c:139
void scrollbar_set_handle_length(scrollbar *sb, unsigned int pos_length)
Definition scrollbar.c:145
struct _listview listview
Definition listview.h:45
void listview_set_selected(listview *lv, unsigned int selected)
Definition listview.c:651
struct _widget widget
Definition widget.h:49
#define WIDGET(a)
Definition widget.h:117
WidgetTriggerActionResult
Definition widget.h:74
@ WIDGET_TYPE_SCROLLBAR
Definition widget.h:64
@ WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_END
Definition widget.h:82
@ WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_BEGIN
Definition widget.h:80
@ ROFI_ORIENTATION_HORIZONTAL
Definition rofi-types.h:141
static void scrollbar_free(widget *)
Definition scrollbar.c:128
static void scrollbar_scroll(scrollbar *sb, int y)
Definition scrollbar.c:74
static int scrollbar_get_desired_height(widget *wid, G_GNUC_UNUSED const int width)
Definition scrollbar.c:44
static void scrollbar_draw(widget *, cairo_t *)
Definition scrollbar.c:163
#define DEFAULT_SCROLLBAR_WIDTH
Definition scrollbar.c:39
static gboolean scrollbar_motion_notify(widget *wid, G_GNUC_UNUSED gint x, gint y)
Definition scrollbar.c:97
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:80
RofiDistanceUnit base
Definition rofi-types.h:131
RofiDistance top
Definition rofi-types.h:208
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
int(*) get_desired_height(struct _widget *, const int width)
RofiPadding border
void(*) draw(struct _widget *widget, cairo_t *draw)
gboolean(*) motion_notify(struct _widget *, gint x, gint y)
widget_trigger_action_cb trigger_action
void(*) free(struct _widget *widget)
struct _widget * parent
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
Definition theme.c:1404
int rofi_theme_get_boolean(const widget *wid, const char *property, int def)
Definition theme.c:903
RofiDistance rofi_theme_get_distance(const widget *wid, const char *property, int def)
Definition theme.c:877
void rofi_theme_get_color(const widget *wid, const char *property, cairo_t *d)
Definition theme.c:1067
int widget_padding_get_remaining_width(const widget *wid)
Definition widget.c:619
void widget_init(widget *wid, widget *parent, WidgetType type, const char *name)
Definition widget.c:36
int widget_padding_get_padding_width(const widget *wid)
Definition widget.c:637
int widget_padding_get_left(const widget *wid)
Definition widget.c:576
int widget_padding_get_padding_height(const widget *wid)
Definition widget.c:631
int widget_padding_get_top(const widget *wid)
Definition widget.c:598
int widget_padding_get_remaining_height(const widget *wid)
Definition widget.c:625