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
This commit is contained in:
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}\" CFLAGS += -DI3_VERSION=\"${GIT_VERSION}\"
LDFLAGS += -lm LDFLAGS += -lm
LDFLAGS += -lxcb-wm LDFLAGS += -lxcb-event
LDFLAGS += -lxcb-property
LDFLAGS += -lxcb-keysyms LDFLAGS += -lxcb-keysyms
LDFLAGS += -lxcb-atom
LDFLAGS += -lxcb-aux
LDFLAGS += -lxcb-icccm
LDFLAGS += -lxcb-xinerama LDFLAGS += -lxcb-xinerama
LDFLAGS += -lX11 LDFLAGS += -lX11
LDFLAGS += -L/usr/local/lib -L/usr/pkg/lib LDFLAGS += -L/usr/local/lib -L/usr/pkg/lib

View File

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

View File

@ -9,11 +9,13 @@
* *
*/ */
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcb_property.h>
#include <xcb/xcb_event.h> #include <xcb/xcb_event.h>
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
#include "queue.h" #include "queue.h"
#include "data.h"
#ifndef _I3_H #ifndef _I3_H
#define _I3_H #define _I3_H
@ -28,4 +30,9 @@ extern xcb_event_handlers_t evenths;
extern int num_screens; extern int num_screens;
extern xcb_atom_t atoms[NUM_ATOMS]; 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 #endif

View File

@ -36,6 +36,9 @@ while (0)
delete the preceding comma */ delete the preceding comma */
#define LOG(fmt, ...) slog("%s:%s:%d - " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) #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 min(int a, int b);
int max(int a, int b); int max(int a, int b);
@ -74,6 +77,24 @@ void *scalloc(size_t size);
*/ */
char *sstrdup(const char *str); 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 * 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), * to avoid zombie processes. As the started applications parent exits (immediately),

View File

@ -15,7 +15,7 @@
#include <time.h> #include <time.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcb_wm.h> #include <xcb/xcb_atom.h>
#include <xcb/xcb_icccm.h> #include <xcb/xcb_icccm.h>
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
@ -149,10 +149,10 @@ int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_
return 1; return 1;
/* This was either a focus for a clients parent (= titlebar)… */ /* 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 */ /* …or the client itself */
if (client == NULL) if (client == NULL)
client = table_get(byChild, event->event); client = table_get(&by_child, event->event);
/* Check for stack windows */ /* Check for stack windows */
if (client == NULL) { 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) { int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_event_t *event) {
LOG("button press!\n"); LOG("button press!\n");
/* This was either a focus for a clients parent (= titlebar)… */ /* 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; bool border_click = false;
if (client == NULL) { if (client == NULL) {
client = table_get(byParent, event->event); client = table_get(&by_parent, event->event);
border_click = true; border_click = true;
} }
if (client == NULL) { 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("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); 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) { 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"); 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}; 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); 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 /* 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. */ was generated by us reparenting the window. In that case, we just ignore it. */
if (client != NULL && client->awaiting_useless_unmap) { 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; return 0;
} }
client = table_remove(byChild, event->window); client = table_remove(&by_child, event->window);
if (client->name != NULL) if (client->name != NULL)
free(client->name); 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_reparent_window(conn, client->child, root, 0, 0);
xcb_destroy_window(conn, client->frame); xcb_destroy_window(conn, client->frame);
xcb_flush(conn); xcb_flush(conn);
table_remove(byParent, client->frame); table_remove(&by_parent, client->frame);
if (client->container != NULL) { if (client->container != NULL) {
cleanup_table(conn, client->container->workspace); 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"); LOG("_NET_WM_NAME not specified, not changing\n");
return 1; return 1;
} }
Client *client = table_get(byChild, window); Client *client = table_get(&by_child, window);
if (client == NULL) if (client == NULL)
return 1; return 1;
@ -736,7 +736,7 @@ int handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t
LOG("prop == NULL\n"); LOG("prop == NULL\n");
return 1; return 1;
} }
Client *client = table_get(byChild, window); Client *client = table_get(&by_child, window);
if (client == NULL) if (client == NULL)
return 1; return 1;
@ -793,7 +793,7 @@ int handle_expose_event(void *data, xcb_connection_t *conn, xcb_expose_event_t *
return 1; return 1;
LOG("window = %08x\n", event->window); LOG("window = %08x\n", event->window);
Client *client = table_get(byParent, event->window); Client *client = table_get(&by_parent, event->window);
if (client == NULL) { if (client == NULL) {
/* There was no client in the table, so this is probably an expose event for /* There was no client in the table, so this is probably an expose event for
one of our stack_windows. */ 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"); LOG("fullscreen\n");
Client *client = table_get(byChild, event->window); Client *client = table_get(&by_child, event->window);
if (client == NULL) if (client == NULL)
return 0; 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, 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) { xcb_atom_t name, xcb_get_property_reply_t *reply) {
LOG("handle_normal_hints\n"); LOG("handle_normal_hints\n");
Client *client = table_get(byChild, window); Client *client = table_get(&by_child, window);
if (client == NULL) { if (client == NULL) {
LOG("No such client\n"); LOG("No such client\n");
return 1; return 1;

View File

@ -23,7 +23,7 @@
#include <X11/extensions/XKB.h> #include <X11/extensions/XKB.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcb_wm.h> #include <xcb/xcb_atom.h>
#include <xcb/xcb_aux.h> #include <xcb/xcb_aux.h>
#include <xcb/xcb_event.h> #include <xcb/xcb_event.h>
#include <xcb/xcb_property.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; goto out;
/* Check if the window is already managed */ /* Check if the window is already managed */
if (table_get(byChild, window)) if (table_get(&by_child, window))
goto out; goto out;
/* Get the initial geometry (position, size, …) */ /* Get the initial geometry (position, size, …) */
@ -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); 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); 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() */ /* Events for already managed windows should already be filtered in manage_window() */
assert(new == NULL); 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 */ /* Put our data structure (Client) into the table */
table_put(byParent, new->frame, new); table_put(&by_parent, new->frame, new);
table_put(byChild, child, new); table_put(&by_child, child, new);
/* We need to grab the mouse buttons for click to focus */ /* We need to grab the mouse buttons for click to focus */
xcb_grab_button(conn, false, child, XCB_EVENT_MASK_BUTTON_PRESS, 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(&evenths, 0, sizeof(xcb_event_handlers_t));
memset(&prophs, 0, sizeof(xcb_property_handlers_t)); memset(&prophs, 0, sizeof(xcb_property_handlers_t));
byChild = alloc_table();
byParent = alloc_table();
load_configuration(override_configpath); load_configuration(override_configpath);
conn = xcb_connect(NULL, &screens); conn = xcb_connect(NULL, &screens);

View File

@ -29,6 +29,8 @@
#include "xcb.h" #include "xcb.h"
static iconv_t conversion_descriptor = 0; 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) { int min(int a, int b) {
return (a < b ? a : b); return (a < b ? a : b);
@ -96,6 +98,44 @@ char *sstrdup(const char *str) {
return result; 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 * 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), * to avoid zombie processes. As the started applications parent exits (immediately),