diff --git a/awesome.c b/awesome.c index 6c848db8..01ed304e 100644 --- a/awesome.c +++ b/awesome.c @@ -208,14 +208,14 @@ a_xcb_check_cb(EV_P_ ev_check *w, int revents) } else { - xcb_event_handle(&globalconf.evenths, event); + event_handle(event); p_delete(&event); } } if(mouse) { - xcb_event_handle(&globalconf.evenths, mouse); + event_handle(mouse); p_delete(&mouse); } } @@ -226,20 +226,6 @@ a_xcb_io_cb(EV_P_ ev_io *w, int revents) /* empty */ } -/** Startup Error handler to check if another window manager - * is already running. - * \param data Additional optional parameters data. - * \param c X connection. - * \param error Error event. - */ -static int __attribute__ ((noreturn)) -xerrorstart(void * data __attribute__ ((unused)), - xcb_connection_t * c __attribute__ ((unused)), - xcb_generic_error_t * error __attribute__ ((unused))) -{ - fatal("another window manager is already running"); -} - static void signal_fatal(int signum) { @@ -275,37 +261,6 @@ restart_on_signal(EV_P_ ev_signal *w, int revents) awesome_restart(); } -/** \brief awesome xerror function. - * There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. - * \param data Currently unused. - * \param c The connection to the X server. - * \param e The error event. - * \return 0 if no error, or xerror's xlib return status. - */ -static int -xerror(void *data __attribute__ ((unused)), - xcb_connection_t *c __attribute__ ((unused)), - xcb_generic_error_t *e) -{ - /* ignore this */ - if(e->error_code == XCB_EVENT_ERROR_BAD_WINDOW - || (e->error_code == XCB_EVENT_ERROR_BAD_MATCH - && e->major_code == XCB_SET_INPUT_FOCUS) - || (e->error_code == XCB_EVENT_ERROR_BAD_VALUE - && e->major_code == XCB_KILL_CLIENT) - || (e->major_code == XCB_CONFIGURE_WINDOW - && e->error_code == XCB_EVENT_ERROR_BAD_MATCH)) - return 0; - - warn("X error: request=%s, error=%s", - xcb_event_get_request_label(e->major_code), - xcb_event_get_error_label(e->error_code)); - - return 0; -} - /** Print help and exit(2) with given exit_code. * \param exit_code The exit code. */ @@ -456,10 +411,6 @@ main(int argc, char **argv) ev_prepare_start(globalconf.loop, &a_refresh); ev_unref(globalconf.loop); - /* Allocate a handler which will holds all errors and events */ - xcb_event_handlers_init(globalconf.connection, &globalconf.evenths); - xutil_error_handler_catch_all_set(&globalconf.evenths, xerrorstart, NULL); - for(screen_nbr = 0; screen_nbr < xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); screen_nbr++) @@ -475,11 +426,10 @@ main(int argc, char **argv) /* Need to xcb_flush to validate error handler */ xcb_aux_sync(globalconf.connection); - /* Process all errors in the queue if any */ - xcb_event_poll_for_event_loop(&globalconf.evenths); - - /* Set the default xerror handler */ - xutil_error_handler_catch_all_set(&globalconf.evenths, xerror, NULL); + /* Process all errors in the queue if any. There can be no events yet, so if + * this function returns something, it must be an error. */ + if (xcb_poll_for_event(globalconf.connection) != NULL) + fatal("another window manager is already running"); /* Prefetch the maximum request length */ xcb_prefetch_maximum_request_length(globalconf.connection); @@ -556,11 +506,6 @@ main(int argc, char **argv) /* scan existing windows */ scan(); - /* process all errors in the queue if any */ - xcb_event_poll_for_event_loop(&globalconf.evenths); - a_xcb_set_event_handlers(); - a_xcb_set_property_handlers(); - /* we will receive events, stop grabbing server */ xcb_ungrab_server(globalconf.connection); xcb_flush(globalconf.connection); diff --git a/common/xutil.c b/common/xutil.c index ec29ecfa..3d80e8d6 100644 --- a/common/xutil.c +++ b/common/xutil.c @@ -93,16 +93,6 @@ xutil_lock_mask_get(xcb_connection_t *connection, /* Number of different errors */ #define ERRORS_NBR 256 -void -xutil_error_handler_catch_all_set(xcb_event_handlers_t *evenths, - xcb_generic_error_handler_t handler, - void *data) -{ - int err_num; - for(err_num = 0; err_num < ERRORS_NBR; err_num++) - xcb_event_set_error_handler(evenths, err_num, handler, data); -} - uint16_t xutil_key_mask_fromstr(const char *keyname, size_t len) { diff --git a/event.c b/event.c index 77baf9e5..3d17e59f 100644 --- a/event.c +++ b/event.c @@ -27,6 +27,7 @@ #include "awesome.h" #include "event.h" +#include "property.h" #include "objects/tag.h" #include "xwindow.h" #include "ewmh.h" @@ -836,36 +837,79 @@ event_handle_reparentnotify(void *data, return 0; } -void a_xcb_set_event_handlers(void) +/** \brief awesome xerror function. + * There's no way to check accesses to destroyed windows, thus those cases are + * ignored (especially on UnmapNotify's). + * \param e The error event. + */ +static void +xerror(xcb_generic_error_t *e) { - const xcb_query_extension_reply_t *randr_query; + /* ignore this */ + if(e->error_code == XCB_EVENT_ERROR_BAD_WINDOW + || (e->error_code == XCB_EVENT_ERROR_BAD_MATCH + && e->major_code == XCB_SET_INPUT_FOCUS) + || (e->error_code == XCB_EVENT_ERROR_BAD_VALUE + && e->major_code == XCB_KILL_CLIENT) + || (e->major_code == XCB_CONFIGURE_WINDOW + && e->error_code == XCB_EVENT_ERROR_BAD_MATCH)) + return; - xcb_event_set_button_press_handler(&globalconf.evenths, event_handle_button, NULL); - xcb_event_set_button_release_handler(&globalconf.evenths, event_handle_button, NULL); - xcb_event_set_configure_request_handler(&globalconf.evenths, event_handle_configurerequest, NULL); - xcb_event_set_configure_notify_handler(&globalconf.evenths, event_handle_configurenotify, NULL); - xcb_event_set_destroy_notify_handler(&globalconf.evenths, event_handle_destroynotify, NULL); - xcb_event_set_enter_notify_handler(&globalconf.evenths, event_handle_enternotify, NULL); - xcb_event_set_leave_notify_handler(&globalconf.evenths, event_handle_leavenotify, NULL); - xcb_event_set_focus_in_handler(&globalconf.evenths, event_handle_focusin, NULL); - xcb_event_set_motion_notify_handler(&globalconf.evenths, event_handle_motionnotify, NULL); - xcb_event_set_expose_handler(&globalconf.evenths, event_handle_expose, NULL); - xcb_event_set_key_press_handler(&globalconf.evenths, event_handle_key, NULL); - xcb_event_set_key_release_handler(&globalconf.evenths, event_handle_key, NULL); - xcb_event_set_map_request_handler(&globalconf.evenths, event_handle_maprequest, NULL); - xcb_event_set_unmap_notify_handler(&globalconf.evenths, event_handle_unmapnotify, NULL); - xcb_event_set_client_message_handler(&globalconf.evenths, event_handle_clientmessage, NULL); - xcb_event_set_mapping_notify_handler(&globalconf.evenths, event_handle_mappingnotify, NULL); - xcb_event_set_reparent_notify_handler(&globalconf.evenths, event_handle_reparentnotify, NULL); + warn("X error: request=%s, error=%s", + xcb_event_get_request_label(e->major_code), + xcb_event_get_error_label(e->error_code)); - /* check for randr extension */ - randr_query = xcb_get_extension_data(globalconf.connection, &xcb_randr_id); - if(randr_query->present) - xcb_event_set_handler(&globalconf.evenths, - randr_query->first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY, - (xcb_generic_event_handler_t) event_handle_randr_screen_change_notify, - NULL); + return; +} +void event_handle(xcb_generic_event_t *event) +{ + uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(event); + + if(response_type == 0) + { + /* This is an error, not a event */ + xerror((xcb_generic_error_t *) event); + return; + } + + switch(response_type) + { +#define EVENT(type, callback) case type: callback(NULL, globalconf.connection, (void *) event); return + EVENT(XCB_BUTTON_PRESS, event_handle_button); + EVENT(XCB_BUTTON_RELEASE, event_handle_button); + EVENT(XCB_CONFIGURE_REQUEST, event_handle_configurerequest); + EVENT(XCB_CONFIGURE_NOTIFY, event_handle_configurenotify); + EVENT(XCB_DESTROY_NOTIFY, event_handle_destroynotify); + EVENT(XCB_ENTER_NOTIFY, event_handle_enternotify); + EVENT(XCB_CLIENT_MESSAGE, event_handle_clientmessage); + EVENT(XCB_EXPOSE, event_handle_expose); + EVENT(XCB_FOCUS_IN, event_handle_focusin); + EVENT(XCB_KEY_PRESS, event_handle_key); + EVENT(XCB_KEY_RELEASE, event_handle_key); + EVENT(XCB_LEAVE_NOTIFY, event_handle_leavenotify); + EVENT(XCB_MAPPING_NOTIFY, event_handle_mappingnotify); + EVENT(XCB_MAP_REQUEST, event_handle_maprequest); + EVENT(XCB_MOTION_NOTIFY, event_handle_motionnotify); + EVENT(XCB_PROPERTY_NOTIFY, property_handle_propertynotify); + EVENT(XCB_REPARENT_NOTIFY, event_handle_reparentnotify); + EVENT(XCB_UNMAP_NOTIFY, event_handle_unmapnotify); +#undef EVENT + } + + static uint8_t randr_screen_change_notify = 0; + + if(randr_screen_change_notify == 0) + { + /* check for randr extension */ + const xcb_query_extension_reply_t *randr_query; + randr_query = xcb_get_extension_data(globalconf.connection, &xcb_randr_id); + if(randr_query->present) + randr_screen_change_notify = randr_query->first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY; + } + + if (response_type == randr_screen_change_notify) + event_handle_randr_screen_change_notify(NULL, globalconf.connection, (void *) event); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/event.h b/event.h index 1dc1e77d..1f895e3c 100644 --- a/event.h +++ b/event.h @@ -36,7 +36,7 @@ awesome_refresh(void) return xcb_flush(globalconf.connection); } -void a_xcb_set_event_handlers(void); +void event_handle(xcb_generic_event_t *event); #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/globalconf.h b/globalconf.h index 383113c8..169df940 100644 --- a/globalconf.h +++ b/globalconf.h @@ -53,8 +53,6 @@ typedef struct { /** Connection ref */ xcb_connection_t *connection; - /** Event and error handlers */ - xcb_event_handlers_t evenths; /** Default screen number */ int default_screen; /** Keys symbol table */ diff --git a/property.c b/property.c index 3e62e4fd..1b2e11fe 100644 --- a/property.c +++ b/property.c @@ -406,10 +406,10 @@ property_handle_net_wm_opacity(uint8_t state, * \param ev The event. * \return Status code, 0 if everything's fine. */ -static int -handle_propertynotify(void *data, - xcb_connection_t *c, - xcb_property_notify_event_t *ev) +int +property_handle_propertynotify(void *data, + xcb_connection_t *c, + xcb_property_notify_event_t *ev) { uint32_t length; int (*handler)(uint8_t state, @@ -477,10 +477,4 @@ handle_propertynotify(void *data, return ret; } -void a_xcb_set_property_handlers(void) -{ - /* Register our handler for PropertyNotify events */ - xcb_event_set_property_notify_handler(&globalconf.evenths, handle_propertynotify, NULL); -} - // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/property.h b/property.h index 7da99b05..3fb70e35 100644 --- a/property.h +++ b/property.h @@ -38,7 +38,10 @@ void property_update_wm_client_machine(client_t *, xcb_get_property_reply_t *); void property_update_wm_window_role(client_t *, xcb_get_property_reply_t *); void property_update_net_wm_pid(client_t *, xcb_get_property_reply_t *); void property_update_net_wm_icon(client_t *, xcb_get_property_reply_t *); -void a_xcb_set_property_handlers(void); + +int property_handle_propertynotify(void *data, + xcb_connection_t *c, + xcb_property_notify_event_t *ev); #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/selection.c b/selection.c index a4433642..e6e4792b 100644 --- a/selection.c +++ b/selection.c @@ -74,7 +74,7 @@ luaA_selection_get(lua_State *L) * Anyway that's still brakes the socket or D-Bus, so maybe using * ev_loop() would be even better. */ - xcb_event_handle(&globalconf.evenths, event); + event_handle(event); p_delete(&event); awesome_refresh(); continue;