Make i3 compatible with the very latest xcb

This involves:
 • Compiling with xcb-util instead of xcb-{atom,aux} (they merged the libraries)
 • Not using xcb-{event,property} anymore (code removed upstream)
 • Not using the predefined WINDOW, CARDINEL, … atoms (removed upstream)
 • Using the new xcb_icccm_* data types/functions instead of just xcb_*
   (for example xcb_icccm_get_wm_hints instead of xcb_get_wm_hints)

Also I refactored the atoms to use x-macros.
This commit is contained in:
Michael Stapelberg 2011-03-18 14:36:36 +01:00
parent 36664c6289
commit 0639a7d95b
20 changed files with 336 additions and 229 deletions

View File

@ -11,6 +11,10 @@ endif
GIT_VERSION:="$(shell git describe --tags --always) ($(shell git log --pretty=format:%cd --date=short -n1), branch $(shell [ -f .git/HEAD ] && sed 's/ref: refs\/heads\/\(.*\)/\\\\\\"\1\\\\\\"/g' .git/HEAD || echo 'unknown'))" GIT_VERSION:="$(shell git describe --tags --always) ($(shell git log --pretty=format:%cd --date=short -n1), branch $(shell [ -f .git/HEAD ] && sed 's/ref: refs\/heads\/\(.*\)/\\\\\\"\1\\\\\\"/g' .git/HEAD || echo 'unknown'))"
VERSION:=$(shell git describe --tags --abbrev=0) VERSION:=$(shell git describe --tags --abbrev=0)
ifeq ($(shell which pkg-config 2>/dev/null 1>/dev/null || echo 1),1)
$(error "pkg-config was not found")
endif
# An easier way to get CFLAGS and LDFLAGS falling back in case there's # An easier way to get CFLAGS and LDFLAGS falling back in case there's
# no pkg-config support for certain libraries # no pkg-config support for certain libraries
cflags_for_lib = $(shell pkg-config --silence-errors --cflags $(1)) cflags_for_lib = $(shell pkg-config --silence-errors --cflags $(1))
@ -24,11 +28,14 @@ CFLAGS += -Wall
CFLAGS += -Wunused-value CFLAGS += -Wunused-value
CFLAGS += -Iinclude CFLAGS += -Iinclude
CFLAGS += -I/usr/local/include CFLAGS += -I/usr/local/include
CFLAGS += $(call cflags_for_lib, xcb-event)
CFLAGS += $(call cflags_for_lib, xcb-property)
CFLAGS += $(call cflags_for_lib, xcb-keysyms) CFLAGS += $(call cflags_for_lib, xcb-keysyms)
ifeq ($(shell pkg-config --exists xcb-util || echo 1),1)
CFLAGS += -DXCB_COMPAT
CFLAGS += $(call cflags_for_lib, xcb-atom) CFLAGS += $(call cflags_for_lib, xcb-atom)
CFLAGS += $(call cflags_for_lib, xcb-aux) CFLAGS += $(call cflags_for_lib, xcb-aux)
else
CFLAGS += $(call cflags_for_lib, xcb-util)
endif
CFLAGS += $(call cflags_for_lib, xcb-icccm) CFLAGS += $(call cflags_for_lib, xcb-icccm)
CFLAGS += $(call cflags_for_lib, xcb-xinerama) CFLAGS += $(call cflags_for_lib, xcb-xinerama)
CFLAGS += $(call cflags_for_lib, xcb-randr) CFLAGS += $(call cflags_for_lib, xcb-randr)
@ -44,8 +51,12 @@ LDFLAGS += -lm
LDFLAGS += $(call ldflags_for_lib, xcb-event, xcb-event) LDFLAGS += $(call ldflags_for_lib, xcb-event, xcb-event)
LDFLAGS += $(call ldflags_for_lib, xcb-property, xcb-property) LDFLAGS += $(call ldflags_for_lib, xcb-property, xcb-property)
LDFLAGS += $(call ldflags_for_lib, xcb-keysyms, xcb-keysyms) LDFLAGS += $(call ldflags_for_lib, xcb-keysyms, xcb-keysyms)
ifeq ($(shell pkg-config --exists xcb-util || echo 1),1)
LDFLAGS += $(call ldflags_for_lib, xcb-atom, xcb-atom) LDFLAGS += $(call ldflags_for_lib, xcb-atom, xcb-atom)
LDFLAGS += $(call ldflags_for_lib, xcb-aux, xcb-aux) LDFLAGS += $(call ldflags_for_lib, xcb-aux, xcb-aux)
else
LDFLAGS += $(call ldflags_for_lib, xcb-util)
endif
LDFLAGS += $(call ldflags_for_lib, xcb-icccm, xcb-icccm) LDFLAGS += $(call ldflags_for_lib, xcb-icccm, xcb-icccm)
LDFLAGS += $(call ldflags_for_lib, xcb-xinerama, xcb-xinerama) LDFLAGS += $(call ldflags_for_lib, xcb-xinerama, xcb-xinerama)
LDFLAGS += $(call ldflags_for_lib, xcb-randr, xcb-randr) LDFLAGS += $(call ldflags_for_lib, xcb-randr, xcb-randr)

View File

@ -26,10 +26,14 @@
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcb_aux.h> #include <xcb/xcb_aux.h>
#include <xcb/xcb_event.h>
#include <xcb/xcb_keysyms.h> #include <xcb/xcb_keysyms.h>
#include <xcb/xcb_icccm.h> #include <xcb/xcb_icccm.h>
/* Contains compatibility definitions for old libxcb versions */
#ifdef XCB_COMPAT
#include "xcb_compat.h"
#endif
#include "util.h" #include "util.h"
#include "ipc.h" #include "ipc.h"
#include "tree.h" #include "tree.h"

31
include/atoms.xmacro Normal file
View File

@ -0,0 +1,31 @@
xmacro(_NET_SUPPORTED)
xmacro(_NET_SUPPORTING_WM_CHECK)
xmacro(_NET_WM_NAME)
xmacro(_NET_WM_STATE_FULLSCREEN)
xmacro(_NET_WM_STATE)
xmacro(_NET_WM_WINDOW_TYPE)
xmacro(_NET_WM_WINDOW_TYPE_DOCK)
xmacro(_NET_WM_WINDOW_TYPE_DIALOG)
xmacro(_NET_WM_WINDOW_TYPE_UTILITY)
xmacro(_NET_WM_WINDOW_TYPE_TOOLBAR)
xmacro(_NET_WM_WINDOW_TYPE_SPLASH)
xmacro(_NET_WM_DESKTOP)
xmacro(_NET_WM_STRUT_PARTIAL)
xmacro(WM_PROTOCOLS)
xmacro(WM_DELETE_WINDOW)
xmacro(UTF8_STRING)
xmacro(WM_STATE)
xmacro(WM_CLIENT_LEADER)
xmacro(_NET_CURRENT_DESKTOP)
xmacro(_NET_ACTIVE_WINDOW)
xmacro(_NET_WORKAREA)
xmacro(WM_TAKE_FOCUS)
xmacro(WM_HINTS)
xmacro(WM_NORMAL_HINTS)
xmacro(WM_TRANSIENT_FOR)
xmacro(ATOM)
xmacro(WINDOW)
xmacro(WM_NAME)
xmacro(WM_CLASS)
xmacro(STRING)
xmacro(CARDINAL)

