1
0
Fork 0
mirror of https://github.com/davatorium/rofi.git synced 2024-11-18 13:54:36 -05:00

xcb: Move more stuff to xcb.c

Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>
This commit is contained in:
Quentin Glidic 2017-06-01 00:39:11 +02:00
parent 46dee2671d
commit 9b58a9bc31
No known key found for this signature in database
GPG key ID: AC203F96E2C34BB7
10 changed files with 241 additions and 326 deletions

View file

@ -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
*

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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')

View file

@ -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"

View file

@ -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 " );

View file

@ -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:

View file

@ -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 ) {