Compare commits
7 Commits
a46522da3b
...
9b77469ed2
| Author | SHA1 | Date | |
|---|---|---|---|
|
9b77469ed2
|
|||
|
8321175915
|
|||
|
850b63bf82
|
|||
|
f225dc7011
|
|||
|
b28c9cd58b
|
|||
|
b645c4cf39
|
|||
|
9397e9e572
|
@@ -5,3 +5,4 @@
|
|||||||
void spawn(const user_action_arg_t *arg);
|
void spawn(const user_action_arg_t *arg);
|
||||||
void quit(const user_action_arg_t *arg);
|
void quit(const user_action_arg_t *arg);
|
||||||
void select_tag(const user_action_arg_t *arg);
|
void select_tag(const user_action_arg_t *arg);
|
||||||
|
void kill_client(const user_action_arg_t *arg);
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ const keybinding_t keys[] = {
|
|||||||
{SUPER, XK_p, spawn, {.ptr = launcher}},
|
{SUPER, XK_p, spawn, {.ptr = launcher}},
|
||||||
{SUPER | SHIFT, XK_q, quit, {.b = false}},
|
{SUPER | SHIFT, XK_q, quit, {.b = false}},
|
||||||
{SUPER | CTRL, XK_r, quit, {.b = true}},
|
{SUPER | CTRL, XK_r, quit, {.b = true}},
|
||||||
|
{SUPER | SHIFT, XK_c, kill_client, {0}},
|
||||||
{SUPER, XK_1, select_tag, {.ui = 0}},
|
{SUPER, XK_1, select_tag, {.ui = 0}},
|
||||||
{SUPER, XK_2, select_tag, {.ui = 1}},
|
{SUPER, XK_2, select_tag, {.ui = 1}},
|
||||||
{SUPER, XK_3, select_tag, {.ui = 2}},
|
{SUPER, XK_3, select_tag, {.ui = 2}},
|
||||||
|
|||||||
@@ -125,8 +125,17 @@ typedef struct property_notify_event_t {
|
|||||||
property_state_t state;
|
property_state_t state;
|
||||||
} property_notify_event_t;
|
} property_notify_event_t;
|
||||||
|
|
||||||
|
typedef union client_message_data_t {
|
||||||
|
uint8_t data8[20];
|
||||||
|
uint16_t data16[10];
|
||||||
|
uint32_t data32[5];
|
||||||
|
} client_message_data_t;
|
||||||
typedef struct client_message_event_t {
|
typedef struct client_message_event_t {
|
||||||
event_type_t type;
|
event_type_t type;
|
||||||
|
xcb_window_t window;
|
||||||
|
uint32_t message_type;
|
||||||
|
client_message_data_t data;
|
||||||
|
uint8_t format;
|
||||||
} client_message_event_t;
|
} client_message_event_t;
|
||||||
|
|
||||||
typedef union generic_event_t {
|
typedef union generic_event_t {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ typedef struct window_geometry_t {
|
|||||||
* @returns 返回几何信息指针,使用完后记得使用 free 释放内存
|
* @returns 返回几何信息指针,使用完后记得使用 free 释放内存
|
||||||
*/
|
*/
|
||||||
window_geometry_t *get_window_geometry(xcb_window_t window);
|
window_geometry_t *get_window_geometry(xcb_window_t window);
|
||||||
void map_window(xcb_window_t window);
|
void map_window(xcb_window_t window, bool map_sub_window);
|
||||||
/**
|
/**
|
||||||
* @brief 获取窗口名
|
* @brief 获取窗口名
|
||||||
* @returns 返回窗口名字符串指针,使用完后记得使用 free 释放内存
|
* @returns 返回窗口名字符串指针,使用完后记得使用 free 释放内存
|
||||||
@@ -50,6 +50,23 @@ char *get_window_name(xcb_window_t window);
|
|||||||
void set_window_event_mask(xcb_window_t window, bool clear);
|
void set_window_event_mask(xcb_window_t window, bool clear);
|
||||||
void change_window_border_color(xcb_window_t window, uint32_t argb);
|
void change_window_border_color(xcb_window_t window, uint32_t argb);
|
||||||
void focus_window(xcb_window_t window);
|
void focus_window(xcb_window_t window);
|
||||||
|
/**
|
||||||
|
* @brief 将 window 置于堆叠顺序的顶部
|
||||||
|
*/
|
||||||
|
void raise_window(xcb_window_t window);
|
||||||
|
/**
|
||||||
|
* @brief 在堆叠顺序中将 window 置于 sibling 之上
|
||||||
|
*/
|
||||||
|
void place_window_above_sibling(xcb_window_t window, xcb_window_t sibling);
|
||||||
|
/**
|
||||||
|
* @brief 在堆叠顺序中将 window 置于 sibling 之下
|
||||||
|
*/
|
||||||
|
void place_window_below_sibling(xcb_window_t window, xcb_window_t sibling);
|
||||||
|
/**
|
||||||
|
* @brief 关闭窗口并清理资源
|
||||||
|
*/
|
||||||
|
void kill_window(xcb_window_t window);
|
||||||
|
void set_window_fullscreen_state(xcb_window_t window, bool fullscreen);
|
||||||
|
|
||||||
typedef struct bar_cairo_params_t {
|
typedef struct bar_cairo_params_t {
|
||||||
xcb_connection_t *conn;
|
xcb_connection_t *conn;
|
||||||
@@ -107,6 +124,8 @@ typedef enum atom_t {
|
|||||||
atom_wm_delete,
|
atom_wm_delete,
|
||||||
atom_wm_take_focus,
|
atom_wm_take_focus,
|
||||||
atom_net_wm_name,
|
atom_net_wm_name,
|
||||||
|
atom_net_wm_state,
|
||||||
|
atom_net_wm_fullscreen,
|
||||||
atom__xrootpmap_id,
|
atom__xrootpmap_id,
|
||||||
atom_esetroot_pmap_id,
|
atom_esetroot_pmap_id,
|
||||||
} atom_t;
|
} atom_t;
|
||||||
@@ -122,3 +141,8 @@ void set_window_state(xcb_window_t window, wm_state_t state);
|
|||||||
void set_window_list(xcb_window_t *list, uint32_t length);
|
void set_window_list(xcb_window_t *list, uint32_t length);
|
||||||
|
|
||||||
bool get_pointer_position(int32_t *x, int32_t *y);
|
bool get_pointer_position(int32_t *x, int32_t *y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 非阻塞检查特定事件掩码(模拟 XCheckMaskEvent)
|
||||||
|
*/
|
||||||
|
bool xcb_check_mask_event(xcb_event_mask_t event_mask);
|
||||||
|
|||||||
15
src/layout.c
15
src/layout.c
@@ -22,12 +22,23 @@ void maximize_client(client_t *c) {
|
|||||||
c->height = m->window_height - 2 * c->border_width;
|
c->height = m->window_height - 2 * c->border_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置全屏窗口的几何属性
|
||||||
|
*/
|
||||||
void fullscreen_client(client_t *c) {
|
void fullscreen_client(client_t *c) {
|
||||||
|
if (c->floating) {
|
||||||
|
c->old_x = c->x;
|
||||||
|
c->old_y = c->y;
|
||||||
|
c->old_width = c->width;
|
||||||
|
c->old_height = c->height;
|
||||||
|
}
|
||||||
monitor_t *m = c->monitor;
|
monitor_t *m = c->monitor;
|
||||||
c->x = m->monitor_x;
|
c->x = m->monitor_x;
|
||||||
c->y = m->monitor_y;
|
c->y = m->monitor_y;
|
||||||
c->width = m->monitor_width - 2 * c->border_width;
|
c->width = m->monitor_width;
|
||||||
c->height = m->monitor_height - 2 * c->border_width;
|
c->height = m->monitor_height;
|
||||||
|
c->old_border_width = c->border_width;
|
||||||
|
c->border_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void monocle(monitor_t *monitor) {
|
void monocle(monitor_t *monitor) {
|
||||||
|
|||||||
107
src/main.c
107
src/main.c
@@ -47,6 +47,7 @@ static void motion_notify(motion_notify_event_t *event);
|
|||||||
static void enter_notify(enter_notify_event_t *event);
|
static void enter_notify(enter_notify_event_t *event);
|
||||||
static void focus_in(focus_in_event_t *event);
|
static void focus_in(focus_in_event_t *event);
|
||||||
static void property_notify(property_notify_event_t *event);
|
static void property_notify(property_notify_event_t *event);
|
||||||
|
static void client_message(client_message_event_t *event);
|
||||||
static void manage_window(xcb_window_t window);
|
static void manage_window(xcb_window_t window);
|
||||||
static void unmanage_client(client_t *client, bool destroyed);
|
static void unmanage_client(client_t *client, bool destroyed);
|
||||||
static void update_client_list(void);
|
static void update_client_list(void);
|
||||||
@@ -62,6 +63,7 @@ static void show_hide_client(client_t *client);
|
|||||||
static void restack(monitor_t *monitor);
|
static void restack(monitor_t *monitor);
|
||||||
static void focus(client_t *client);
|
static void focus(client_t *client);
|
||||||
static void unfocus(client_t *client, bool set_focus);
|
static void unfocus(client_t *client, bool set_focus);
|
||||||
|
static void set_client_fullscreen(client_t *client, bool fullscreen);
|
||||||
static void apply_monitor_layout(monitor_t *monitor);
|
static void apply_monitor_layout(monitor_t *monitor);
|
||||||
static client_t *get_client_of_window(xcb_window_t window);
|
static client_t *get_client_of_window(xcb_window_t window);
|
||||||
static monitor_t *get_monitor_of_window(xcb_window_t window);
|
static monitor_t *get_monitor_of_window(xcb_window_t window);
|
||||||
@@ -104,6 +106,15 @@ void select_tag(const user_action_arg_t *arg) {
|
|||||||
arrange(current_monitor);
|
arrange(current_monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kill_client(const user_action_arg_t *arg) {
|
||||||
|
client_t *client = current_monitor->selected_client;
|
||||||
|
if (!client) return;
|
||||||
|
|
||||||
|
if (!send_event(client->window, get_xcb_atom(atom_wm_delete))) {
|
||||||
|
kill_window(client->window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 调试函数,开发完成后删除 */
|
/* 调试函数,开发完成后删除 */
|
||||||
static void print_monitor_list_info(monitor_t *monitor_list) {
|
static void print_monitor_list_info(monitor_t *monitor_list) {
|
||||||
logger("========================= monitor info =========================\n");
|
logger("========================= monitor info =========================\n");
|
||||||
@@ -252,9 +263,6 @@ char **get_monitor_tags(uint32_t monitor_count, uint32_t monitor_index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void init_wallpaper(void) {
|
void init_wallpaper(void) {
|
||||||
wallpaper_config = parse_wallpaper_config();
|
|
||||||
if (!wallpaper_config) return;
|
|
||||||
|
|
||||||
bar_cairo_params_t *p = prepare_wallpaper_surface_params();
|
bar_cairo_params_t *p = prepare_wallpaper_surface_params();
|
||||||
rect_size_t *screen_size = get_screen_size();
|
rect_size_t *screen_size = get_screen_size();
|
||||||
if (wallpaper_cr) cairo_destroy(wallpaper_cr);
|
if (wallpaper_cr) cairo_destroy(wallpaper_cr);
|
||||||
@@ -277,8 +285,12 @@ void init_wallpaper(void) {
|
|||||||
wallpaper_cr = cr;
|
wallpaper_cr = cr;
|
||||||
cairo_surface_destroy(surface);
|
cairo_surface_destroy(surface);
|
||||||
|
|
||||||
|
wallpaper_config = parse_wallpaper_config();
|
||||||
|
if (!wallpaper_config) return;
|
||||||
|
|
||||||
update_wallpaper(wallpaper_config);
|
update_wallpaper(wallpaper_config);
|
||||||
if (!wallpaper_interval) return;
|
if (!wallpaper_interval) return;
|
||||||
|
|
||||||
g_timeout_add_seconds(wallpaper_interval, update_wallpaper, wallpaper_config);
|
g_timeout_add_seconds(wallpaper_interval, update_wallpaper, wallpaper_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,6 +519,7 @@ void xcb_event_handler(generic_event_t *event, void *user_data) {
|
|||||||
EVENT(EVENT_TYPE_ENTER_NOTIFY, enter_notify);
|
EVENT(EVENT_TYPE_ENTER_NOTIFY, enter_notify);
|
||||||
EVENT(EVENT_TYPE_FOCUS_IN, focus_in);
|
EVENT(EVENT_TYPE_FOCUS_IN, focus_in);
|
||||||
EVENT(EVENT_TYPE_PROPERTY_NOTIFY, property_notify);
|
EVENT(EVENT_TYPE_PROPERTY_NOTIFY, property_notify);
|
||||||
|
EVENT(EVENT_TYPE_CLIENT_MESSAGE, client_message);
|
||||||
|
|
||||||
#undef EVENT
|
#undef EVENT
|
||||||
|
|
||||||
@@ -550,7 +563,10 @@ void map_request(map_request_event_t *event) {
|
|||||||
|
|
||||||
void unmap_notify(unmap_notify_event_t *event) {
|
void unmap_notify(unmap_notify_event_t *event) {
|
||||||
client_t *c = get_client_of_window(event->window);
|
client_t *c = get_client_of_window(event->window);
|
||||||
|
logger("unmap window: 0x%x, send event: %s\n", event->window,
|
||||||
|
event->send_event ? "true" : "false");
|
||||||
if (c) {
|
if (c) {
|
||||||
|
print_client(c);
|
||||||
if (event->send_event) {
|
if (event->send_event) {
|
||||||
set_window_state(event->window, wm_state_withdrawn);
|
set_window_state(event->window, wm_state_withdrawn);
|
||||||
} else {
|
} else {
|
||||||
@@ -610,10 +626,14 @@ void focus_in(focus_in_event_t *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void property_notify(property_notify_event_t *event) {
|
void property_notify(property_notify_event_t *event) {
|
||||||
|
logger("window: 0x%x state: %u, atom: %u\n", event->window, event->state,
|
||||||
|
event->xcb_atom);
|
||||||
if (event->state == property_delete) return;
|
if (event->state == property_delete) return;
|
||||||
|
|
||||||
client_t *c = get_client_of_window(event->window);
|
client_t *c = get_client_of_window(event->window);
|
||||||
if (!c) return;
|
if (!c) return;
|
||||||
|
print_client(c);
|
||||||
|
|
||||||
switch (event->xcb_atom) {
|
switch (event->xcb_atom) {
|
||||||
case XCB_ATOM_WM_TRANSIENT_FOR: {
|
case XCB_ATOM_WM_TRANSIENT_FOR: {
|
||||||
xcb_window_t transient_for;
|
xcb_window_t transient_for;
|
||||||
@@ -635,6 +655,35 @@ void property_notify(property_notify_event_t *event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void client_message(client_message_event_t *event) {
|
||||||
|
client_t *c = get_client_of_window(event->window);
|
||||||
|
if (!c) return;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _NET_WM_STATE_FULLSCREEN 协议数据格式为
|
||||||
|
* data.data32 = {
|
||||||
|
* action, // 操作类型(添加/移除/切换)
|
||||||
|
* property1, // 第一个状态原子(如_NET_WM_STATE_FULLSCREEN)
|
||||||
|
* property2, // 第二个状态原子(可选,通常为0)
|
||||||
|
* 0, // 预留字段(固定为0)
|
||||||
|
* 0 // 预留字段(固定为0)
|
||||||
|
* };
|
||||||
|
* action 值可能为
|
||||||
|
* _NET_WM_STATE_ADD(1):添加全屏状态,窗口进入全屏模式
|
||||||
|
* _NET_WM_STATE_REMOVE(0):移除全屏状态,窗口退出全屏模式
|
||||||
|
* _NET_WM_STATE_TOGGLE(2):切换全屏状态(若当前全屏则退出,反之进入)
|
||||||
|
*/
|
||||||
|
if (event->message_type == get_xcb_atom(atom_net_wm_state)) {
|
||||||
|
uint32_t fullscreen_atom = get_xcb_atom(atom_net_wm_fullscreen);
|
||||||
|
if (event->data.data32[1] == fullscreen_atom ||
|
||||||
|
event->data.data32[2] == fullscreen_atom) {
|
||||||
|
bool set_fullscreen = event->data.data32[0] == 1;
|
||||||
|
bool toggle_to_fullscreen = event->data.data32[0] == 2 && !c->fullscreen;
|
||||||
|
set_client_fullscreen(c, set_fullscreen || toggle_to_fullscreen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void manage_window(xcb_window_t window) {
|
void manage_window(xcb_window_t window) {
|
||||||
window_geometry_t *geometry = get_window_geometry(window);
|
window_geometry_t *geometry = get_window_geometry(window);
|
||||||
client_t *c = ecalloc(1, sizeof(client_t));
|
client_t *c = ecalloc(1, sizeof(client_t));
|
||||||
@@ -647,7 +696,7 @@ void manage_window(xcb_window_t window) {
|
|||||||
c->border_width = border_px;
|
c->border_width = border_px;
|
||||||
update_client_name(c);
|
update_client_name(c);
|
||||||
|
|
||||||
logger("== manage window: %u\n", window);
|
logger("== manage window: 0x%x\n", window);
|
||||||
logger("== x: %d, y: %d, w: %u, h: %u, bw: %u\n", c->x, c->y, c->width,
|
logger("== x: %d, y: %d, w: %u, h: %u, bw: %u\n", c->x, c->y, c->width,
|
||||||
c->height, c->border_width);
|
c->height, c->border_width);
|
||||||
|
|
||||||
@@ -661,15 +710,20 @@ void manage_window(xcb_window_t window) {
|
|||||||
apply_rules(c);
|
apply_rules(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
attach_client(c);
|
|
||||||
attach_stack_client(c);
|
|
||||||
set_window_event_mask(window, false);
|
set_window_event_mask(window, false);
|
||||||
change_window_border_color(window, color_set->border_color.argb);
|
change_window_border_color(window, color_set->border_color.argb);
|
||||||
|
|
||||||
|
attach_client(c);
|
||||||
|
attach_stack_client(c);
|
||||||
|
update_client_list();
|
||||||
|
set_window_state(window, wm_state_normal);
|
||||||
|
|
||||||
if (c->monitor == current_monitor) {
|
if (c->monitor == current_monitor) {
|
||||||
unfocus(current_monitor->selected_client, false);
|
unfocus(current_monitor->selected_client, false);
|
||||||
}
|
}
|
||||||
|
c->monitor->selected_client = c;
|
||||||
arrange(c->monitor);
|
arrange(c->monitor);
|
||||||
map_window(window);
|
map_window(window, false);
|
||||||
focus(NULL);
|
focus(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -822,7 +876,24 @@ void arrange(monitor_t *monitor) {
|
|||||||
|
|
||||||
void restack(monitor_t *monitor) {
|
void restack(monitor_t *monitor) {
|
||||||
draw_monitor_bar(monitor);
|
draw_monitor_bar(monitor);
|
||||||
/* TODO: */
|
if (!monitor->selected_client) return;
|
||||||
|
if (monitor->selected_client->floating || !monitor->layout->arrange) {
|
||||||
|
raise_window(monitor->selected_client->window);
|
||||||
|
}
|
||||||
|
if (monitor->layout->arrange) {
|
||||||
|
xcb_window_t sibling = monitor->bar_window;
|
||||||
|
for (client_t *c = monitor->clients_stack; c; c = c->stack_next) {
|
||||||
|
if (!CLIENT_VISIBLE(c)) continue;
|
||||||
|
if (c->fullscreen) {
|
||||||
|
place_window_above_sibling(c->window, monitor->bar_window);
|
||||||
|
} else if (!c->floating) {
|
||||||
|
place_window_below_sibling(c->window, sibling);
|
||||||
|
sibling = c->window;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flush_xcb_connection();
|
||||||
|
while (xcb_check_mask_event(XCB_EVENT_MASK_ENTER_WINDOW));
|
||||||
}
|
}
|
||||||
void focus(client_t *client) {
|
void focus(client_t *client) {
|
||||||
if (!client || !CLIENT_VISIBLE(client)) {
|
if (!client || !CLIENT_VISIBLE(client)) {
|
||||||
@@ -854,6 +925,26 @@ void unfocus(client_t *client, bool set_focus) {
|
|||||||
if (set_focus) focus_window(WINDOW_NONE);
|
if (set_focus) focus_window(WINDOW_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_client_fullscreen(client_t *client, bool fullscreen) {
|
||||||
|
set_window_fullscreen_state(client->window, true);
|
||||||
|
client->fullscreen = fullscreen;
|
||||||
|
if (fullscreen) {
|
||||||
|
fullscreen_client(client);
|
||||||
|
configure_window(client->window, client->x, client->y, client->width,
|
||||||
|
client->height, client->border_width);
|
||||||
|
raise_window(client->window);
|
||||||
|
} else {
|
||||||
|
client->x = client->old_x;
|
||||||
|
client->y = client->old_y;
|
||||||
|
client->width = client->old_width;
|
||||||
|
client->height = client->old_height;
|
||||||
|
client->border_width = client->old_border_width;
|
||||||
|
configure_window(client->window, client->x, client->y, client->width,
|
||||||
|
client->height, client->border_width);
|
||||||
|
arrange(client->monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void show_hide_client(client_t *client) {
|
void show_hide_client(client_t *client) {
|
||||||
if (!client) return;
|
if (!client) return;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xcb_event.h>
|
#include <xcb/xcb_event.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
@@ -112,9 +113,15 @@ static void convert_event(xcb_generic_event_t *xcb_event,
|
|||||||
event->property_notify.state = ev->state;
|
event->property_notify.state = ev->state;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XCB_CLIENT_MESSAGE:
|
case XCB_CLIENT_MESSAGE: {
|
||||||
event->type = EVENT_TYPE_CLIENT_MESSAGE;
|
xcb_client_message_event_t *ev = (xcb_client_message_event_t *)xcb_event;
|
||||||
|
event->client_message.type = EVENT_TYPE_CLIENT_MESSAGE;
|
||||||
|
event->client_message.window = ev->window;
|
||||||
|
event->client_message.message_type = ev->type;
|
||||||
|
event->client_message.format = ev->format;
|
||||||
|
memcpy(&event->client_message.data, &ev->data, sizeof(ev->data));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
event->type = -1;
|
event->type = -1;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -238,9 +238,9 @@ window_geometry_t *get_window_geometry(xcb_window_t window) {
|
|||||||
return geometry;
|
return geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void map_window(xcb_window_t window) {
|
void map_window(xcb_window_t window, bool map_sub_window) {
|
||||||
xcb_map_window(conn, window);
|
xcb_map_window(conn, window);
|
||||||
xcb_map_subwindows(conn, window);
|
if (map_sub_window) xcb_map_subwindows(conn, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *get_window_name(xcb_window_t window) {
|
char *get_window_name(xcb_window_t window) {
|
||||||
@@ -300,3 +300,43 @@ void focus_window(xcb_window_t window) {
|
|||||||
send_event(window, atom_wm_take_focus);
|
send_event(window, atom_wm_take_focus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void raise_window(xcb_window_t window) {
|
||||||
|
xcb_params_configure_window_t params = {.stack_mode = XCB_STACK_MODE_TOP_IF};
|
||||||
|
xcb_aux_configure_window(conn, window, XCB_CONFIG_WINDOW_STACK_MODE, ¶ms);
|
||||||
|
xcb_flush(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void place_window_above_sibling(xcb_window_t window, xcb_window_t sibling) {
|
||||||
|
uint16_t mask = XCB_CONFIG_WINDOW_STACK_MODE | XCB_CONFIG_WINDOW_SIBLING;
|
||||||
|
xcb_params_configure_window_t params = {
|
||||||
|
.stack_mode = XCB_STACK_MODE_ABOVE,
|
||||||
|
.sibling = sibling,
|
||||||
|
};
|
||||||
|
xcb_aux_configure_window(conn, window, mask, ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void place_window_below_sibling(xcb_window_t window, xcb_window_t sibling) {
|
||||||
|
uint16_t mask = XCB_CONFIG_WINDOW_STACK_MODE | XCB_CONFIG_WINDOW_SIBLING;
|
||||||
|
xcb_params_configure_window_t params = {
|
||||||
|
.stack_mode = XCB_STACK_MODE_BELOW,
|
||||||
|
.sibling = sibling,
|
||||||
|
};
|
||||||
|
xcb_aux_configure_window(conn, window, mask, ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kill_window(xcb_window_t window) {
|
||||||
|
xcb_grab_server(conn);
|
||||||
|
xcb_set_close_down_mode(conn, XCB_CLOSE_DOWN_DESTROY_ALL);
|
||||||
|
xcb_kill_client(conn, window);
|
||||||
|
xcb_flush(conn);
|
||||||
|
xcb_ungrab_server(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_window_fullscreen_state(xcb_window_t window, bool fullscreen) {
|
||||||
|
xcb_atom_t atom = fullscreen ? ewmh->_NET_WM_STATE_FULLSCREEN : 0;
|
||||||
|
uint32_t data_len = fullscreen ? 1 : 0;
|
||||||
|
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, window, atom,
|
||||||
|
XCB_ATOM_WINDOW, 32, data_len, &atom);
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ static atom_map_t atom_map[] = {
|
|||||||
{.atom = atom_wm_delete, .name = "WM_DELETE_WINDOW"},
|
{.atom = atom_wm_delete, .name = "WM_DELETE_WINDOW"},
|
||||||
{.atom = atom_wm_take_focus, .name = "WM_TAKE_FOCUS"},
|
{.atom = atom_wm_take_focus, .name = "WM_TAKE_FOCUS"},
|
||||||
{.atom = atom_net_wm_name, .name = "_NET_WM_NAME"},
|
{.atom = atom_net_wm_name, .name = "_NET_WM_NAME"},
|
||||||
|
{.atom = atom_net_wm_state, .name = "_NET_WM_STATE"},
|
||||||
|
{.atom = atom_net_wm_fullscreen, .name = "_NET_WM_STATE_FULLSCREEN"},
|
||||||
{.atom = atom__xrootpmap_id, .name = "_XROOTPMAP_ID"},
|
{.atom = atom__xrootpmap_id, .name = "_XROOTPMAP_ID"},
|
||||||
{.atom = atom_esetroot_pmap_id, .name = "ESETROOT_PMAP_ID"},
|
{.atom = atom_esetroot_pmap_id, .name = "ESETROOT_PMAP_ID"},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -285,6 +285,7 @@ void free_window_list(window_list_t *window_list) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void clean_xcb(void) {
|
void clean_xcb(void) {
|
||||||
|
focus_window(XCB_WINDOW_NONE);
|
||||||
clean_xcb_cursor();
|
clean_xcb_cursor();
|
||||||
clean_ewmh_extension();
|
clean_ewmh_extension();
|
||||||
xcb_disconnect(conn);
|
xcb_disconnect(conn);
|
||||||
@@ -331,3 +332,12 @@ bool get_pointer_position(int32_t *x, int32_t *y) {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool xcb_check_mask_event(xcb_event_mask_t event_mask) {
|
||||||
|
xcb_generic_event_t *event = xcb_poll_for_event(conn);
|
||||||
|
if (!event) return false;
|
||||||
|
|
||||||
|
bool result = XCB_EVENT_RESPONSE_TYPE(event) == event_mask;
|
||||||
|
free(event);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user