View File

@ -7,7 +7,6 @@
* include/data.h: This file defines all data structures used by i3 * include/data.h: This file defines all data structures used by i3
* *
*/ */
#include <xcb/xcb.h>
#include <xcb/randr.h> #include <xcb/randr.h>
#include <xcb/xcb_atom.h> #include <xcb/xcb_atom.h>
#include <stdbool.h> #include <stdbool.h>

View File

@ -13,9 +13,24 @@
#include <xcb/randr.h> #include <xcb/randr.h>
extern int randr_base;
void add_ignore_event(const int sequence); void add_ignore_event(const int sequence);
/**
* Takes an xcb_generic_event_t and calls the appropriate handler, based on the
* event type.
*
*/
void handle_event(int type, xcb_generic_event_t *event);
/**
* Sets the appropriate atoms for the property handlers after the atoms were
* received from X11
*
*/
void property_handlers_init();
/** /**
* There was a key press. We compare this key code with our bindings table and * There was a key press. We compare this key code with our bindings table and
* pass the bound action to parse_command(). * pass the bound action to parse_command().

View File

@ -8,9 +8,6 @@
* See file LICENSE for license information. * See file LICENSE for license information.
* *
*/ */
#include <xcb/xcb.h>
#include <xcb/xcb_property.h>
#include <xcb/xcb_event.h>
#include <xcb/xcb_keysyms.h> #include <xcb/xcb_keysyms.h>
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
@ -31,11 +28,8 @@ extern TAILQ_HEAD(bindings_head, Binding) *bindings;
extern TAILQ_HEAD(autostarts_head, Autostart) autostarts; extern TAILQ_HEAD(autostarts_head, Autostart) autostarts;
extern TAILQ_HEAD(assignments_head, Assignment) assignments; extern TAILQ_HEAD(assignments_head, Assignment) assignments;
extern SLIST_HEAD(stack_wins_head, Stack_Window) stack_wins; extern SLIST_HEAD(stack_wins_head, Stack_Window) stack_wins;
extern xcb_event_handlers_t evenths;
extern xcb_property_handlers_t prophs;
extern uint8_t root_depth; extern uint8_t root_depth;
extern bool xcursor_supported, xkb_supported; extern bool xcursor_supported, xkb_supported;
extern xcb_atom_t atoms[NUM_ATOMS];
extern xcb_window_t root; extern xcb_window_t root;
#endif #endif

View File

@ -8,7 +8,6 @@
* See file LICENSE for license information. * See file LICENSE for license information.
* *
*/ */
#include <xcb/xcb.h>
#include "data.h" #include "data.h"

View File

@ -8,7 +8,6 @@
* See file LICENSE for license information. * See file LICENSE for license information.
* *
*/ */
#include <xcb/xcb.h>
#include <err.h> #include <err.h>
#include "data.h" #include "data.h"

View File

@ -8,7 +8,6 @@
* See file LICENSE for license information. * See file LICENSE for license information.
* *
*/ */
#include <xcb/xcb.h>
#include "data.h" #include "data.h"
#include "tree.h" #include "tree.h"

View File

@ -44,32 +44,9 @@
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | /* …subwindows get notifies */ \ XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | /* …subwindows get notifies */ \
XCB_EVENT_MASK_ENTER_WINDOW) /* …user moves cursor inside our window */ XCB_EVENT_MASK_ENTER_WINDOW) /* …user moves cursor inside our window */
#define xmacro(atom) xcb_atom_t A_ ## atom;
enum { #include "atoms.xmacro"
_NET_SUPPORTED = 0, #undef xmacro
_NET_SUPPORTING_WM_CHECK,
_NET_WM_NAME,
_NET_WM_STATE_FULLSCREEN,
_NET_WM_STATE,
_NET_WM_WINDOW_TYPE,
_NET_WM_WINDOW_TYPE_DOCK,
_NET_WM_WINDOW_TYPE_DIALOG,
_NET_WM_WINDOW_TYPE_UTILITY,
_NET_WM_WINDOW_TYPE_TOOLBAR,
_NET_WM_WINDOW_TYPE_SPLASH,
_NET_WM_DESKTOP,
_NET_WM_STRUT_PARTIAL,
WM_PROTOCOLS,
WM_DELETE_WINDOW,
UTF8_STRING,
WM_STATE,
WM_CLIENT_LEADER,
_NET_CURRENT_DESKTOP,
_NET_ACTIVE_WINDOW,
_NET_WORKAREA,
WM_TAKE_FOCUS,
NUM_ATOMS
};
extern unsigned int xcb_numlock_mask; extern unsigned int xcb_numlock_mask;

24
include/xcb_compat.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef _XCB_COMPAT_H
#define _XCB_COMPAT_H
#define xcb_icccm_get_wm_protocols_reply_t xcb_get_wm_protocols_reply_t
#define xcb_icccm_get_wm_protocols_unchecked xcb_get_wm_protocols_unchecked
#define xcb_icccm_get_wm_protocols_reply xcb_get_wm_protocols_reply
#define xcb_icccm_get_wm_protocols_reply_wipe xcb_get_wm_protocols_reply_wipe
#define XCB_ICCCM_WM_STATE_NORMAL XCB_WM_STATE_NORMAL
#define XCB_ICCCM_WM_STATE_WITHDRAWN XCB_WM_STATE_WITHDRAWN
#define xcb_icccm_get_wm_size_hints_from_reply xcb_get_wm_size_hints_from_reply
#define xcb_icccm_get_wm_normal_hints_reply xcb_get_wm_normal_hints_reply
#define xcb_icccm_get_wm_normal_hints_unchecked xcb_get_wm_normal_hints_unchecked
#define XCB_ICCCM_SIZE_HINT_P_MIN_SIZE XCB_SIZE_HINT_P_MIN_SIZE
#define XCB_ICCCM_SIZE_HINT_P_RESIZE_INC XCB_SIZE_HINT_P_RESIZE_INC
#define XCB_ICCCM_SIZE_HINT_BASE_SIZE XCB_SIZE_HINT_BASE_SIZE
#define XCB_ICCCM_SIZE_HINT_P_ASPECT XCB_SIZE_HINT_P_ASPECT
#define xcb_icccm_wm_hints_t xcb_wm_hints_t
#define xcb_icccm_get_wm_hints_from_reply xcb_get_wm_hints_from_reply
#define xcb_icccm_get_wm_hints_reply xcb_get_wm_hints_reply
#define xcb_icccm_get_wm_hints_unchecked xcb_get_wm_hints_unchecked
#define xcb_icccm_wm_hints_get_urgency xcb_wm_hints_get_urgency
#define xcb_icccm_get_wm_transient_for_from_reply xcb_get_wm_transient_for_from_reply
#endif

