Compare commits

...

5 Commits

8 changed files with 120 additions and 29 deletions

View File

@@ -12,3 +12,4 @@ COMPOUND_TEXT
_NET_ACTIVE_WINDOW _NET_ACTIVE_WINDOW
_NET_WM_NAME _NET_WM_NAME
_NET_WM_ICON_NAME _NET_WM_ICON_NAME
_NET_SUPPORTING_WM_CHECK

View File

@@ -115,8 +115,24 @@ void client_manage(xcb_window_t window,
client_t *c = p_new(client_t, 1); client_t *c = p_new(client_t, 1);
c->window = window; c->window = window;
client_attach_list(c); client_move_to(c, geometry_reply->x, geometry_reply->y);
client_attach_stack(c); client_resize(c, geometry_reply->width, geometry_reply->height);
client_change_border_width(c, geometry_reply->border_width);
{
const xcb_params_cw_t params = {
.event_mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE |
XCB_EVENT_MASK_PROPERTY_CHANGE |
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,
};
xcb_aux_change_window_attributes(wm.xcb_conn, window, XCB_CW_EVENT_MASK,
&params);
xcb_map_window(wm.xcb_conn, window);
}
client_update_names(c);
xwindow_get_text_property(c->window, WM_WINDOW_ROLE, &c->role);
client_update_wm_hints(c);
{ {
xcb_icccm_get_wm_class_reply_t prop; xcb_icccm_get_wm_class_reply_t prop;
@@ -127,7 +143,6 @@ void client_manage(xcb_window_t window,
c->instance = strdup(prop.instance_name); c->instance = strdup(prop.instance_name);
xcb_icccm_get_wm_class_reply_wipe(&prop); xcb_icccm_get_wm_class_reply_wipe(&prop);
} }
xwindow_get_text_property(c->window, WM_WINDOW_ROLE, &c->role);
} }
{ {
@@ -149,20 +164,12 @@ void client_manage(xcb_window_t window,
client_tags_apply(c); client_tags_apply(c);
} }
monitor_arrange(c->monitor); client_attach_list(c);
{ client_attach_stack(c);
const xcb_params_cw_t params = {
.event_mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE |
XCB_EVENT_MASK_PROPERTY_CHANGE |
XCB_EVENT_MASK_STRUCTURE_NOTIFY,
};
xcb_aux_change_window_attributes(wm.xcb_conn, window, XCB_CW_EVENT_MASK,
&params);
xcb_map_window(wm.xcb_conn, window);
}
client_update_names(c); monitor_arrange(c->monitor);
monitor_draw_bar(c->monitor); monitor_draw_bar(c->monitor);
xcb_flush(wm.xcb_conn); xcb_flush(wm.xcb_conn);
} }
@@ -204,6 +211,29 @@ void client_resize(client_t *client, uint16_t width, uint16_t height) {
width, height); width, height);
} }
void client_change_border_width(client_t *client, uint16_t border_width) {
if (client->border_width == border_width) return;
uint16_t mask = XCB_CONFIG_WINDOW_BORDER_WIDTH;
const xcb_params_configure_window_t params = {.border_width = border_width};
xcb_aux_configure_window(wm.xcb_conn, client->window, mask, &params);
client->border_width = border_width;
}
void client_update_wm_hints(client_t *client) {
xcb_get_property_cookie_t cookie =
xcb_icccm_get_wm_hints(wm.xcb_conn, client->window);
xcb_icccm_wm_hints_t hints;
if (xcb_icccm_get_wm_hints_reply(wm.xcb_conn, cookie, &hints, nullptr)) {
if (client == wm.client_focused &&
(hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY)) {
hints.flags &= ~XCB_ICCCM_WM_HINT_X_URGENCY;
xcb_icccm_set_wm_hints(wm.xcb_conn, client->window, &hints);
} else {
client->urgent = hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY;
}
}
}
void client_unmanage(client_t *client) { void client_unmanage(client_t *client) {
monitor_t *m = client->monitor; monitor_t *m = client->monitor;
@@ -221,6 +251,19 @@ void client_unmanage(client_t *client) {
xcb_flush(wm.xcb_conn); xcb_flush(wm.xcb_conn);
} }
void client_apply_task_geometry(client_t *client, task_in_tag_t *task) {
if (!client || !task || client != task->client) return;
if (task->geometry.x != client->geometry.x ||
task->geometry.y != client->geometry.y) {
client_move_to(client, task->geometry.x, task->geometry.y);
}
if (task->geometry.width != client->geometry.width ||
task->geometry.height != client->geometry.height) {
client_resize(client, task->geometry.width, task->geometry.height);
}
}
bool client_is_visible(client_t *client) { bool client_is_visible(client_t *client) {
return client->tags & client->monitor->selected_tag->mask; return client->tags & client->monitor->selected_tag->mask;
} }

View File

@@ -20,6 +20,8 @@ void client_resize(client_t *client, uint16_t width, uint16_t height);
void client_change_border_color(client_t *client, color_t *color); void client_change_border_color(client_t *client, color_t *color);
void client_change_border_width(client_t *client, uint16_t border_width); void client_change_border_width(client_t *client, uint16_t border_width);
void client_update_wm_hints(client_t *client);
void client_set_floating(client_t *client, bool floating); void client_set_floating(client_t *client, bool floating);
void client_set_fullscreen(client_t *client, bool fullscreen); void client_set_fullscreen(client_t *client, bool fullscreen);
void client_set_maximize(client_t *client, bool maximize); void client_set_maximize(client_t *client, bool maximize);
@@ -43,6 +45,7 @@ void client_set_leader_window(client_t *client, xcb_window_t leader_window);
void client_kill(client_t *client); void client_kill(client_t *client);
void client_unmanage(client_t *client); void client_unmanage(client_t *client);
void client_apply_task_geometry(client_t *client, task_in_tag_t *task);
void client_focus(client_t *client); void client_focus(client_t *client);
void client_stack_raise(client_t *client); void client_stack_raise(client_t *client);

View File

@@ -55,7 +55,23 @@ static void button_press(xcb_button_press_event_t *ev) {
static void configure_request(xcb_configure_request_event_t *ev) { static void configure_request(xcb_configure_request_event_t *ev) {
client_t *client = client_get_by_window(ev->window); client_t *client = client_get_by_window(ev->window);
if (!client) { if (client) {
if (ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) {
client_change_border_width(client, ev->border_width);
} else {
tag_t *tag = client->monitor->selected_tag;
task_in_tag_t *task = client_get_task_in_tag(client, tag);
if (!task || !(client->floating || !tag->layout->arrange)) return;
if (ev->value_mask & XCB_CONFIG_WINDOW_X) task->geometry.x = ev->x;
if (ev->value_mask & XCB_CONFIG_WINDOW_Y) task->geometry.y = ev->y;
if (ev->value_mask & XCB_CONFIG_WINDOW_WIDTH)
task->geometry.width = ev->width;
if (ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
task->geometry.height = ev->height;
client_apply_task_geometry(client, task);
}
} else {
uint16_t value_mask = ev->value_mask; uint16_t value_mask = ev->value_mask;
xcb_configure_window_value_list_t value_list = { xcb_configure_window_value_list_t value_list = {
.x = ev->x, .x = ev->x,
@@ -136,6 +152,9 @@ static void property_notify(xcb_property_notify_event_t *ev) {
} else if (ev->atom == _NET_WM_ICON_NAME) { } else if (ev->atom == _NET_WM_ICON_NAME) {
xwindow_get_text_property(ev->window, ev->atom, &client->net_icon_name); xwindow_get_text_property(ev->window, ev->atom, &client->net_icon_name);
monitor_draw_bar(client->monitor); monitor_draw_bar(client->monitor);
} else if (ev->atom == XCB_ATOM_WM_HINTS) {
client_update_wm_hints(client);
monitor_draw_bar(client->monitor);
} }
} }

View File

@@ -5,7 +5,9 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <xcb/xcb_aux.h> #include <xcb/xcb_aux.h>
#include <xcb/xcb_icccm.h>
#include "app.h"
#include "base.h" #include "base.h"
#include "client.h" #include "client.h"
#include "color.h" #include "color.h"
@@ -119,6 +121,9 @@ void monitor_init_bar(monitor_t *monitor) {
cookie = xcb_map_window(conn, window); cookie = xcb_map_window(conn, window);
if (xcb_request_check(conn, cookie)) fatal("cannot map bar window:"); if (xcb_request_check(conn, cookie)) fatal("cannot map bar window:");
xwindow_set_class_instance(window);
xwindow_set_name_static(window, APP_NAME "_bar");
xcb_aux_sync(conn); xcb_aux_sync(conn);
uint16_t width = monitor->geometry.width; uint16_t width = monitor->geometry.width;
@@ -248,14 +253,7 @@ void monitor_arrange(monitor_t *monitor) {
for (client_t *c = wm.client_list; c; c = c->next) { for (client_t *c = wm.client_list; c; c = c->next) {
task_in_tag_t *task = client_get_task_in_tag(c, tag); task_in_tag_t *task = client_get_task_in_tag(c, tag);
if (task) { if (task) {
if (task->geometry.x != c->geometry.x || client_apply_task_geometry(c, task);
task->geometry.y != c->geometry.y) {
client_move_to(c, task->geometry.x, task->geometry.y);
}
if (task->geometry.width != c->geometry.width ||
task->geometry.height != c->geometry.height) {
client_resize(c, task->geometry.width, task->geometry.height);
}
} else { } else {
int16_t x = -c->geometry.width; int16_t x = -c->geometry.width;
int16_t y = -c->geometry.height; int16_t y = -c->geometry.height;

View File

@@ -5,18 +5,20 @@
#include <glibconfig.h> #include <glibconfig.h>
#include <signal.h> #include <signal.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <xcb/randr.h> #include <xcb/randr.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcb_aux.h> #include <xcb/xcb_aux.h>
#include <xcb/xcb_icccm.h>
#include <xcb/xcb_keysyms.h> #include <xcb/xcb_keysyms.h>
#include <xcb/xfixes.h> #include <xcb/xfixes.h>
#include <xcb/xinerama.h> #include <xcb/xinerama.h>
#include <xcb/xproto.h> #include <xcb/xproto.h>
#include "app.h"
#include "atoms-extern.h"
#include "atoms.h" #include "atoms.h"
#include "backtrace.h" #include "backtrace.h"
#include "buffer.h" #include "buffer.h"
@@ -263,6 +265,9 @@ void wm_clean(void) {
if (source_id) g_source_remove(source_id); if (source_id) g_source_remove(source_id);
} }
xcb_destroy_window(wm.xcb_conn, wm.wm_check_window);
wm.wm_check_window = XCB_WINDOW_NONE;
xcursor_clean(); xcursor_clean();
xkb_free(); xkb_free();
xcb_ungrab_key(wm.xcb_conn, XCB_GRAB_ANY, wm.screen->root, modifier_any); xcb_ungrab_key(wm.xcb_conn, XCB_GRAB_ANY, wm.screen->root, modifier_any);
@@ -290,16 +295,37 @@ static void wm_setup(void) {
monitor_draw_bar(m); monitor_draw_bar(m);
} }
uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
xcb_params_cw_t params = { xcb_params_cw_t params = {
.cursor = xcursor_get_xcb_cursor(cursor_normal), .cursor = xcursor_get_xcb_cursor(cursor_normal),
.event_mask = .event_mask =
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_KEY_PRESS, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_KEY_PRESS,
}; };
xcb_aux_change_window_attributes(wm.xcb_conn, wm.screen->root, XCB_CW_CURSOR, xcb_aux_change_window_attributes(wm.xcb_conn, wm.screen->root, mask, &params);
&params);
wm_setup_keybindings(); wm_setup_keybindings();
atoms_init(wm.xcb_conn); atoms_init(wm.xcb_conn);
{
wm.wm_check_window = xcb_generate_id(wm.xcb_conn);
xcb_create_window(wm.xcb_conn, wm.screen->root_depth, wm.wm_check_window,
wm.screen->root, -1, -1, 1, 1, 0, XCB_COPY_FROM_PARENT,
wm.screen->root_visual, XCB_NONE, nullptr);
xwindow_set_class_instance(wm.wm_check_window);
#define NAME APP_NAME "_wm_check"
xwindow_set_name_static(wm.wm_check_window, NAME);
const void *data = &wm.wm_check_window;
xcb_atom_t type = XCB_ATOM_WINDOW;
uint8_t mode = XCB_PROP_MODE_REPLACE;
xcb_change_property(wm.xcb_conn, mode, wm.wm_check_window, _NET_WM_NAME,
UTF8_STRING, 8, sizeof(NAME) - 1, NAME);
xcb_change_property(wm.xcb_conn, mode, wm.wm_check_window,
_NET_SUPPORTING_WM_CHECK, type, 32, 1, data);
xcb_change_property(wm.xcb_conn, mode, wm.screen->root,
_NET_SUPPORTING_WM_CHECK, type, 32, 1, data);
#undef NAME
}
xkb_init(); xkb_init();
xcb_flush(wm.xcb_conn); xcb_flush(wm.xcb_conn);
} }
@@ -362,8 +388,8 @@ int main(int argc, char *argv[]) {
wm_check_xcb_extensions(); wm_check_xcb_extensions();
wm_detect_monitor(); wm_detect_monitor();
setup_event_loop();
wm_setup(); wm_setup();
setup_event_loop();
debug_show_monitor_list(); debug_show_monitor_list();

View File

@@ -24,6 +24,7 @@ typedef struct wm_t {
xcb_connection_t *xcb_conn; xcb_connection_t *xcb_conn;
xcb_screen_t *screen; xcb_screen_t *screen;
xcb_key_symbols_t *key_symbols; xcb_key_symbols_t *key_symbols;
xcb_window_t wm_check_window;
int default_screen; int default_screen;
bool have_xfixes; bool have_xfixes;
bool have_xinerama; bool have_xinerama;

View File

@@ -184,7 +184,7 @@ void xwindow_get_text_property(xcb_window_t window, xcb_atom_t property,
if (out == nullptr) return; if (out == nullptr) return;
xcb_get_property_cookie_t cookie = xcb_get_property_unchecked( xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(
wm.xcb_conn, false, window, property, XCB_ATOM_STRING, 0, UINT32_MAX); wm.xcb_conn, false, window, property, XCB_ATOM_ANY, 0, UINT32_MAX);
xcb_get_property_reply_t *reply = xcb_get_property_reply_t *reply =
xcb_get_property_reply(wm.xcb_conn, cookie, nullptr); xcb_get_property_reply(wm.xcb_conn, cookie, nullptr);
int length = xcb_get_property_value_length(reply); int length = xcb_get_property_value_length(reply);