Don’t rely on libxcb-wm any longer, as it got removed in libxcb 0.3.4

See http://cgit.freedesktop.org/xcb/util/commit/?id=4c9a707f472e49bc3005354db265a0214071d46b
next
Michael Stapelberg 2009-04-19 20:44:34 +02:00
parent 22e0ea5141
commit 982e453251
7 changed files with 114 additions and 25 deletions

View File

@ -14,8 +14,12 @@ CFLAGS += -I/usr/local/include
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

View File

@ -11,6 +11,7 @@
*
*/
#include <xcb/xcb.h>
#include <xcb/xcb_atom.h>
#include <stdbool.h>
#ifndef _DATA_H
@ -116,6 +117,25 @@ struct Ignore_Event {
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
*****************************************************************************/

View File

@ -9,11 +9,13 @@
*
*/
#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
@ -28,4 +30,9 @@ extern xcb_event_handlers_t evenths;
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

View File

@ -36,6 +36,9 @@ while (0)
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);
@ -74,6 +77,24 @@ void *scalloc(size_t size);
*/
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 applications parent exits (immediately),

View File

@ -15,7 +15,7 @@
#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>
@ -149,10 +149,10 @@ int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_
return 1;
/* This was either a focus for a clients 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) {
@ -279,10 +279,10 @@ static bool button_press_bar(xcb_connection_t *conn, xcb_button_press_event_t *e
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 clients 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) {
@ -534,7 +534,7 @@ int handle_configure_request(void *prophs, xcb_connection_t *conn, xcb_configure
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};
@ -582,7 +582,7 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti
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) {
@ -598,7 +598,7 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti
return 0;
}
client = table_remove(byChild, event->window);
client = table_remove(&by_child, event->window);
if (client->name != NULL)
free(client->name);
@ -630,7 +630,7 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti
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);
@ -673,7 +673,7 @@ int handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state,
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;
@ -736,7 +736,7 @@ int handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t
LOG("prop == NULL\n");
return 1;
}
Client *client = table_get(byChild, window);
Client *client = table_get(&by_child, window);
if (client == NULL)
return 1;
@ -793,7 +793,7 @@ int handle_expose_event(void *data, xcb_connection_t *conn, xcb_expose_event_t *
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. */
@ -861,7 +861,7 @@ int handle_client_message(void *data, xcb_connection_t *conn, xcb_client_message
LOG("fullscreen\n");
Client *client = table_get(byChild, event->window);
Client *client = table_get(&by_child, event->window);
if (client == NULL)
return 0;
@ -899,7 +899,7 @@ int handle_window_type(void *data, xcb_connection_t *conn, uint8_t state, xcb_wi
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;

View File

@ -23,7 +23,7 @@
#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>
@ -91,7 +91,7 @@ void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *conn, xcb_
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, …) */
@ -124,8 +124,8 @@ out:
*
*/
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;
@ -144,7 +144,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
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);
@ -207,8 +207,8 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
}
/* 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,
@ -362,9 +362,6 @@ int main(int argc, char *argv[], char *env[]) {
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);

View File

@ -29,6 +29,8 @@
#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);
@ -96,6 +98,44 @@ char *sstrdup(const char *str) {
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 applications parent exits (immediately),