View File

@ -504,10 +504,10 @@ void con_toggle_fullscreen(Con *con) {
unsigned int num = 0; unsigned int num = 0;
if (con->fullscreen_mode != CF_NONE) if (con->fullscreen_mode != CF_NONE)
values[num++] = atoms[_NET_WM_STATE_FULLSCREEN]; values[num++] = A__NET_WM_STATE_FULLSCREEN;
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id, xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id,
atoms[_NET_WM_STATE], ATOM, 32, num, values); A__NET_WM_STATE, A_ATOM, 32, num, values);
} }
/* /*

View File

@ -31,7 +31,7 @@ void ewmh_update_current_desktop() {
TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) { TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
if (ws == focused_ws) { if (ws == focused_ws) {
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
atoms[_NET_CURRENT_DESKTOP], CARDINAL, 32, 1, &idx); A__NET_CURRENT_DESKTOP, A_CARDINAL, 32, 1, &idx);
return; return;
} }
++idx; ++idx;
@ -48,7 +48,7 @@ void ewmh_update_current_desktop() {
*/ */
void ewmh_update_active_window(xcb_window_t window) { void ewmh_update_active_window(xcb_window_t window) {
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
atoms[_NET_ACTIVE_WINDOW], WINDOW, 32, 1, &window); A__NET_ACTIVE_WINDOW, A_WINDOW, 32, 1, &window);
} }
/* /*
@ -104,7 +104,7 @@ void ewmh_update_workarea() {
} }
} }
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
atoms[_NET_WORKAREA], CARDINAL, 32, A__NET_WORKAREA, A_CARDINAL, 32,
num_workspaces * (sizeof(Rect) / sizeof(uint32_t)), num_workspaces * (sizeof(Rect) / sizeof(uint32_t)),
workarea); workarea);
free(workarea); free(workarea);

View File

@ -374,19 +374,15 @@ void drag_pointer(Con *con, xcb_button_press_event_t *event, xcb_window_t
while ((inside_event = xcb_wait_for_event(conn))) { while ((inside_event = xcb_wait_for_event(conn))) {
/* We now handle all events we can get using xcb_poll_for_event */ /* We now handle all events we can get using xcb_poll_for_event */
do { do {
/* Same as get_event_handler in xcb */ /* skip x11 errors */
int nr = inside_event->response_type; if (inside_event->response_type == 0) {
if (nr == 0) {
/* An error occured */
//handle_event(NULL, conn, inside_event);
free(inside_event); free(inside_event);
continue; continue;
} }
assert(nr < 256); /* Strip off the highest bit (set if the event is generated) */
nr &= XCB_EVENT_RESPONSE_TYPE_MASK; int type = (inside_event->response_type & 0x7F);
assert(nr >= 2);
switch (nr) { switch (type) {
case XCB_BUTTON_RELEASE: case XCB_BUTTON_RELEASE:
goto done; goto done;
@ -398,13 +394,13 @@ void drag_pointer(Con *con, xcb_button_press_event_t *event, xcb_window_t
case XCB_UNMAP_NOTIFY: case XCB_UNMAP_NOTIFY:
DLOG("Unmap-notify, aborting\n"); DLOG("Unmap-notify, aborting\n");
xcb_event_handle(&evenths, inside_event); handle_event(type, inside_event);
goto done; goto done;
default: default:
DLOG("Passing to original handler\n"); DLOG("Passing to original handler\n");
/* Use original handler */ /* Use original handler */
xcb_event_handle(&evenths, inside_event); handle_event(type, inside_event);
break; break;
} }
if (last_motion_notify != inside_event) if (last_motion_notify != inside_event)

View File

@ -6,14 +6,19 @@
* *
*/ */
#include <time.h> #include <time.h>
#include <limits.h>
#include <xcb/xcb_atom.h>
#include <xcb/randr.h> #include <xcb/randr.h>
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
#include "all.h" #include "all.h"
int randr_base = -1;
/* forward declaration for property_notify */
static int property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom);
/* After mapping/unmapping windows, a notify event is generated. However, we dont want it, /* After mapping/unmapping windows, a notify event is generated. However, we dont want it,
since itd trigger an infinite loop of switching between the different windows when since itd trigger an infinite loop of switching between the different windows when
changing workspaces */ changing workspaces */
@ -59,6 +64,143 @@ static bool event_is_ignored(const int sequence) {
return false; return false;
} }
/*
* Takes an xcb_generic_event_t and calls the appropriate handler, based on the
* event type.
*
*/
void handle_event(int type, xcb_generic_event_t *event) {
/* XXX: remove the NULL and conn parameters as soon as this version of libxcb is required */
if (randr_base > -1 &&
type == randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
handle_screen_change(NULL, conn, event);
return;
}
switch (type) {
case XCB_KEY_PRESS:
handle_key_press(NULL, conn, (xcb_key_press_event_t*)event);
break;
case XCB_BUTTON_PRESS:
handle_button_press(NULL, conn, (xcb_button_press_event_t*)event);
break;
case XCB_MAP_REQUEST:
handle_map_request(NULL, conn, (xcb_map_request_event_t*)event);
break;
case XCB_UNMAP_NOTIFY:
handle_unmap_notify_event(NULL, conn, (xcb_unmap_notify_event_t*)event);
break;
case XCB_DESTROY_NOTIFY:
handle_destroy_notify_event(NULL, conn, (xcb_destroy_notify_event_t*)event);
break;
case XCB_EXPOSE:
handle_expose_event(NULL, conn, (xcb_expose_event_t*)event);
break;
case XCB_MOTION_NOTIFY:
handle_motion_notify(NULL, conn, (xcb_motion_notify_event_t*)event);
break;
/* Enter window = user moved his mouse over the window */
case XCB_ENTER_NOTIFY:
handle_enter_notify(NULL, conn, (xcb_enter_notify_event_t*)event);
break;
/* Client message are sent to the root window. The only interesting
* client message for us is _NET_WM_STATE, we honour
* _NET_WM_STATE_FULLSCREEN */
case XCB_CLIENT_MESSAGE:
handle_client_message(NULL, conn, (xcb_client_message_event_t*)event);
break;
/* Configure request = window tried to change size on its own */
case XCB_CONFIGURE_REQUEST:
handle_configure_request(NULL, conn, (xcb_configure_request_event_t*)event);
break;
/* Mapping notify = keyboard mapping changed (Xmodmap), re-grab bindings */
case XCB_MAPPING_NOTIFY:
handle_mapping_notify(NULL, conn, (xcb_mapping_notify_event_t*)event);
break;
case XCB_PROPERTY_NOTIFY:
DLOG("Property notify\n");
xcb_property_notify_event_t *e = (xcb_property_notify_event_t*)event;
property_notify(e->state, e->window, e->atom);
break;
default:
DLOG("Unhandled event of type %d\n", type);
break;
}
}
typedef int (*cb_property_handler_t)(void *data, xcb_connection_t *c, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *property);
struct property_handler_t {
xcb_atom_t atom;
uint32_t long_len;
cb_property_handler_t cb;
};
static struct property_handler_t property_handlers[] = {
{ 0, 128, handle_windowname_change },
{ 0, UINT_MAX, handle_hints },
{ 0, 128, handle_windowname_change_legacy },
{ 0, UINT_MAX, handle_normal_hints },
{ 0, UINT_MAX, handle_clientleader_change },
{ 0, UINT_MAX, handle_transient_for }
};
#define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
/*
* Sets the appropriate atoms for the property handlers after the atoms were
* received from X11
*
*/
void property_handlers_init() {
property_handlers[0].atom = A__NET_WM_NAME;
property_handlers[1].atom = A_WM_HINTS;
property_handlers[2].atom = A_WM_NAME;
property_handlers[3].atom = A_WM_NORMAL_HINTS;
property_handlers[4].atom = A_WM_CLIENT_LEADER;
property_handlers[5].atom = A_WM_TRANSIENT_FOR;
}
static int property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom) {
struct property_handler_t *handler = NULL;
xcb_get_property_reply_t *propr = NULL;
int ret;
for (int c = 0; c < sizeof(property_handlers) / sizeof(struct property_handler_t); c++) {
if (property_handlers[c].atom != atom)
continue;
handler = &property_handlers[c];
break;
}
if (handler == NULL) {
DLOG("Unhandled property notify for atom %d (0x%08x)\n", atom, atom);
return 0;
}
if (state != XCB_PROPERTY_DELETE) {
xcb_get_property_cookie_t cookie = xcb_get_property(conn, 0, window, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, handler->long_len);
propr = xcb_get_property_reply(conn, cookie, 0);
}
ret = handler->cb(NULL, conn, state, window, atom, propr);
FREE(propr);
return ret;
}
/* /*
* There was a key press. We compare this key code with our bindings table and pass * There was a key press. We compare this key code with our bindings table and pass
* the bound action to parse_command(). * the bound action to parse_command().
@ -627,10 +769,10 @@ int handle_expose_event(void *data, xcb_connection_t *conn, xcb_expose_event_t *
*/ */
int handle_client_message(void *data, xcb_connection_t *conn, xcb_client_message_event_t *event) { int handle_client_message(void *data, xcb_connection_t *conn, xcb_client_message_event_t *event) {
LOG("ClientMessage for window 0x%08x\n", event->window); LOG("ClientMessage for window 0x%08x\n", event->window);
if (event->type == atoms[_NET_WM_STATE]) { if (event->type == A__NET_WM_STATE) {
if (event->format != 32 || event->data.data32[1] != atoms[_NET_WM_STATE_FULLSCREEN]) { if (event->format != 32 || event->data.data32[1] != A__NET_WM_STATE_FULLSCREEN) {
DLOG("atom in clientmessage is %d, fullscreen is %d\n", DLOG("atom in clientmessage is %d, fullscreen is %d\n",
event->data.data32[1], atoms[_NET_WM_STATE_FULLSCREEN]); event->data.data32[1], A__NET_WM_STATE_FULLSCREEN);
DLOG("not about fullscreen atom\n"); DLOG("not about fullscreen atom\n");
return 0; return 0;
} }
@ -693,17 +835,17 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w
/* If the hints were already in this event, use them, if not, request them */ /* If the hints were already in this event, use them, if not, request them */
if (reply != NULL) if (reply != NULL)
xcb_get_wm_size_hints_from_reply(&size_hints, reply); xcb_icccm_get_wm_size_hints_from_reply(&size_hints, reply);
else else
xcb_get_wm_normal_hints_reply(conn, xcb_get_wm_normal_hints_unchecked(conn, con->window->id), &size_hints, NULL); xcb_icccm_get_wm_normal_hints_reply(conn, xcb_icccm_get_wm_normal_hints_unchecked(conn, con->window->id), &size_hints, NULL);
if ((size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)) { if ((size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)) {
// TODO: Minimum size is not yet implemented // TODO: Minimum size is not yet implemented
DLOG("Minimum size: %d (width) x %d (height)\n", size_hints.min_width, size_hints.min_height); DLOG("Minimum size: %d (width) x %d (height)\n", size_hints.min_width, size_hints.min_height);
} }
bool changed = false; bool changed = false;
if ((size_hints.flags & XCB_SIZE_HINT_P_RESIZE_INC)) { if ((size_hints.flags & XCB_ICCCM_SIZE_HINT_P_RESIZE_INC)) {
if (size_hints.width_inc > 0 && size_hints.width_inc < 0xFFFF) if (size_hints.width_inc > 0 && size_hints.width_inc < 0xFFFF)
if (con->width_increment != size_hints.width_inc) { if (con->width_increment != size_hints.width_inc) {
con->width_increment = size_hints.width_inc; con->width_increment = size_hints.width_inc;
@ -724,10 +866,10 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w
/* base_width/height are the desired size of the window. /* base_width/height are the desired size of the window.
We check if either the program-specified size or the program-specified We check if either the program-specified size or the program-specified
min-size is available */ min-size is available */
if (size_hints.flags & XCB_SIZE_HINT_BASE_SIZE) { if (size_hints.flags & XCB_ICCCM_SIZE_HINT_BASE_SIZE) {
base_width = size_hints.base_width; base_width = size_hints.base_width;
base_height = size_hints.base_height; base_height = size_hints.base_height;
} else if (size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE) { } else if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) {
/* TODO: is this right? icccm says not */ /* TODO: is this right? icccm says not */
base_width = size_hints.min_width; base_width = size_hints.min_width;
base_height = size_hints.min_height; base_height = size_hints.min_height;
@ -742,7 +884,7 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w
} }
/* If no aspect ratio was set or if it was invalid, we ignore the hints */ /* If no aspect ratio was set or if it was invalid, we ignore the hints */
if (!(size_hints.flags & XCB_SIZE_HINT_P_ASPECT) || if (!(size_hints.flags & XCB_ICCCM_SIZE_HINT_P_ASPECT) ||
(size_hints.min_aspect_num <= 0) || (size_hints.min_aspect_num <= 0) ||
(size_hints.min_aspect_den <= 0)) { (size_hints.min_aspect_den <= 0)) {
goto render_and_return; goto render_and_return;
@ -788,13 +930,13 @@ int handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t
return 1; return 1;
} }
xcb_wm_hints_t hints; xcb_icccm_wm_hints_t hints;
if (reply != NULL) { if (reply != NULL) {
if (!xcb_get_wm_hints_from_reply(&hints, reply)) if (!xcb_icccm_get_wm_hints_from_reply(&hints, reply))
return 1; return 1;
} else { } else {
if (!xcb_get_wm_hints_reply(conn, xcb_get_wm_hints_unchecked(conn, con->window->id), &hints, NULL)) if (!xcb_icccm_get_wm_hints_reply(conn, xcb_icccm_get_wm_hints_unchecked(conn, con->window->id), &hints, NULL))
return 1; return 1;
} }
@ -804,7 +946,7 @@ int handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t
} }
/* Update the flag on the client directly */ /* Update the flag on the client directly */
con->urgent = (xcb_wm_hints_get_urgency(&hints) != 0); con->urgent = (xcb_icccm_wm_hints_get_urgency(&hints) != 0);
//CLIENT_LOG(con); //CLIENT_LOG(con);
LOG("Urgency flag changed to %d\n", con->urgent); LOG("Urgency flag changed to %d\n", con->urgent);
@ -841,7 +983,7 @@ int handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_
if (prop == NULL) { if (prop == NULL) {
prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn, prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
false, window, WM_TRANSIENT_FOR, WINDOW, 0, 32), NULL); false, window, A_WM_TRANSIENT_FOR, A_WINDOW, 0, 32), NULL);
if (prop == NULL) if (prop == NULL)
return 1; return 1;
} }
@ -872,7 +1014,7 @@ int handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state
if (prop == NULL) { if (prop == NULL) {
prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn, prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
false, window, WM_CLIENT_LEADER, WINDOW, 0, 32), NULL); false, window, A_WM_CLIENT_LEADER, A_WINDOW, 0, 32), NULL);
if (prop == NULL) if (prop == NULL)
return 1; return 1;
} }

