Fixes #822.
while (pr != NULL) {
pending_rule_t *next = pr->next;
if (FD_ISSET(pr->fd, &descriptors)) {
- manage_window(pr->win, pr->csq, pr->fd);
+ if (manage_window(pr->win, pr->csq, pr->fd)) {
+ for (event_queue_t *eq = pr->event_head; eq != NULL; eq = eq->next) {
+ handle_event(&eq->event);
+ }
+ }
remove_pending_rule(pr);
}
pr = next;
#include "tree.h"
#include "window.h"
#include "pointer.h"
+#include "rule.h"
#include "events.h"
void handle_event(xcb_generic_event_t *evt)
coordinates_t loc;
if (!locate_window(e->window, &loc)) {
- return;
+ for (pending_rule_t *pr = pending_rule_head; pr != NULL; pr = pr->next) {
+ if (pr->win == e->window) {
+ postpone_event(pr, evt);
+ break;
+ }
+ }
+ return;
}
if (e->atom == XCB_ATOM_WM_HINTS) {
coordinates_t loc;
if (!locate_window(e->window, &loc)) {
+ for (pending_rule_t *pr = pending_rule_head; pr != NULL; pr = pr->next) {
+ if (pr->win == e->window) {
+ postpone_event(pr, evt);
+ break;
+ }
+ }
return;
}
{
pending_rule_t *pr = calloc(1, sizeof(pending_rule_t));
pr->prev = pr->next = NULL;
+ pr->event_head = pr->event_tail = NULL;
pr->fd = fd;
pr->win = win;
pr->csq = csq;
}
close(pr->fd);
free(pr->csq);
+ event_queue_t *eq = pr->event_head;
+ while (eq != NULL) {
+ event_queue_t *next = eq->next;
+ free(eq);
+ eq = next;
+ }
free(pr);
}
+void postpone_event(pending_rule_t *pr, xcb_generic_event_t *evt)
+{
+ event_queue_t *eq = make_event_queue(evt);
+ if (pr->event_tail == NULL) {
+ pr->event_head = pr->event_tail = eq;
+ } else {
+ pr->event_tail->next = eq;
+ eq->prev = pr->event_tail;
+ pr->event_tail = eq;
+ }
+}
+
+event_queue_t *make_event_queue(xcb_generic_event_t *evt)
+{
+ event_queue_t *eq = calloc(1, sizeof(event_queue_t));
+ eq->prev = eq->next = NULL;
+ eq->event = *evt;
+ return eq;
+}
+
+
#define SET_CSQ_STATE(val) \
do { \
if (csq->state == NULL) { \
*(csq->layer) = (val); \
} while (0)
-static void _apply_window_type(xcb_window_t win, rule_consequence_t *csq)
+void _apply_window_type(xcb_window_t win, rule_consequence_t *csq)
{
xcb_ewmh_get_atoms_reply_t win_type;
if (xcb_ewmh_get_wm_window_type_reply(ewmh, xcb_ewmh_get_wm_window_type(ewmh, win), &win_type, NULL) == 1) {
}
}
-static void _apply_window_state(xcb_window_t win, rule_consequence_t *csq)
+void _apply_window_state(xcb_window_t win, rule_consequence_t *csq)
{
xcb_ewmh_get_atoms_reply_t win_state;
if (xcb_ewmh_get_wm_state_reply(ewmh, xcb_ewmh_get_wm_state(ewmh, win), &win_state, NULL) == 1) {
}
}
-static void _apply_transient(xcb_window_t win, rule_consequence_t *csq)
+void _apply_transient(xcb_window_t win, rule_consequence_t *csq)
{
xcb_window_t transient_for = XCB_NONE;
xcb_icccm_get_wm_transient_for_reply(dpy, xcb_icccm_get_wm_transient_for(dpy, win), &transient_for, NULL);
}
}
-static void _apply_hints(xcb_window_t win, rule_consequence_t *csq)
+void _apply_hints(xcb_window_t win, rule_consequence_t *csq)
{
xcb_size_hints_t size_hints;
if (xcb_icccm_get_wm_normal_hints_reply(dpy, xcb_icccm_get_wm_normal_hints(dpy, win), &size_hints, NULL) == 1) {
}
}
-static void _apply_class(xcb_window_t win, rule_consequence_t *csq)
+void _apply_class(xcb_window_t win, rule_consequence_t *csq)
{
xcb_icccm_get_wm_class_reply_t reply;
if (xcb_icccm_get_wm_class_reply(dpy, xcb_icccm_get_wm_class(dpy, win), &reply, NULL) == 1) {
pending_rule_t *make_pending_rule(int fd, xcb_window_t win, rule_consequence_t *csq);
void add_pending_rule(pending_rule_t *pr);
void remove_pending_rule(pending_rule_t *pr);
+void postpone_event(pending_rule_t *pr, xcb_generic_event_t *evt);
+event_queue_t *make_event_queue(xcb_generic_event_t *evt);
+void _apply_window_type(xcb_window_t win, rule_consequence_t *csq);
+void _apply_window_state(xcb_window_t win, rule_consequence_t *csq);
+void _apply_transient(xcb_window_t win, rule_consequence_t *csq);
+void _apply_hints(xcb_window_t win, rule_consequence_t *csq);
+void _apply_class(xcb_window_t win, rule_consequence_t *csq);
+void parse_keys_values(char *buf, rule_consequence_t *csq);
void apply_rules(xcb_window_t win, rule_consequence_t *csq);
bool schedule_rules(xcb_window_t win, rule_consequence_t *csq);
void parse_rule_consequence(int fd, rule_consequence_t *csq);
-void parse_keys_values(char *buf, rule_consequence_t *csq);
void parse_key_value(char *key, char *value, rule_consequence_t *csq);
void list_rules(FILE *rsp);
stacking_list_t *next;
};
+typedef struct event_queue_t event_queue_t;
+struct event_queue_t {
+ xcb_generic_event_t event;
+ event_queue_t *prev;
+ event_queue_t *next;
+};
+
typedef struct subscriber_list_t subscriber_list_t;
struct subscriber_list_t {
int fd;
int fd;
xcb_window_t win;
rule_consequence_t *csq;
+ event_queue_t *event_head;
+ event_queue_t *event_tail;
pending_rule_t *prev;
pending_rule_t *next;
};
}
}
-void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
+bool manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
{
monitor_t *m = mon;
desktop_t *d = mon->desk;
free(csq->layer);
free(csq->state);
window_show(win);
- return;
+ return false;
}
if (csq->node_desc[0] != '\0') {
ewmh_update_client_list(false);
free(csq->layer);
free(csq->state);
+
+ return true;
}
void set_window_state(xcb_window_t win, xcb_icccm_wm_state_t state)
#include "types.h"
void schedule_window(xcb_window_t win);
-void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd);
+bool manage_window(xcb_window_t win, rule_consequence_t *csq, int fd);
void set_window_state(xcb_window_t win, xcb_icccm_wm_state_t state);
void unmanage_window(xcb_window_t win);
bool is_presel_window(xcb_window_t win);