CFLAGS += -DI3_VERSION=\"${GIT_VERSION}\"
LDFLAGS += -lm
-LDFLAGS += -lxcb-wm
+LDFLAGS += -lxcb-event
+LDFLAGS += -lxcb-property
LDFLAGS += -lxcb-keysyms
+LDFLAGS += -lxcb-atom
+LDFLAGS += -lxcb-aux
+LDFLAGS += -lxcb-icccm
LDFLAGS += -lxcb-xinerama
LDFLAGS += -lX11
LDFLAGS += -L/usr/local/lib -L/usr/pkg/lib
*
*/
#include <xcb/xcb.h>
+#include <xcb/xcb_atom.h>
#include <stdbool.h>
#ifndef _DATA_H
SLIST_ENTRY(Ignore_Event) ignore_events;
};
+/*
+ * Emulates the behaviour of tables of libxcb-wm, which in libxcb 0.3.4 suddenly vanished.
+ *
+ */
+struct keyvalue_element {
+ uint32_t key;
+ void *value;
+
+ TAILQ_ENTRY(keyvalue_element) elements;
+};
+
+typedef struct {
+ enum xcb_atom_fast_tag_t tag;
+ union {
+ xcb_get_window_attributes_cookie_t cookie;
+ uint8_t override_redirect;
+ } u;
+} window_attributes_t;
+
/******************************************************************************
* Major types
*****************************************************************************/
*
*/
#include <xcb/xcb.h>
+#include <xcb/xcb_property.h>
#include <xcb/xcb_event.h>
#include <X11/XKBlib.h>
#include "queue.h"
+#include "data.h"
#ifndef _I3_H
#define _I3_H
extern int num_screens;
extern xcb_atom_t atoms[NUM_ATOMS];
+void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *conn, xcb_window_t window, window_attributes_t wa);
+void reparent_window(xcb_connection_t *conn, xcb_window_t child,
+ xcb_visualid_t visual, xcb_window_t root, uint8_t depth,
+ int16_t x, int16_t y, uint16_t width, uint16_t height);
+
#endif
delete the preceding comma */
#define LOG(fmt, ...) slog("%s:%s:%d - " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+TAILQ_HEAD(keyvalue_table_head, keyvalue_element);
+extern struct keyvalue_table_head by_parent;
+extern struct keyvalue_table_head by_child;
int min(int a, int b);
int max(int a, int b);
*/
char *sstrdup(const char *str);
+/**
+ * Inserts an element into the given keyvalue-table using the given key.
+ *
+ */
+bool table_put(struct keyvalue_table_head *head, uint32_t key, void *value);
+
+/**
+ * Removes the element from the given keyvalue-table with the given key and returns its value;
+ *
+ */
+void *table_remove(struct keyvalue_table_head *head, uint32_t key);
+
+/**
+ * Returns the value of the element of the given keyvalue-table with the given key.
+ *
+ */
+void *table_get(struct keyvalue_table_head *head, uint32_t key);
+
/**
* Starts the given application by passing it through a shell. We use double fork
* to avoid zombie processes. As the started application’s parent exits (immediately),
#include <time.h>
#include <xcb/xcb.h>
-#include <xcb/xcb_wm.h>
+#include <xcb/xcb_atom.h>
#include <xcb/xcb_icccm.h>
#include <X11/XKBlib.h>
return 1;
/* This was either a focus for a client’s parent (= titlebar)… */
- Client *client = table_get(byParent, event->event);
+ Client *client = table_get(&by_parent, event->event);
/* …or the client itself */
if (client == NULL)
- client = table_get(byChild, event->event);
+ client = table_get(&by_child, event->event);
/* Check for stack windows */
if (client == NULL) {
int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_event_t *event) {
LOG("button press!\n");
/* This was either a focus for a client’s parent (= titlebar)… */
- Client *client = table_get(byChild, event->event);
+ Client *client = table_get(&by_child, event->event);
bool border_click = false;
if (client == NULL) {
- client = table_get(byParent, event->event);
+ client = table_get(&by_parent, event->event);
border_click = true;
}
if (client == NULL) {
LOG("event->window = %08x\n", event->window);
LOG("application wants to be at %dx%d with %dx%d\n", event->x, event->y, event->width, event->height);
- Client *client = table_get(byChild, event->window);
+ Client *client = table_get(&by_child, event->window);
if (client == NULL) {
LOG("This client is not mapped, so we don't care and just tell the client that he will get its size\n");
Rect rect = {event->x, event->y, event->width, event->height};
add_ignore_event(event->sequence);
- Client *client = table_get(byChild, event->window);
+ Client *client = table_get(&by_child, event->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. */
if (client != NULL && client->awaiting_useless_unmap) {
return 0;
}
- client = table_remove(byChild, event->window);
+ client = table_remove(&by_child, event->window);
if (client->name != NULL)
free(client->name);
xcb_reparent_window(conn, client->child, root, 0, 0);
xcb_destroy_window(conn, client->frame);
xcb_flush(conn);
- table_remove(byParent, client->frame);
+ table_remove(&by_parent, client->frame);
if (client->container != NULL) {
cleanup_table(conn, client->container->workspace);
LOG("_NET_WM_NAME not specified, not changing\n");
return 1;
}
- Client *client = table_get(byChild, window);
+ Client *client = table_get(&by_child, window);
if (client == NULL)
return 1;
LOG("prop == NULL\n");
return 1;
}
- Client *client = table_get(byChild, window);
+ Client *client = table_get(&by_child, window);
if (client == NULL)
return 1;
return 1;
LOG("window = %08x\n", event->window);
- Client *client = table_get(byParent, event->window);
+ Client *client = table_get(&by_parent, event->window);
if (client == NULL) {
/* There was no client in the table, so this is probably an expose event for
one of our stack_windows. */
LOG("fullscreen\n");
- Client *client = table_get(byChild, event->window);
+ Client *client = table_get(&by_child, event->window);
if (client == NULL)
return 0;
int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
xcb_atom_t name, xcb_get_property_reply_t *reply) {
LOG("handle_normal_hints\n");
- Client *client = table_get(byChild, window);
+ Client *client = table_get(&by_child, window);
if (client == NULL) {
LOG("No such client\n");
return 1;
#include <X11/extensions/XKB.h>
#include <xcb/xcb.h>
-#include <xcb/xcb_wm.h>
+#include <xcb/xcb_atom.h>
#include <xcb/xcb_aux.h>
#include <xcb/xcb_event.h>
#include <xcb/xcb_property.h>
goto out;
/* Check if the window is already managed */
- if (table_get(byChild, window))
+ if (table_get(&by_child, window))
goto out;
/* Get the initial geometry (position, size, …) */
*
*/
void reparent_window(xcb_connection_t *conn, xcb_window_t child,
- xcb_visualid_t visual, xcb_window_t root, uint8_t depth,
- int16_t x, int16_t y, uint16_t width, uint16_t height) {
+ xcb_visualid_t visual, xcb_window_t root, uint8_t depth,
+ int16_t x, int16_t y, uint16_t width, uint16_t height) {
xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie;
uint32_t mask = 0;
strut_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_STRUT_PARTIAL], UINT32_MAX);
state_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_STATE], UINT32_MAX);
- Client *new = table_get(byChild, child);
+ Client *new = table_get(&by_child, child);
/* Events for already managed windows should already be filtered in manage_window() */
assert(new == NULL);
}
/* Put our data structure (Client) into the table */
- table_put(byParent, new->frame, new);
- table_put(byChild, child, new);
+ table_put(&by_parent, new->frame, new);
+ table_put(&by_child, child, new);
/* We need to grab the mouse buttons for click to focus */
xcb_grab_button(conn, false, child, XCB_EVENT_MASK_BUTTON_PRESS,
memset(&evenths, 0, sizeof(xcb_event_handlers_t));
memset(&prophs, 0, sizeof(xcb_property_handlers_t));
- byChild = alloc_table();
- byParent = alloc_table();
-
load_configuration(override_configpath);
conn = xcb_connect(NULL, &screens);
#include "xcb.h"
static iconv_t conversion_descriptor = 0;
+struct keyvalue_table_head by_parent = TAILQ_HEAD_INITIALIZER(by_parent);
+struct keyvalue_table_head by_child = TAILQ_HEAD_INITIALIZER(by_child);
int min(int a, int b) {
return (a < b ? a : b);
return result;
}
+/*
+ * The table_* functions emulate the behaviour of libxcb-wm, which in libxcb 0.3.4 suddenly
+ * vanished. Great.
+ *
+ */
+bool table_put(struct keyvalue_table_head *head, uint32_t key, void *value) {
+ struct keyvalue_element *element = scalloc(sizeof(struct keyvalue_element));
+ element->key = key;
+ element->value = value;
+
+ TAILQ_INSERT_TAIL(head, element, elements);
+ return true;
+}
+
+void *table_remove(struct keyvalue_table_head *head, uint32_t key) {
+ struct keyvalue_element *element;
+
+ TAILQ_FOREACH(element, head, elements)
+ if (element->key == key) {
+ void *value = element->value;
+ TAILQ_REMOVE(head, element, elements);
+ free(element);
+ return value;
+ }
+
+ return NULL;
+}
+
+void *table_get(struct keyvalue_table_head *head, uint32_t key) {
+ struct keyvalue_element *element;
+
+ TAILQ_FOREACH(element, head, elements)
+ if (element->key == key)
+ return element->value;
+
+ return NULL;
+}
+
/*
* Starts the given application by passing it through a shell. We use double fork
* to avoid zombie processes. As the started application’s parent exits (immediately),