diff --git a/src/event.c b/src/event.c index ce165bb..20488fd 100644 --- a/src/event.c +++ b/src/event.c @@ -185,6 +185,25 @@ static void unmap_notify(xcb_unmap_notify_event_t *ev) { if (client) client_unmanage(client); } +static void map_notify(xcb_map_notify_event_t *ev) { + /* 锁屏重新进入桌面后绘制 bar 内容以免 bar 不显示内容 */ + for (monitor_t *m = wm.monitor_list; m; m = m->next) { + if (ev->window == m->bar_window) { + monitor_draw_bar(m); + xcb_flush(wm.xcb_conn); + return; + } + } +} + +static void expose(xcb_expose_event_t *ev) { + if (ev->count > 0) return; + + monitor_t *monitor = wm_get_monitor_by_window(ev->window); + monitor_draw_bar(monitor); + xcb_flush(wm.xcb_conn); +} + static void handle_xcb_event(xcb_generic_event_t *event) { uint8_t event_type = XCB_EVENT_RESPONSE_TYPE(event); const char *label = xcb_event_get_label(event_type); @@ -202,6 +221,8 @@ static void handle_xcb_event(xcb_generic_event_t *event) { EVENT(XCB_KEY_RELEASE, key_press); EVENT(XCB_CONFIGURE_REQUEST, configure_request); EVENT(XCB_MAP_REQUEST, map_request); + EVENT(XCB_MAP_NOTIFY, map_notify); + EVENT(XCB_EXPOSE, expose); EVENT(XCB_CLIENT_MESSAGE, client_message); EVENT(XCB_PROPERTY_NOTIFY, property_notify); EVENT(XCB_UNMAP_NOTIFY, unmap_notify); diff --git a/src/wm.c b/src/wm.c index d95915d..b326662 100644 --- a/src/wm.c +++ b/src/wm.c @@ -21,7 +21,9 @@ #include "atoms-extern.h" #include "atoms.h" #include "backtrace.h" +#include "base.h" #include "buffer.h" +#include "client.h" #include "color.h" #include "default_config.h" #include "event.h" @@ -395,6 +397,26 @@ void wm_restack_clients(void) { xcb_flush(wm.xcb_conn); } +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)) * + MAX(0, MIN(area.y + area.height, m->geometry.y + m->geometry.height) - + MAX(area.y, m->geometry.y)); +} + +monitor_t *wm_get_monitor_by_area(area_t area) { + monitor_t *monitor = wm.current_monitor; + int temp_area, max_area = 0; + for (monitor_t *m = wm.monitor_list; m; m = m->next) { + if ((temp_area = intersect(area, m)) > max_area) { + max_area = temp_area; + monitor = m; + } + } + + 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 && @@ -405,6 +427,28 @@ monitor_t *wm_get_monitor_by_point(point_t point) { return wm.monitor_list; } +monitor_t *wm_get_monitor_by_window(xcb_window_t window) { + if (window == wm.screen->root) { + xcb_query_pointer_cookie_t cookie = xcb_query_pointer(wm.xcb_conn, window); + xcb_query_pointer_reply_t *reply = + xcb_query_pointer_reply(wm.xcb_conn, cookie, nullptr); + if (reply) { + area_t area = {reply->root_x, reply->root_y, 1, 1}; + p_delete(&reply); + return wm_get_monitor_by_area(area); + } + } + + for (monitor_t *m = wm.monitor_list; m; m = m->next) { + if (window == m->bar_window) return m; + } + + client_t *c = client_get_by_window(window); + if (c) return c->monitor; + + return wm.current_monitor; +} + monitor_t *wm_get_next_monitor(monitor_t *monitor) { monitor_t *next_monitor = monitor->next; if (next_monitor == nullptr) next_monitor = wm.monitor_list; diff --git a/src/wm.h b/src/wm.h index 24c3155..b3a34f4 100644 --- a/src/wm.h +++ b/src/wm.h @@ -53,5 +53,7 @@ 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); +monitor_t *wm_get_monitor_by_window(xcb_window_t window); monitor_t *wm_get_next_monitor(monitor_t *monitor);