View File

@ -15,9 +15,6 @@ extern Con *focused;
char **start_argv; char **start_argv;
xcb_connection_t *conn; xcb_connection_t *conn;
xcb_event_handlers_t evenths;
xcb_property_handlers_t prophs;
xcb_atom_t atoms[NUM_ATOMS];
xcb_window_t root; xcb_window_t root;
uint8_t root_depth; uint8_t root_depth;
@ -66,8 +63,17 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
xcb_generic_event_t *event; xcb_generic_event_t *event;
while ((event = xcb_poll_for_event(conn)) != NULL) { while ((event = xcb_poll_for_event(conn)) != NULL) {
xcb_event_handle(&evenths, event); if (event->response_type == 0) {
free(event); ELOG("X11 Error received! sequence %x\n", event->sequence);
continue;
}
/* Strip off the highest bit (set if the event is generated) */
int type = (event->response_type & 0x7F);
handle_event(type, event);
free(event);
} }
} }
@ -149,7 +155,6 @@ int main(int argc, char *argv[]) {
bool only_check_config = false; bool only_check_config = false;
bool force_xinerama = false; bool force_xinerama = false;
bool disable_signalhandler = false; bool disable_signalhandler = false;
xcb_intern_atom_cookie_t atom_cookies[NUM_ATOMS];
static struct option long_options[] = { static struct option long_options[] = {
{"no-autostart", no_argument, 0, 'a'}, {"no-autostart", no_argument, 0, 'a'},
{"config", required_argument, 0, 'c'}, {"config", required_argument, 0, 'c'},
@ -272,30 +277,10 @@ int main(int argc, char *argv[]) {
check_error(conn, cookie, "Another window manager seems to be running"); check_error(conn, cookie, "Another window manager seems to be running");
/* Place requests for the atoms we need as soon as possible */ /* Place requests for the atoms we need as soon as possible */
#define REQUEST_ATOM(name) atom_cookies[name] = xcb_intern_atom(conn, 0, strlen(#name), #name); #define xmacro(atom) \
xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
REQUEST_ATOM(_NET_SUPPORTED); #include "atoms.xmacro"
REQUEST_ATOM(_NET_WM_STATE_FULLSCREEN); #undef xmacro
REQUEST_ATOM(_NET_SUPPORTING_WM_CHECK);
REQUEST_ATOM(_NET_WM_NAME);
REQUEST_ATOM(_NET_WM_STATE);
REQUEST_ATOM(_NET_WM_WINDOW_TYPE);
REQUEST_ATOM(_NET_WM_DESKTOP);
REQUEST_ATOM(_NET_WM_WINDOW_TYPE_DOCK);
REQUEST_ATOM(_NET_WM_WINDOW_TYPE_DIALOG);
REQUEST_ATOM(_NET_WM_WINDOW_TYPE_UTILITY);
REQUEST_ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR);
REQUEST_ATOM(_NET_WM_WINDOW_TYPE_SPLASH);
REQUEST_ATOM(_NET_WM_STRUT_PARTIAL);
REQUEST_ATOM(WM_PROTOCOLS);
REQUEST_ATOM(WM_DELETE_WINDOW);
REQUEST_ATOM(UTF8_STRING);
REQUEST_ATOM(WM_STATE);
REQUEST_ATOM(WM_CLIENT_LEADER);
REQUEST_ATOM(_NET_CURRENT_DESKTOP);
REQUEST_ATOM(_NET_ACTIVE_WINDOW);
REQUEST_ATOM(_NET_WORKAREA);
REQUEST_ATOM(WM_TAKE_FOCUS);
/* Initialize the Xlib connection */ /* Initialize the Xlib connection */
xlibdpy = xkbdpy = XOpenDisplay(NULL); xlibdpy = xkbdpy = XOpenDisplay(NULL);
@ -338,95 +323,32 @@ int main(int argc, char *argv[]) {
} }
} }
memset(&evenths, 0, sizeof(xcb_event_handlers_t));
memset(&prophs, 0, sizeof(xcb_property_handlers_t));
xcb_event_handlers_init(conn, &evenths);
xcb_property_handlers_init(&prophs, &evenths);
xcb_event_set_key_press_handler(&evenths, handle_key_press, NULL);
xcb_event_set_button_press_handler(&evenths, handle_button_press, NULL);
xcb_event_set_map_request_handler(&evenths, handle_map_request, NULL);
xcb_event_set_unmap_notify_handler(&evenths, handle_unmap_notify_event, NULL);
xcb_event_set_destroy_notify_handler(&evenths, handle_destroy_notify_event, NULL);
xcb_event_set_expose_handler(&evenths, handle_expose_event, NULL);
xcb_event_set_motion_notify_handler(&evenths, handle_motion_notify, NULL);
/* Enter window = user moved his mouse over the window */
xcb_event_set_enter_notify_handler(&evenths, handle_enter_notify, NULL);
/* Client message are sent to the root window. The only interesting client message
for us is _NET_WM_STATE, we honour _NET_WM_STATE_FULLSCREEN */
xcb_event_set_client_message_handler(&evenths, handle_client_message, NULL);
/* Configure request = window tried to change size on its own */
xcb_event_set_configure_request_handler(&evenths, handle_configure_request, NULL);
/* Setup NetWM atoms */ /* Setup NetWM atoms */
#define GET_ATOM(name) \ #define xmacro(name) \
do { \ do { \
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, atom_cookies[name], NULL); \ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \
if (!reply) { \ if (!reply) { \
ELOG("Could not get atom " #name "\n"); \ ELOG("Could not get atom " #name "\n"); \
exit(-1); \ exit(-1); \
} \ } \
atoms[name] = reply->atom; \ A_ ## name = reply->atom; \
free(reply); \ free(reply); \
} while (0) } while (0);
#include "atoms.xmacro"
#undef xmacro
GET_ATOM(_NET_SUPPORTED); property_handlers_init();
GET_ATOM(_NET_WM_STATE_FULLSCREEN);
GET_ATOM(_NET_SUPPORTING_WM_CHECK);
GET_ATOM(_NET_WM_NAME);
GET_ATOM(_NET_WM_STATE);
GET_ATOM(_NET_WM_WINDOW_TYPE);
GET_ATOM(_NET_WM_DESKTOP);
GET_ATOM(_NET_WM_WINDOW_TYPE_DOCK);
GET_ATOM(_NET_WM_WINDOW_TYPE_DIALOG);
GET_ATOM(_NET_WM_WINDOW_TYPE_UTILITY);
GET_ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR);
GET_ATOM(_NET_WM_WINDOW_TYPE_SPLASH);
GET_ATOM(_NET_WM_STRUT_PARTIAL);
GET_ATOM(WM_PROTOCOLS);
GET_ATOM(WM_DELETE_WINDOW);
GET_ATOM(UTF8_STRING);
GET_ATOM(WM_STATE);
GET_ATOM(WM_CLIENT_LEADER);
GET_ATOM(_NET_CURRENT_DESKTOP);
GET_ATOM(_NET_ACTIVE_WINDOW);
GET_ATOM(_NET_WORKAREA);
GET_ATOM(WM_TAKE_FOCUS);
/* Watch _NET_WM_NAME (title of the window encoded in UTF-8) */
xcb_property_set_handler(&prophs, atoms[_NET_WM_NAME], 128, handle_windowname_change, NULL);
/* Watch WM_HINTS (contains the urgent property) */
xcb_property_set_handler(&prophs, WM_HINTS, UINT_MAX, handle_hints, NULL);
/* Watch WM_NAME (title of the window encoded in COMPOUND_TEXT) */
xcb_watch_wm_name(&prophs, 128, handle_windowname_change_legacy, NULL);
/* Watch WM_NORMAL_HINTS (aspect ratio, size increments, …) */
xcb_property_set_handler(&prophs, WM_NORMAL_HINTS, UINT_MAX, handle_normal_hints, NULL);
/* Watch WM_CLIENT_LEADER (= logical parent window for toolbars etc.) */
xcb_property_set_handler(&prophs, atoms[WM_CLIENT_LEADER], UINT_MAX, handle_clientleader_change, NULL);
/* Watch WM_TRANSIENT_FOR property (to which client this popup window belongs) */
xcb_property_set_handler(&prophs, WM_TRANSIENT_FOR, UINT_MAX, handle_transient_for, NULL);
/* Mapping notify = keyboard mapping changed (Xmodmap), re-grab bindings */
xcb_event_set_mapping_notify_handler(&evenths, handle_mapping_notify, NULL);
/* Set up the atoms we support */ /* Set up the atoms we support */
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTED], ATOM, 32, 7, atoms); xcb_atom_t supported_atoms[] = {
#define xmacro(atom) A_ ## atom,
#include "atoms.xmacro"
#undef xmacro
};
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, A_ATOM, 32, 7, supported_atoms);
/* Set up the window managers name */ /* Set up the window managers name */
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTING_WM_CHECK], WINDOW, 32, 1, &root); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTING_WM_CHECK, A_WINDOW, 32, 1, &root);
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_WM_NAME], atoms[UTF8_STRING], 8, strlen("i3"), "i3"); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3"), "i3");
keysyms = xcb_key_symbols_alloc(conn); keysyms = xcb_key_symbols_alloc(conn);
@ -446,17 +368,11 @@ int main(int argc, char *argv[]) {
if (needs_tree_init) if (needs_tree_init)
tree_init(); tree_init();
int randr_base;
if (force_xinerama) { if (force_xinerama) {
xinerama_init(); xinerama_init();
} else { } else {
DLOG("Checking for XRandR...\n"); DLOG("Checking for XRandR...\n");
randr_init(&randr_base); randr_init(&randr_base);
xcb_event_set_handler(&evenths,
randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY,
handle_screen_change,
NULL);
} }
tree_render(); tree_render();

View File

@ -85,15 +85,6 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
utf8_title_cookie, title_cookie, utf8_title_cookie, title_cookie,
class_cookie, leader_cookie, transient_cookie; class_cookie, leader_cookie, transient_cookie;
wm_type_cookie = xcb_get_any_property_unchecked(conn, false, window, atoms[_NET_WM_WINDOW_TYPE], UINT32_MAX);
strut_cookie = xcb_get_any_property_unchecked(conn, false, window, atoms[_NET_WM_STRUT_PARTIAL], UINT32_MAX);
state_cookie = xcb_get_any_property_unchecked(conn, false, window, atoms[_NET_WM_STATE], UINT32_MAX);
utf8_title_cookie = xcb_get_any_property_unchecked(conn, false, window, atoms[_NET_WM_NAME], 128);
leader_cookie = xcb_get_any_property_unchecked(conn, false, window, atoms[WM_CLIENT_LEADER], UINT32_MAX);
transient_cookie = xcb_get_any_property_unchecked(conn, false, window, WM_TRANSIENT_FOR, UINT32_MAX);
title_cookie = xcb_get_any_property_unchecked(conn, false, window, WM_NAME, 128);
class_cookie = xcb_get_any_property_unchecked(conn, false, window, WM_CLASS, 128);
/* TODO: also get wm_normal_hints here. implement after we got rid of xcb-event */
geomc = xcb_get_geometry(conn, d); geomc = xcb_get_geometry(conn, d);
@ -126,6 +117,18 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
goto out; goto out;
} }
#define GET_PROPERTY(atom, len) xcb_get_property_unchecked(conn, false, window, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, len)
wm_type_cookie = GET_PROPERTY(A__NET_WM_WINDOW_TYPE, UINT32_MAX);
strut_cookie = GET_PROPERTY(A__NET_WM_STRUT_PARTIAL, UINT32_MAX);
state_cookie = GET_PROPERTY(A__NET_WM_STATE, UINT32_MAX);
utf8_title_cookie = GET_PROPERTY(A__NET_WM_NAME, 128);
leader_cookie = GET_PROPERTY(A_WM_CLIENT_LEADER, UINT32_MAX);
transient_cookie = GET_PROPERTY(A_WM_TRANSIENT_FOR, UINT32_MAX);
title_cookie = GET_PROPERTY(A_WM_NAME, 128);
class_cookie = GET_PROPERTY(A_WM_CLASS, 128);
/* TODO: also get wm_normal_hints here. implement after we got rid of xcb-event */
DLOG("reparenting!\n"); DLOG("reparenting!\n");
uint32_t mask = 0; uint32_t mask = 0;
uint32_t values[1]; uint32_t values[1];
@ -157,7 +160,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
Con *search_at = croot; Con *search_at = croot;
xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, wm_type_cookie, NULL); xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, wm_type_cookie, NULL);
if (xcb_reply_contains_atom(reply, atoms[_NET_WM_WINDOW_TYPE_DOCK])) { if (xcb_reply_contains_atom(reply, A__NET_WM_WINDOW_TYPE_DOCK)) {
LOG("This window is of type dock\n"); LOG("This window is of type dock\n");
Output *output = get_output_containing(geom->x, geom->y); Output *output = get_output_containing(geom->x, geom->y);
if (output != NULL) { if (output != NULL) {
@ -254,10 +257,10 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
/* set floating if necessary */ /* set floating if necessary */
bool want_floating = false; bool want_floating = false;
if (xcb_reply_contains_atom(reply, atoms[_NET_WM_WINDOW_TYPE_DIALOG]) || if (xcb_reply_contains_atom(reply, A__NET_WM_WINDOW_TYPE_DIALOG) ||
xcb_reply_contains_atom(reply, atoms[_NET_WM_WINDOW_TYPE_UTILITY]) || xcb_reply_contains_atom(reply, A__NET_WM_WINDOW_TYPE_UTILITY) ||
xcb_reply_contains_atom(reply, atoms[_NET_WM_WINDOW_TYPE_TOOLBAR]) || xcb_reply_contains_atom(reply, A__NET_WM_WINDOW_TYPE_TOOLBAR) ||
xcb_reply_contains_atom(reply, atoms[_NET_WM_WINDOW_TYPE_SPLASH])) { xcb_reply_contains_atom(reply, A__NET_WM_WINDOW_TYPE_SPLASH)) {
LOG("This window is a dialog window, setting floating\n"); LOG("This window is a dialog window, setting floating\n");
want_floating = true; want_floating = true;
} }
@ -308,7 +311,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
xcb_change_window_attributes(conn, window, mask, values); xcb_change_window_attributes(conn, window, mask, values);
reply = xcb_get_property_reply(conn, state_cookie, NULL); reply = xcb_get_property_reply(conn, state_cookie, NULL);
if (xcb_reply_contains_atom(reply, atoms[_NET_WM_STATE_FULLSCREEN])) if (xcb_reply_contains_atom(reply, A__NET_WM_STATE_FULLSCREEN))
con_toggle_fullscreen(nc); con_toggle_fullscreen(nc);
/* Put the client inside the save set. Upon termination (whether killed or /* Put the client inside the save set. Upon termination (whether killed or

View File

@ -26,12 +26,7 @@
#include <X11/keysym.h> #include <X11/keysym.h>
#include "i3.h" #include "all.h"
#include "util.h"
#include "xcb.h"
#include "log.h"
#include "config.h"
#include "randr.h"
static xcb_gcontext_t pixmap_gc; static xcb_gcontext_t pixmap_gc;
static xcb_pixmap_t pixmap; static xcb_pixmap_t pixmap;
@ -159,12 +154,6 @@ void handle_signal(int sig, siginfo_t *info, void *data) {
sigaction(sig, &action, NULL); sigaction(sig, &action, NULL);
raised_signal = sig; raised_signal = sig;
/* setup event handler for key presses */
xcb_event_handlers_t sig_evenths;
memset(&sig_evenths, 0, sizeof(xcb_event_handlers_t));
xcb_event_handlers_init(conn, &sig_evenths);
xcb_event_set_key_press_handler(&sig_evenths, sig_handle_key_press, NULL);
/* width and height of the popup window, so that the text fits in */ /* width and height of the popup window, so that the text fits in */
int crash_text_num = sizeof(crash_text) / sizeof(char*); int crash_text_num = sizeof(crash_text) / sizeof(char*);
int height = 13 + (crash_text_num * config.font.height); int height = 13 + (crash_text_num * config.font.height);
@ -203,7 +192,16 @@ void handle_signal(int sig, siginfo_t *info, void *data) {
xcb_flush(conn); xcb_flush(conn);
} }
xcb_event_wait_for_event_loop(&sig_evenths); xcb_generic_event_t *event;
/* Yay, more own eventhandlers… */
while ((event = xcb_wait_for_event(conn))) {
/* Strip off the highest bit (set if the event is generated) */
int type = (event->response_type & 0x7F);
if (type == XCB_KEY_PRESS) {
sig_handle_key_press(NULL, conn, (xcb_key_press_event_t*)event);
}
free(event);
}
} }
/* /*

View File

@ -136,7 +136,7 @@ void window_update_transient_for(i3Window *win, xcb_get_property_reply_t *prop)
} }
xcb_window_t transient_for; xcb_window_t transient_for;
if (!xcb_get_wm_transient_for_from_reply(&transient_for, prop)) if (!xcb_icccm_get_wm_transient_for_from_reply(&transient_for, prop))
return; return;
DLOG("Transient for changed to %08x\n", transient_for); DLOG("Transient for changed to %08x\n", transient_for);

28
src/x.c
View File

@ -180,11 +180,11 @@ void x_con_kill(Con *con) {
*/ */
static bool window_supports_protocol(xcb_window_t window, xcb_atom_t atom) { static bool window_supports_protocol(xcb_window_t window, xcb_atom_t atom) {
xcb_get_property_cookie_t cookie; xcb_get_property_cookie_t cookie;
xcb_get_wm_protocols_reply_t protocols; xcb_icccm_get_wm_protocols_reply_t protocols;
bool result = false; bool result = false;
cookie = xcb_get_wm_protocols_unchecked(conn, window, atoms[WM_PROTOCOLS]); cookie = xcb_icccm_get_wm_protocols_unchecked(conn, window, A_WM_PROTOCOLS);
if (xcb_get_wm_protocols_reply(conn, cookie, &protocols, NULL) != 1) if (xcb_icccm_get_wm_protocols_reply(conn, cookie, &protocols, NULL) != 1)
return false; return false;
/* Check if the clients protocols have the requested atom set */ /* Check if the clients protocols have the requested atom set */
@ -192,7 +192,7 @@ static bool window_supports_protocol(xcb_window_t window, xcb_atom_t atom) {
if (protocols.atoms[i] == atom) if (protocols.atoms[i] == atom)
result = true; result = true;
xcb_get_wm_protocols_reply_wipe(&protocols); xcb_icccm_get_wm_protocols_reply_wipe(&protocols);
return result; return result;
} }
@ -203,7 +203,7 @@ static bool window_supports_protocol(xcb_window_t window, xcb_atom_t atom) {
*/ */
void x_window_kill(xcb_window_t window) { void x_window_kill(xcb_window_t window) {
/* if this window does not support WM_DELETE_WINDOW, we kill it the hard way */ /* if this window does not support WM_DELETE_WINDOW, we kill it the hard way */
if (!window_supports_protocol(window, atoms[WM_DELETE_WINDOW])) { if (!window_supports_protocol(window, A_WM_DELETE_WINDOW)) {
LOG("Killing window the hard way\n"); LOG("Killing window the hard way\n");
xcb_kill_client(conn, window); xcb_kill_client(conn, window);
return; return;
@ -215,9 +215,9 @@ void x_window_kill(xcb_window_t window) {
ev.response_type = XCB_CLIENT_MESSAGE; ev.response_type = XCB_CLIENT_MESSAGE;
ev.window = window; ev.window = window;
ev.type = atoms[WM_PROTOCOLS]; ev.type = A_WM_PROTOCOLS;
ev.format = 32; ev.format = 32;
ev.data.data32[0] = atoms[WM_DELETE_WINDOW]; ev.data.data32[0] = A_WM_DELETE_WINDOW;
ev.data.data32[1] = XCB_CURRENT_TIME; ev.data.data32[1] = XCB_CURRENT_TIME;
LOG("Sending WM_DELETE to the client\n"); LOG("Sending WM_DELETE to the client\n");
@ -389,7 +389,7 @@ static void x_push_node(Con *con) {
DLOG("pushing name %s for con %p\n", state->name, con); DLOG("pushing name %s for con %p\n", state->name, con);
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->frame, xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->frame,
WM_NAME, STRING, 8, strlen(state->name), state->name); A_WM_NAME, A_STRING, 8, strlen(state->name), state->name);
FREE(state->name); FREE(state->name);
} }
@ -468,9 +468,9 @@ static void x_push_node(Con *con) {
if (con->window != NULL) { if (con->window != NULL) {
/* Set WM_STATE_NORMAL because GTK applications dont want to /* Set WM_STATE_NORMAL because GTK applications dont want to
* drag & drop if we dont. Also, xprop(1) needs it. */ * drag & drop if we dont. Also, xprop(1) needs it. */
long data[] = { XCB_WM_STATE_NORMAL, XCB_NONE }; long data[] = { XCB_ICCCM_WM_STATE_NORMAL, XCB_NONE };
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id, xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id,
atoms[WM_STATE], atoms[WM_STATE], 32, 2, data); A_WM_STATE, A_WM_STATE, 32, 2, data);
} }
if (!state->child_mapped && con->window != NULL) { if (!state->child_mapped && con->window != NULL) {
@ -528,9 +528,9 @@ static void x_push_node_unmaps(Con *con) {
xcb_void_cookie_t cookie; xcb_void_cookie_t cookie;
if (con->window != NULL) { if (con->window != NULL) {
/* Set WM_STATE_WITHDRAWN, it seems like Java apps need it */ /* Set WM_STATE_WITHDRAWN, it seems like Java apps need it */
long data[] = { XCB_WM_STATE_WITHDRAWN, XCB_NONE }; long data[] = { XCB_ICCCM_WM_STATE_WITHDRAWN, XCB_NONE };
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id, xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id,
atoms[WM_STATE], atoms[WM_STATE], 32, 2, data); A_WM_STATE, A_WM_STATE, 32, 2, data);
} }
cookie = xcb_unmap_window(conn, con->frame); cookie = xcb_unmap_window(conn, con->frame);
@ -624,9 +624,9 @@ void x_push_changes(Con *con) {
ev.response_type = XCB_CLIENT_MESSAGE; ev.response_type = XCB_CLIENT_MESSAGE;
ev.window = to_focus; ev.window = to_focus;
ev.type = atoms[WM_PROTOCOLS]; ev.type = A_WM_PROTOCOLS;
ev.format = 32; ev.format = 32;
ev.data.data32[0] = atoms[WM_TAKE_FOCUS]; ev.data.data32[0] = A_WM_TAKE_FOCUS;
ev.data.data32[1] = XCB_CURRENT_TIME; ev.data.data32[1] = XCB_CURRENT_TIME;
DLOG("Sending WM_TAKE_FOCUS to the client\n"); DLOG("Sending WM_TAKE_FOCUS to the client\n");