diff --git a/src/action.c b/src/action.c index 26139cd..aa9e231 100644 --- a/src/action.c +++ b/src/action.c @@ -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); diff --git a/src/client.c b/src/client.c index c83daea..6f9506c 100644 --- a/src/client.c +++ b/src/client.c @@ -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); diff --git a/src/event.c b/src/event.c index 2f5101f..04eb834 100644 --- a/src/event.c +++ b/src/event.c @@ -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; diff --git a/src/monitor.c b/src/monitor.c index 76d85b8..43e6572 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -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); } diff --git a/src/wm.c b/src/wm.c index 84ec9b8..3818aae 100644 --- a/src/wm.c +++ b/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) { diff --git a/src/wm.h b/src/wm.h index 7e76cee..3c3e73a 100644 --- a/src/wm.h +++ b/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);