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:
parent
46dee2671d
commit
9b58a9bc31
10 changed files with 241 additions and 326 deletions
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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')
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
232
source/rofi.c
232
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 " );
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
218
source/xcb.c
218
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 ) {
|
||||
|
|
Loading…
Reference in a new issue