feat: 统一 current_monitor 切换并让光标跟随 current_monitor 变化
- 新增 wm_set_current_monitor ,切换前记录光标当前所在 monitor 的最后 位置 - 切换到目标 monitor 时按需恢复该 monitor 的光标位置 - 将 action/event/client 中直接赋值 wm.current_monitor 的逻辑改为统一 调用 wm_set_current_monitor - 优化 monitor_restore_cursor_point:首次未初始化时计算并设置位置 - 为 wm_get_monitor_by_area / wm_get_monitor_by_point 增加 returns_nonnull 约束,并让 by_point 复用 by_area
This commit is contained in:
@@ -65,7 +65,7 @@ void raise_or_run(const user_action_arg_t *arg) {
|
||||
if (client && client == wm.client_focused) return;
|
||||
|
||||
if (client) {
|
||||
wm.current_monitor = client->monitor;
|
||||
wm_set_current_monitor(client->monitor);
|
||||
monitor_select_tag(client->monitor, client->tags);
|
||||
client_stack_raise(client);
|
||||
client_focus(client);
|
||||
|
||||
@@ -295,7 +295,7 @@ void client_send_to_monitor(client_t *client, monitor_t *monitor) {
|
||||
client->tags = monitor->selected_tag->mask;
|
||||
client_add_to_tag(client, monitor->selected_tag);
|
||||
|
||||
wm.current_monitor = monitor;
|
||||
wm_set_current_monitor(monitor);
|
||||
monitor_arrange(m);
|
||||
monitor_arrange(monitor);
|
||||
monitor_draw_bar(m);
|
||||
@@ -607,7 +607,7 @@ void client_apply_rules(client_t *client, const rule_t rules[],
|
||||
client->tags = t->mask;
|
||||
|
||||
if (r->switch_to_tag) {
|
||||
wm.current_monitor = m;
|
||||
wm_set_current_monitor(m);
|
||||
m->selected_tag = t;
|
||||
|
||||
logger("++ switch to tag: %u\n", t->index);
|
||||
|
||||
@@ -34,7 +34,7 @@ static void button_press(xcb_button_press_event_t *ev) {
|
||||
|
||||
if (!monitor) return;
|
||||
|
||||
wm.current_monitor = monitor;
|
||||
wm_set_current_monitor(monitor);
|
||||
if (ev->event_x >= monitor->tag_extent.start &&
|
||||
ev->event_x <= monitor->tag_extent.end) {
|
||||
click_area = click_tag;
|
||||
@@ -188,7 +188,7 @@ static void client_message(xcb_client_message_event_t *ev) {
|
||||
|
||||
switch (ev->data.data32[0]) {
|
||||
case 2: /* 来自 pager */
|
||||
wm.current_monitor = c->monitor;
|
||||
wm_set_current_monitor(c->monitor);
|
||||
monitor_select_tag(c->monitor, t->mask);
|
||||
client_focus(c);
|
||||
break;
|
||||
|
||||
@@ -361,14 +361,13 @@ void monitor_save_cursor_point(monitor_t *monitor) {
|
||||
}
|
||||
|
||||
void monitor_restore_cursor_point(monitor_t *monitor) {
|
||||
if (monitor->position_inited) {
|
||||
xcursor_set_pointer_position(monitor->cursor_position);
|
||||
return;
|
||||
if (!monitor->position_inited) {
|
||||
point_t point = xcursor_query_pointer_position();
|
||||
monitor_t *m = wm_get_monitor_by_point(point);
|
||||
monitor->cursor_position.x = point.x - m->geometry.x + monitor->geometry.x;
|
||||
monitor->cursor_position.y = point.y - m->geometry.y + monitor->geometry.y;
|
||||
monitor->position_inited = true;
|
||||
}
|
||||
|
||||
point_t point = xcursor_query_pointer_position();
|
||||
monitor_t *m = wm_get_monitor_by_point(point);
|
||||
monitor->cursor_position.x = point.x - m->geometry.x + monitor->geometry.x;
|
||||
monitor->cursor_position.y = point.y - m->geometry.y + monitor->geometry.y;
|
||||
monitor->position_inited = true;
|
||||
xcursor_set_pointer_position(monitor->cursor_position);
|
||||
}
|
||||
|
||||
32
src/wm.c
32
src/wm.c
@@ -517,6 +517,20 @@ void wm_restack_clients(void) {
|
||||
xcb_flush(wm.xcb_conn);
|
||||
}
|
||||
|
||||
void wm_set_current_monitor(monitor_t *monitor) {
|
||||
if (!monitor || wm.current_monitor == monitor) return;
|
||||
|
||||
point_t point = xcursor_query_pointer_position();
|
||||
monitor_t *point_monitor = wm_get_monitor_by_point(point);
|
||||
point_monitor->cursor_position = point;
|
||||
point_monitor->position_inited = true;
|
||||
|
||||
wm.current_monitor = monitor;
|
||||
if (point_monitor != monitor) {
|
||||
monitor_restore_cursor_point(monitor);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int intersect(area_t area, monitor_t *m) {
|
||||
return MAX(0, MIN(area.x + area.width, m->geometry.x + m->geometry.width) -
|
||||
MAX(area.x, m->geometry.x)) *
|
||||
@@ -524,7 +538,11 @@ static inline int intersect(area_t area, monitor_t *m) {
|
||||
MAX(area.y, m->geometry.y));
|
||||
}
|
||||
|
||||
monitor_t *wm_get_monitor_by_area(area_t area) {
|
||||
monitor_t *__attribute__((returns_nonnull)) wm_get_monitor_by_area(area_t area) {
|
||||
if (wm.current_monitor == nullptr) {
|
||||
fatal("wm_get_monitor_by_area: current monitor is nullptr");
|
||||
}
|
||||
|
||||
monitor_t *monitor = wm.current_monitor;
|
||||
int temp_area, max_area = 0;
|
||||
for (monitor_t *m = wm.monitor_list; m; m = m->next) {
|
||||
@@ -537,14 +555,10 @@ monitor_t *wm_get_monitor_by_area(area_t area) {
|
||||
return monitor;
|
||||
}
|
||||
|
||||
monitor_t *wm_get_monitor_by_point(point_t point) {
|
||||
for (monitor_t *m = wm.monitor_list; m; m = m->next) {
|
||||
if (m->geometry.x <= point.x &&
|
||||
point.x < m->geometry.x + m->geometry.width) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return wm.monitor_list;
|
||||
monitor_t *__attribute__((returns_nonnull)) wm_get_monitor_by_point(
|
||||
point_t point) {
|
||||
area_t area = {.x = point.x, .y = point.y, .width = 1, .height = 1};
|
||||
return wm_get_monitor_by_area(area);
|
||||
}
|
||||
|
||||
monitor_t *wm_get_monitor_by_window(xcb_window_t window) {
|
||||
|
||||
6
src/wm.h
6
src/wm.h
@@ -57,7 +57,9 @@ extern wm_t wm;
|
||||
void wm_restart(void);
|
||||
void wm_quit(void);
|
||||
void wm_restack_clients(void);
|
||||
monitor_t *wm_get_monitor_by_area(area_t area);
|
||||
monitor_t *wm_get_monitor_by_point(point_t point);
|
||||
void wm_set_current_monitor(monitor_t *monitor);
|
||||
monitor_t *__attribute__((returns_nonnull)) wm_get_monitor_by_area(area_t area);
|
||||
monitor_t *__attribute__((returns_nonnull)) wm_get_monitor_by_point(
|
||||
point_t point);
|
||||
monitor_t *wm_get_monitor_by_window(xcb_window_t window);
|
||||
monitor_t *wm_get_next_monitor(monitor_t *monitor);
|
||||
|
||||
Reference in New Issue
Block a user