Trying to list all windows from _NET_CLIENT_LIST
This commit is contained in:
parent
36cb48c650
commit
a5cf7cabf3
|
@ -1 +1,2 @@
|
|||
scrall
|
||||
*.o
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
CFLAGS += -Wall -Wextra `exec pkg-config --cflags raylib xcb xcb-composite`
|
||||
LDFLAGS := -lm `pkg-config --libs raylib xcb xcb-composite`
|
||||
|
||||
scrall: main.c
|
||||
$(CC) $(CFLAGS) main.c $(LDFLAGS) -o scrall
|
||||
OBJECTS = ./screenshot.o ./windowtree.o
|
||||
|
||||
scrall: main.c $(OBJECTS)
|
||||
$(CC) $(CFLAGS) main.c $(LDFLAGS) -o scrall $(OBJECTS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $^ -o $@
|
||||
|
||||
clean:
|
||||
$(RM) scrall
|
||||
|
|
|
@ -1,85 +1,38 @@
|
|||
// x-run: make run
|
||||
#include <assert.h>
|
||||
#include <raylib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xproto.h>
|
||||
#include <xcb/composite.h>
|
||||
#include "screenshot.h"
|
||||
#include "windowtree.h"
|
||||
|
||||
|
||||
Image get_screenshot(xcb_connection_t *conn, xcb_window_t wid);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
xcb_connection_t *xcb = xcb_connect(NULL, NULL);
|
||||
|
||||
xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
|
||||
|
||||
printf("root: 0x%08x\n", screen->root);
|
||||
|
||||
size_t n_windows;
|
||||
struct window_info *windows = get_windows_list(xcb, &n_windows);
|
||||
|
||||
for (int i = 0; i < n_windows; i++) {
|
||||
printf("0x%08x %02x %s\n", windows[i].wid, windows[i].win_gravity, windows[i].title);
|
||||
}
|
||||
|
||||
xcb_disconnect(xcb);
|
||||
|
||||
return 0;
|
||||
|
||||
SetConfigFlags(FLAG_WINDOW_TRANSPARENT);
|
||||
InitWindow(0, 0, "img/scrall");
|
||||
|
||||
|
||||
Image screenshot = get_screenshot(xcb, 50331654);
|
||||
assert(screenshot.width > 0);
|
||||
|
||||
Texture2D screenshot_tex = LoadTextureFromImage(screenshot);
|
||||
SetWindowSize(screenshot.width, screenshot.height);
|
||||
|
||||
while (!WindowShouldClose()) {
|
||||
BeginDrawing();
|
||||
ClearBackground(BLANK);
|
||||
DrawTexture(screenshot_tex, 0, 0, WHITE);
|
||||
EndDrawing();
|
||||
}
|
||||
}
|
||||
|
||||
Image get_screenshot(xcb_connection_t *conn, xcb_window_t wid) {
|
||||
xcb_generic_error_t *err = NULL;
|
||||
|
||||
xcb_composite_redirect_window(conn, wid, XCB_COMPOSITE_REDIRECT_AUTOMATIC);
|
||||
|
||||
xcb_get_geometry_cookie_t gg_cookie = xcb_get_geometry(conn, wid);
|
||||
xcb_get_geometry_reply_t *gg_reply = xcb_get_geometry_reply(conn, gg_cookie, &err);
|
||||
|
||||
if (!gg_reply) {
|
||||
fprintf(stderr, "xcb: error: geometry: %d\n", err->error_code);
|
||||
return (Image){
|
||||
.data = err, .width = 0, .height = 0, .format = 0, .mipmaps = 0
|
||||
};
|
||||
}
|
||||
|
||||
int win_w = gg_reply->width;
|
||||
int win_h = gg_reply->height;
|
||||
assert(gg_reply->depth == 32);
|
||||
fprintf(stderr, "width: %d\nheight: %d\n", win_w, win_h);
|
||||
|
||||
free(gg_reply);
|
||||
|
||||
xcb_pixmap_t win_pixmap = xcb_generate_id(conn);
|
||||
xcb_composite_name_window_pixmap(conn, wid, win_pixmap);
|
||||
|
||||
xcb_get_image_cookie_t gi_cookie = xcb_get_image(conn, XCB_IMAGE_FORMAT_Z_PIXMAP, win_pixmap, 0, 0, win_w, win_h, (uint32_t)(~0UL));
|
||||
xcb_get_image_reply_t *gi_reply = xcb_get_image_reply(conn, gi_cookie, &err);
|
||||
if (!gi_reply) {
|
||||
fprintf(stderr, "xcb: error: get_image_reply: %d\n", err->error_code);
|
||||
return (Image){
|
||||
.data = err, .width = 0, .height = 0, .format = 0, .mipmaps = 0
|
||||
};
|
||||
}
|
||||
|
||||
int data_len = xcb_get_image_data_length(gi_reply);
|
||||
fprintf(stderr, "data_len: %d\n", data_len);
|
||||
|
||||
uint8_t *data = xcb_get_image_data(gi_reply);
|
||||
|
||||
Image img = GenImageColor(win_w, win_h, BLANK);
|
||||
|
||||
for (int i = 0; i < data_len; i += 4) {
|
||||
((uint8_t *)img.data)[i + 0] = data[i + 2];
|
||||
((uint8_t *)img.data)[i + 1] = data[i + 1];
|
||||
((uint8_t *)img.data)[i + 2] = data[i + 0];
|
||||
((uint8_t *)img.data)[i + 3] = data[i + 3];
|
||||
}
|
||||
|
||||
free(gi_reply);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
#include "screenshot.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <xcb/composite.h>
|
||||
|
||||
Image get_screenshot(xcb_connection_t *conn, xcb_window_t wid) {
|
||||
xcb_generic_error_t *err = NULL;
|
||||
|
||||
xcb_composite_redirect_window(conn, wid, XCB_COMPOSITE_REDIRECT_AUTOMATIC);
|
||||
|
||||
xcb_get_geometry_cookie_t gg_cookie = xcb_get_geometry(conn, wid);
|
||||
xcb_get_geometry_reply_t *gg_reply = xcb_get_geometry_reply(conn, gg_cookie, &err);
|
||||
|
||||
if (!gg_reply) {
|
||||
fprintf(stderr, "xcb: error: geometry: %d\n", err->error_code);
|
||||
return (Image){
|
||||
.data = err, .width = 0, .height = 0, .format = 0, .mipmaps = 0
|
||||
};
|
||||
}
|
||||
|
||||
int win_w = gg_reply->width;
|
||||
int win_h = gg_reply->height;
|
||||
assert(gg_reply->depth == 32);
|
||||
fprintf(stderr, "width: %d\nheight: %d\n", win_w, win_h);
|
||||
|
||||
free(gg_reply);
|
||||
|
||||
xcb_pixmap_t win_pixmap = xcb_generate_id(conn);
|
||||
xcb_composite_name_window_pixmap(conn, wid, win_pixmap);
|
||||
|
||||
xcb_get_image_cookie_t gi_cookie = xcb_get_image(conn, XCB_IMAGE_FORMAT_Z_PIXMAP, win_pixmap, 0, 0, win_w, win_h, (uint32_t)(~0UL));
|
||||
xcb_get_image_reply_t *gi_reply = xcb_get_image_reply(conn, gi_cookie, &err);
|
||||
if (!gi_reply) {
|
||||
fprintf(stderr, "xcb: error: get_image_reply: %d\n", err->error_code);
|
||||
return (Image){
|
||||
.data = err, .width = 0, .height = 0, .format = 0, .mipmaps = 0
|
||||
};
|
||||
}
|
||||
|
||||
int data_len = xcb_get_image_data_length(gi_reply);
|
||||
fprintf(stderr, "data_len: %d\n", data_len);
|
||||
|
||||
uint8_t *data = xcb_get_image_data(gi_reply);
|
||||
|
||||
Image img = GenImageColor(win_w, win_h, BLANK);
|
||||
|
||||
for (int i = 0; i < data_len; i += 4) {
|
||||
((uint8_t *)img.data)[i + 0] = data[i + 2];
|
||||
((uint8_t *)img.data)[i + 1] = data[i + 1];
|
||||
((uint8_t *)img.data)[i + 2] = data[i + 0];
|
||||
((uint8_t *)img.data)[i + 3] = data[i + 3];
|
||||
}
|
||||
|
||||
free(gi_reply);
|
||||
|
||||
return img;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef _SCREENSHOT_H_
|
||||
#define _SCREENSHOT_H_
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <raylib.h>
|
||||
|
||||
Image get_screenshot(xcb_connection_t *conn, xcb_window_t wid);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,238 @@
|
|||
let SessionLoad = 1
|
||||
let s:so_save = &g:so | let s:siso_save = &g:siso | setg so=0 siso=0 | setl so=-1 siso=-1
|
||||
let v:this_session=expand("<sfile>:p")
|
||||
silent only
|
||||
silent tabonly
|
||||
cd ~/projects/things/img/scrall
|
||||
if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == ''
|
||||
let s:wipebuf = bufnr('%')
|
||||
endif
|
||||
let s:shortmess_save = &shortmess
|
||||
if &shortmess =~ 'A'
|
||||
set shortmess=aoOA
|
||||
else
|
||||
set shortmess=aoO
|
||||
endif
|
||||
badd +15 main.c
|
||||
badd +61 ~/projects/experiments/composegrab.c
|
||||
badd +4 Makefile
|
||||
badd +1 term://~/projects/things/img/scrall//871627:/bin/bash
|
||||
badd +2 screenshot.c
|
||||
badd +9 screenshot.h
|
||||
badd +40 term://~/projects/things/img/scrall//1272817:elinks
|
||||
badd +66 ~/projects/livewp/src/rootwindow.c
|
||||
badd +1 term://elinks\ https://stackoverflow.com/questions/71947949/how-to-get-top-level-windows-and-their-names-using-libxcb
|
||||
badd +1 term://\'elinks\ https://stackoverflow.com/questions/71947949/how-to-get-top-level-windows-and-their-names-using-libxcb\'
|
||||
badd +1 term://sh\ -c\ \'elinks\ https://stackoverflow.com/questions/71947949/how-to-get-top-level-windows-and-their-names-using-libxcb\'
|
||||
badd +1 term://~/projects/things/img/scrall//1274970:elinks
|
||||
badd +15 windowtree.h
|
||||
badd +0 man://xcb_get_property_value
|
||||
badd +2 windowtree.c
|
||||
badd +372 /usr/include/xcb/xcb.h
|
||||
badd +1 /usr/include/xcb/xcb_atom.h
|
||||
badd +1 /usr/include/xcb/xcb_util.h
|
||||
badd +2 /usr/include/xcb/xcb_aux.h
|
||||
badd +0 /usr/include/xcb/xproto.h
|
||||
argglobal
|
||||
%argdel
|
||||
$argadd main.c
|
||||
edit main.c
|
||||
let s:save_splitbelow = &splitbelow
|
||||
let s:save_splitright = &splitright
|
||||
set splitbelow splitright
|
||||
wincmd _ | wincmd |
|
||||
vsplit
|
||||
1wincmd h
|
||||
wincmd _ | wincmd |
|
||||
split
|
||||
1wincmd k
|
||||
wincmd _ | wincmd |
|
||||
vsplit
|
||||
1wincmd h
|
||||
wincmd w
|
||||
wincmd w
|
||||
wincmd _ | wincmd |
|
||||
vsplit
|
||||
1wincmd h
|
||||
wincmd w
|
||||
wincmd w
|
||||
wincmd _ | wincmd |
|
||||
split
|
||||
1wincmd k
|
||||
wincmd w
|
||||
let &splitbelow = s:save_splitbelow
|
||||
let &splitright = s:save_splitright
|
||||
wincmd t
|
||||
let s:save_winminheight = &winminheight
|
||||
let s:save_winminwidth = &winminwidth
|
||||
set winminheight=0
|
||||
set winheight=1
|
||||
set winminwidth=0
|
||||
set winwidth=1
|
||||
exe '1resize ' . ((&lines * 42 + 43) / 86)
|
||||
exe 'vert 1resize ' . ((&columns * 106 + 159) / 319)
|
||||
exe '2resize ' . ((&lines * 42 + 43) / 86)
|
||||
exe 'vert 2resize ' . ((&columns * 106 + 159) / 319)
|
||||
exe '3resize ' . ((&lines * 41 + 43) / 86)
|
||||
exe 'vert 3resize ' . ((&columns * 106 + 159) / 319)
|
||||
exe '4resize ' . ((&lines * 41 + 43) / 86)
|
||||
exe 'vert 4resize ' . ((&columns * 106 + 159) / 319)
|
||||
exe '5resize ' . ((&lines * 42 + 43) / 86)
|
||||
exe 'vert 5resize ' . ((&columns * 105 + 159) / 319)
|
||||
exe '6resize ' . ((&lines * 41 + 43) / 86)
|
||||
exe 'vert 6resize ' . ((&columns * 105 + 159) / 319)
|
||||
argglobal
|
||||
balt term://~/projects/things/img/scrall//871627:/bin/bash
|
||||
setlocal fdm=manual
|
||||
setlocal fde=0
|
||||
setlocal fmr={{{,}}}
|
||||
setlocal fdi=#
|
||||
setlocal fdl=0
|
||||
setlocal fml=1
|
||||
setlocal fdn=20
|
||||
setlocal fen
|
||||
silent! normal! zE
|
||||
let &fdl = &fdl
|
||||
let s:l = 15 - ((14 * winheight(0) + 21) / 42)
|
||||
if s:l < 1 | let s:l = 1 | endif
|
||||
keepjumps exe s:l
|
||||
normal! zt
|
||||
keepjumps 15
|
||||
normal! 07|
|
||||
wincmd w
|
||||
argglobal
|
||||
if bufexists(fnamemodify("/usr/include/xcb/xproto.h", ":p")) | buffer /usr/include/xcb/xproto.h | else | edit /usr/include/xcb/xproto.h | endif
|
||||
if &buftype ==# 'terminal'
|
||||
silent file /usr/include/xcb/xproto.h
|
||||
endif
|
||||
balt /usr/include/xcb/xcb_aux.h
|
||||
setlocal fdm=manual
|
||||
setlocal fde=0
|
||||
setlocal fmr={{{,}}}
|
||||
setlocal fdi=#
|
||||
setlocal fdl=0
|
||||
setlocal fml=1
|
||||
setlocal fdn=20
|
||||
setlocal fen
|
||||
silent! normal! zE
|
||||
let &fdl = &fdl
|
||||
let s:l = 2000 - ((30 * winheight(0) + 21) / 42)
|
||||
if s:l < 1 | let s:l = 1 | endif
|
||||
keepjumps exe s:l
|
||||
normal! zt
|
||||
keepjumps 2000
|
||||
normal! 019|
|
||||
wincmd w
|
||||
argglobal
|
||||
if bufexists(fnamemodify("windowtree.h", ":p")) | buffer windowtree.h | else | edit windowtree.h | endif
|
||||
if &buftype ==# 'terminal'
|
||||
silent file windowtree.h
|
||||
endif
|
||||
balt Makefile
|
||||
setlocal fdm=manual
|
||||
setlocal fde=0
|
||||
setlocal fmr={{{,}}}
|
||||
setlocal fdi=#
|
||||
setlocal fdl=0
|
||||
setlocal fml=1
|
||||
setlocal fdn=20
|
||||
setlocal fen
|
||||
silent! normal! zE
|
||||
let &fdl = &fdl
|
||||
let s:l = 14 - ((13 * winheight(0) + 20) / 41)
|
||||
if s:l < 1 | let s:l = 1 | endif
|
||||
keepjumps exe s:l
|
||||
normal! zt
|
||||
keepjumps 14
|
||||
normal! 0
|
||||
wincmd w
|
||||
argglobal
|
||||
if bufexists(fnamemodify("windowtree.c", ":p")) | buffer windowtree.c | else | edit windowtree.c | endif
|
||||
if &buftype ==# 'terminal'
|
||||
silent file windowtree.c
|
||||
endif
|
||||
balt windowtree.h
|
||||
setlocal fdm=manual
|
||||
setlocal fde=0
|
||||
setlocal fmr={{{,}}}
|
||||
setlocal fdi=#
|
||||
setlocal fdl=0
|
||||
setlocal fml=1
|
||||
setlocal fdn=20
|
||||
setlocal fen
|
||||
silent! normal! zE
|
||||
let &fdl = &fdl
|
||||
let s:l = 74 - ((38 * winheight(0) + 20) / 41)
|
||||
if s:l < 1 | let s:l = 1 | endif
|
||||
keepjumps exe s:l
|
||||
normal! zt
|
||||
keepjumps 74
|
||||
normal! 0
|
||||
wincmd w
|
||||
argglobal
|
||||
enew
|
||||
file man://xcb_get_property_value
|
||||
balt ~/projects/experiments/composegrab.c
|
||||
setlocal fdm=manual
|
||||
setlocal fde=0
|
||||
setlocal fmr={{{,}}}
|
||||
setlocal fdi=#
|
||||
setlocal fdl=0
|
||||
setlocal fml=1
|
||||
setlocal fdn=20
|
||||
setlocal nofen
|
||||
wincmd w
|
||||
argglobal
|
||||
if bufexists(fnamemodify("~/projects/livewp/src/rootwindow.c", ":p")) | buffer ~/projects/livewp/src/rootwindow.c | else | edit ~/projects/livewp/src/rootwindow.c | endif
|
||||
if &buftype ==# 'terminal'
|
||||
silent file ~/projects/livewp/src/rootwindow.c
|
||||
endif
|
||||
balt ~/projects/experiments/composegrab.c
|
||||
setlocal fdm=manual
|
||||
setlocal fde=0
|
||||
setlocal fmr={{{,}}}
|
||||
setlocal fdi=#
|
||||
setlocal fdl=0
|
||||
setlocal fml=1
|
||||
setlocal fdn=20
|
||||
setlocal fen
|
||||
silent! normal! zE
|
||||
let &fdl = &fdl
|
||||
let s:l = 82 - ((25 * winheight(0) + 20) / 41)
|
||||
if s:l < 1 | let s:l = 1 | endif
|
||||
keepjumps exe s:l
|
||||
normal! zt
|
||||
keepjumps 82
|
||||
normal! 0
|
||||
wincmd w
|
||||
exe '1resize ' . ((&lines * 42 + 43) / 86)
|
||||
exe 'vert 1resize ' . ((&columns * 106 + 159) / 319)
|
||||
exe '2resize ' . ((&lines * 42 + 43) / 86)
|
||||
exe 'vert 2resize ' . ((&columns * 106 + 159) / 319)
|
||||
exe '3resize ' . ((&lines * 41 + 43) / 86)
|
||||
exe 'vert 3resize ' . ((&columns * 106 + 159) / 319)
|
||||
exe '4resize ' . ((&lines * 41 + 43) / 86)
|
||||
exe 'vert 4resize ' . ((&columns * 106 + 159) / 319)
|
||||
exe '5resize ' . ((&lines * 42 + 43) / 86)
|
||||
exe 'vert 5resize ' . ((&columns * 105 + 159) / 319)
|
||||
exe '6resize ' . ((&lines * 41 + 43) / 86)
|
||||
exe 'vert 6resize ' . ((&columns * 105 + 159) / 319)
|
||||
tabnext 1
|
||||
if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'
|
||||
silent exe 'bwipe ' . s:wipebuf
|
||||
endif
|
||||
unlet! s:wipebuf
|
||||
set winheight=1 winwidth=20
|
||||
let &shortmess = s:shortmess_save
|
||||
let &winminheight = s:save_winminheight
|
||||
let &winminwidth = s:save_winminwidth
|
||||
let s:sx = expand("<sfile>:p:r")."x.vim"
|
||||
if filereadable(s:sx)
|
||||
exe "source " . fnameescape(s:sx)
|
||||
endif
|
||||
let &g:so = s:so_save | let &g:siso = s:siso_save
|
||||
set hlsearch
|
||||
nohlsearch
|
||||
doautoall SessionLoadPost
|
||||
unlet SessionLoad
|
||||
" vim: set ft=vim :
|
|
@ -0,0 +1,130 @@
|
|||
// x-run: make run
|
||||
#include "windowtree.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
|
||||
struct _cookies_container {
|
||||
xcb_get_property_cookie_t gp_cookie;
|
||||
xcb_get_geometry_cookie_t gg_cookie;
|
||||
xcb_get_window_attributes_cookie_t ga_cookie;
|
||||
};
|
||||
|
||||
struct window_info *get_windows_list(xcb_connection_t *conn, size_t *n_windows) {
|
||||
xcb_generic_error_t *err;
|
||||
|
||||
xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
|
||||
|
||||
#if 0
|
||||
xcb_query_tree_reply_t *qt_reply;
|
||||
xcb_query_tree_cookie_t qt_cookie = xcb_query_tree(conn, screen->root);
|
||||
|
||||
if (!(qt_reply = xcb_query_tree_reply(conn, qt_cookie, &err))) {
|
||||
fprintf(stderr, "xcb: error: xcb_query_tree_reply: %d\n", err->error_code);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xcb_window_t *children = xcb_query_tree_children(qt_reply);
|
||||
|
||||
*n_windows = xcb_query_tree_children_length(qt_reply);
|
||||
struct window_info *windows = calloc(*n_windows, sizeof(struct window_info));
|
||||
#else
|
||||
xcb_intern_atom_cookie_t ia_cookie = xcb_intern_atom(conn, 1, 16, "_NET_CLIENT_LIST");
|
||||
xcb_intern_atom_reply_t *ia_reply = xcb_intern_atom_reply(conn, ia_cookie, &err);
|
||||
|
||||
enum xcb_atom_enum_t at_list = XCB_ATOM_WINDOW;
|
||||
|
||||
/*if (!ia_reply) {*/
|
||||
/* printf("using _WIN_CLIENT_LIST\n");*/
|
||||
/* ia_cookie = xcb_intern_atom(conn, 1, 16, "_WIN_CLIENT_LIST");*/
|
||||
/* ia_reply = xcb_intern_atom_reply(conn, ia_cookie, &err);*/
|
||||
/* at_list = XCB_ATOM_CARDINAL;*/
|
||||
/*}*/
|
||||
|
||||
if (!ia_reply) {
|
||||
fprintf(stderr, "xcb: error: xcb_intern_atom_reply: %d\n", err->error_code);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xcb_get_property_cookie_t gp_client_list_cookie = xcb_get_property(conn, 0, screen->root, ia_reply->atom, at_list, 0, 1024);
|
||||
free(ia_reply);
|
||||
|
||||
xcb_get_property_reply_t *gp_client_list_reply = xcb_get_property_reply(conn, gp_client_list_cookie, &err);
|
||||
|
||||
if (!gp_client_list_reply) {
|
||||
fprintf(stderr, "xcb: error: xcb_get_property_reply: %d\n", err->error_code);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*n_windows = xcb_get_property_value_length(gp_client_list_reply);
|
||||
printf("length: %zu\n", *n_windows);
|
||||
|
||||
struct window_info *windows = calloc(*n_windows, sizeof(struct window_info));
|
||||
xcb_window_t *child = (xcb_window_t *)xcb_get_property_value(gp_client_list_reply);
|
||||
|
||||
for (int i = 0; i < *n_windows; i++) {
|
||||
printf("WID 0x%08d\n", child[i]);
|
||||
windows[i].wid = child[i];
|
||||
}
|
||||
|
||||
free(gp_client_list_reply);
|
||||
|
||||
#endif
|
||||
|
||||
struct _cookies_container *cookies = calloc(*n_windows, sizeof(struct _cookies_container));
|
||||
// queueing requests
|
||||
for (int i = 0; i < *n_windows; i++) {
|
||||
cookies[i].gp_cookie = xcb_get_property(conn, 0, windows[i].wid, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 1023);
|
||||
cookies[i].gg_cookie = xcb_get_geometry(conn, windows[i].wid);
|
||||
cookies[i].ga_cookie = xcb_get_window_attributes(conn, windows[i].wid);
|
||||
}
|
||||
|
||||
// reading results
|
||||
for (int i = 0; i < *n_windows; i++) {
|
||||
xcb_get_geometry_reply_t *gg_reply = xcb_get_geometry_reply(conn, cookies[i].gg_cookie, &err);
|
||||
if (!gg_reply) {
|
||||
fprintf(stderr, "xcb: error: xcb_get_geometry: %d\n", err->error_code);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
windows[i].rect.x = gg_reply->x;
|
||||
windows[i].rect.y = gg_reply->y;
|
||||
windows[i].rect.width = gg_reply->width;
|
||||
windows[i].rect.height = gg_reply->height;
|
||||
|
||||
free(gg_reply);
|
||||
|
||||
xcb_get_property_reply_t *gp_reply = xcb_get_property_reply(conn, cookies[i].gp_cookie, &err);
|
||||
if (!gp_reply) {
|
||||
fprintf(stderr, "xcb: error: xcb_get_property: %d\n", err->error_code);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
char *gp_value = (char *)xcb_get_property_value(gp_reply);
|
||||
|
||||
memset(windows[i].title, 0, 1024);
|
||||
strncpy(windows[i].title, gp_value, 1023);
|
||||
|
||||
free(gp_reply);
|
||||
|
||||
xcb_get_window_attributes_reply_t *ga_reply = xcb_get_window_attributes_reply(conn, cookies[i].ga_cookie, &err);
|
||||
if (!gp_reply) {
|
||||
fprintf(stderr, "xcb: error: xcb_get_window_attributes: %d\n", err->error_code);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
windows[i].win_gravity = ga_reply->win_gravity;
|
||||
|
||||
free(ga_reply);
|
||||
}
|
||||
|
||||
free(cookies); // yay!
|
||||
return windows; // ewww
|
||||
|
||||
failure:
|
||||
free(cookies);
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef _WINDOWTREE_H_
|
||||
#define _WINDOWTREE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
struct window_info {
|
||||
xcb_window_t wid;
|
||||
xcb_rectangle_t rect;
|
||||
char title[1024];
|
||||
uint8_t win_gravity;
|
||||
};
|
||||
|
||||
struct window_info *get_windows_list(xcb_connection_t *conn, size_t *n_windows);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue