int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_event_t *event);
int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_event_t *event);
int handle_map_notify_event(void *prophs, xcb_connection_t *conn, xcb_map_notify_event_t *event);
+int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_notify_event_t *event);
int handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state,
xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop);
int handle_expose_event(void *data, xcb_connection_t *conn, xcb_expose_event_t *event);
/* Restore focus on the new workspace */
if (CUR_CELL->currently_focused != NULL)
- xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, CUR_CELL->currently_focused->child, XCB_CURRENT_TIME);
+ set_focus(conn, CUR_CELL->currently_focused);
else xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, root, XCB_CURRENT_TIME);
//xcb_ungrab_server(conn);
#include "util.h"
#include "xinerama.h"
+/* After mapping/unmapping windows, a notify event is generated. However, we don’t want it,
+ since it’d trigger an infinite loop of switching between the different windows when
+ changing workspaces */
+int ignore_notify_event = -1;
+
/*
* Due to bindings like Mode_switch + <a>, we need to bind some keys in XCB_GRAB_MODE_SYNC.
* Therefore, we just replay all key presses.
*
*/
int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_event_t *event) {
- printf("enter_notify for %08x\n", event->event);
+ printf("enter_notify for %08x, serial %d\n", event->event, event->sequence);
+ /* Some events are not interesting, because they were not generated actively by the
+ user, but be reconfiguration of windows */
+ if (event->sequence == ignore_notify_event) {
+ printf("Ignoring, because of previous map\n");
+ return 1;
+ }
/* This was either a focus for a client’s parent (= titlebar)… */
Client *client = table_get(byParent, event->event);
int handle_map_notify_event(void *prophs, xcb_connection_t *conn, xcb_map_notify_event_t *event) {
window_attributes_t wa = { TAG_VALUE };
wa.u.override_redirect = event->override_redirect;
- printf("MapNotify for 0x%08x.\n", event->window);
+ printf("MapNotify for 0x%08x, serial is %d.\n", event->window, event->sequence);
+ ignore_notify_event = event->sequence;
manage_window(prophs, conn, event->window, wa);
return 1;
}
+/*
+ * Configuration notifies are only handled because we need to set up ignore for the following
+ * enter notify events
+ *
+ */
+int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_notify_event_t *event) {
+ printf("handle_configure_event\n");
+ ignore_notify_event = event->sequence;
+ return 1;
+}
+
/*
* Our window decorations were unmapped. That means, the window will be killed now,
* so we better clean up before.
int handle_unmap_notify_event(void *data, xcb_connection_t *c, xcb_unmap_notify_event_t *e) {
xcb_window_t root = xcb_setup_roots_iterator(xcb_get_setup(c)).data->root;
+ ignore_notify_event = e->sequence;
+
Client *client = table_get(byChild, e->window);
/* First, we need to check if the client is awaiting an unmap-request which
was generated by us reparenting the window. In that case, we just ignore it. */
wa.u.override_redirect = attr->override_redirect;
}
- /* Check if the window is already managed */
- if (!wa.u.override_redirect && table_get(byChild, window))
- goto out;
-
/* Don’t manage clients with the override_redirect flag */
if (wa.u.override_redirect)
goto out;
+ /* Check if the window is already managed */
+ if (table_get(byChild, window))
+ goto out;
+
/* Get the initial geometry (position, size, …) */
geomc = xcb_get_geometry(c, d);
if (!attr) {
strut_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_STRUT_PARTIAL], UINT32_MAX);
Client *new = table_get(byChild, child);
- if (new == NULL) {
- /* TODO: When does this happen for existing clients? Is that a bug? */
- printf("oh, it's new\n");
- new = calloc(sizeof(Client), 1);
- new->force_reconfigure = true;
- }
+
+ /* Events for already managed windows should already be filtered in manage_window() */
+ assert(new == NULL);
+
+ printf("reparenting new client\n");
+ new = calloc(sizeof(Client), 1);
+ new->force_reconfigure = true;
uint32_t mask = 0;
uint32_t values[3];
it any longer. Usually, the client destroys the window shortly afterwards. */
xcb_event_set_unmap_notify_handler(&evenths, handle_unmap_notify_event, 0);
+ /* Configure notify = window’s configuration (geometry, stacking, …). We only need
+ it to set up ignore the following enter_notify events */
+ xcb_event_set_configure_notify_handler(&evenths, handle_configure_event, 0);
+
/* Client message = client changed its properties (EWMH) */
/* TODO: can’t we do this via property handlers? */
xcb_event_set_client_message_handler(&evenths, handle_client_message, 0);
current_col = client->container->col;
current_row = client->container->row;
+ printf("set_focus(frame %08x, child %08x)\n", client->frame, client->child);
/* Set focus to the entered window, and flush xcb buffer immediately */
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, client->child, XCB_CURRENT_TIME);
//xcb_warp_pointer(conn, XCB_NONE, client->child, 0, 0, 0, 0, 10, 10);
- /* Update last/current client’s titlebar */
- if (old_client != NULL)
- decorate_window(conn, old_client, old_client->frame, old_client->titlegc, 0);
- decorate_window(conn, client, client->frame, client->titlegc, 0);
/* If we’re in stacking mode, we render the container to update changes in the title
bars and to raise the focused client */
if (client->container->mode == MODE_STACK)
render_container(conn, client->container);
+ else {
+ /* Update last/current client’s titlebar */
+ if (old_client != NULL)
+ decorate_window(conn, old_client, old_client->frame, old_client->titlegc, 0);
+ decorate_window(conn, client, client->frame, client->titlegc, 0);
+ }
xcb_flush(conn);
}