From b4fce75270a75d91280b5ebf0b8d07652d3d7961 Mon Sep 17 00:00:00 2001 From: sqooky! Date: Wed, 10 Sep 2025 13:23:26 -0400 Subject: [PATCH 1/6] feat: tablet support --- src/ext-protocol/all.h | 3 +- src/ext-protocol/tablet.h | 230 ++++++++++++++++++++++++++++++++++++++ src/mango.c | 31 +++-- 3 files changed, 255 insertions(+), 9 deletions(-) create mode 100644 src/ext-protocol/tablet.h diff --git a/src/ext-protocol/all.h b/src/ext-protocol/all.h index 0103248b..1ec7407e 100644 --- a/src/ext-protocol/all.h +++ b/src/ext-protocol/all.h @@ -1,4 +1,5 @@ #include "dwl-ipc.h" #include "ext-workspace.h" #include "foreign-toplevel.h" -#include "text-input.h" \ No newline at end of file +#include "tablet.h" +#include "text-input.h" diff --git a/src/ext-protocol/tablet.h b/src/ext-protocol/tablet.h new file mode 100644 index 00000000..79580818 --- /dev/null +++ b/src/ext-protocol/tablet.h @@ -0,0 +1,230 @@ +#include +#include +#include + +static const int tabletmaptosurface = + 0; /* map tablet input to surface(1) or monitor(0) */ + +static void createtablet(struct wlr_input_device *device); +static void destroytablet(struct wl_listener *listener, void *data); +static void destroytabletsurfacenotify(struct wl_listener *listener, + void *data); +static void destroytablettool(struct wl_listener *listener, void *data); + +static void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, + bool change_x, bool change_y, double x, double y, + double dx, double dy); +static void tablettoolproximity(struct wl_listener *listener, void *data); +static void tablettoolaxis(struct wl_listener *listener, void *data); +static void tablettoolbutton(struct wl_listener *listener, void *data); +static void tablettooltip(struct wl_listener *listener, void *data); +static struct wlr_tablet_manager_v2 *tablet_mgr; +static struct wlr_tablet_v2_tablet *tablet = NULL; +static struct wlr_tablet_v2_tablet_tool *tablet_tool = NULL; +static struct wlr_tablet_v2_tablet_pad *tablet_pad = NULL; +static struct wlr_surface *tablet_curr_surface = NULL; +static struct wl_listener destroy_tablet_surface_listener = { + .notify = destroytabletsurfacenotify}; +static struct wl_listener tablet_device_destroy = {.notify = destroytablet}; +static struct wl_listener tablet_tool_axis = {.notify = tablettoolaxis}; +static struct wl_listener tablet_tool_button = {.notify = tablettoolbutton}; +static struct wl_listener tablet_tool_destroy = {.notify = destroytablettool}; +static struct wl_listener tablet_tool_proximity = {.notify = + tablettoolproximity}; +static struct wl_listener tablet_tool_tip = {.notify = tablettooltip}; + +void createtablet(struct wlr_input_device *device) { + if (!tablet) { + struct libinput_device *device_handle = NULL; + if (!wlr_input_device_is_libinput(device) || + !(device_handle = wlr_libinput_get_device_handle(device))) + return; + + tablet = wlr_tablet_create(tablet_mgr, seat, device); + wl_signal_add(&tablet->wlr_device->events.destroy, + &tablet_device_destroy); + if (libinput_device_config_send_events_get_modes(device_handle)) { + libinput_device_config_send_events_set_mode(device_handle, + send_events_mode); + wlr_cursor_attach_input_device(cursor, device); + } + } else if (device == tablet->wlr_device) { + wlr_log(WLR_ERROR, "createtablet: duplicate device"); + } else { + wlr_log(WLR_ERROR, "createtablet: already have one tablet"); + } +} + +void destroytablet(struct wl_listener *listener, void *data) { tablet = NULL; } + +void destroytabletsurfacenotify(struct wl_listener *listener, void *data) { + if (tablet_curr_surface) + wl_list_remove(&destroy_tablet_surface_listener.link); + tablet_curr_surface = NULL; +} + +void destroytablettool(struct wl_listener *listener, void *data) { + destroytabletsurfacenotify(NULL, NULL); + tablet_tool = NULL; +} + +void tabletapplymap(double tablet_width, double tablet_height, + struct wlr_fbox box, double *x, double *y) +{ + if ((!box.x && !box.y && !box.width && !box.height) + || !tablet_width || !tablet_height) { + return; + } + + if (!box.width) { + box.width = tablet_width - box.x; + } + if (!box.height) { + box.height = tablet_height - box.y; + } + + if (box.x + box.width <= tablet_width) { + const double max_x = 1; + double width_offset = max_x * box.x / tablet_width; + *x = (*x - width_offset) * tablet_width / box.width; + } + if (box.y + box.height <= tablet_height) { + const double max_y = 1; + double height_offset = max_y * box.y / tablet_height; + *y = (*y - height_offset) * tablet_height / box.height; + } +} + +void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, + bool change_y, double x, double y, double dx, double dy) { + struct wlr_surface *surface = NULL; + double sx, sy; + + if (!change_x && !change_y) + return; + + tabletapplymap(tablet->wlr_tablet->width_mm, tablet->wlr_tablet->height_mm, + (struct wlr_fbox){0}, &x, &y); + + // TODO: apply constraints + switch (tablet_tool->wlr_tool->type) { + case WLR_TABLET_TOOL_TYPE_LENS: + case WLR_TABLET_TOOL_TYPE_MOUSE: + wlr_cursor_move(cursor, tablet->wlr_device, dx, dy); + break; + default: + wlr_cursor_warp_absolute(cursor, tablet->wlr_device, change_x ? x : NAN, + change_y ? y : NAN); + break; + } + + motionnotify(0, NULL, 0, 0, 0, 0); + + xytonode(cursor->x, cursor->y, &surface, NULL, NULL, &sx, &sy); + if (surface && !wlr_surface_accepts_tablet_v2(surface, tablet)) + surface = NULL; + + if (surface != tablet_curr_surface) { + if (tablet_curr_surface) { + // TODO: wait until all buttons released before leaving + if (tablet_tool) + wlr_tablet_v2_tablet_tool_notify_proximity_out(tablet_tool); + if (tablet_pad) + wlr_tablet_v2_tablet_pad_notify_leave(tablet_pad, + tablet_curr_surface); + wl_list_remove(&destroy_tablet_surface_listener.link); + } + if (surface) { + if (tablet_pad) + wlr_tablet_v2_tablet_pad_notify_enter(tablet_pad, tablet, + surface); + if (tablet_tool) + wlr_tablet_v2_tablet_tool_notify_proximity_in(tablet_tool, + tablet, surface); + wl_signal_add(&surface->events.destroy, + &destroy_tablet_surface_listener); + } + tablet_curr_surface = surface; + } + + if (surface) + wlr_tablet_v2_tablet_tool_notify_motion(tablet_tool, sx, sy); +} + +void tablettoolproximity(struct wl_listener *listener, void *data) { + struct wlr_tablet_tool_proximity_event *event = data; + struct wlr_tablet_tool *tool = event->tool; + + if (!tablet_tool) { + tablet_tool = wlr_tablet_tool_create(tablet_mgr, seat, tool); + wl_signal_add(&tablet_tool->wlr_tool->events.destroy, + &tablet_tool_destroy); + wl_signal_add(&tablet_tool->events.set_cursor, &request_cursor); + } + + switch (event->state) { + case WLR_TABLET_TOOL_PROXIMITY_OUT: + wlr_tablet_v2_tablet_tool_notify_proximity_out(tablet_tool); + destroytabletsurfacenotify(NULL, NULL); + break; + case WLR_TABLET_TOOL_PROXIMITY_IN: + tablettoolmotion(tablet_tool, true, true, event->x, event->y, 0, 0); + break; + } +} + +void tablettoolaxis(struct wl_listener *listener, void *data) { + struct wlr_tablet_tool_axis_event *event = data; + + tablettoolmotion(tablet_tool, event->updated_axes & WLR_TABLET_TOOL_AXIS_X, + event->updated_axes & WLR_TABLET_TOOL_AXIS_Y, event->x, + event->y, event->dx, event->dy); + + if (event->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE) + wlr_tablet_v2_tablet_tool_notify_pressure(tablet_tool, event->pressure); + if (event->updated_axes & WLR_TABLET_TOOL_AXIS_DISTANCE) + wlr_tablet_v2_tablet_tool_notify_distance(tablet_tool, event->distance); + if (event->updated_axes & + (WLR_TABLET_TOOL_AXIS_TILT_X | WLR_TABLET_TOOL_AXIS_TILT_Y)) { + printf("DEBUGGING: In axis event handling\n"); + wlr_tablet_v2_tablet_tool_notify_tilt(tablet_tool, event->tilt_x, + event->tilt_y); + } + if (event->updated_axes & WLR_TABLET_TOOL_AXIS_ROTATION) + wlr_tablet_v2_tablet_tool_notify_rotation(tablet_tool, event->rotation); + if (event->updated_axes & WLR_TABLET_TOOL_AXIS_SLIDER) + wlr_tablet_v2_tablet_tool_notify_slider(tablet_tool, event->slider); + if (event->updated_axes & WLR_TABLET_TOOL_AXIS_WHEEL) + wlr_tablet_v2_tablet_tool_notify_wheel(tablet_tool, event->wheel_delta, + 0); +} + +void tablettoolbutton(struct wl_listener *listener, void *data) { + struct wlr_tablet_tool_button_event *event = data; + wlr_tablet_v2_tablet_tool_notify_button( + tablet_tool, event->button, + (enum zwp_tablet_pad_v2_button_state)event->state); +} + +void tablettooltip(struct wl_listener *listener, void *data) { + struct wlr_tablet_tool_tip_event *event = data; + + if (!tablet_curr_surface) { + struct wlr_pointer_button_event fakeptrbtnevent = { + .button = BTN_LEFT, + .state = event->state == WLR_TABLET_TOOL_TIP_UP + ? WL_POINTER_BUTTON_STATE_RELEASED + : WL_POINTER_BUTTON_STATE_PRESSED, + .time_msec = event->time_msec, + }; + buttonpress(NULL, (void *)&fakeptrbtnevent); + } + + if (event->state == WLR_TABLET_TOOL_TIP_UP) { + wlr_tablet_v2_tablet_tool_notify_up(tablet_tool); + return; + } + + wlr_tablet_v2_tablet_tool_notify_down(tablet_tool); + wlr_tablet_tool_v2_start_implicit_grab(tablet_tool); +} diff --git a/src/mango.c b/src/mango.c index b5f208ad..db226a00 100644 --- a/src/mango.c +++ b/src/mango.c @@ -68,6 +68,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -3164,6 +3167,12 @@ void inputdevice(struct wl_listener *listener, void *data) { case WLR_INPUT_DEVICE_KEYBOARD: createkeyboard(wlr_keyboard_from_input_device(device)); break; + case WLR_INPUT_DEVICE_TABLET: + createtablet(device); + break; + case WLR_INPUT_DEVICE_TABLET_PAD: + tablet_pad = wlr_tablet_pad_create(tablet_mgr, seat, device); + break; case WLR_INPUT_DEVICE_POINTER: createpointer(wlr_pointer_from_input_device(device)); break; @@ -4629,14 +4638,15 @@ void setup(void) { dpy = wl_display_create(); event_loop = wl_display_get_event_loop(dpy); pointer_manager = wlr_relative_pointer_manager_v1_create(dpy); - /* The backend is a wlroots feature which abstracts the underlying input - * and output hardware. The autocreate option will choose the most - * suitable backend based on the current environment, such as opening an - * X11 window if an X11 server is running. The NULL argument here - * optionally allows you to pass in a custom renderer if wlr_renderer - * doesn't meet your needs. The backend uses the renderer, for example, - * to fall back to software cursors if the backend does not support - * hardware cursors (some older GPUs don't). */ + tablet_mgr = wlr_tablet_v2_create(dpy); + /* The backend is a wlroots feature which abstracts the underlying input and + * output hardware. The autocreate option will choose the most suitable + * backend based on the current environment, such as opening an X11 window + * if an X11 server is running. The NULL argument here optionally allows you + * to pass in a custom renderer if wlr_renderer doesn't meet your needs. The + * backend uses the renderer, for example, to fall back to software cursors + * if the backend does not support hardware cursors (some older GPUs + * don't). */ if (!(backend = wlr_backend_autocreate(event_loop, &session))) die("couldn't create backend"); @@ -4803,6 +4813,11 @@ void setup(void) { wl_signal_add(&cursor->events.button, &cursor_button); wl_signal_add(&cursor->events.axis, &cursor_axis); wl_signal_add(&cursor->events.frame, &cursor_frame); + wl_signal_add(&cursor->events.tablet_tool_proximity, + &tablet_tool_proximity); + wl_signal_add(&cursor->events.tablet_tool_axis, &tablet_tool_axis); + wl_signal_add(&cursor->events.tablet_tool_button, &tablet_tool_button); + wl_signal_add(&cursor->events.tablet_tool_tip, &tablet_tool_tip); // 这两句代码会造成obs窗口里的鼠标光标消失,不知道注释有什么影响 cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); From 92ed929a3c38cc10b453017520592e8f2e500cfa Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 13 Sep 2025 10:14:02 +0800 Subject: [PATCH 2/6] fix: miss remove destroy destroy listener after tablet devece destroy --- src/ext-protocol/tablet.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/ext-protocol/tablet.h b/src/ext-protocol/tablet.h index 79580818..2e1f21eb 100644 --- a/src/ext-protocol/tablet.h +++ b/src/ext-protocol/tablet.h @@ -55,7 +55,10 @@ void createtablet(struct wlr_input_device *device) { } } -void destroytablet(struct wl_listener *listener, void *data) { tablet = NULL; } +void destroytablet(struct wl_listener *listener, void *data) { + wl_list_remove(&listener->link); + tablet = NULL; +} void destroytabletsurfacenotify(struct wl_listener *listener, void *data) { if (tablet_curr_surface) @@ -69,10 +72,9 @@ void destroytablettool(struct wl_listener *listener, void *data) { } void tabletapplymap(double tablet_width, double tablet_height, - struct wlr_fbox box, double *x, double *y) -{ - if ((!box.x && !box.y && !box.width && !box.height) - || !tablet_width || !tablet_height) { + struct wlr_fbox box, double *x, double *y) { + if ((!box.x && !box.y && !box.width && !box.height) || !tablet_width || + !tablet_height) { return; } @@ -104,7 +106,7 @@ void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, return; tabletapplymap(tablet->wlr_tablet->width_mm, tablet->wlr_tablet->height_mm, - (struct wlr_fbox){0}, &x, &y); + (struct wlr_fbox){0}, &x, &y); // TODO: apply constraints switch (tablet_tool->wlr_tool->type) { From eb399526a6a26e29942e5c6162e64f3a1b03eb60 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 20 Oct 2025 17:58:01 +0800 Subject: [PATCH 3/6] opt: make tag animation more consistent --- src/animation/tag.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/animation/tag.h b/src/animation/tag.h index 4110efbe..cd13237d 100644 --- a/src/animation/tag.h +++ b/src/animation/tag.h @@ -9,18 +9,18 @@ void set_tagin_animation(Monitor *m, Client *c) { c->animainit_geom.x = tag_animation_direction == VERTICAL ? c->animation.current.x - : c->mon->m.x + c->mon->m.width; + : c->geom.x + c->mon->m.width; c->animainit_geom.y = tag_animation_direction == VERTICAL - ? c->mon->m.y + c->mon->m.height + ? c->geom.y + c->mon->m.height : c->animation.current.y; } else { c->animainit_geom.x = tag_animation_direction == VERTICAL ? c->animation.current.x - : m->m.x - c->geom.width; + : c->geom.x - c->mon->m.width; c->animainit_geom.y = tag_animation_direction == VERTICAL - ? m->m.y - c->geom.height + ? c->geom.y - c->mon->m.height : c->animation.current.y; } } @@ -54,9 +54,9 @@ void set_tagout_animation(Monitor *m, Client *c) { c->pending = c->geom; c->pending.x = tag_animation_direction == VERTICAL ? c->animation.current.x - : c->mon->m.x - c->geom.width; + : c->geom.x - c->mon->m.width; c->pending.y = tag_animation_direction == VERTICAL - ? c->mon->m.y - c->geom.height + ? c->geom.y - c->mon->m.height : c->animation.current.y; resize(c, c->geom, 0); @@ -64,9 +64,9 @@ void set_tagout_animation(Monitor *m, Client *c) { c->pending = c->geom; c->pending.x = tag_animation_direction == VERTICAL ? c->animation.current.x - : c->mon->m.x + c->mon->m.width; + : c->geom.x + c->mon->m.width; c->pending.y = tag_animation_direction == VERTICAL - ? c->mon->m.y + c->mon->m.height + ? c->geom.y + c->mon->m.height : c->animation.current.y; resize(c, c->geom, 0); } From 9c576518782224d1f0c466efa694314e3a432555 Mon Sep 17 00:00:00 2001 From: David Delarosa Date: Mon, 20 Oct 2025 13:50:43 +0300 Subject: [PATCH 4/6] opt: limit scanf string length to 255 --- src/config/parse_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index d6260c9d..8e509cc2 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -1812,7 +1812,7 @@ void parse_option(Config *config, char *key, char *value) { arg_value[256] = "0\0", arg_value2[256] = "0\0", arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value5[256] = "0\0"; - if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", + if (sscanf(value, "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^\n]", mod_str, keysym_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { fprintf(stderr, "Error: Invalid bind format: %s\n", value); From 754daa68eb3f3432484cd48607c22a0c43917990 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 20 Oct 2025 19:16:36 +0800 Subject: [PATCH 5/6] opt: limit config parse string length to 255 --- src/config/parse_config.h | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 8e509cc2..e4f00b1d 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -1412,14 +1412,6 @@ void parse_option(Config *config, char *key, char *value) { } else { convert_hex_to_rgba(config->overlaycolor, color); } - } else if (strcmp(key, "autostart") == 0) { - if (sscanf(value, "%[^,],%[^,],%[^,]", config->autostart[0], - config->autostart[1], config->autostart[2]) != 3) { - fprintf(stderr, "Error: Invalid autostart format: %s\n", value); - } - trim_whitespace(config->autostart[0]); - trim_whitespace(config->autostart[1]); - trim_whitespace(config->autostart[2]); } else if (strcmp(key, "tagrule") == 0) { config->tag_rules = realloc(config->tag_rules, @@ -1654,7 +1646,7 @@ void parse_option(Config *config, char *key, char *value) { rule->isfullscreen = atoi(val); } else if (strcmp(key, "globalkeybinding") == 0) { char mod_str[256], keysym_str[256]; - sscanf(val, "%[^-]-%[a-zA-Z]", mod_str, keysym_str); + sscanf(val, "%255[^-]-%255[a-zA-Z]", mod_str, keysym_str); trim_whitespace(mod_str); trim_whitespace(keysym_str); rule->globalkeybinding.mod = parse_mod(mod_str); @@ -1736,7 +1728,7 @@ void parse_option(Config *config, char *key, char *value) { } else if (strncmp(key, "env", 3) == 0) { char env_type[256], env_value[256]; - if (sscanf(value, "%[^,],%[^\n]", env_type, env_value) < 2) { + if (sscanf(value, "%255[^,],%255[^\n]", env_type, env_value) < 2) { fprintf(stderr, "Error: Invalid bind format: %s\n", value); return; } @@ -1812,7 +1804,9 @@ void parse_option(Config *config, char *key, char *value) { arg_value[256] = "0\0", arg_value2[256] = "0\0", arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value5[256] = "0\0"; - if (sscanf(value, "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^\n]", + if (sscanf(value, + "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[" + "^,],%255[^\n]", mod_str, keysym_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { fprintf(stderr, "Error: Invalid bind format: %s\n", value); @@ -1883,7 +1877,9 @@ void parse_option(Config *config, char *key, char *value) { arg_value[256] = "0\0", arg_value2[256] = "0\0", arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value5[256] = "0\0"; - if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", + if (sscanf(value, + "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[" + "^,],%255[^\n]", mod_str, button_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { fprintf(stderr, "Error: Invalid mousebind format: %s\n", value); @@ -1942,7 +1938,9 @@ void parse_option(Config *config, char *key, char *value) { arg_value[256] = "0\0", arg_value2[256] = "0\0", arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value5[256] = "0\0"; - if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", + if (sscanf(value, + "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[" + "^,],%255[^\n]", mod_str, dir_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { fprintf(stderr, "Error: Invalid axisbind format: %s\n", value); @@ -2004,7 +2002,9 @@ void parse_option(Config *config, char *key, char *value) { arg_value[256] = "0\0", arg_value2[256] = "0\0", arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value5[256] = "0\0"; - if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", + if (sscanf(value, + "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[" + "^\n]", fold_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { fprintf(stderr, "Error: Invalid switchbind format: %s\n", value); @@ -2061,7 +2061,8 @@ void parse_option(Config *config, char *key, char *value) { arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value5[256] = "0\0"; if (sscanf(value, - "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", + "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[" + "^,],%255[^,],%255[^\n]", mod_str, motion_str, fingers_count_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 4) { fprintf(stderr, "Error: Invalid gesturebind format: %s\n", value); @@ -2116,7 +2117,7 @@ void parse_option(Config *config, char *key, char *value) { void parse_config_line(Config *config, const char *line) { char key[256], value[256]; - if (sscanf(line, "%[^=]=%[^\n]", key, value) != 2) { + if (sscanf(line, "%255[^=]=%255[^\n]", key, value) != 2) { // fprintf(stderr, "Error: Invalid line format: %s\n", line); return; } From 75966db58f59741fda5e355abacfd936ffca334a Mon Sep 17 00:00:00 2001 From: werapi Date: Mon, 20 Oct 2025 19:11:27 +0200 Subject: [PATCH 6/6] fix: ensure tag changes happen on correct monitor --- src/ext-protocol/foreign-toplevel.h | 2 +- src/mango.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ext-protocol/foreign-toplevel.h b/src/ext-protocol/foreign-toplevel.h index fb441351..adfcd21b 100644 --- a/src/ext-protocol/foreign-toplevel.h +++ b/src/ext-protocol/foreign-toplevel.h @@ -25,7 +25,7 @@ void handle_foreign_activate_request(struct wl_listener *listener, void *data) { } target = get_tags_first_tag(c->tags); - view(&(Arg){.ui = target}, true); + view_in_mon(&(Arg){.ui = target}, true, c->mon, true); focusclient(c, 1); wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true); } diff --git a/src/mango.c b/src/mango.c index 218e5024..c9f4bd0c 100644 --- a/src/mango.c +++ b/src/mango.c @@ -5395,7 +5395,7 @@ urgent(struct wl_listener *listener, void *data) { if (focus_on_activate && !c->istagsilent && c != selmon->sel) { if (!(c->mon == selmon && c->tags & c->mon->tagset[c->mon->seltags])) - view(&(Arg){.ui = c->tags}, true); + view_in_mon(&(Arg){.ui = c->tags}, true, c->mon, true); focusclient(c, 1); } else if (c != focustop(selmon)) { if (client_surface(c)->mapped) @@ -5542,7 +5542,7 @@ void activatex11(struct wl_listener *listener, void *data) { if (focus_on_activate && !c->istagsilent && c != selmon->sel) { if (!(c->mon == selmon && c->tags & c->mon->tagset[c->mon->seltags])) - view(&(Arg){.ui = c->tags}, true); + view_in_mon(&(Arg){.ui = c->tags}, true, c->mon, true); wlr_xwayland_surface_activate(c->surface.xwayland, 1); focusclient(c, 1); need_arrange = true;