summaryrefslogtreecommitdiffstats
path: root/source/rofi.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/rofi.c')
-rw-r--r--source/rofi.c342
1 files changed, 22 insertions, 320 deletions
diff --git a/source/rofi.c b/source/rofi.c
index 441edebf..9c52437c 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,14 +46,12 @@
#include <libgwater-xcb.h>
#include "xcb-internal.h"
-#include "xkb-internal.h"
#include "settings.h"
#include "mode.h"
#include "rofi.h"
#include "helper.h"
#include "widgets/textbox.h"
-#include "x11-helper.h"
#include "xrmoptions.h"
#include "dialogs/dialogs.h"
@@ -87,11 +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,
-};
/** Path to the configuration file */
G_MODULE_EXPORT char *config_path = NULL;
@@ -109,8 +97,6 @@ unsigned int curr_switcher = 0;
/** Glib main loop. */
GMainLoop *main_loop = NULL;
-/** GWater xcb source, signalling events from the X server */
-GWaterXcbSource *main_loop_source = NULL;
/** Flag indicating we are in dmenu mode. */
static int dmenu_mode = FALSE;
@@ -152,21 +138,6 @@ static int switcher_get ( const char *name )
}
/**
- * Do needed steps to start showing the gui
- */
-static int setup ()
-{
- // Create pid file
- int pfd = create_pid_file ( pidfile );
- if ( pfd >= 0 ) {
- // Request truecolor visual.
- x11_create_visual_and_colormap ( );
- textbox_setup ();
- }
- return pfd;
-}
-
-/**
* Teardown the gui.
*/
static void teardown ( int pfd )
@@ -175,9 +146,7 @@ static void teardown ( int pfd )
// Cleanup font setup.
textbox_cleanup ( );
- // Release the window.
- release_keyboard ( );
- release_pointer ( );
+ x11_early_cleanup ();
// Cleanup view
rofi_view_cleanup ();
@@ -426,18 +395,11 @@ static void cleanup ()
}
rofi_view_workers_finalize ();
if ( main_loop != NULL ) {
- if ( main_loop_source ) {
- g_water_xcb_source_free ( main_loop_source );
- }
g_main_loop_unref ( main_loop );
main_loop = NULL;
}
- // XKB Cleanup
- //
- nk_bindings_free ( xkb.bindings );
-
// Cleanup
- xcb_stuff_wipe ( xcb );
+ xcb_stuff_wipe ();
// Cleaning up memory allocated by the Xresources file.
config_xresource_free ();
@@ -629,74 +591,9 @@ 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 )
+void rofi_quit_main_loop ( void )
{
- 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_get_context ( xkb.bindings ), xcb->connection, xkb.device_id, 0 );
- struct xkb_state *state = xkb_x11_state_new_from_device ( keymap, xcb->connection, xkb.device_id );
- nk_bindings_update_keymap ( xkb.bindings, 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_update_mask ( xkb.bindings,
- 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;
+ g_main_loop_quit ( main_loop );
}
static gboolean main_loop_signal_handler_int ( G_GNUC_UNUSED gpointer data )
@@ -706,55 +603,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. */
-unsigned int lazy_grab_retry_count_pt = 0;
-static gboolean lazy_grab_pointer ( G_GNUC_UNUSED gpointer data )
-{
- // After 5 sec.
- if ( lazy_grab_retry_count_pt > ( 5 * 1000 ) ) {
- g_warning ( "Failed to grab pointer after %u times. Giving up.", lazy_grab_retry_count_pt );
- return G_SOURCE_REMOVE;
- }
- if ( take_pointer ( xcb_stuff_get_root_window ( xcb ), 0 ) ) {
- return G_SOURCE_REMOVE;
- }
- lazy_grab_retry_count_pt++;
- return G_SOURCE_CONTINUE;
-}
-static gboolean lazy_grab_keyboard ( G_GNUC_UNUSED gpointer data )
-{
- // After 5 sec.
- if ( lazy_grab_retry_count_kb > ( 5 * 1000 ) ) {
- g_warning ( "Failed to grab keyboard after %u times. Giving up.", lazy_grab_retry_count_kb );
- g_main_loop_quit ( main_loop );
- return G_SOURCE_REMOVE;
- }
- if ( take_keyboard ( xcb_stuff_get_root_window ( xcb ), 0 ) ) {
- return G_SOURCE_REMOVE;
- }
- lazy_grab_retry_count_kb++;
- return G_SOURCE_CONTINUE;
-}
-
static gboolean startup ( G_GNUC_UNUSED gpointer data )
{
TICK_N ( "Startup" );
@@ -766,41 +614,10 @@ static gboolean startup ( G_GNUC_UNUSED gpointer data )
if ( find_arg ( "-normal-window" ) >= 0 ) {
window_flags |= MENU_NORMAL_WINDOW;
}
-
- /**
- * Create window (without showing)
- */
- // Try to grab the keyboard as early as possible.
- // We grab this using the rootwindow (as dmenu does it).
- // this seems to result in the smallest delay for most people.
- if ( ( window_flags & MENU_NORMAL_WINDOW ) == 0 ) {
- if ( find_arg ( "-no-lazy-grab" ) >= 0 ) {
- if ( !take_keyboard ( xcb_stuff_get_root_window ( xcb ), 500 ) ) {
- g_warning ( "Failed to grab keyboard, even after %d uS.", 500 * 1000 );
- g_main_loop_quit ( main_loop );
- return G_SOURCE_REMOVE;
- }
- if ( !take_pointer ( xcb_stuff_get_root_window ( xcb ), 100 ) ) {
- g_warning ( "Failed to grab mouse pointer, even after %d uS.", 100 * 1000 );
- }
- }
- else {
- if ( !take_keyboard ( xcb_stuff_get_root_window ( xcb ), 0 ) ) {
- g_timeout_add ( 1, lazy_grab_keyboard, NULL );
- }
- if ( !take_pointer ( xcb_stuff_get_root_window ( xcb ), 0 ) ) {
- g_timeout_add ( 1, lazy_grab_pointer, NULL );
- }
- }
- }
TICK_N ( "Grab keyboard" );
__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,143 +777,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;
- }
-
- struct xkb_context *xkb_context = xkb_context_new ( XKB_CONTEXT_NO_FLAGS );
- if ( xkb_context == NULL ) {
- g_warning ( "cannot create XKB context!" );
- 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 );
-
- struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device ( xkb_context, 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;
- }
-
- xkb.bindings = nk_bindings_new ( xkb_context, 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 ) ) {
- g_warning ( "Connection has error" );
- cleanup ();
- return EXIT_FAILURE;
- }
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 ) ) {
+ if ( !x11_setup ( main_loop ) ) {
g_warning ( "Connection has error" );
cleanup ();
return EXIT_FAILURE;
}
- TICK_N ( "Startup Notification" );
+ TICK_N ( "Setup Display" );
+
// Setup keybinding
setup_abe ();
TICK_N ( "Setup abe" );
@@ -1184,23 +879,30 @@ 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 );
-
- TICK_N ( "X11 Setup " );
rofi_view_workers_initialize ();
+ // Create pid file
+ int pfd = create_pid_file ( pidfile );
+ if ( pfd < 0 ) {
+ cleanup ();
+ return EXIT_FAILURE;
+ }
+ textbox_setup ();
+
+ if ( !x11_late_setup () ) {
+ g_warning ( "Failed to properly finish display setup" );
+ cleanup ();
+ return EXIT_FAILURE;
+ }
+ TICK_N ( "Setup late Display" );
+
// Setup signal handling sources.
// SIGINT
g_unix_signal_add ( SIGINT, main_loop_signal_handler_int, NULL );
g_idle_add ( startup, NULL );
- // Pidfile + visuals
- int pfd = setup ();
- if ( pfd < 0 ) {
- return EXIT_FAILURE;
- }
// Start mainloop.
g_main_loop_run ( main_loop );
teardown ( pfd );