Compare commits
4 Commits
7eea0ee2d3
...
8f892633cc
| Author | SHA1 | Date | |
|---|---|---|---|
|
8f892633cc
|
|||
|
165dd0733c
|
|||
|
0039cd2c43
|
|||
|
bac73368e3
|
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <xcb/xproto.h>
|
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
@@ -78,14 +78,18 @@ typedef struct map_request_event_t {
|
|||||||
typedef struct unmap_notify_event_t {
|
typedef struct unmap_notify_event_t {
|
||||||
event_type_t type;
|
event_type_t type;
|
||||||
xcb_window_t window;
|
xcb_window_t window;
|
||||||
|
bool send_event;
|
||||||
} unmap_notify_event_t;
|
} unmap_notify_event_t;
|
||||||
|
|
||||||
typedef struct destroy_notify_event_t {
|
typedef struct destroy_notify_event_t {
|
||||||
event_type_t type;
|
event_type_t type;
|
||||||
|
xcb_window_t window;
|
||||||
} destroy_notify_event_t;
|
} destroy_notify_event_t;
|
||||||
|
|
||||||
typedef struct expose_event_t {
|
typedef struct expose_event_t {
|
||||||
event_type_t type;
|
event_type_t type;
|
||||||
|
xcb_window_t window;
|
||||||
|
uint32_t count;
|
||||||
} expose_event_t;
|
} expose_event_t;
|
||||||
|
|
||||||
typedef struct motion_notify_event_t {
|
typedef struct motion_notify_event_t {
|
||||||
@@ -110,8 +114,15 @@ typedef struct focus_in_event_t {
|
|||||||
xcb_window_t window;
|
xcb_window_t window;
|
||||||
} focus_in_event_t;
|
} focus_in_event_t;
|
||||||
|
|
||||||
|
typedef enum property_state_t {
|
||||||
|
property_new_value = 0,
|
||||||
|
property_delete = 1
|
||||||
|
} property_state_t;
|
||||||
typedef struct property_notify_event_t {
|
typedef struct property_notify_event_t {
|
||||||
event_type_t type;
|
event_type_t type;
|
||||||
|
xcb_window_t window;
|
||||||
|
uint32_t xcb_atom;
|
||||||
|
property_state_t state;
|
||||||
} property_notify_event_t;
|
} property_notify_event_t;
|
||||||
|
|
||||||
typedef struct client_message_event_t {
|
typedef struct client_message_event_t {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ void map_window(xcb_window_t window);
|
|||||||
* @returns 返回窗口名字符串指针,使用完后记得使用 free 释放内存
|
* @returns 返回窗口名字符串指针,使用完后记得使用 free 释放内存
|
||||||
*/
|
*/
|
||||||
char *get_window_name(xcb_window_t window);
|
char *get_window_name(xcb_window_t window);
|
||||||
void init_window_event_mask(xcb_window_t window);
|
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);
|
||||||
|
|
||||||
@@ -84,8 +84,10 @@ rect_size_t *get_screen_size(void);
|
|||||||
void set_wallpaper(uint32_t *wallpaper_data);
|
void set_wallpaper(uint32_t *wallpaper_data);
|
||||||
|
|
||||||
typedef struct window_list_t {
|
typedef struct window_list_t {
|
||||||
uint32_t count;
|
xcb_window_t *normal_list;
|
||||||
xcb_window_t *list;
|
xcb_window_t *transient_list;
|
||||||
|
uint32_t normal_count;
|
||||||
|
uint32_t transient_count;
|
||||||
} window_list_t;
|
} window_list_t;
|
||||||
window_list_t *scan_window_list(void);
|
window_list_t *scan_window_list(void);
|
||||||
void free_window_list(window_list_t *window_list);
|
void free_window_list(window_list_t *window_list);
|
||||||
@@ -101,7 +103,17 @@ typedef enum atom_t {
|
|||||||
atom_wm_protocols,
|
atom_wm_protocols,
|
||||||
atom_wm_delete,
|
atom_wm_delete,
|
||||||
atom_wm_take_focus,
|
atom_wm_take_focus,
|
||||||
|
atom_net_wm_name,
|
||||||
} atom_t;
|
} atom_t;
|
||||||
|
xcb_atom_t get_xcb_atom(atom_t atom);
|
||||||
bool send_event(xcb_window_t window, atom_t atom);
|
bool send_event(xcb_window_t window, atom_t atom);
|
||||||
|
typedef enum wm_state_t {
|
||||||
|
wm_state_withdrawn = 0,
|
||||||
|
wm_state_normal = 1,
|
||||||
|
wm_state_iconic = 3
|
||||||
|
} wm_state_t;
|
||||||
|
int32_t get_window_state(xcb_window_t window);
|
||||||
|
void set_window_state(xcb_window_t window, wm_state_t state);
|
||||||
|
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);
|
||||||
|
|||||||
127
src/main.c
127
src/main.c
@@ -10,6 +10,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@@ -39,11 +40,15 @@ static void key_press(key_press_event_t *event);
|
|||||||
static void configure_request(configure_request_event_t *event);
|
static void configure_request(configure_request_event_t *event);
|
||||||
static void map_request(map_request_event_t *event);
|
static void map_request(map_request_event_t *event);
|
||||||
static void unmap_notify(unmap_notify_event_t *event);
|
static void unmap_notify(unmap_notify_event_t *event);
|
||||||
|
static void destroy_notify(destroy_notify_event_t *event);
|
||||||
|
static void expose(expose_event_t *event);
|
||||||
static void motion_notify(motion_notify_event_t *event);
|
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 manage_window(xcb_window_t window);
|
static void manage_window(xcb_window_t window);
|
||||||
static void unmanage_client(client_t *client);
|
static void unmanage_client(client_t *client, bool destroyed);
|
||||||
|
static void update_client_list(void);
|
||||||
static void update_client_name(client_t *client);
|
static void update_client_name(client_t *client);
|
||||||
static void apply_rules(client_t *client);
|
static void apply_rules(client_t *client);
|
||||||
static uint32_t get_tags_mask_of_monitor(monitor_t *monitor);
|
static uint32_t get_tags_mask_of_monitor(monitor_t *monitor);
|
||||||
@@ -146,8 +151,11 @@ static void print_window_list(window_list_t *window_list) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < window_list->count; i++) {
|
for (uint32_t i = 0; i < window_list->normal_count; i++) {
|
||||||
logger("window[%u]: 0x%x\n", i, window_list->list[i]);
|
logger("normal window[%u]: 0x%x\n", i, window_list->normal_list[i]);
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < window_list->transient_count; i++) {
|
||||||
|
logger("transient window[%u]: 0x%x\n", i, window_list->transient_list[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static char *bool2string(bool b) { return b ? "true" : "false"; }
|
static char *bool2string(bool b) { return b ? "true" : "false"; }
|
||||||
@@ -462,9 +470,12 @@ void xcb_event_handler(generic_event_t *event, void *user_data) {
|
|||||||
EVENT(EVENT_TYPE_CONFIGURE_REQUEST, configure_request);
|
EVENT(EVENT_TYPE_CONFIGURE_REQUEST, configure_request);
|
||||||
EVENT(EVENT_TYPE_MAP_REQUEST, map_request);
|
EVENT(EVENT_TYPE_MAP_REQUEST, map_request);
|
||||||
EVENT(EVENT_TYPE_UNMAP_NOTIFY, unmap_notify);
|
EVENT(EVENT_TYPE_UNMAP_NOTIFY, unmap_notify);
|
||||||
|
EVENT(EVENT_TYPE_DESTROY_NOTIFY, destroy_notify);
|
||||||
|
EVENT(EVENT_TYPE_EXPOSE, expose);
|
||||||
EVENT(EVENT_TYPE_MOTION_NOTIFY, motion_notify);
|
EVENT(EVENT_TYPE_MOTION_NOTIFY, motion_notify);
|
||||||
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);
|
||||||
|
|
||||||
#undef EVENT
|
#undef EVENT
|
||||||
|
|
||||||
@@ -509,7 +520,23 @@ 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);
|
||||||
if (c) {
|
if (c) {
|
||||||
unmanage_client(c);
|
if (event->send_event) {
|
||||||
|
set_window_state(event->window, wm_state_withdrawn);
|
||||||
|
} else {
|
||||||
|
unmanage_client(c, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_notify(destroy_notify_event_t *event) {
|
||||||
|
client_t *c = get_client_of_window(event->window);
|
||||||
|
if (c) unmanage_client(c, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expose(expose_event_t *event) {
|
||||||
|
monitor_t *m = NULL;
|
||||||
|
if (event->count == 0 && (m = get_monitor_of_window(event->window))) {
|
||||||
|
draw_monitor_bar(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,6 +582,32 @@ void focus_in(focus_in_event_t *event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void property_notify(property_notify_event_t *event) {
|
||||||
|
if (event->state == property_delete) return;
|
||||||
|
|
||||||
|
client_t *c = get_client_of_window(event->window);
|
||||||
|
if (!c) return;
|
||||||
|
switch (event->xcb_atom) {
|
||||||
|
case XCB_ATOM_WM_TRANSIENT_FOR: {
|
||||||
|
xcb_window_t transient_for;
|
||||||
|
if (!c->floating &&
|
||||||
|
((transient_for = get_transient_window_for(event->window)) !=
|
||||||
|
WINDOW_NONE) &&
|
||||||
|
(c->floating = (get_client_of_window(transient_for) != NULL))) {
|
||||||
|
arrange(c->monitor);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (event->xcb_atom == XCB_ATOM_WM_NAME ||
|
||||||
|
event->xcb_atom == get_xcb_atom(atom_net_wm_name)) {
|
||||||
|
update_client_name(c);
|
||||||
|
if (c->tags & c->monitor->selected_tags) draw_monitor_bar(c->monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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));
|
||||||
@@ -583,7 +636,7 @@ void manage_window(xcb_window_t window) {
|
|||||||
|
|
||||||
attach_client(c);
|
attach_client(c);
|
||||||
attach_stack_client(c);
|
attach_stack_client(c);
|
||||||
init_window_event_mask(window);
|
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);
|
||||||
if (c->monitor == current_monitor) {
|
if (c->monitor == current_monitor) {
|
||||||
unfocus(current_monitor->selected_client, false);
|
unfocus(current_monitor->selected_client, false);
|
||||||
@@ -593,14 +646,41 @@ void manage_window(xcb_window_t window) {
|
|||||||
focus(NULL);
|
focus(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unmanage_client(client_t *client) {
|
void unmanage_client(client_t *client, bool destroyed) {
|
||||||
monitor_t *monitor = client->monitor;
|
monitor_t *monitor = client->monitor;
|
||||||
|
|
||||||
detach_client(client);
|
detach_client(client);
|
||||||
detach_stack_client(client);
|
detach_stack_client(client);
|
||||||
|
if (!destroyed) {
|
||||||
|
set_window_event_mask(client->window, true);
|
||||||
|
configure_window(client->window, client->x, client->y, client->width,
|
||||||
|
client->height, client->old_border_width);
|
||||||
|
set_window_state(client->window, wm_state_withdrawn);
|
||||||
|
flush_xcb_connection();
|
||||||
|
}
|
||||||
free(client);
|
free(client);
|
||||||
|
focus(NULL);
|
||||||
|
update_client_list();
|
||||||
arrange(monitor);
|
arrange(monitor);
|
||||||
flush_xcb_connection();
|
}
|
||||||
|
|
||||||
|
void update_client_list(void) {
|
||||||
|
uint32_t length = 0;
|
||||||
|
for (monitor_t *m = monitors; m; m = m->next) {
|
||||||
|
for (client_t *c = m->clients; c; c = c->next) length++;
|
||||||
|
}
|
||||||
|
if (!length) {
|
||||||
|
set_window_list(NULL, length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_window_t *list = ecalloc(length, sizeof(xcb_window_t));
|
||||||
|
uint32_t i = 0;
|
||||||
|
for (monitor_t *m = monitors; m; m = m->next) {
|
||||||
|
for (client_t *c = m->clients; c; c = c->next) list[i++] = c->window;
|
||||||
|
}
|
||||||
|
set_window_list(list, length);
|
||||||
|
free(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_client_name(client_t *client) {
|
void update_client_name(client_t *client) {
|
||||||
@@ -823,23 +903,12 @@ gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cleanup(void) {
|
void cleanup(void) {
|
||||||
clean_pango_context();
|
|
||||||
|
|
||||||
free_wallpaper_config(wallpaper_config);
|
|
||||||
wallpaper_config = NULL;
|
|
||||||
|
|
||||||
free(color_set);
|
|
||||||
color_set = NULL;
|
|
||||||
|
|
||||||
free(font_family);
|
|
||||||
font_family = NULL;
|
|
||||||
|
|
||||||
monitor_t *m = monitors;
|
monitor_t *m = monitors;
|
||||||
client_t *c = m->clients;
|
client_t *c = m->clients;
|
||||||
while (m) {
|
while (m) {
|
||||||
while (c) {
|
while (c) {
|
||||||
client_t *tc = c->next;
|
client_t *tc = c->next;
|
||||||
free(c);
|
unmanage_client(c, false);
|
||||||
c = tc;
|
c = tc;
|
||||||
}
|
}
|
||||||
monitor_t *next_monitor = m->next;
|
monitor_t *next_monitor = m->next;
|
||||||
@@ -851,6 +920,17 @@ void cleanup(void) {
|
|||||||
}
|
}
|
||||||
monitors = NULL;
|
monitors = NULL;
|
||||||
|
|
||||||
|
clean_pango_context();
|
||||||
|
|
||||||
|
free_wallpaper_config(wallpaper_config);
|
||||||
|
wallpaper_config = NULL;
|
||||||
|
|
||||||
|
free(color_set);
|
||||||
|
color_set = NULL;
|
||||||
|
|
||||||
|
free(font_family);
|
||||||
|
font_family = NULL;
|
||||||
|
|
||||||
destroy_event_adapter(adapter);
|
destroy_event_adapter(adapter);
|
||||||
adapter = NULL;
|
adapter = NULL;
|
||||||
|
|
||||||
@@ -877,6 +957,15 @@ int main(int argc, char *argv[]) {
|
|||||||
print_wallpaper_config(wallpaper_config);
|
print_wallpaper_config(wallpaper_config);
|
||||||
print_window_list(window_list);
|
print_window_list(window_list);
|
||||||
|
|
||||||
|
if (window_list) {
|
||||||
|
for (uint32_t i = 0; i < window_list->normal_count; i++) {
|
||||||
|
manage_window(window_list->normal_list[i]);
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < window_list->transient_count; i++) {
|
||||||
|
manage_window(window_list->transient_list[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free_window_list(window_list);
|
free_window_list(window_list);
|
||||||
|
|
||||||
grab_keybindings(keys, LENGTH(keys));
|
grab_keybindings(keys, LENGTH(keys));
|
||||||
|
|||||||
@@ -65,13 +65,21 @@ static void convert_event(xcb_generic_event_t *xcb_event,
|
|||||||
xcb_unmap_notify_event_t *ev = (xcb_unmap_notify_event_t *)xcb_event;
|
xcb_unmap_notify_event_t *ev = (xcb_unmap_notify_event_t *)xcb_event;
|
||||||
event->unmap_notify.type = EVENT_TYPE_UNMAP_NOTIFY;
|
event->unmap_notify.type = EVENT_TYPE_UNMAP_NOTIFY;
|
||||||
event->unmap_notify.window = ev->window;
|
event->unmap_notify.window = ev->window;
|
||||||
|
event->unmap_notify.send_event = XCB_EVENT_SENT(ev);
|
||||||
} break;
|
} break;
|
||||||
case XCB_DESTROY_NOTIFY:
|
case XCB_DESTROY_NOTIFY: {
|
||||||
event->type = EVENT_TYPE_DESTROY_NOTIFY;
|
xcb_destroy_notify_event_t *ev = (xcb_destroy_notify_event_t *)xcb_event;
|
||||||
|
event->destroy_notify.type = EVENT_TYPE_DESTROY_NOTIFY;
|
||||||
|
event->destroy_notify.window = ev->window;
|
||||||
break;
|
break;
|
||||||
case XCB_EXPOSE:
|
}
|
||||||
event->type = EVENT_TYPE_EXPOSE;
|
case XCB_EXPOSE: {
|
||||||
|
xcb_expose_event_t *ev = (xcb_expose_event_t *)xcb_event;
|
||||||
|
event->expose.type = EVENT_TYPE_EXPOSE;
|
||||||
|
event->expose.window = ev->window;
|
||||||
|
event->expose.count = ev->count;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case XCB_MOTION_NOTIFY: {
|
case XCB_MOTION_NOTIFY: {
|
||||||
xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)xcb_event;
|
xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)xcb_event;
|
||||||
event->motiion_notify.type = EVENT_TYPE_MOTION_NOTIFY;
|
event->motiion_notify.type = EVENT_TYPE_MOTION_NOTIFY;
|
||||||
@@ -96,9 +104,15 @@ static void convert_event(xcb_generic_event_t *xcb_event,
|
|||||||
event->focus_in.type = EVENT_TYPE_FOCUS_IN;
|
event->focus_in.type = EVENT_TYPE_FOCUS_IN;
|
||||||
event->focus_in.window = ev->event;
|
event->focus_in.window = ev->event;
|
||||||
} break;
|
} break;
|
||||||
case XCB_PROPERTY_NOTIFY:
|
case XCB_PROPERTY_NOTIFY: {
|
||||||
event->type = EVENT_TYPE_PROPERTY_NOTIFY;
|
xcb_property_notify_event_t *ev =
|
||||||
|
(xcb_property_notify_event_t *)xcb_event;
|
||||||
|
event->property_notify.type = EVENT_TYPE_PROPERTY_NOTIFY;
|
||||||
|
event->property_notify.window = ev->window;
|
||||||
|
event->property_notify.xcb_atom = ev->atom;
|
||||||
|
event->property_notify.state = ev->state;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case XCB_CLIENT_MESSAGE:
|
case XCB_CLIENT_MESSAGE:
|
||||||
event->type = EVENT_TYPE_CLIENT_MESSAGE;
|
event->type = EVENT_TYPE_CLIENT_MESSAGE;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -218,11 +218,14 @@ bool get_window_visible(xcb_window_t window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
xcb_window_t get_transient_window_for(xcb_window_t window) {
|
xcb_window_t get_transient_window_for(xcb_window_t window) {
|
||||||
xcb_window_t transient_for = XCB_NONE;
|
xcb_window_t transient_for = WINDOW_NONE;
|
||||||
xcb_get_property_cookie_t cookie =
|
xcb_get_property_cookie_t cookie =
|
||||||
xcb_icccm_get_wm_transient_for(conn, window);
|
xcb_icccm_get_wm_transient_for(conn, window);
|
||||||
xcb_icccm_get_wm_transient_for_reply(conn, cookie, &transient_for, NULL);
|
if (xcb_icccm_get_wm_transient_for_reply(conn, cookie, &transient_for,
|
||||||
return transient_for;
|
NULL)) {
|
||||||
|
return transient_for;
|
||||||
|
}
|
||||||
|
return WINDOW_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
window_geometry_t *get_window_geometry(xcb_window_t window) {
|
window_geometry_t *get_window_geometry(xcb_window_t window) {
|
||||||
@@ -271,13 +274,14 @@ char *get_window_name(xcb_window_t window) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_window_event_mask(xcb_window_t window) {
|
void set_window_event_mask(xcb_window_t window, bool clear) {
|
||||||
xcb_cw_t change_mask = XCB_CW_EVENT_MASK;
|
xcb_cw_t change_mask = XCB_CW_EVENT_MASK;
|
||||||
xcb_params_cw_t params = {
|
uint32_t event_mask = clear ? XCB_EVENT_MASK_NO_EVENT
|
||||||
.event_mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE |
|
: XCB_EVENT_MASK_ENTER_WINDOW |
|
||||||
XCB_EVENT_MASK_PROPERTY_CHANGE |
|
XCB_EVENT_MASK_FOCUS_CHANGE |
|
||||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,
|
XCB_EVENT_MASK_PROPERTY_CHANGE |
|
||||||
};
|
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
|
||||||
|
xcb_params_cw_t params = {.event_mask = event_mask};
|
||||||
xcb_aux_change_window_attributes(conn, window, change_mask, ¶ms);
|
xcb_aux_change_window_attributes(conn, window, change_mask, ¶ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_ewmh.h>
|
||||||
#include <xcb/xcb_icccm.h>
|
#include <xcb/xcb_icccm.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ static atom_map_t atom_map[] = {
|
|||||||
{.atom = atom_wm_protocols, .name = "WM_PROTOCOLS"},
|
{.atom = atom_wm_protocols, .name = "WM_PROTOCOLS"},
|
||||||
{.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"},
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_icccm_extension(void) {
|
void init_icccm_extension(void) {
|
||||||
@@ -96,6 +98,11 @@ void clean_ewmh_extension(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xcb_atom_t get_xcb_atom(atom_t atom) {
|
||||||
|
if (atom < 0 || atom >= LENGTH(atom_map)) return XCB_ATOM_NONE;
|
||||||
|
return atom_map[atom].xcb_atom;
|
||||||
|
}
|
||||||
|
|
||||||
bool send_event(xcb_window_t window, atom_t atom) {
|
bool send_event(xcb_window_t window, atom_t atom) {
|
||||||
if (atom < 0 || atom >= LENGTH(atom_map)) return false;
|
if (atom < 0 || atom >= LENGTH(atom_map)) return false;
|
||||||
|
|
||||||
@@ -125,3 +132,38 @@ bool send_event(xcb_window_t window, atom_t atom) {
|
|||||||
|
|
||||||
return exist;
|
return exist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t get_window_state(xcb_window_t window) {
|
||||||
|
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, NULL)) return -1;
|
||||||
|
return hints.initial_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_window_state(xcb_window_t window, wm_state_t state) {
|
||||||
|
xcb_icccm_wm_hints_t hints;
|
||||||
|
xcb_icccm_wm_hints_set_none(&hints);
|
||||||
|
switch (state) {
|
||||||
|
case wm_state_withdrawn:
|
||||||
|
xcb_icccm_wm_hints_set_withdrawn(&hints);
|
||||||
|
break;
|
||||||
|
case wm_state_normal:
|
||||||
|
xcb_icccm_wm_hints_set_normal(&hints);
|
||||||
|
break;
|
||||||
|
case wm_state_iconic:
|
||||||
|
xcb_icccm_wm_hints_set_iconic(&hints);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xcb_icccm_set_wm_hints(conn, window, &hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_window_list(xcb_window_t *list, uint32_t length) {
|
||||||
|
int screen_nbr = 0;
|
||||||
|
for (int i = 0; i < ewmh->nb_screens; i++) {
|
||||||
|
if (screen == ewmh->screens[i]) {
|
||||||
|
screen_nbr = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xcb_ewmh_set_client_list(ewmh, screen_nbr, length, list);
|
||||||
|
}
|
||||||
|
|||||||
@@ -184,9 +184,11 @@ window_list_t *scan_window_list(void) {
|
|||||||
|
|
||||||
xcb_window_t *list = xcb_query_tree_children(tree_reply);
|
xcb_window_t *list = xcb_query_tree_children(tree_reply);
|
||||||
int len = xcb_query_tree_children_length(tree_reply);
|
int len = xcb_query_tree_children_length(tree_reply);
|
||||||
|
if (!len) return NULL;
|
||||||
|
|
||||||
uint32_t count = 0;
|
uint32_t normal_count = 0, transient_count = 0;
|
||||||
xcb_window_t temp_window_array[len];
|
xcb_window_t *normal_window_array = ecalloc(len, sizeof(xcb_window_t));
|
||||||
|
xcb_window_t *transient_window_array = ecalloc(len, sizeof(xcb_window_t));
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
xcb_window_t window = list[i];
|
xcb_window_t window = list[i];
|
||||||
|
|
||||||
@@ -199,34 +201,34 @@ window_list_t *scan_window_list(void) {
|
|||||||
uint8_t override_redirect = attribute_reply->override_redirect;
|
uint8_t override_redirect = attribute_reply->override_redirect;
|
||||||
uint8_t map_state = attribute_reply->map_state;
|
uint8_t map_state = attribute_reply->map_state;
|
||||||
free(attribute_reply);
|
free(attribute_reply);
|
||||||
if (override_redirect || map_state != XCB_MAP_STATE_VIEWABLE) continue;
|
if (!(map_state == XCB_MAP_STATE_VIEWABLE ||
|
||||||
|
get_window_state(window) == wm_state_iconic)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
xcb_window_t transient_for = XCB_NONE;
|
xcb_window_t transient_for = get_transient_window_for(window);
|
||||||
xcb_get_property_cookie_t p_cookie =
|
if (transient_for) {
|
||||||
xcb_icccm_get_wm_transient_for(conn, window);
|
transient_window_array[transient_count++] = window;
|
||||||
xcb_icccm_get_wm_transient_for_reply(conn, p_cookie, &transient_for, NULL);
|
} else if (!override_redirect) {
|
||||||
if (transient_for != XCB_NONE) continue;
|
normal_window_array[normal_count++] = window;
|
||||||
|
}
|
||||||
temp_window_array[count] = window;
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
free(tree_reply);
|
free(tree_reply);
|
||||||
|
|
||||||
if (!count) return NULL;
|
|
||||||
|
|
||||||
xcb_window_t *window_list = ecalloc(count, sizeof(xcb_window_t));
|
|
||||||
for (uint32_t i = 0; i < count; i++) window_list[i] = temp_window_array[i];
|
|
||||||
|
|
||||||
window_list_t *r = ecalloc(1, sizeof(window_list_t));
|
window_list_t *r = ecalloc(1, sizeof(window_list_t));
|
||||||
r->count = count;
|
r->normal_list = normal_window_array;
|
||||||
r->list = window_list;
|
r->transient_list = transient_window_array;
|
||||||
|
r->normal_count = normal_count;
|
||||||
|
r->transient_count = transient_count;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_window_list(window_list_t *window_list) {
|
void free_window_list(window_list_t *window_list) {
|
||||||
if (window_list == NULL) return;
|
if (window_list == NULL) return;
|
||||||
free(window_list->list);
|
|
||||||
|
if (window_list->normal_list) free(window_list->normal_list);
|
||||||
|
if (window_list->transient_list) free(window_list->transient_list);
|
||||||
free(window_list);
|
free(window_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user