summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuentin Glidic <sardemff7+git@sardemff7.net>2017-06-01 00:39:11 +0200
committerQuentin Glidic <sardemff7+git@sardemff7.net>2017-06-01 00:39:11 +0200
commit9b58a9bc3117591480b200612dd637989f97dcb4 (patch)
treef6c2565cf261c076479d0818bc2321f9e63df568
parent46dee2671dfa23635d885e855d36d46df63586b1 (diff)
xcb: Move more stuff to xcb.c
Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>
-rw-r--r--include/view.h3
-rw-r--r--include/xcb-internal.h11
-rw-r--r--include/xcb.h5
-rw-r--r--include/xkb-internal.h46
-rw-r--r--include/xkb.h35
-rw-r--r--meson.build2
-rw-r--r--source/keyb.c2
-rw-r--r--source/rofi.c232
-rw-r--r--source/view.c13
-rw-r--r--source/xcb.c218
10 files changed, 241 insertions, 326 deletions
diff --git a/include/view.h b/include/view.h
index 6dd82230..e9a437c1 100644
--- a/include/view.h
+++ b/include/view.h
@@ -28,7 +28,6 @@
#ifndef ROFI_VIEW_H
#define ROFI_VIEW_H
#include "mode.h"
-#include "xkb.h"
/**
* @defgroup View View
@@ -99,7 +98,7 @@ unsigned int rofi_view_get_next_position ( const RofiViewState *state );
*
* Process an Xevent.
*/
-void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, xkb_stuff *xkb );
+void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, NkBindingsSeat *seat );
/**
* @param state the Menu handle
*
diff --git a/include/xcb-internal.h b/include/xcb-internal.h
index 0e6a6382..ef151a79 100644
--- a/include/xcb-internal.h
+++ b/include/xcb-internal.h
@@ -34,6 +34,8 @@
#include <xcb/xcb.h>
#include <xcb/xcb_ewmh.h>
+#include "nkutils-bindings.h"
+
/**
* Structure to keep xcb stuff around.
*/
@@ -46,6 +48,15 @@ struct _xcb_stuff
SnDisplay *sndisplay;
SnLauncheeContext *sncontext;
struct _workarea *monitors;
+ struct
+ {
+ /** Flag indicating first event */
+ uint8_t first_event;
+ /** Keyboard device id */
+ int32_t device_id;
+ } xkb;
+ NkBindings *bindings;
+ NkBindingsSeat *bindings_seat;
};
#endif
diff --git a/include/xcb.h b/include/xcb.h
index e7743a45..47906170 100644
--- a/include/xcb.h
+++ b/include/xcb.h
@@ -40,6 +40,8 @@ typedef struct _xcb_stuff xcb_stuff;
*/
extern xcb_stuff *xcb;
+gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UNUSED gpointer data );
+
/**
* @param xcb the xcb data structure
*
@@ -55,7 +57,6 @@ xcb_window_t xcb_stuff_get_root_window ( xcb_stuff *xcb );
*/
void xcb_stuff_wipe ( xcb_stuff *xcb );
-
/**
* @param w The xcb_window_t to read property from.
* @param atom The property identifier
@@ -192,7 +193,7 @@ int take_pointer ( xcb_window_t w, int iters );
* * Numlock detection
* * Cache
*/
-void x11_setup ( void );
+gboolean x11_setup ( void );
/**
* Depth of visual
diff --git a/include/xkb-internal.h b/include/xkb-internal.h
deleted file mode 100644
index 861d4462..00000000
--- a/include/xkb-internal.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * rofi
- *
- * MIT/X11 License
- * Copyright © 2013-2017 Qball Cow <qball@gmpclient.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#ifndef ROFI_XKB_INTERNAL_H
-#define ROFI_XKB_INTERNAL_H
-
-#include "nkutils-bindings.h"
-#include <xkbcommon/xkbcommon.h>
-
-struct xkb_stuff
-{
- /** connection to the X server*/
- xcb_connection_t *xcb_connection;
- /** Flag indicating first event */
- uint8_t first_event;
- /** Keyboard device id */
- int32_t device_id;
- NkBindings *bindings;
- NkBindingsSeat *bindings_seat;
-};
-
-#endif
diff --git a/include/xkb.h b/include/xkb.h
deleted file mode 100644
index 52202c18..00000000
--- a/include/xkb.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * rofi
- *
- * MIT/X11 License
- * Copyright © 2013-2017 Qball Cow <qball@gmpclient.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#ifndef ROFI_XKB_H
-#define ROFI_XKB_H
-
-/**
- * Structure holding xkb related state.
- */
-typedef struct xkb_stuff xkb_stuff;
-#endif
diff --git a/meson.build b/meson.build
index df39486d..d852d148 100644
--- a/meson.build
+++ b/meson.build
@@ -197,8 +197,6 @@ rofi_sources = files(
'include/dialogs/window.h',
'include/dialogs/dialogs.h',
'include/dialogs/help-keys.h',
- 'include/xkb.h',
- 'include/xkb-internal.h',
)
theme_lexer_sources = files('lexer/theme-lexer.l')
theme_parser_sources = files('lexer/theme-parser.y')
diff --git a/source/keyb.c b/source/keyb.c
index 394be6eb..a5a7ceb0 100644
--- a/source/keyb.c
+++ b/source/keyb.c
@@ -28,8 +28,6 @@
#include <config.h>
#include <string.h>
#include "rofi.h"
-#include "xkb.h"
-#include "xkb-internal.h"
#include "nkutils-bindings.h"
#include "xrmoptions.h"
diff --git a/source/rofi.c b/source/rofi.c
index 38c5cd12..1bea2436 100644
--- a/source/rofi.c
+++ b/source/rofi.c
@@ -39,11 +39,6 @@
#include <locale.h>
#include <gmodule.h>
#include <xcb/xcb.h>
-#include <xcb/xcb_aux.h>
-#include <xcb/xcb_ewmh.h>
-#include <xcb/xkb.h>
-#include <xkbcommon/xkbcommon.h>
-#include <xkbcommon/xkbcommon-x11.h>
#include <sys/types.h>
#include <glib-unix.h>
@@ -51,7 +46,6 @@
#include <libgwater-xcb.h>
#include "xcb-internal.h"
-#include "xkb-internal.h"
#include "settings.h"
#include "mode.h"
@@ -86,12 +80,6 @@ void rofi_add_error_message ( GString *str )
{
list_of_error_msgs = g_list_append ( list_of_error_msgs, str );
}
-/** global structure holding the keyboard status */
-struct xkb_stuff xkb = {
- .xcb_connection = NULL,
- .bindings = NULL,
- .bindings_seat = NULL,
-};
/** Path to the configuration file */
G_MODULE_EXPORT char *config_path = NULL;
@@ -432,10 +420,6 @@ static void cleanup ()
g_main_loop_unref ( main_loop );
main_loop = NULL;
}
- // XKB Cleanup
- //
- nk_bindings_free ( xkb.bindings );
-
// Cleanup
xcb_stuff_wipe ( xcb );
@@ -629,76 +613,6 @@ static gboolean setup_modi ( void )
return FALSE;
}
-/**
- * Process X11 events in the main-loop (gui-thread) of the application.
- */
-static void main_loop_x11_event_handler_view ( xcb_generic_event_t *ev )
-{
- RofiViewState *state = rofi_view_get_active ();
- if ( state != NULL ) {
- rofi_view_itterrate ( state, ev, &xkb );
- if ( rofi_view_get_completed ( state ) ) {
- // This menu is done.
- rofi_view_finalize ( state );
- // cleanup
- if ( rofi_view_get_active () == NULL ) {
- g_main_loop_quit ( main_loop );
- }
- }
- }
-}
-static gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UNUSED gpointer data )
-{
- if ( ev == NULL ) {
- int status = xcb_connection_has_error ( xcb->connection );
- if ( status > 0 ) {
- g_warning ( "The XCB connection to X server had a fatal error: %d", status );
- g_main_loop_quit ( main_loop );
- return G_SOURCE_REMOVE;
- }
- else {
- g_warning ( "main_loop_x11_event_handler: ev == NULL, status == %d", status );
- return G_SOURCE_CONTINUE;
- }
- }
- uint8_t type = ev->response_type & ~0x80;
- if ( type == xkb.first_event ) {
- switch ( ev->pad0 )
- {
- case XCB_XKB_MAP_NOTIFY:
- {
- struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device ( nk_bindings_seat_get_context ( xkb.bindings_seat ), xcb->connection, xkb.device_id, 0 );
- struct xkb_state *state = xkb_x11_state_new_from_device ( keymap, xcb->connection, xkb.device_id );
- nk_bindings_seat_update_keymap ( xkb.bindings_seat, keymap, state );
- xkb_keymap_unref ( keymap );
- xkb_state_unref ( state );
- break;
- }
- case XCB_XKB_STATE_NOTIFY:
- {
- xcb_xkb_state_notify_event_t *ksne = (xcb_xkb_state_notify_event_t *) ev;
- nk_bindings_seat_update_mask ( xkb.bindings_seat,
- ksne->baseMods,
- ksne->latchedMods,
- ksne->lockedMods,
- ksne->baseGroup,
- ksne->latchedGroup,
- ksne->lockedGroup );
- xcb_generic_event_t dev;
- dev.response_type = 0;
- main_loop_x11_event_handler_view ( &dev );
- break;
- }
- }
- return G_SOURCE_CONTINUE;
- }
- if ( xcb->sndisplay != NULL ) {
- sn_xcb_display_process_event ( xcb->sndisplay, ev );
- }
- main_loop_x11_event_handler_view ( ev );
- return G_SOURCE_CONTINUE;
-}
-
static gboolean main_loop_signal_handler_int ( G_GNUC_UNUSED gpointer data )
{
// Break out of loop.
@@ -706,23 +620,6 @@ static gboolean main_loop_signal_handler_int ( G_GNUC_UNUSED gpointer data )
return G_SOURCE_CONTINUE;
}
-/** X server error depth. to handle nested errors. */
-static int error_trap_depth = 0;
-static void error_trap_push ( G_GNUC_UNUSED SnDisplay *display, G_GNUC_UNUSED xcb_connection_t *xdisplay )
-{
- ++error_trap_depth;
-}
-
-static void error_trap_pop ( G_GNUC_UNUSED SnDisplay *display, xcb_connection_t *xdisplay )
-{
- if ( error_trap_depth == 0 ) {
- g_warning ( "Error trap underflow!" );
- exit ( EXIT_FAILURE );
- }
-
- xcb_flush ( xdisplay );
- --error_trap_depth;
-}
/** Retry count of grabbing keyboard. */
unsigned int lazy_grab_retry_count_kb = 0;
/** Retry count of grabbing pointer. */
@@ -797,10 +694,6 @@ static gboolean startup ( G_GNUC_UNUSED gpointer data )
__create_window ( window_flags );
TICK_N ( "Create Window" );
// Parse the keybindings.
- if ( !parse_keys_abe ( xkb.bindings ) ) {
- // Error dialog
- return G_SOURCE_REMOVE;
- }
TICK_N ( "Parse ABE" );
// Sanity check
config_sanity_check ( );
@@ -960,138 +853,21 @@ int main ( int argc, char *argv[] )
return EXIT_FAILURE;
}
- // Get DISPLAY, first env, then argument.
- // We never modify display_str content.
- char *display_str = ( char *) g_getenv ( "DISPLAY" );
- find_arg_str ( "-display", &display_str );
-
- xcb->connection = xcb_connect ( display_str, &xcb->screen_nbr );
- if ( xcb_connection_has_error ( xcb->connection ) ) {
- g_warning ( "Failed to open display: %s", display_str );
- cleanup ();
- return EXIT_FAILURE;
- }
-
- TICK_N ( "Open Display" );
rofi_collect_modi ();
rofi_collect_modi_setup ();
TICK_N ( "Collect MODI" );
- xcb->screen = xcb_aux_get_screen ( xcb->connection, xcb->screen_nbr );
-
- x11_build_monitor_layout ();
-
- xcb_intern_atom_cookie_t *ac = xcb_ewmh_init_atoms ( xcb->connection, &xcb->ewmh );
- xcb_generic_error_t *errors = NULL;
- xcb_ewmh_init_atoms_replies ( &xcb->ewmh, ac, &errors );
- if ( errors ) {
- g_warning ( "Failed to create EWMH atoms" );
- free ( errors );
- }
- // Discover the current active window manager.
- x11_helper_discover_window_manager ();
- TICK_N ( "Setup XCB" );
-
- if ( xkb_x11_setup_xkb_extension ( xcb->connection, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION,
- XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &xkb.first_event, NULL ) < 0 ) {
- g_warning ( "cannot setup XKB extension!" );
- cleanup ();
- return EXIT_FAILURE;
- }
-
- xkb.xcb_connection = xcb->connection;
-
- xkb.device_id = xkb_x11_get_core_keyboard_device_id ( xcb->connection );
-
- enum
- {
- required_events =
- ( XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
- XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
- XCB_XKB_EVENT_TYPE_STATE_NOTIFY ),
-
- required_nkn_details =
- ( XCB_XKB_NKN_DETAIL_KEYCODES ),
-
- required_map_parts =
- ( XCB_XKB_MAP_PART_KEY_TYPES |
- XCB_XKB_MAP_PART_KEY_SYMS |
- XCB_XKB_MAP_PART_MODIFIER_MAP |
- XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
- XCB_XKB_MAP_PART_KEY_ACTIONS |
- XCB_XKB_MAP_PART_VIRTUAL_MODS |
- XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP ),
-
- required_state_details =
- ( XCB_XKB_STATE_PART_MODIFIER_BASE |
- XCB_XKB_STATE_PART_MODIFIER_LATCH |
- XCB_XKB_STATE_PART_MODIFIER_LOCK |
- XCB_XKB_STATE_PART_GROUP_BASE |
- XCB_XKB_STATE_PART_GROUP_LATCH |
- XCB_XKB_STATE_PART_GROUP_LOCK ),
- };
-
- static const xcb_xkb_select_events_details_t details = {
- .affectNewKeyboard = required_nkn_details,
- .newKeyboardDetails = required_nkn_details,
- .affectState = required_state_details,
- .stateDetails = required_state_details,
- };
- xcb_xkb_select_events ( xcb->connection, xkb.device_id, required_events, /* affectWhich */
- 0, /* clear */
- required_events, /* selectAll */
- required_map_parts, /* affectMap */
- required_map_parts, /* map */
- &details );
-
- xkb.bindings = nk_bindings_new ();
- xkb.bindings_seat = nk_bindings_seat_new ( xkb.bindings, XKB_CONTEXT_NO_FLAGS );
- struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device ( nk_bindings_seat_get_context ( xkb.bindings_seat ), xcb->connection, xkb.device_id, XKB_KEYMAP_COMPILE_NO_FLAGS );
- if ( keymap == NULL ) {
- g_warning ( "Failed to get Keymap for current keyboard device." );
- cleanup ();
- return EXIT_FAILURE;
- }
- struct xkb_state *state = xkb_x11_state_new_from_device ( keymap, xcb->connection, xkb.device_id );
- if ( state == NULL ) {
- g_warning ( "Failed to get state object for current keyboard device." );
- cleanup ();
- return EXIT_FAILURE;
- }
-
- nk_bindings_seat_update_keymap ( xkb.bindings_seat, keymap, state );
-
- if ( xcb_connection_has_error ( xcb->connection ) ) {
- g_warning ( "Connection has error" );
- cleanup ();
- return EXIT_FAILURE;
- }
- x11_setup ();
- TICK_N ( "Setup xkb" );
- if ( xcb_connection_has_error ( xcb->connection ) ) {
+ if ( !x11_setup () ) {
g_warning ( "Connection has error" );
cleanup ();
return EXIT_FAILURE;
}
+ TICK_N ( "Setup X11" );
+
main_loop = g_main_loop_new ( NULL, FALSE );
TICK_N ( "Setup mainloop" );
- // startup not.
- xcb->sndisplay = sn_xcb_display_new ( xcb->connection, error_trap_push, error_trap_pop );
- if ( xcb_connection_has_error ( xcb->connection ) ) {
- g_warning ( "Connection has error" );
- cleanup ();
- return EXIT_FAILURE;
- }
- if ( xcb->sndisplay != NULL ) {
- xcb->sncontext = sn_launchee_context_new_from_environment ( xcb->sndisplay, xcb->screen_nbr );
- }
- if ( xcb_connection_has_error ( xcb->connection ) ) {
- g_warning ( "Connection has error" );
- cleanup ();
- return EXIT_FAILURE;
- }
TICK_N ( "Startup Notification" );
// Setup keybinding
setup_abe ();
@@ -1180,7 +956,7 @@ int main ( int argc, char *argv[] )
if ( find_arg_uint ( "-record-screenshots", &interval ) ) {
g_timeout_add ( 1000 / (double) interval, record, NULL );
}
- main_loop_source = g_water_xcb_source_new_for_connection ( NULL, xcb->connection, main_loop_x11_event_handler, NULL, NULL );
+ main_loop_source = g_water_xcb_source_new_for_connection ( NULL, xcb->connection, main_loop_x11_event_handler, main_loop, NULL );
TICK_N ( "X11 Setup " );
diff --git a/source/view.c b/source/view.c
index f3569532..47adad17 100644
--- a/source/view.c
+++ b/source/view.c
@@ -55,7 +55,6 @@
#include "rofi.h"
#include "mode.h"
#include "xcb-internal.h"
-#include "xkb-internal.h"
#include "helper.h"
#include "helper-theme.h"
#include "xrmoptions.h"
@@ -1383,7 +1382,7 @@ gboolean rofi_view_trigger_action ( RofiViewState *state, BindingsScope scope, g
return FALSE;
}
-void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, xkb_stuff *xkb )
+void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, NkBindingsSeat *seat )
{
switch ( event->response_type & ~0x80 )
{
@@ -1437,13 +1436,13 @@ void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, xkb
xcb_button_press_event_t *bpe = (xcb_button_press_event_t *) event;
state->mouse.x = bpe->event_x;
state->mouse.y = bpe->event_y;
- nk_bindings_seat_handle_button ( xkb->bindings_seat, bpe->detail, NK_BINDINGS_BUTTON_STATE_PRESS, bpe->time );
+ nk_bindings_seat_handle_button ( seat, bpe->detail, NK_BINDINGS_BUTTON_STATE_PRESS, bpe->time );
break;
}
case XCB_BUTTON_RELEASE:
{
xcb_button_release_event_t *bre = (xcb_button_release_event_t *) event;
- nk_bindings_seat_handle_button ( xkb->bindings_seat, bre->detail, NK_BINDINGS_BUTTON_STATE_RELEASE, bre->time );
+ nk_bindings_seat_handle_button ( seat, bre->detail, NK_BINDINGS_BUTTON_STATE_RELEASE, bre->time );
if ( config.click_to_exit == TRUE ) {
if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == 0 ) {
if ( ( state->mouse_seen == FALSE ) && ( bre->event != CacheState.main_window ) ) {
@@ -1466,7 +1465,7 @@ void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, xkb
for ( gint8 bi = 0; bi < 7; ++bi ) {
if ( kne->keys[by] & ( 1 << bi ) ) {
// X11 keycodes starts at 8
- nk_bindings_seat_handle_key ( xkb->bindings_seat, ( 8 * by + bi ) + 8, NK_BINDINGS_KEY_STATE_PRESSED );
+ nk_bindings_seat_handle_key ( seat, ( 8 * by + bi ) + 8, NK_BINDINGS_KEY_STATE_PRESSED );
}
}
}
@@ -1477,7 +1476,7 @@ void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, xkb
xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *) event;
gchar *text;
- text = nk_bindings_seat_handle_key ( xkb->bindings_seat, xkpe->detail, NK_BINDINGS_KEY_STATE_PRESS );
+ text = nk_bindings_seat_handle_key ( seat, xkpe->detail, NK_BINDINGS_KEY_STATE_PRESS );
if ( ( text != NULL ) && ( textbox_append_char ( state->text, text, strlen ( text ) ) ) ) {
state->refilter = TRUE;
}
@@ -1486,7 +1485,7 @@ void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, xkb
case XCB_KEY_RELEASE:
{
xcb_key_release_event_t *xkre = (xcb_key_release_event_t *) event;
- nk_bindings_seat_handle_key ( xkb->bindings_seat, xkre->detail, NK_BINDINGS_KEY_STATE_RELEASE );
+ nk_bindings_seat_handle_key ( seat, xkre->detail, NK_BINDINGS_KEY_STATE_RELEASE );
break;
}
default:
diff --git a/source/xcb.c b/source/xcb.c
index e9a300a2..e9414058 100644
--- a/source/xcb.c
+++ b/source/xcb.c
@@ -46,15 +46,18 @@
#include <xcb/xinerama.h>
#include <xcb/xcb_ewmh.h>
#include <xcb/xproto.h>
+#include <xcb/xkb.h>
+#include <xkbcommon/xkbcommon.h>
+#include <xkbcommon/xkbcommon-x11.h>
#include "xcb-internal.h"
#include "xcb.h"
#include "settings.h"
#include "helper.h"
+#include "timings.h"
#include <rofi.h>
/** Checks if the if x and y is inside rectangle. */
#define INTERSECT( x, y, x1, y1, w1, h1 ) ( ( ( ( x ) >= ( x1 ) ) && ( ( x ) < ( x1 + w1 ) ) ) && ( ( ( y ) >= ( y1 ) ) && ( ( y ) < ( y1 + h1 ) ) ) )
-#include "xkb-internal.h"
WindowManager current_window_manager = WM_EWHM;
/**
@@ -614,6 +617,24 @@ void release_pointer ( void )
xcb_ungrab_pointer ( xcb->connection, XCB_CURRENT_TIME );
}
+/** X server error depth. to handle nested errors. */
+static int error_trap_depth = 0;
+static void error_trap_push ( G_GNUC_UNUSED SnDisplay *display, G_GNUC_UNUSED xcb_connection_t *xdisplay )
+{
+ ++error_trap_depth;
+}
+
+static void error_trap_pop ( G_GNUC_UNUSED SnDisplay *display, xcb_connection_t *xdisplay )
+{
+ if ( error_trap_depth == 0 ) {
+ g_warning ( "Error trap underflow!" );
+ exit ( EXIT_FAILURE );
+ }
+
+ xcb_flush ( xdisplay );
+ --error_trap_depth;
+}
+
/**
* Fill in the list of frequently used X11 Atoms.
*/
@@ -630,10 +651,129 @@ static void x11_create_frequently_used_atoms ( void )
}
}
-void x11_setup ( void )
+gboolean x11_setup ( void )
{
+ // Get DISPLAY, first env, then argument.
+ // We never modify display_str content.
+ char *display_str = ( char *) g_getenv ( "DISPLAY" );
+ find_arg_str ( "-display", &display_str );
+
+ xcb->connection = xcb_connect ( display_str, &xcb->screen_nbr );
+ if ( xcb_connection_has_error ( xcb->connection ) ) {
+ g_warning ( "Failed to open display: %s", display_str );
+ return FALSE;
+ }
+
+ TICK_N ( "Open Display" );
+
+ xcb->screen = xcb_aux_get_screen ( xcb->connection, xcb->screen_nbr );
+
+ x11_build_monitor_layout ();
+
+ xcb_intern_atom_cookie_t *ac = xcb_ewmh_init_atoms ( xcb->connection, &xcb->ewmh );
+ xcb_generic_error_t *errors = NULL;
+ xcb_ewmh_init_atoms_replies ( &xcb->ewmh, ac, &errors );
+ if ( errors ) {
+ g_warning ( "Failed to create EWMH atoms" );
+ free ( errors );
+ }
+ // Discover the current active window manager.
+ x11_helper_discover_window_manager ();
+ TICK_N ( "Setup XCB" );
+
+ if ( xkb_x11_setup_xkb_extension ( xcb->connection, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION,
+ XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &xcb->xkb.first_event, NULL ) < 0 ) {
+ g_warning ( "cannot setup XKB extension!" );
+ return FALSE;
+ }
+
+ xcb->xkb.device_id = xkb_x11_get_core_keyboard_device_id ( xcb->connection );
+
+ enum
+ {
+ required_events =
+ ( XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
+ XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
+ XCB_XKB_EVENT_TYPE_STATE_NOTIFY ),
+
+ required_nkn_details =
+ ( XCB_XKB_NKN_DETAIL_KEYCODES ),
+
+ required_map_parts =
+ ( XCB_XKB_MAP_PART_KEY_TYPES |
+ XCB_XKB_MAP_PART_KEY_SYMS |
+ XCB_XKB_MAP_PART_MODIFIER_MAP |
+ XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
+ XCB_XKB_MAP_PART_KEY_ACTIONS |
+ XCB_XKB_MAP_PART_VIRTUAL_MODS |
+ XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP ),
+
+ required_state_details =
+ ( XCB_XKB_STATE_PART_MODIFIER_BASE |
+ XCB_XKB_STATE_PART_MODIFIER_LATCH |
+ XCB_XKB_STATE_PART_MODIFIER_LOCK |
+ XCB_XKB_STATE_PART_GROUP_BASE |
+ XCB_XKB_STATE_PART_GROUP_LATCH |
+ XCB_XKB_STATE_PART_GROUP_LOCK ),
+ };
+
+ static const xcb_xkb_select_events_details_t details = {
+ .affectNewKeyboard = required_nkn_details,
+ .newKeyboardDetails = required_nkn_details,
+ .affectState = required_state_details,
+ .stateDetails = required_state_details,
+ };
+ xcb_xkb_select_events ( xcb->connection, xcb->xkb.device_id, required_events, /* affectWhich */
+ 0, /* clear */
+ required_events, /* selectAll */
+ required_map_parts, /* affectMap */
+ required_map_parts, /* map */
+ &details );
+
+ xcb->bindings = nk_bindings_new ();
+ xcb->bindings_seat = nk_bindings_seat_new ( xcb->bindings, XKB_CONTEXT_NO_FLAGS );
+ struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device ( nk_bindings_seat_get_context ( xcb->bindings_seat ), xcb->connection, xcb->xkb.device_id, XKB_KEYMAP_COMPILE_NO_FLAGS );
+ if ( keymap == NULL ) {
+ g_warning ( "Failed to get Keymap for current keyboard device." );
+ return FALSE;
+ }
+ struct xkb_state *state = xkb_x11_state_new_from_device ( keymap, xcb->connection, xcb->xkb.device_id );
+ if ( state == NULL ) {
+ g_warning ( "Failed to get state object for current keyboard device." );
+ return FALSE;
+ }
+
+ nk_bindings_seat_update_keymap ( xcb->bindings_seat, keymap, state );
+
+ if ( !parse_keys_abe ( xcb->bindings ) ) {
+ // Error dialog
+ return FALSE;
+ }
+
// determine numlock mask so we can bind on keys with and without it
x11_create_frequently_used_atoms ( );
+
+ if ( xcb_connection_has_error ( xcb->connection ) ) {
+ g_warning ( "Connection has error" );
+ return FALSE;
+ }
+
+ // startup not.
+ xcb->sndisplay = sn_xcb_display_new ( xcb->connection, error_trap_push, error_trap_pop );
+ if ( xcb_connection_has_error ( xcb->connection ) ) {
+ g_warning ( "Connection has error" );
+ return FALSE;
+ }
+
+ if ( xcb->sndisplay != NULL ) {
+ xcb->sncontext = sn_launchee_context_new_from_environment ( xcb->sndisplay, xcb->screen_nbr );
+ }
+ if ( xcb_connection_has_error ( xcb->connection ) ) {
+ g_warning ( "Connection has error" );
+ return FALSE;
+ }
+
+ return TRUE;
}
void x11_create_visual_and_colormap ( void )
@@ -676,6 +816,77 @@ void x11_create_visual_and_colormap ( void )
}
}
+/**
+ * Process X11 events in the main-loop (gui-thread) of the application.
+ */
+static void main_loop_x11_event_handler_view ( xcb_generic_event_t *ev, GMainLoop *main_loop )
+{
+ RofiViewState *state = rofi_view_get_active ();
+ if ( state != NULL ) {
+ rofi_view_itterrate ( state, ev, xcb->bindings_seat );
+ if ( rofi_view_get_completed ( state ) ) {
+ // This menu is done.
+ rofi_view_finalize ( state );
+ // cleanup
+ if ( rofi_view_get_active () == NULL ) {
+ g_main_loop_quit ( main_loop );
+ }
+ }
+ }
+}
+
+gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, gpointer user_data )
+{
+ if ( ev == NULL ) {
+ int status = xcb_connection_has_error ( xcb->connection );
+ if ( status > 0 ) {
+ g_warning ( "The XCB connection to X server had a fatal error: %d", status );
+ g_main_loop_quit ( user_data );
+ return G_SOURCE_REMOVE;
+ }
+ else {
+ g_warning ( "main_loop_x11_event_handler: ev == NULL, status == %d", status );
+ return G_SOURCE_CONTINUE;
+ }
+ }
+ uint8_t type = ev->response_type & ~0x80;
+ if ( type == xcb->xkb.first_event ) {
+ switch ( ev->pad0 )
+ {
+ case XCB_XKB_MAP_NOTIFY:
+ {
+ struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device ( nk_bindings_seat_get_context ( xcb->bindings_seat ), xcb->connection, xcb->xkb.device_id, 0 );
+ struct xkb_state *state = xkb_x11_state_new_from_device ( keymap, xcb->connection, xcb->xkb.device_id );
+ nk_bindings_seat_update_keymap ( xcb->bindings_seat, keymap, state );
+ xkb_keymap_unref ( keymap );
+ xkb_state_unref ( state );
+ break;
+ }
+ case XCB_XKB_STATE_NOTIFY:
+ {
+ xcb_xkb_state_notify_event_t *ksne = (xcb_xkb_state_notify_event_t *) ev;
+ nk_bindings_seat_update_mask ( xcb->bindings_seat,
+ ksne->baseMods,
+ ksne->latchedMods,
+ ksne->lockedMods,
+ ksne->baseGroup,
+ ksne->latchedGroup,
+ ksne->lockedGroup );
+ xcb_generic_event_t dev;
+ dev.response_type = 0;
+ main_loop_x11_event_handler_view ( &dev, user_data );
+ break;
+ }
+ }
+ return G_SOURCE_CONTINUE;
+ }
+ if ( xcb->sndisplay != NULL ) {
+ sn_xcb_display_process_event ( xcb->sndisplay, ev );
+ }
+ main_loop_x11_event_handler_view ( ev, user_data );
+ return G_SOURCE_CONTINUE;
+}
+
xcb_window_t xcb_stuff_get_root_window ( xcb_stuff *xcb )
{
return xcb->screen->root;
@@ -683,6 +894,9 @@ xcb_window_t xcb_stuff_get_root_window ( xcb_stuff *xcb )
void xcb_stuff_wipe ( xcb_stuff *xcb )
{
+ nk_bindings_seat_free ( xcb->bindings_seat );
+ nk_bindings_free ( xcb->bindings );
+
if ( xcb->connection != NULL ) {
g_debug ( "Cleaning up XCB and XKB" );
if ( xcb->sncontext != NULL ) {