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:
parent
22e0ea5141
commit
982e453251
6
Makefile
6
Makefile
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 application’s parent exits (immediately),
|
* to avoid zombie processes. As the started application’s parent exits (immediately),
|
||||||
|
|
|
@ -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 client’s parent (= titlebar)… */
|
/* 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 */
|
/* …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 client’s parent (= titlebar)… */
|
/* 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;
|
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;
|
||||||
|
|
17
src/mainx.c
17
src/mainx.c
|
@ -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, …) */
|
||||||
|
@ -124,8 +124,8 @@ out:
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void reparent_window(xcb_connection_t *conn, xcb_window_t child,
|
void reparent_window(xcb_connection_t *conn, xcb_window_t child,
|
||||||
xcb_visualid_t visual, xcb_window_t root, uint8_t depth,
|
xcb_visualid_t visual, xcb_window_t root, uint8_t depth,
|
||||||
int16_t x, int16_t y, uint16_t width, uint16_t height) {
|
int16_t x, int16_t y, uint16_t width, uint16_t height) {
|
||||||
|
|
||||||
xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie;
|
xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie;
|
||||||
uint32_t mask = 0;
|
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);
|
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);
|
||||||
|
|
40
src/util.c
40
src/util.c
|
@ -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 application’s parent exits (immediately),
|
* to avoid zombie processes. As the started application’s parent exits (immediately),
|
||||||
|
|
Loading…
Reference in New Issue