Skip to content

Commit 73cd62c

Browse files
committed
fix: miss free switch toggle listener when switch VT
1 parent 0d83025 commit 73cd62c

File tree

2 files changed

+60
-34
lines changed

2 files changed

+60
-34
lines changed

src/config/parse_config.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2780,9 +2780,14 @@ void reapply_keyboard(void) {
27802780
}
27812781

27822782
void reapply_pointer(void) {
2783-
struct input_device *id;
2783+
InputDevice *id;
27842784
struct libinput_device *device;
2785-
wl_list_for_each(id, &pointers, link) {
2785+
wl_list_for_each(id, &inputdevices, link) {
2786+
2787+
if (id->wlr_device->type != WLR_INPUT_DEVICE_POINTER) {
2788+
continue;
2789+
}
2790+
27862791
device = id->libinput_device;
27872792
if (wlr_input_device_is_libinput(id->wlr_device) && device) {
27882793
configure_pointer(device);

src/mango.c

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -195,17 +195,19 @@ typedef struct {
195195
const Arg arg;
196196
} Axis;
197197

198-
struct input_device {
198+
typedef struct {
199199
struct wl_list link;
200200
struct wlr_input_device *wlr_device;
201201
struct libinput_device *libinput_device;
202202
struct wl_listener destroy_listener; // 用于监听设备销毁事件
203-
};
203+
void *device_data; // 新增:指向设备特定数据(如 Switch)
204+
} InputDevice;
204205

205206
typedef struct {
206207
struct wl_list link;
207208
struct wlr_switch *wlr_switch;
208209
struct wl_listener toggle;
210+
InputDevice *input_dev;
209211
} Switch;
210212

211213
struct dwl_animation {
@@ -515,10 +517,9 @@ static void createmon(struct wl_listener *listener, void *data);
515517
static void createnotify(struct wl_listener *listener, void *data);
516518
static void createpointer(struct wlr_pointer *pointer);
517519
static void configure_pointer(struct libinput_device *device);
518-
static void destroypointer(struct wl_listener *listener, void *data);
520+
static void destroyinputdevice(struct wl_listener *listener, void *data);
519521
static void createswitch(struct wlr_switch *switch_device);
520522
static void switch_toggle(struct wl_listener *listener, void *data);
521-
static void cleanupswitches();
522523
static void createpointerconstraint(struct wl_listener *listener, void *data);
523524
static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
524525
static void commitpopup(struct wl_listener *listener, void *data);
@@ -746,8 +747,7 @@ static struct wlr_pointer_constraint_v1 *active_constraint;
746747
static struct wlr_seat *seat;
747748
static KeyboardGroup *kb_group;
748749
static struct wl_list keyboards;
749-
static struct wl_list pointers;
750-
static struct wl_list switches;
750+
static struct wl_list inputdevices;
751751
static unsigned int cursor_mode;
752752
static Client *grabc;
753753
static int grabcx, grabcy; /* client-relative */
@@ -1999,8 +1999,6 @@ void cleanup(void) {
19991999

20002000
dwl_im_relay_finish(dwl_input_method_relay);
20012001

2002-
cleanupswitches();
2003-
20042002
/* If it's not destroyed manually it will cause a use-after-free of
20052003
* wlr_seat. Destroy it until it's fixed in the wlroots side */
20062004
wlr_backend_destroy(backend);
@@ -2697,13 +2695,32 @@ createnotify(struct wl_listener *listener, void *data) {
26972695
LISTEN(&toplevel->events.set_title, &c->set_title, updatetitle);
26982696
}
26992697

2700-
void destroypointer(struct wl_listener *listener, void *data) {
2701-
struct input_device *input_dev =
2698+
void destroyinputdevice(struct wl_listener *listener, void *data) {
2699+
InputDevice *input_dev =
27022700
wl_container_of(listener, input_dev, destroy_listener);
27032701

2702+
// 清理设备特定数据
2703+
if (input_dev->device_data) {
2704+
// 根据设备类型进行特定清理
2705+
switch (input_dev->wlr_device->type) {
2706+
case WLR_INPUT_DEVICE_SWITCH: {
2707+
Switch *sw = (Switch *)input_dev->device_data;
2708+
// 移除 toggle 监听器
2709+
wl_list_remove(&sw->toggle.link);
2710+
// 释放 Switch 内存
2711+
free(sw);
2712+
break;
2713+
}
2714+
// 可以添加其他设备类型的清理代码
2715+
default:
2716+
break;
2717+
}
2718+
input_dev->device_data = NULL;
2719+
}
2720+
27042721
// 从设备列表中移除
27052722
wl_list_remove(&input_dev->link);
2706-
// 移除监听器
2723+
// 移除 destroy 监听器
27072724
wl_list_remove(&input_dev->destroy_listener.link);
27082725
// 释放内存
27092726
free(input_dev);
@@ -2759,14 +2776,14 @@ void createpointer(struct wlr_pointer *pointer) {
27592776
configure_pointer(device);
27602777
}
27612778

2762-
struct input_device *input_dev = calloc(1, sizeof(struct input_device));
2779+
InputDevice *input_dev = calloc(1, sizeof(InputDevice));
27632780
input_dev->wlr_device = &pointer->base;
27642781
input_dev->libinput_device = device;
27652782

2766-
input_dev->destroy_listener.notify = destroypointer;
2783+
input_dev->destroy_listener.notify = destroyinputdevice;
27672784
wl_signal_add(&pointer->base.events.destroy, &input_dev->destroy_listener);
27682785

2769-
wl_list_insert(&pointers, &input_dev->link);
2786+
wl_list_insert(&inputdevices, &input_dev->link);
27702787

27712788
wlr_cursor_attach_input_device(cursor, &pointer->base);
27722789
}
@@ -2792,27 +2809,32 @@ void switch_toggle(struct wl_listener *listener, void *data) {
27922809
}
27932810

27942811
void createswitch(struct wlr_switch *switch_device) {
2812+
struct libinput_device *device =
2813+
wlr_libinput_get_device_handle(&switch_device->base);
2814+
2815+
InputDevice *input_dev = calloc(1, sizeof(InputDevice));
2816+
input_dev->wlr_device = &switch_device->base;
2817+
input_dev->libinput_device = device;
2818+
input_dev->device_data = NULL; // 初始化为 NULL
2819+
2820+
input_dev->destroy_listener.notify = destroyinputdevice;
2821+
wl_signal_add(&switch_device->base.events.destroy,
2822+
&input_dev->destroy_listener);
2823+
2824+
// 创建 Switch 特定数据
27952825
Switch *sw = calloc(1, sizeof(Switch));
27962826
sw->wlr_switch = switch_device;
27972827
sw->toggle.notify = switch_toggle;
2798-
wl_signal_add(&switch_device->events.toggle, &sw->toggle);
2828+
sw->input_dev = input_dev;
27992829

2800-
// 添加到全局列表(可选,用于统一管理)
2801-
wl_list_insert(&switches, &sw->link);
2802-
}
2803-
2804-
void cleanupswitches() {
2805-
Switch *sw, *tmp;
2806-
wl_list_for_each_safe(sw, tmp, &switches, link) {
2807-
// 移除事件监听
2808-
wl_list_remove(&sw->toggle.link);
2830+
// 将 Switch 指针保存到 input_device 中
2831+
input_dev->device_data = sw;
28092832

2810-
// 从列表中移除
2811-
wl_list_remove(&sw->link);
2833+
// 添加 toggle 监听器
2834+
wl_signal_add(&switch_device->events.toggle, &sw->toggle);
28122835

2813-
// 释放内存
2814-
free(sw);
2815-
}
2836+
// 添加到全局列表
2837+
wl_list_insert(&inputdevices, &input_dev->link);
28162838
}
28172839

28182840
void createpointerconstraint(struct wl_listener *listener, void *data) {
@@ -3654,7 +3676,7 @@ void motionabsolute(struct wl_listener *listener, void *data) {
36543676
return;
36553677
}
36563678

3657-
if (!event->time_msec) /* this is 0 with virtual pointers */
3679+
if (!event->time_msec) /* this is 0 with virtual pointer */
36583680
wlr_cursor_warp_absolute(cursor, &event->pointer->base, event->x,
36593681
event->y);
36603682

@@ -4756,8 +4778,7 @@ void setup(void) {
47564778
* to let us know when new input devices are available on the backend.
47574779
*/
47584780
wl_list_init(&keyboards);
4759-
wl_list_init(&pointers);
4760-
wl_list_init(&switches);
4781+
wl_list_init(&inputdevices);
47614782
wl_signal_add(&backend->events.new_input, &new_input_device);
47624783
virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy);
47634784
wl_signal_add(&virtual_keyboard_mgr->events.new_virtual_keyboard,

0 commit comments

Comments
 (0)