diff --git a/CMakeLists.txt b/CMakeLists.txt index b4f7e83..5f9bdbf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ pkg_check_modules(deps REQUIRED xcb xcb-aux xcb-cursor + xcb-icccm xcb-keysyms xcb-randr xcb-xfixes diff --git a/src/atoms-list.txt b/src/atoms-list.txt index b4aa89b..00b45bc 100644 --- a/src/atoms-list.txt +++ b/src/atoms-list.txt @@ -1 +1,6 @@ _XKB_RULES_NAMES + +WM_PROTOCOLS +WM_TAKE_FOCUS + +_NET_ACTIVE_WINDOW diff --git a/src/xwindow.c b/src/xwindow.c index 9d54e2f..6acf407 100644 --- a/src/xwindow.c +++ b/src/xwindow.c @@ -1,11 +1,14 @@ #include "xwindow.h" +#include #include #include +#include #include #include #include "action.h" +#include "atoms-extern.h" #include "utils.h" #include "wm.h" #include "xcursor.h" @@ -127,3 +130,44 @@ void xwindow_grab_keys(xcb_window_t window, const keyboard_t *keys, } } } + +bool xwindow_send_event(xcb_window_t window, xcb_atom_t atom) { + bool exist = false; + + xcb_get_property_cookie_t cookie = + xcb_icccm_get_wm_protocols(wm.xcb_conn, window, atom); + xcb_icccm_get_wm_protocols_reply_t reply; + if (xcb_icccm_get_wm_protocols_reply(wm.xcb_conn, cookie, &reply, nullptr)) { + for (uint32_t i = 0; !exist && i < reply.atoms_len; i++) { + exist = reply.atoms[i] == atom; + } + xcb_icccm_get_wm_protocols_reply_wipe(&reply); + } + + if (exist) { + xcb_client_message_event_t ev; + p_clear(&ev, 1); + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = window; + ev.type = WM_PROTOCOLS; + ev.data.data32[0] = atom; + ev.data.data32[1] = XCB_CURRENT_TIME; + } + + return exist; +} + +void xwindow_focus(xcb_window_t window) { + if (window == XCB_WINDOW_NONE || window == wm.screen->root) { + xcb_set_input_focus(wm.xcb_conn, XCB_INPUT_FOCUS_POINTER_ROOT, + wm.screen->root, XCB_CURRENT_TIME); + xcb_delete_property(wm.xcb_conn, wm.screen->root, _NET_ACTIVE_WINDOW); + } else { + xcb_set_input_focus(wm.xcb_conn, XCB_INPUT_FOCUS_POINTER_ROOT, window, + XCB_CURRENT_TIME); + xcb_change_property(wm.xcb_conn, XCB_PROP_MODE_REPLACE, wm.screen->root, + _NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 32, 1, &window); + xwindow_send_event(window, WM_TAKE_FOCUS); + } +} diff --git a/src/xwindow.h b/src/xwindow.h index 3373778..7d4d820 100644 --- a/src/xwindow.h +++ b/src/xwindow.h @@ -15,3 +15,5 @@ visual_t *xwindow_get_xcb_visual(bool prefer_alpha); void xwindow_change_cursor(xcb_window_t window, cursor_t cursor); void xwindow_grab_keys(xcb_window_t window, const keyboard_t *keys, int keys_length); +bool xwindow_send_event(xcb_window_t window, xcb_atom_t atom); +void xwindow_focus(xcb_window_t window);