Compare commits
5 Commits
ef1f71e92f
...
194816ec2d
| Author | SHA1 | Date | |
|---|---|---|---|
|
194816ec2d
|
|||
|
0c029b7bfd
|
|||
|
ffc39cd2bf
|
|||
|
db4bcfcb81
|
|||
|
9594b84237
|
@@ -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
|
||||||
|
|||||||
73
src/client.c
73
src/client.c
@@ -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,
|
||||||
|
¶ms);
|
||||||
|
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,
|
|
||||||
¶ms);
|
|
||||||
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, ¶ms);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
21
src/event.c
21
src/event.c
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
34
src/wm.c
34
src/wm.c
@@ -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, ¶ms);
|
||||||
¶ms);
|
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
|
|||||||
1
src/wm.h
1
src/wm.h
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user