Compare commits
9 Commits
049b18a496
...
5ecaa97f10
| Author | SHA1 | Date | |
|---|---|---|---|
|
5ecaa97f10
|
|||
|
99d2e33a46
|
|||
|
d1fa848632
|
|||
|
23fb95a5e4
|
|||
|
47d578ca71
|
|||
|
ef37f28fa5
|
|||
|
3d5f8ab7e0
|
|||
|
21d7adf882
|
|||
|
3e2bf57218
|
18
src/action.c
18
src/action.c
@@ -57,3 +57,21 @@ void quit(const user_action_arg_t *arg) {
|
||||
wm_quit();
|
||||
}
|
||||
}
|
||||
|
||||
void raise_or_run(const user_action_arg_t *arg) {
|
||||
const char *class = ((const char **)arg->ptr)[0];
|
||||
client_t *client = client_get_next_by_class(wm.client_focused, class);
|
||||
if (client && client == wm.client_focused) return;
|
||||
|
||||
if (client) {
|
||||
wm.current_monitor = client->monitor;
|
||||
monitor_select_tag(client->monitor, client->tags);
|
||||
client_stack_raise(client);
|
||||
client_focus(client);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *command = ((const char **)arg->ptr)[1];
|
||||
user_action_arg_t arguments = {.ptr = command};
|
||||
spawn(&arguments);
|
||||
}
|
||||
|
||||
@@ -54,3 +54,4 @@ void send_client_to_tag(const user_action_arg_t *arg);
|
||||
void send_client_to_next_monitor(const user_action_arg_t *arg);
|
||||
void spawn(const user_action_arg_t *arg);
|
||||
void quit(const user_action_arg_t *arg);
|
||||
void raise_or_run(const user_action_arg_t *arg);
|
||||
|
||||
@@ -11,6 +11,7 @@ COMPOUND_TEXT
|
||||
|
||||
_NET_ACTIVE_WINDOW
|
||||
_NET_CLIENT_LIST
|
||||
_NET_WM_DESKTOP
|
||||
_NET_WM_NAME
|
||||
_NET_WM_ICON_NAME
|
||||
_NET_SUPPORTING_WM_CHECK
|
||||
|
||||
30
src/client.c
30
src/client.c
@@ -23,6 +23,19 @@ client_t *client_get_by_window(xcb_window_t window) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
client_t *client_get_next_by_class(client_t *current, const char *class) {
|
||||
client_t *start = current ? current->next : wm.client_list;
|
||||
for (client_t *c = start; c; c = c->next) {
|
||||
if (strcmp(class, c->class) == 0) return c;
|
||||
}
|
||||
|
||||
for (client_t *c = wm.client_list; c && c != start; c = c->next) {
|
||||
if (strcmp(class, c->class) == 0) return c;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void client_attach_list(client_t *client) {
|
||||
client->next = wm.client_list;
|
||||
wm.client_list = client;
|
||||
@@ -77,6 +90,8 @@ task_in_tag_t *client_get_previous_task_in_tag(client_t *client, tag_t *tag) {
|
||||
static void client_add_to_tag(client_t *client, tag_t *tag) {
|
||||
if (client_get_task_in_tag(client, tag)) return;
|
||||
|
||||
xwindow_set_wm_desktop(client->window, tag->index);
|
||||
|
||||
task_in_tag_t *task = p_new(task_in_tag_t, 1);
|
||||
task->client = client;
|
||||
task->next = tag->task_list;
|
||||
@@ -145,6 +160,20 @@ static inline void client_init_geometry(client_t *c) {
|
||||
client_change_border_width(c, wm.border_width);
|
||||
}
|
||||
|
||||
static void client_init_tag_by_wm_desktop(client_t *client) {
|
||||
uint32_t tag_index = 0;
|
||||
if (!xwindow_get_wm_desktop(client->window, &tag_index)) return;
|
||||
for (monitor_t *m = wm.monitor_list; m; m = m->next) {
|
||||
for (tag_t *tag = m->tag_list; tag; tag = tag->next) {
|
||||
if (tag->index == tag_index) {
|
||||
client->monitor = m;
|
||||
client->tags = tag->mask;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void client_manage(xcb_window_t window,
|
||||
xcb_get_geometry_reply_t *geometry_reply) {
|
||||
client_t *c = p_new(client_t, 1);
|
||||
@@ -198,6 +227,7 @@ void client_manage(xcb_window_t window,
|
||||
}
|
||||
|
||||
client_init_geometry(c);
|
||||
client_init_tag_by_wm_desktop(c);
|
||||
client_tags_apply(c);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "types.h"
|
||||
|
||||
client_t *client_get_by_window(xcb_window_t window);
|
||||
client_t *client_get_next_by_class(client_t *current,const char *class);
|
||||
task_in_tag_t *client_get_task_in_tag(client_t *client, tag_t *tag);
|
||||
task_in_tag_t *client_get_next_task_in_tag(client_t *client, tag_t *tag);
|
||||
task_in_tag_t *client_get_previous_task_in_tag(client_t *client, tag_t *tag);
|
||||
|
||||
@@ -31,18 +31,49 @@ static const button_t button_list[] = {
|
||||
};
|
||||
|
||||
#define TAGKEYS(KEY, TAG) \
|
||||
{modifier_alt, KEY, select_tag_of_current_monitor, {.ui = TAG}}, { \
|
||||
modifier_alt | modifier_shift, KEY, send_client_to_tag, {.ui = TAG}, \
|
||||
{modifier_super, KEY, select_tag_of_current_monitor, {.ui = TAG}}, { \
|
||||
modifier_super | modifier_shift, KEY, send_client_to_tag, {.ui = TAG}, \
|
||||
}
|
||||
|
||||
static const char launcher[] =
|
||||
"rofi -show combi -modes combi -combi-modes window,drun,run,ssh,windowcd";
|
||||
static const char terminal[] = "xterm";
|
||||
static const char terminal_class[] = "XTerm";
|
||||
static const char editor[] = "emacsclient -a '' -r";
|
||||
static const char editor_class[] = "Emacs";
|
||||
static const char browser[] = "firefox-bin";
|
||||
static const char browser_class[] = "firefox";
|
||||
static const keyboard_t key_list[] = {
|
||||
{modifier_alt, XK_p, spawn, {.ptr = launcher}},
|
||||
{modifier_alt, XK_q, quit, {.b = false}},
|
||||
{modifier_alt, XK_r, quit, {.b = true}},
|
||||
{modifier_alt | modifier_shift, XK_j, focus_client_in_same_tag, {.b = true}},
|
||||
{modifier_alt | modifier_shift, XK_k, focus_client_in_same_tag, {.b = false}},
|
||||
{modifier_super, XK_r, spawn, {.ptr = launcher}},
|
||||
{modifier_super, XK_Return, spawn, {.ptr = terminal}},
|
||||
{
|
||||
modifier_control | modifier_alt,
|
||||
XK_r,
|
||||
raise_or_run,
|
||||
{.ptr = (const char *[]){terminal_class, terminal}},
|
||||
},
|
||||
{
|
||||
modifier_super,
|
||||
XK_e,
|
||||
raise_or_run,
|
||||
{.ptr = (const char *[]){editor_class, editor}},
|
||||
},
|
||||
{
|
||||
modifier_super,
|
||||
XK_q,
|
||||
raise_or_run,
|
||||
{.ptr = (const char *[]){browser_class, browser}},
|
||||
},
|
||||
{modifier_super | modifier_shift, XK_q, quit, {.b = false}},
|
||||
{modifier_super | modifier_control, XK_r, quit, {.b = true}},
|
||||
{modifier_super | modifier_shift,
|
||||
XK_j,
|
||||
focus_client_in_same_tag,
|
||||
{.b = true}},
|
||||
{modifier_super | modifier_shift,
|
||||
XK_k,
|
||||
focus_client_in_same_tag,
|
||||
{.b = false}},
|
||||
|
||||
TAGKEYS(XK_1, 1 << 0),
|
||||
TAGKEYS(XK_2, 1 << 1),
|
||||
@@ -54,7 +85,7 @@ static const keyboard_t key_list[] = {
|
||||
TAGKEYS(XK_8, 1 << 7),
|
||||
TAGKEYS(XK_9, 1 << 8),
|
||||
|
||||
{modifier_alt, XK_o, send_client_to_next_monitor, {0}},
|
||||
{modifier_super, XK_o, send_client_to_next_monitor, {0}},
|
||||
};
|
||||
|
||||
static const layout_t layout_list[] = {
|
||||
|
||||
31
src/event.c
31
src/event.c
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_event.h>
|
||||
#include <xcb/xcb_keysyms.h>
|
||||
@@ -83,6 +82,7 @@ static void configure_request(xcb_configure_request_event_t *ev) {
|
||||
.stack_mode = ev->stack_mode,
|
||||
};
|
||||
xcb_configure_window_aux(wm.xcb_conn, ev->window, value_mask, &value_list);
|
||||
xcb_flush(wm.xcb_conn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,10 +106,8 @@ static void key_press(xcb_key_press_event_t *ev) {
|
||||
}
|
||||
|
||||
static void map_request(xcb_map_request_event_t *ev) {
|
||||
xcb_get_window_attributes_cookie_t wa_cookie =
|
||||
xcb_get_window_attributes_unchecked(wm.xcb_conn, ev->window);
|
||||
xcb_get_window_attributes_reply_t *wa_reply =
|
||||
xcb_get_window_attributes_reply(wm.xcb_conn, wa_cookie, nullptr);
|
||||
xwindow_get_attributes_reply(ev->window);
|
||||
|
||||
if (!wa_reply) return;
|
||||
if (wa_reply->override_redirect) {
|
||||
@@ -119,10 +117,8 @@ static void map_request(xcb_map_request_event_t *ev) {
|
||||
|
||||
client_t *c = client_get_by_window(ev->window);
|
||||
if (!c) {
|
||||
xcb_get_geometry_cookie_t geo_cookie =
|
||||
xcb_get_geometry(wm.xcb_conn, ev->window);
|
||||
xcb_get_geometry_reply_t *geo_reply =
|
||||
xcb_get_geometry_reply(wm.xcb_conn, geo_cookie, nullptr);
|
||||
xwindow_get_geometry_reply(ev->window);
|
||||
if (!geo_reply) {
|
||||
p_delete(&wa_reply);
|
||||
return;
|
||||
@@ -184,6 +180,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);
|
||||
@@ -201,6 +216,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);
|
||||
|
||||
130
src/wm.c
130
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"
|
||||
@@ -50,9 +52,6 @@ wm_t wm;
|
||||
/** argv used to run wm */
|
||||
static char **cmd_argv;
|
||||
|
||||
/** A pipe that is used to asynchronously handle SIGCHLD */
|
||||
static int sigchld_pipe[2];
|
||||
|
||||
static gboolean restart_on_signal(gpointer data) {
|
||||
wm_restart();
|
||||
return TRUE;
|
||||
@@ -69,14 +68,6 @@ static void signal_fatal(int signal_number) {
|
||||
fatal("signal %d, dumping backtrace\n%s", signal_number, buffer.s);
|
||||
}
|
||||
|
||||
/* Signal handler for SIGCHLD. Causes reap_children() to be called. */
|
||||
static void signal_child(int signum) {
|
||||
assert(signum == SIGCHLD);
|
||||
int res = write(sigchld_pipe[1], " ", 1);
|
||||
(void)res;
|
||||
assert(res == 1);
|
||||
}
|
||||
|
||||
static guint sources[3] = {0};
|
||||
|
||||
void wm_setup_signal(void) {
|
||||
@@ -92,10 +83,6 @@ void wm_setup_signal(void) {
|
||||
sigaction(SIGILL, &sa, 0);
|
||||
sigaction(SIGSEGV, &sa, 0);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
sa.sa_handler = signal_child;
|
||||
sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
|
||||
sigaction(SIGCHLD, &sa, 0);
|
||||
}
|
||||
|
||||
void wm_check_other_wm(void) {
|
||||
@@ -256,7 +243,67 @@ void wm_detect_monitor(void) {
|
||||
wm.current_monitor = monitor;
|
||||
}
|
||||
|
||||
void wm_scan_clients(void) {}
|
||||
typedef struct window_list_t {
|
||||
xcb_window_t *normal_list;
|
||||
xcb_window_t *transient_list;
|
||||
uint32_t normal_count;
|
||||
uint32_t transient_count;
|
||||
} window_list_t;
|
||||
void wm_scan_clients(void) {
|
||||
xcb_query_tree_cookie_t cookie = xcb_query_tree(wm.xcb_conn, wm.screen->root);
|
||||
xcb_query_tree_reply_t *tree_reply =
|
||||
xcb_query_tree_reply(wm.xcb_conn, cookie, nullptr);
|
||||
if (!tree_reply) return;
|
||||
|
||||
xcb_window_t *list = xcb_query_tree_children(tree_reply);
|
||||
int len = xcb_query_tree_children_length(tree_reply);
|
||||
if (!len) {
|
||||
p_delete(&tree_reply);
|
||||
return;
|
||||
}
|
||||
|
||||
xcb_get_window_attributes_reply_t *wa_reply = nullptr;
|
||||
xcb_get_geometry_reply_t *geo_reply = nullptr;
|
||||
for (int i = 0; i < len; i++) {
|
||||
xcb_window_t window = list[i];
|
||||
wa_reply = xwindow_get_attributes_reply(window);
|
||||
if (!wa_reply) continue;
|
||||
|
||||
uint8_t override_redirect = wa_reply->override_redirect;
|
||||
uint8_t map_state = wa_reply->map_state;
|
||||
p_delete(&wa_reply);
|
||||
|
||||
if (override_redirect || xwindow_get_transient_for(window)) continue;
|
||||
|
||||
geo_reply = xwindow_get_geometry_reply(window);
|
||||
if (!geo_reply) continue;
|
||||
|
||||
if (map_state == XCB_MAP_STATE_VIEWABLE ||
|
||||
xwindow_get_state(window) == XCB_ICCCM_WM_STATE_ICONIC) {
|
||||
client_manage(window, geo_reply);
|
||||
}
|
||||
p_delete(&geo_reply);
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
xcb_window_t window = list[i];
|
||||
wa_reply = xwindow_get_attributes_reply(window);
|
||||
if (!wa_reply) continue;
|
||||
|
||||
uint8_t map_state = wa_reply->map_state;
|
||||
p_delete(&wa_reply);
|
||||
|
||||
geo_reply = xwindow_get_geometry_reply(window);
|
||||
if (!geo_reply) continue;
|
||||
|
||||
if (xwindow_get_transient_for(window) &&
|
||||
(map_state == XCB_MAP_STATE_VIEWABLE ||
|
||||
xwindow_get_state(window) == XCB_ICCCM_WM_STATE_ICONIC)) {
|
||||
client_manage(window, geo_reply);
|
||||
}
|
||||
p_delete(&geo_reply);
|
||||
}
|
||||
p_delete(&tree_reply);
|
||||
}
|
||||
|
||||
void wm_clean(void) {
|
||||
text_clean_pango_layout();
|
||||
@@ -267,6 +314,11 @@ void wm_clean(void) {
|
||||
if (source_id) g_source_remove(source_id);
|
||||
}
|
||||
|
||||
xcb_delete_property(wm.xcb_conn, wm.screen->root, _NET_CLIENT_LIST);
|
||||
xcb_delete_property(wm.xcb_conn, wm.screen->root, _NET_ACTIVE_WINDOW);
|
||||
xcb_delete_property(wm.xcb_conn, wm.screen->root, _NET_SUPPORTING_WM_CHECK);
|
||||
xcb_aux_sync(wm.xcb_conn);
|
||||
|
||||
xcb_destroy_window(wm.xcb_conn, wm.wm_check_window);
|
||||
wm.wm_check_window = XCB_WINDOW_NONE;
|
||||
|
||||
@@ -299,8 +351,9 @@ static void wm_setup(void) {
|
||||
monitor_draw_bar(m);
|
||||
}
|
||||
|
||||
uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
|
||||
uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR | XCB_CW_BACK_PIXEL;
|
||||
xcb_params_cw_t params = {
|
||||
.back_pixel = wm.screen->black_pixel,
|
||||
.cursor = xcursor_get_xcb_cursor(cursor_normal),
|
||||
.event_mask =
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_KEY_PRESS,
|
||||
@@ -409,6 +462,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 &&
|
||||
@@ -419,6 +492,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;
|
||||
@@ -453,6 +548,7 @@ int main(int argc, char *argv[]) {
|
||||
wm_detect_monitor();
|
||||
wm_setup();
|
||||
setup_event_loop();
|
||||
wm_scan_clients();
|
||||
|
||||
debug_show_monitor_list();
|
||||
|
||||
|
||||
2
src/wm.h
2
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);
|
||||
|
||||
@@ -205,3 +205,56 @@ void xwindow_get_text_property(xcb_window_t window, xcb_atom_t property,
|
||||
|
||||
p_delete(&reply);
|
||||
}
|
||||
|
||||
void xwindow_set_wm_desktop(xcb_window_t window, uint32_t desktop) {
|
||||
xcb_change_property(wm.xcb_conn, XCB_PROP_MODE_REPLACE, window,
|
||||
_NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, &desktop);
|
||||
}
|
||||
|
||||
bool xwindow_get_wm_desktop(xcb_window_t window, uint32_t *desktop) {
|
||||
xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(
|
||||
wm.xcb_conn, false, window, _NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 0, 1);
|
||||
xcb_get_property_reply_t *reply =
|
||||
xcb_get_property_reply(wm.xcb_conn, cookie, nullptr);
|
||||
if (!reply) return false;
|
||||
|
||||
bool success = reply->type == XCB_ATOM_CARDINAL && reply->format == 32;
|
||||
if (success) *desktop = *(uint32_t *)xcb_get_property_value(reply);
|
||||
|
||||
p_delete(&reply);
|
||||
return success;
|
||||
}
|
||||
|
||||
xcb_window_t xwindow_get_transient_for(xcb_window_t window) {
|
||||
xcb_connection_t *conn = wm.xcb_conn;
|
||||
xcb_window_t t_window = XCB_WINDOW_NONE;
|
||||
xcb_get_property_cookie_t cookie =
|
||||
xcb_icccm_get_wm_transient_for(conn, window);
|
||||
xcb_icccm_get_wm_transient_for_reply(conn, cookie, &t_window, nullptr);
|
||||
return t_window;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取窗口的状态
|
||||
* @param window 目标窗口
|
||||
* @returns 成功返回 xcb_icccm_wm_state_t 枚举类型,失败返回 -1
|
||||
*/
|
||||
int32_t xwindow_get_state(xcb_window_t window) {
|
||||
xcb_connection_t *conn = wm.xcb_conn;
|
||||
xcb_icccm_wm_hints_t hints;
|
||||
xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_hints(conn, window);
|
||||
if (!xcb_icccm_get_wm_hints_reply(conn, cookie, &hints, nullptr)) return -1;
|
||||
return hints.initial_state;
|
||||
}
|
||||
|
||||
xcb_get_geometry_reply_t *xwindow_get_geometry_reply(xcb_window_t window) {
|
||||
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(wm.xcb_conn, window);
|
||||
return xcb_get_geometry_reply(wm.xcb_conn, cookie, nullptr);
|
||||
}
|
||||
|
||||
xcb_get_window_attributes_reply_t *xwindow_get_attributes_reply(
|
||||
xcb_window_t window) {
|
||||
xcb_get_window_attributes_cookie_t wa_cookie =
|
||||
xcb_get_window_attributes(wm.xcb_conn, window);
|
||||
return xcb_get_window_attributes_reply(wm.xcb_conn, wa_cookie, nullptr);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,14 @@ bool xwindow_send_event(xcb_window_t window, xcb_atom_t atom);
|
||||
void xwindow_focus(xcb_window_t window);
|
||||
void xwindow_get_text_property(xcb_window_t window, xcb_atom_t property,
|
||||
char **out);
|
||||
void xwindow_set_wm_desktop(xcb_window_t window, uint32_t desktop);
|
||||
bool xwindow_get_wm_desktop(xcb_window_t window, uint32_t *desktop);
|
||||
|
||||
xcb_window_t xwindow_get_transient_for(xcb_window_t window);
|
||||
int32_t xwindow_get_state(xcb_window_t window);
|
||||
xcb_get_geometry_reply_t *xwindow_get_geometry_reply(xcb_window_t window);
|
||||
xcb_get_window_attributes_reply_t *xwindow_get_attributes_reply(
|
||||
xcb_window_t window);
|
||||
|
||||
#define xwindow_set_name_static(window, name) \
|
||||
xcb_icccm_set_wm_name(wm.xcb_conn, window, XCB_ATOM_STRING, 8, \
|
||||
|
||||
Reference in New Issue
Block a user