Trying to list all windows from _NET_CLIENT_LIST
This commit is contained in:
parent
36cb48c650
commit
a5cf7cabf3
|
@ -1 +1,2 @@
|
||||||
scrall
|
scrall
|
||||||
|
*.o
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
CFLAGS += -Wall -Wextra `exec pkg-config --cflags raylib xcb xcb-composite`
|
CFLAGS += -Wall -Wextra `exec pkg-config --cflags raylib xcb xcb-composite`
|
||||||
LDFLAGS := -lm `pkg-config --libs raylib xcb xcb-composite`
|
LDFLAGS := -lm `pkg-config --libs raylib xcb xcb-composite`
|
||||||
|
|
||||||
scrall: main.c
|
OBJECTS = ./screenshot.o ./windowtree.o
|
||||||
$(CC) $(CFLAGS) main.c $(LDFLAGS) -o scrall
|
|
||||||
|
|
||||||
|
scrall: main.c $(OBJECTS)
|
||||||
|
$(CC) $(CFLAGS) main.c $(LDFLAGS) -o scrall $(OBJECTS)
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c $^ -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) scrall
|
$(RM) scrall
|
||||||
|
|
|
@ -1,85 +1,38 @@
|
||||||
// x-run: make run
|
// x-run: make run
|
||||||
#include <assert.h>
|
|
||||||
#include <raylib.h>
|
#include <raylib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xproto.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) {
|
int main(int argc, char **argv) {
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
xcb_connection_t *xcb = xcb_connect(NULL, NULL);
|
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);
|
SetConfigFlags(FLAG_WINDOW_TRANSPARENT);
|
||||||
InitWindow(0, 0, "img/scrall");
|
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()) {
|
while (!WindowShouldClose()) {
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(BLANK);
|
ClearBackground(BLANK);
|
||||||
DrawTexture(screenshot_tex, 0, 0, WHITE);
|
|
||||||
EndDrawing();
|
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