扫描窗口管理器启动时需要管理的窗口
This commit is contained in:
@@ -27,6 +27,7 @@ find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(XCB REQUIRED
|
||||
xcb
|
||||
xcb-cursor
|
||||
xcb-ewmh
|
||||
xcb-icccm
|
||||
xcb-keysyms
|
||||
xcb-util
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
bool has_other_wm_running(void);
|
||||
|
||||
typedef struct monitor_rect_t monitor_rect_t;
|
||||
struct monitor_rect_t {
|
||||
@@ -11,6 +14,11 @@ struct monitor_rect_t {
|
||||
uint32_t height;
|
||||
monitor_rect_t *next;
|
||||
};
|
||||
|
||||
bool has_other_wm_running(void);
|
||||
monitor_rect_t *detect_monitor_rect(void);
|
||||
|
||||
typedef struct window_list_t {
|
||||
uint32_t count;
|
||||
xcb_window_t *list;
|
||||
} window_list_t;
|
||||
window_list_t *scan_window_list(void);
|
||||
void free_window_list(window_list_t *window_list);
|
||||
|
||||
11
src/main.c
11
src/main.c
@@ -21,5 +21,16 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
window_list_t *window_list = scan_window_list();
|
||||
if (window_list) {
|
||||
for (uint32_t i = 0; i < window_list->count; i++) {
|
||||
printf("window[%u]: 0x%x\n", i, window_list->list[i]);
|
||||
}
|
||||
} else {
|
||||
printf("no window\n");
|
||||
}
|
||||
|
||||
free_window_list(window_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
extern xcb_connection_t *conn;
|
||||
extern xcb_screen_t *screen;
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
#include "xcb.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_aux.h>
|
||||
#include <xcb/xcb_ewmh.h>
|
||||
#include <xcb/xcb_icccm.h>
|
||||
#include <xcb/xinerama.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "xcb-private.h"
|
||||
|
||||
xcb_connection_t *conn = NULL;
|
||||
xcb_screen_t *screen = NULL;
|
||||
|
||||
bool has_other_wm_running(void) {
|
||||
conn = xcb_connect(NULL, NULL);
|
||||
@@ -17,7 +23,7 @@ bool has_other_wm_running(void) {
|
||||
|
||||
const xcb_setup_t *setup = xcb_get_setup(conn);
|
||||
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
|
||||
xcb_screen_t *screen = iter.data;
|
||||
screen = iter.data;
|
||||
uint32_t mask = XCB_CW_EVENT_MASK;
|
||||
xcb_params_cw_t params = {
|
||||
.event_mask = XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_ENTER_WINDOW |
|
||||
@@ -36,6 +42,14 @@ bool has_other_wm_running(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 xinerama 扩展探测每个屏幕的配置信息
|
||||
*
|
||||
* @TODO: 后续考虑兼容无 xinerama 扩展或扩展未启用的情况
|
||||
* 当前仅需函数在自己环境下能正常工作即可,先不考虑其他环境
|
||||
*
|
||||
* @note: 返回值使用完后记得释放其内存
|
||||
*/
|
||||
monitor_rect_t *detect_monitor_rect(void) {
|
||||
monitor_rect_t *list, *prev;
|
||||
xcb_xinerama_query_screens_cookie_t cookie = xcb_xinerama_query_screens(conn);
|
||||
@@ -68,3 +82,73 @@ monitor_rect_t *detect_monitor_rect(void) {
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static xcb_ewmh_connection_t *ewmh = NULL;
|
||||
static void init_ewmh_extension(void) {
|
||||
if (ewmh) return;
|
||||
|
||||
ewmh = ecalloc(1, sizeof(xcb_ewmh_connection_t));
|
||||
xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(conn, ewmh);
|
||||
if (!xcb_ewmh_init_atoms_replies(ewmh, cookie, NULL)) {
|
||||
free(ewmh);
|
||||
ewmh = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
screen = ewmh->screens[ewmh->nb_screens - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描窗口列表
|
||||
* @returns 若无窗口,返回 NULL,否则返回窗口列表
|
||||
* @note: 返回的窗口列表数据使用完后使用 free_window_list 释放
|
||||
*/
|
||||
window_list_t *scan_window_list(void) {
|
||||
init_ewmh_extension();
|
||||
|
||||
xcb_query_tree_cookie_t cookie = xcb_query_tree(conn, screen->root);
|
||||
xcb_query_tree_reply_t *reply = xcb_query_tree_reply(conn, cookie, NULL);
|
||||
xcb_window_t *list = xcb_query_tree_children(reply);
|
||||
int len = xcb_query_tree_children_length(reply);
|
||||
|
||||
uint32_t count = 0;
|
||||
xcb_window_t temp_windoow_array[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
xcb_window_t window = list[i];
|
||||
|
||||
xcb_get_window_attributes_cookie_t wa_cookie =
|
||||
xcb_get_window_attributes(conn, window);
|
||||
xcb_get_window_attributes_reply_t *reply =
|
||||
xcb_get_window_attributes_reply(conn, wa_cookie, NULL);
|
||||
uint8_t override_redirect = reply->override_redirect;
|
||||
uint8_t map_state = reply->map_state;
|
||||
free(reply);
|
||||
if (override_redirect || map_state != XCB_MAP_STATE_VIEWABLE) continue;
|
||||
|
||||
xcb_window_t transient_for = XCB_NONE;
|
||||
xcb_get_property_cookie_t p_cookie =
|
||||
xcb_icccm_get_wm_transient_for(conn, window);
|
||||
xcb_icccm_get_wm_transient_for_reply(conn, p_cookie, &transient_for, NULL);
|
||||
if (transient_for != XCB_NONE) continue;
|
||||
|
||||
temp_windoow_array[count] = window;
|
||||
count++;
|
||||
}
|
||||
|
||||
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_windoow_array[i];
|
||||
|
||||
window_list_t *r = ecalloc(1, sizeof(window_list_t));
|
||||
r->count = count;
|
||||
r->list = window_list;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void free_window_list(window_list_t *window_list) {
|
||||
if (window_list == NULL) return;
|
||||
free(window_list->list);
|
||||
free(window_list);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user