mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 10:26:59 +00:00
PR: Fixing settings && Adding a option for cursor scale (#11)
* Adding slider widget * feat: Add mouse cursor scale commands and settings improvement speed * Correct wallpaper scanning and thumbnail loading
This commit is contained in:
@@ -497,3 +497,149 @@ bool widget_checkbox_handle_mouse(widget_checkbox_t *cb, int mx, int my, bool mo
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// --- Slider ---
|
||||
void widget_slider_init(widget_slider_t *sl, int x, int y, int w, int h, float min, float max, float value) {
|
||||
sl->x = x;
|
||||
sl->y = y;
|
||||
sl->w = w;
|
||||
sl->h = h;
|
||||
|
||||
sl->min = min;
|
||||
sl->max = max;
|
||||
sl->value = value;
|
||||
sl->step = 0.0f;
|
||||
|
||||
sl->dragging = false;
|
||||
sl->hovered = false;
|
||||
sl->on_change = NULL;
|
||||
}
|
||||
|
||||
void widget_slider_draw(widget_context_t *ctx, widget_slider_t *sl) {
|
||||
uint32_t track_bg = ctx->use_light_theme ? 0xFFD0D0D0 : 0xFF404040;
|
||||
uint32_t fill_color = ctx->use_light_theme ? 0xFF007AFF : 0xFF4A90E2;
|
||||
uint32_t thumb_color = ctx->use_light_theme ? 0xFF606060 : 0xFFDDDDDD;
|
||||
|
||||
if (sl->dragging) {
|
||||
thumb_color = ctx->use_light_theme ? 0xFF404040 : 0xFFFFFFFF;
|
||||
} else if (sl->hovered) {
|
||||
thumb_color = ctx->use_light_theme ? 0xFF505050 : 0xFFF0F0F0;
|
||||
}
|
||||
|
||||
int track_h = 4;
|
||||
int track_y = sl->y + (sl->h - track_h) / 2;
|
||||
|
||||
float t = (sl->value - sl->min) / (sl->max - sl->min);
|
||||
if (t < 0) t = 0;
|
||||
if (t > 1) t = 1;
|
||||
|
||||
int thumb_x = sl->x + (int)(t * sl->w);
|
||||
|
||||
if (ctx->draw_rounded_rect_filled) {
|
||||
ctx->draw_rounded_rect_filled(ctx->user_data, sl->x, track_y, sl->w, track_h, 2, track_bg);
|
||||
} else {
|
||||
ctx->draw_rect(ctx->user_data, sl->x, track_y, sl->w, track_h, track_bg);
|
||||
}
|
||||
|
||||
if (ctx->draw_rounded_rect_filled) {
|
||||
ctx->draw_rounded_rect_filled(ctx->user_data, sl->x, track_y, thumb_x - sl->x, track_h, 2, fill_color);
|
||||
} else {
|
||||
ctx->draw_rect(ctx->user_data, sl->x, track_y, thumb_x - sl->x, track_h, fill_color);
|
||||
}
|
||||
|
||||
int radius = sl->h / 2;
|
||||
int cx = thumb_x - radius;
|
||||
|
||||
if (ctx->draw_rounded_rect_filled) {
|
||||
ctx->draw_rounded_rect_filled(ctx->user_data, cx, sl->y, sl->h, sl->h, radius, thumb_color);
|
||||
} else {
|
||||
ctx->draw_rect(ctx->user_data, cx, sl->y, sl->h, sl->h, thumb_color);
|
||||
}
|
||||
}
|
||||
|
||||
static float widget_roundf(float x) {
|
||||
return (x >= 0.0f) ? (float)((int)(x + 0.5f)) : (float)((int)(x - 0.5f));
|
||||
}
|
||||
|
||||
bool widget_slider_handle_mouse(widget_slider_t *sl, int mx, int my, bool mouse_down, bool mouse_clicked, void *user_data) {
|
||||
bool in_bounds = (mx >= sl->x && mx < sl->x + sl->w &&
|
||||
my >= sl->y && my < sl->y + sl->h);
|
||||
|
||||
sl->hovered = in_bounds;
|
||||
|
||||
if (mouse_clicked && in_bounds) {
|
||||
sl->dragging = true;
|
||||
}
|
||||
|
||||
if (!mouse_down) {
|
||||
sl->dragging = false;
|
||||
}
|
||||
|
||||
if (sl->dragging) {
|
||||
float t = (float)(mx - sl->x) / (float)sl->w;
|
||||
|
||||
if (t < 0) t = 0;
|
||||
if (t > 1) t = 1;
|
||||
|
||||
float new_value = sl->min + t * (sl->max - sl->min);
|
||||
|
||||
if (sl->step > 0.0f) {
|
||||
new_value = sl->min + widget_roundf((new_value - sl->min) / sl->step) * sl->step;
|
||||
}
|
||||
|
||||
if (new_value != sl->value) {
|
||||
sl->value = new_value;
|
||||
if (sl->on_change) sl->on_change(user_data, sl->value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return in_bounds;
|
||||
}
|
||||
|
||||
static void widget_itoa(int value, char *buf) {
|
||||
int i = 0;
|
||||
int neg = 0;
|
||||
|
||||
if (value == 0) {
|
||||
buf[0] = '0';
|
||||
buf[1] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value < 0) {
|
||||
neg = 1;
|
||||
value = -value;
|
||||
}
|
||||
|
||||
while (value > 0) {
|
||||
buf[i++] = (char)('0' + (value % 10));
|
||||
value /= 10;
|
||||
}
|
||||
|
||||
if (neg) {
|
||||
buf[i++] = '-';
|
||||
}
|
||||
|
||||
buf[i] = 0;
|
||||
|
||||
for (int a = 0, b = i - 1; a < b; a++, b--) {
|
||||
char t = buf[a];
|
||||
buf[a] = buf[b];
|
||||
buf[b] = t;
|
||||
}
|
||||
}
|
||||
|
||||
void widget_slider_draw_value(widget_context_t *ctx, widget_slider_t *sl) {
|
||||
if (!ctx->draw_string) return;
|
||||
|
||||
char buf[16];
|
||||
widget_itoa((int)sl->value, buf);
|
||||
|
||||
ctx->draw_string(ctx->user_data,
|
||||
sl->x + sl->w + 8,
|
||||
sl->y + (sl->h - 8) / 2,
|
||||
buf,
|
||||
ctx->use_light_theme ? 0xFF000000 : 0xFFFFFFFF);
|
||||
}
|
||||
@@ -86,6 +86,29 @@ typedef struct {
|
||||
void (*on_toggle)(void *user_data, bool new_state);
|
||||
} widget_checkbox_t;
|
||||
|
||||
// --- Slider ---
|
||||
typedef struct {
|
||||
int x, y, w, h;
|
||||
|
||||
float min;
|
||||
float max;
|
||||
float value;
|
||||
float step; // 0 = not steps
|
||||
|
||||
bool dragging;
|
||||
bool hovered;
|
||||
|
||||
void (*on_change)(void *user_data, float value);
|
||||
} widget_slider_t;
|
||||
void widget_slider_init(widget_slider_t *sl, int x, int y, int w, int h,
|
||||
float min, float max, float value);
|
||||
|
||||
void widget_slider_draw(widget_context_t *ctx, widget_slider_t *sl);
|
||||
|
||||
bool widget_slider_handle_mouse(widget_slider_t *sl, int mx, int my,
|
||||
bool mouse_down, bool mouse_clicked,
|
||||
void *user_data);
|
||||
|
||||
void widget_checkbox_init(widget_checkbox_t *cb, int x, int y, int w, int h, const char *text, bool is_radio);
|
||||
void widget_checkbox_draw(widget_context_t *ctx, widget_checkbox_t *cb);
|
||||
bool widget_checkbox_handle_mouse(widget_checkbox_t *cb, int mx, int my, bool mouse_clicked, void *user_data);
|
||||
|
||||
102
src/wm/wm.c
102
src/wm/wm.c
@@ -408,9 +408,14 @@ static uint32_t timer_ticks = 0;
|
||||
|
||||
static int last_cursor_x = 400;
|
||||
static int last_cursor_y = 300;
|
||||
static int last_cursor_w = 18;
|
||||
static int last_cursor_h = 18;
|
||||
|
||||
#define CURSOR_W 18
|
||||
#define CURSOR_H 18
|
||||
#define CURSOR_BASE_W 18
|
||||
#define CURSOR_BASE_H 18
|
||||
#define CURSOR_SCALE_MIN_TENTHS 10
|
||||
#define CURSOR_SCALE_MAX_TENTHS 40
|
||||
#define CURSOR_SCALE_DEFAULT_TENTHS 10
|
||||
|
||||
static bool periodic_refresh_pending = false;
|
||||
|
||||
@@ -433,10 +438,62 @@ int desktop_max_cols = 23;
|
||||
|
||||
// Mouse Settings
|
||||
int mouse_speed = 10;
|
||||
static int mouse_cursor_scale_tenths = CURSOR_SCALE_DEFAULT_TENTHS;
|
||||
static int mouse_accum_x = 0;
|
||||
static int mouse_accum_y = 0;
|
||||
Window *active_mouse_capture_win = NULL;
|
||||
|
||||
static int cursor_clamp_scale_tenths(int scale) {
|
||||
if (scale < CURSOR_SCALE_MIN_TENTHS) return CURSOR_SCALE_MIN_TENTHS;
|
||||
if (scale > CURSOR_SCALE_MAX_TENTHS) return CURSOR_SCALE_MAX_TENTHS;
|
||||
return scale;
|
||||
}
|
||||
|
||||
static int cursor_scaled_size(int base, int scale_tenths) {
|
||||
scale_tenths = cursor_clamp_scale_tenths(scale_tenths);
|
||||
return (base * scale_tenths + 9) / 10;
|
||||
}
|
||||
|
||||
static int cursor_width_for_scale(int scale_tenths) {
|
||||
return cursor_scaled_size(CURSOR_BASE_W, scale_tenths);
|
||||
}
|
||||
|
||||
static int cursor_height_for_scale(int scale_tenths) {
|
||||
return cursor_scaled_size(CURSOR_BASE_H, scale_tenths);
|
||||
}
|
||||
|
||||
static int cursor_current_width(void) {
|
||||
return cursor_width_for_scale(mouse_cursor_scale_tenths);
|
||||
}
|
||||
|
||||
static int cursor_current_height(void) {
|
||||
return cursor_height_for_scale(mouse_cursor_scale_tenths);
|
||||
}
|
||||
|
||||
void wm_set_cursor_scale_tenths(int scale) {
|
||||
scale = cursor_clamp_scale_tenths(scale);
|
||||
|
||||
uint64_t rflags = wm_lock_acquire();
|
||||
if (scale != mouse_cursor_scale_tenths) {
|
||||
int old_w = cursor_current_width();
|
||||
int old_h = cursor_current_height();
|
||||
|
||||
mouse_cursor_scale_tenths = scale;
|
||||
|
||||
wm_mark_dirty(last_cursor_x, last_cursor_y, last_cursor_w, last_cursor_h);
|
||||
wm_mark_dirty(mx, my, old_w, old_h);
|
||||
wm_mark_dirty(mx, my, cursor_current_width(), cursor_current_height());
|
||||
}
|
||||
wm_lock_release(rflags);
|
||||
}
|
||||
|
||||
int wm_get_cursor_scale_tenths(void) {
|
||||
uint64_t rflags = wm_lock_acquire();
|
||||
int scale = mouse_cursor_scale_tenths;
|
||||
wm_lock_release(rflags);
|
||||
return scale;
|
||||
}
|
||||
|
||||
// Helper to check if string ends with suffix
|
||||
static bool str_ends_with(const char *str, const char *suffix) {
|
||||
int str_len = 0; while(str[str_len]) str_len++;
|
||||
@@ -2198,7 +2255,7 @@ void draw_window(Window *win) {
|
||||
|
||||
void draw_cursor(int x, int y) {
|
||||
// '.' transparent, 'w' white outline, 'b' black fill
|
||||
static const char cursor_bitmap[CURSOR_H][CURSOR_W + 1] = {
|
||||
static const char cursor_bitmap[CURSOR_BASE_H][CURSOR_BASE_W + 1] = {
|
||||
"w.................",
|
||||
"ww................",
|
||||
"wbw...............",
|
||||
@@ -2216,16 +2273,21 @@ void draw_cursor(int x, int y) {
|
||||
"wwwwbbbw..........",
|
||||
"....wbbw..........",
|
||||
".....wbw..........",
|
||||
"......ww..........."
|
||||
"......ww.........."
|
||||
};
|
||||
|
||||
for (int r = 0; r < CURSOR_H; r++) {
|
||||
for (int c = 0; c < CURSOR_W; c++) {
|
||||
int draw_w = cursor_current_width();
|
||||
int draw_h = cursor_current_height();
|
||||
|
||||
for (int y_off = 0; y_off < draw_h; y_off++) {
|
||||
int r = (y_off * CURSOR_BASE_H) / draw_h;
|
||||
for (int x_off = 0; x_off < draw_w; x_off++) {
|
||||
int c = (x_off * CURSOR_BASE_W) / draw_w;
|
||||
char p = cursor_bitmap[r][c];
|
||||
if (p == 'w') {
|
||||
put_pixel(x + c, y + r, COLOR_WHITE);
|
||||
put_pixel(x + x_off, y + y_off, COLOR_WHITE);
|
||||
} else if (p == 'b') {
|
||||
put_pixel(x + c, y + r, COLOR_BLACK);
|
||||
put_pixel(x + x_off, y + y_off, COLOR_BLACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2239,8 +2301,8 @@ static void erase_cursor(int x, int y) {
|
||||
// Clamp to screen
|
||||
int x1 = x < 0 ? 0 : x;
|
||||
int y1 = y < 0 ? 0 : y;
|
||||
int x2 = x + CURSOR_W > sw ? sw : x + CURSOR_W;
|
||||
int y2 = y + CURSOR_H > sh ? sh : y + CURSOR_H;
|
||||
int x2 = x + cursor_current_width() > sw ? sw : x + cursor_current_width();
|
||||
int y2 = y + cursor_current_height() > sh ? sh : y + cursor_current_height();
|
||||
int w = x2 - x1;
|
||||
int h = y2 - y1;
|
||||
|
||||
@@ -2644,8 +2706,10 @@ void wm_paint(void) {
|
||||
int sh = get_screen_height();
|
||||
uint64_t rflags;
|
||||
rflags = wm_lock_acquire();
|
||||
wm_mark_dirty(last_cursor_x, last_cursor_y, CURSOR_W, CURSOR_H);
|
||||
wm_mark_dirty(mx, my, CURSOR_W, CURSOR_H);
|
||||
int cursor_w = cursor_current_width();
|
||||
int cursor_h = cursor_current_height();
|
||||
wm_mark_dirty(last_cursor_x, last_cursor_y, last_cursor_w, last_cursor_h);
|
||||
wm_mark_dirty(mx, my, cursor_w, cursor_h);
|
||||
|
||||
DirtyRect dirty = graphics_get_dirty_rect();
|
||||
if (menubar_dirty_pending) {
|
||||
@@ -2719,6 +2783,8 @@ void wm_paint(void) {
|
||||
draw_cursor(mx, my);
|
||||
last_cursor_x = mx;
|
||||
last_cursor_y = my;
|
||||
last_cursor_w = cursor_w;
|
||||
last_cursor_h = cursor_h;
|
||||
graphics_flip_buffer();
|
||||
graphics_clear_dirty_no_lock();
|
||||
wm_lock_release(rflags);
|
||||
@@ -3230,8 +3296,10 @@ static void wm_handle_mouse_internal(int dx, int dy, uint8_t buttons, int dz) {
|
||||
if (my >= sh) my = sh - 1;
|
||||
|
||||
if (move_x != 0 || move_y != 0) {
|
||||
wm_mark_dirty(prev_mx, prev_my, CURSOR_W, CURSOR_H);
|
||||
wm_mark_dirty(mx, my, CURSOR_W, CURSOR_H);
|
||||
int cursor_w = cursor_current_width();
|
||||
int cursor_h = cursor_current_height();
|
||||
wm_mark_dirty(prev_mx, prev_my, cursor_w, cursor_h);
|
||||
wm_mark_dirty(mx, my, cursor_w, cursor_h);
|
||||
}
|
||||
|
||||
if (dz != 0) {
|
||||
@@ -3792,8 +3860,10 @@ static void wm_handle_mouse_internal(int dx, int dy, uint8_t buttons, int dz) {
|
||||
|
||||
if (prev_mx != mx || prev_my != my) {
|
||||
// Cursor moved - just mark dirty cursor areas
|
||||
wm_mark_dirty(prev_mx, prev_my, CURSOR_W, CURSOR_H);
|
||||
wm_mark_dirty(mx, my, CURSOR_W, CURSOR_H);
|
||||
int cursor_w = cursor_current_width();
|
||||
int cursor_h = cursor_current_height();
|
||||
wm_mark_dirty(prev_mx, prev_my, cursor_w, cursor_h);
|
||||
wm_mark_dirty(mx, my, cursor_w, cursor_h);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -152,5 +152,7 @@ extern int desktop_max_cols;
|
||||
|
||||
// Mouse Settings
|
||||
extern int mouse_speed;
|
||||
void wm_set_cursor_scale_tenths(int scale);
|
||||
int wm_get_cursor_scale_tenths(void);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user