Skip to content

Commit

Permalink
wm: wire up the new wm_tree structure to X events
Browse files Browse the repository at this point in the history
To let it process some events to validate that it is working. The output
of wm_tree is not yet used besides debugging logs.

Note because we don't quite setup event subscription the way wm_tree
expects, there will be some errors logged, which is normal.

Signed-off-by: Yuxuan Shui <[email protected]>
  • Loading branch information
yshui committed Jun 19, 2024
1 parent 468797a commit 82fbcd5
Show file tree
Hide file tree
Showing 7 changed files with 417 additions and 29 deletions.
11 changes: 9 additions & 2 deletions src/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ static inline void ev_focus_out(session_t *ps, xcb_focus_out_event_t *ev) {
}

static inline void ev_create_notify(session_t *ps, xcb_create_notify_event_t *ev) {
wm_import_incomplete(ps->wm, ev->window, ev->parent);

if (ev->parent == ps->c.screen_info->root) {
wm_stack_add_top(ps->wm, ev->window);
ps->pending_updates = true;
Expand Down Expand Up @@ -294,6 +296,8 @@ static inline void ev_configure_notify(session_t *ps, xcb_configure_notify_event
}

static inline void ev_destroy_notify(session_t *ps, xcb_destroy_notify_event_t *ev) {
wm_destroy(ps->wm, ev->window);

auto subwin = wm_subwin_find(ps->wm, ev->window);
if (subwin) {
wm_subwin_remove(ps->wm, subwin);
Expand Down Expand Up @@ -370,8 +374,11 @@ static inline void ev_unmap_notify(session_t *ps, xcb_unmap_notify_event_t *ev)
}

static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) {
log_debug("Window %#010x has new parent: %#010x, override_redirect: %d",
ev->window, ev->parent, ev->override_redirect);
log_debug("Window %#010x has new parent: %#010x, override_redirect: %d, "
"send_event: %#010x",
ev->window, ev->parent, ev->override_redirect, ev->event);

wm_reparent(ps->wm, ev->window, ev->parent);

auto old_toplevel = wm_find_by_client(ps->wm, ev->window);
auto old_w = wm_find(ps->wm, ev->window);
Expand Down
33 changes: 31 additions & 2 deletions src/picom.c
Original file line number Diff line number Diff line change
Expand Up @@ -1572,6 +1572,8 @@ static void handle_queued_x_events(EV_P attr_unused, ev_prepare *w, int revents
}

static void handle_new_windows(session_t *ps) {
wm_complete_import(ps->wm, &ps->c, ps->atoms);

list_foreach_safe(struct win, w, wm_stack_end(ps->wm), stack_neighbour) {
if (w->is_new) {
auto new_w = maybe_allocate_managed_win(ps, w);
Expand Down Expand Up @@ -1633,11 +1635,36 @@ static void handle_pending_updates(EV_P_ struct session *ps, double delta_t) {

// Catching up with X server
handle_queued_x_events(EV_A, &ps->event_check, 0);
if (ps->pending_updates) {
if (ps->pending_updates || wm_has_incomplete_imports(ps->wm) ||
wm_has_tree_changes(ps->wm)) {
log_debug("Delayed handling of events, entering critical section");
// Process new windows, and maybe allocate struct managed_win for them
handle_new_windows(ps);

while (true) {
auto wm_change = wm_dequeue_change(ps->wm);
if (wm_change.type == WM_TREE_CHANGE_NONE) {
break;
}
switch (wm_change.type) {
case WM_TREE_CHANGE_TOPLEVEL_NEW:
log_debug("New window %#010x",
wm_ref_win_id(wm_change.toplevel));
break;
case WM_TREE_CHANGE_TOPLEVEL_KILLED:
log_debug("Destroying window %#010x",
wm_ref_win_id(wm_change.toplevel));
break;
case WM_TREE_CHANGE_CLIENT:
log_debug("Client message for window %#010x changed from "
"%#010x to %#010x",
wm_ref_win_id(wm_change.toplevel),
wm_change.client.old.x, wm_change.client.new_.x);
break;
default: break;
}
}

// Handle screen changes
// This HAS TO be called before refresh_windows, as handle_root_flags
// could call configure_root, which will release images and mark them
Expand Down Expand Up @@ -2473,6 +2500,9 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
#endif
}

ps->wm = wm_new();
wm_import_incomplete(ps->wm, ps->c.screen_info->root, XCB_NONE);

e = xcb_request_check(ps->c.c, xcb_grab_server_checked(ps->c.c));
if (e) {
log_fatal_x_error(e, "Failed to grab X server");
Expand Down Expand Up @@ -2500,7 +2530,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy,

ps->server_grabbed = false;

ps->wm = wm_new();
if (query_tree_reply) {
xcb_window_t *children;
int nchildren;
Expand Down
4 changes: 2 additions & 2 deletions src/utils/dynarr.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,8 @@ static inline void dynarr_remove_swap_impl(size_t size, void *arr, size_t idx) {
#define dynarr_foreach_rev(arr, i) \
for (typeof(arr)(i) = dynarr_end(arr) - 1; (i) >= (arr); (i)--)

/// Find the index of an element in the array by using trivial comparison, returns -1 if
/// not found.
/// Find the index of the first appearance of an element in the array by using trivial
/// comparison, returns -1 if not found.
#define dynarr_find_pod(arr, needle) \
({ \
ptrdiff_t dynarr_find_ret = -1; \
Expand Down
3 changes: 1 addition & 2 deletions src/wm/tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,7 @@ struct wm_tree_change wm_tree_dequeue_change(struct wm_tree *tree) {

/// Return the next node in the subtree after `node` in a pre-order traversal. Returns
/// NULL if `node` is the last node in the traversal.
static struct wm_tree_node *
wm_tree_next(struct wm_tree_node *node, struct wm_tree_node *subroot) {
struct wm_tree_node *wm_tree_next(struct wm_tree_node *node, struct wm_tree_node *subroot) {
if (!list_is_empty(&node->children)) {
// Descend if there are children
return list_entry(node->children.next, struct wm_tree_node, siblings);
Expand Down
Loading

0 comments on commit 82fbcd5

Please sign in to comment.