2013-07-19 14:55:01 +00:00
|
|
|
/**
|
2014-03-01 16:27:52 +00:00
|
|
|
* rofi
|
2014-01-10 09:35:38 +00:00
|
|
|
*
|
2013-07-19 14:55:01 +00:00
|
|
|
* MIT/X11 License
|
|
|
|
* Copyright (c) 2012 Sean Pringle <sean.pringle@gmail.com>
|
2015-12-31 23:27:00 +00:00
|
|
|
* Modified 2013-2016 Qball Cow <qball@gmpclient.org>
|
2014-01-10 09:35:38 +00:00
|
|
|
*
|
2013-07-19 14:55:01 +00:00
|
|
|
* 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:
|
2014-01-10 09:35:38 +00:00
|
|
|
*
|
2013-07-19 14:55:01 +00:00
|
|
|
* The above copyright notice and this permission notice shall be
|
|
|
|
* included in all copies or substantial portions of the Software.
|
2014-01-10 09:35:38 +00:00
|
|
|
*
|
2013-07-19 14:55:01 +00:00
|
|
|
* 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.
|
|
|
|
*/
|
2015-11-14 12:47:45 +00:00
|
|
|
|
2014-08-22 07:26:46 +00:00
|
|
|
#include <config.h>
|
2012-06-29 17:10:13 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2014-06-05 15:48:25 +00:00
|
|
|
#include <stdint.h>
|
2012-06-29 17:10:13 +00:00
|
|
|
#include <signal.h>
|
2014-01-21 13:56:25 +00:00
|
|
|
#include <errno.h>
|
2014-03-16 12:47:44 +00:00
|
|
|
#include <time.h>
|
2015-11-22 12:57:51 +00:00
|
|
|
#include <locale.h>
|
2014-01-20 22:36:20 +00:00
|
|
|
#include <X11/X.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include <X11/Xproto.h>
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
#include <X11/XKBlib.h>
|
2015-01-30 20:55:31 +00:00
|
|
|
#include <sys/wait.h>
|
2015-02-01 09:03:16 +00:00
|
|
|
#include <sys/types.h>
|
2014-03-18 09:55:25 +00:00
|
|
|
|
2016-01-18 19:51:35 +00:00
|
|
|
#include <glib-unix.h>
|
|
|
|
|
2015-09-26 18:34:34 +00:00
|
|
|
#include <cairo.h>
|
|
|
|
#include <cairo-xlib.h>
|
|
|
|
|
2015-09-13 15:29:50 +00:00
|
|
|
#define SN_API_NOT_YET_FROZEN
|
|
|
|
#include <libsn/sn.h>
|
|
|
|
|
2016-01-07 15:01:56 +00:00
|
|
|
#include "settings.h"
|
2016-01-09 15:22:09 +00:00
|
|
|
#include "mode.h"
|
2015-02-14 18:42:04 +00:00
|
|
|
#include "rofi.h"
|
2015-01-30 20:55:31 +00:00
|
|
|
#include "helper.h"
|
2015-02-14 18:42:04 +00:00
|
|
|
#include "textbox.h"
|
2015-02-09 18:35:51 +00:00
|
|
|
#include "x11-helper.h"
|
2016-01-18 21:02:07 +00:00
|
|
|
#include "x11-event-source.h"
|
2015-02-09 18:35:51 +00:00
|
|
|
#include "xrmoptions.h"
|
2015-08-31 05:57:29 +00:00
|
|
|
#include "dialogs/dialogs.h"
|
2015-09-19 10:21:30 +00:00
|
|
|
|
2016-02-07 11:31:17 +00:00
|
|
|
#include "view.h"
|
|
|
|
#include "view-internal.h"
|
|
|
|
|
2016-02-06 13:27:36 +00:00
|
|
|
gboolean daemon_mode = FALSE;
|
2015-02-03 07:00:33 +00:00
|
|
|
// Pidfile.
|
2016-02-06 13:27:36 +00:00
|
|
|
char *pidfile = NULL;
|
|
|
|
const char *cache_dir = NULL;
|
|
|
|
SnDisplay *sndisplay = NULL;
|
|
|
|
SnLauncheeContext *sncontext = NULL;
|
|
|
|
Display *display = NULL;
|
|
|
|
char *display_str = NULL;
|
|
|
|
char *config_path = NULL;
|
|
|
|
unsigned int normal_window_mode = FALSE;
|
2015-11-25 08:26:38 +00:00
|
|
|
// Array of modi.
|
2016-02-06 13:27:36 +00:00
|
|
|
Mode **modi = NULL;
|
|
|
|
unsigned int num_modi = 0;
|
2015-01-17 17:27:41 +00:00
|
|
|
// Current selected switcher.
|
2016-02-06 13:27:36 +00:00
|
|
|
unsigned int curr_switcher = 0;
|
2015-09-26 18:34:34 +00:00
|
|
|
|
2016-01-22 17:18:26 +00:00
|
|
|
GThreadPool *tpool = NULL;
|
|
|
|
GMainLoop *main_loop = NULL;
|
|
|
|
GSource *main_loop_source = NULL;
|
|
|
|
gboolean quiet = FALSE;
|
2016-02-06 12:06:58 +00:00
|
|
|
RofiViewState *current_active_menu = NULL;
|
2016-01-20 19:57:26 +00:00
|
|
|
|
2016-02-06 12:06:58 +00:00
|
|
|
static void process_result ( RofiViewState *state );
|
2016-02-06 12:40:25 +00:00
|
|
|
gboolean main_loop_x11_event_handler ( G_GNUC_UNUSED gpointer data );
|
2015-12-14 20:02:36 +00:00
|
|
|
|
2014-12-02 07:11:53 +00:00
|
|
|
/**
|
|
|
|
* @param name Name of the switcher to lookup.
|
|
|
|
*
|
|
|
|
* Find the index of the switcher with name.
|
|
|
|
*
|
2015-11-25 08:26:38 +00:00
|
|
|
* @returns index of the switcher in modi, -1 if not found.
|
2014-12-02 07:11:53 +00:00
|
|
|
*/
|
|
|
|
static int switcher_get ( const char *name )
|
2014-07-21 19:39:24 +00:00
|
|
|
{
|
2015-11-25 08:26:38 +00:00
|
|
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
if ( strcmp ( mode_get_name ( modi[i] ), name ) == 0 ) {
|
2014-07-21 19:39:24 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-02-16 01:03:26 +00:00
|
|
|
/**
|
|
|
|
* @param key the Key to match
|
|
|
|
* @param modstate the modifier state to match
|
|
|
|
*
|
2015-11-25 08:26:38 +00:00
|
|
|
* Match key and modifier state against modi.
|
2015-02-16 08:07:05 +00:00
|
|
|
*
|
|
|
|
* @return the index of the switcher that matches the key combination
|
2015-02-16 01:03:26 +00:00
|
|
|
* specified by key and modstate. Returns -1 if none was found
|
|
|
|
*/
|
|
|
|
extern unsigned int NumlockMask;
|
2016-02-06 13:27:36 +00:00
|
|
|
int locate_switcher ( KeySym key, unsigned int modstate )
|
2015-02-17 09:31:59 +00:00
|
|
|
{
|
2015-02-16 01:03:26 +00:00
|
|
|
// ignore annoying modifiers
|
2015-02-17 09:31:59 +00:00
|
|
|
unsigned int modstate_filtered = modstate & ~( LockMask | NumlockMask );
|
2015-11-25 08:26:38 +00:00
|
|
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
if ( mode_check_keybinding ( modi[i], key, modstate_filtered ) ) {
|
2016-01-07 20:27:20 +00:00
|
|
|
return i;
|
2015-02-16 01:03:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2015-12-09 07:29:18 +00:00
|
|
|
|
2015-01-08 12:16:44 +00:00
|
|
|
/**
|
2015-07-30 06:57:09 +00:00
|
|
|
* Do needed steps to start showing the gui
|
2015-01-08 12:16:44 +00:00
|
|
|
*/
|
2015-07-30 06:57:09 +00:00
|
|
|
static int setup ()
|
2014-08-05 07:07:41 +00:00
|
|
|
{
|
2015-02-01 14:17:43 +00:00
|
|
|
// Create pid file
|
2015-07-30 06:57:09 +00:00
|
|
|
int pfd = create_pid_file ( pidfile );
|
|
|
|
if ( pfd >= 0 ) {
|
|
|
|
// Request truecolor visual.
|
|
|
|
create_visual_and_colormap ( display );
|
2015-09-28 19:41:58 +00:00
|
|
|
textbox_setup ( display );
|
2015-07-30 06:57:09 +00:00
|
|
|
}
|
|
|
|
return pfd;
|
|
|
|
}
|
2016-02-06 13:27:36 +00:00
|
|
|
|
2015-07-30 06:57:09 +00:00
|
|
|
/**
|
|
|
|
* Teardown the gui.
|
|
|
|
*/
|
|
|
|
static void teardown ( int pfd )
|
|
|
|
{
|
2014-08-05 07:07:41 +00:00
|
|
|
// Cleanup font setup.
|
2015-01-21 09:04:15 +00:00
|
|
|
textbox_cleanup ( );
|
|
|
|
|
2015-07-28 20:22:18 +00:00
|
|
|
// Release the window.
|
|
|
|
release_keyboard ( display );
|
2015-11-30 09:15:53 +00:00
|
|
|
|
2016-02-06 13:27:36 +00:00
|
|
|
// Cleanup view
|
|
|
|
rofi_view_cleanup ();
|
2015-07-28 20:22:18 +00:00
|
|
|
// Cleanup pid file.
|
2015-07-30 06:57:09 +00:00
|
|
|
remove_pid_file ( pfd );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Start dmenu mode.
|
|
|
|
*/
|
|
|
|
static int run_dmenu ()
|
|
|
|
{
|
2015-08-20 19:42:53 +00:00
|
|
|
int ret_state = EXIT_FAILURE;
|
|
|
|
int pfd = setup ();
|
2015-07-30 06:57:09 +00:00
|
|
|
if ( pfd < 0 ) {
|
|
|
|
return ret_state;
|
2015-07-28 20:22:18 +00:00
|
|
|
}
|
2015-07-30 06:57:09 +00:00
|
|
|
|
|
|
|
// Dmenu modi has a return state.
|
2015-08-20 19:42:53 +00:00
|
|
|
ret_state = dmenu_switcher_dialog ();
|
2015-07-30 06:57:09 +00:00
|
|
|
teardown ( pfd );
|
2014-08-05 07:07:41 +00:00
|
|
|
return ret_state;
|
|
|
|
}
|
|
|
|
|
2016-01-20 19:57:26 +00:00
|
|
|
static int pfd = -1;
|
2016-02-07 11:31:17 +00:00
|
|
|
|
|
|
|
static void __run_switcher_internal ( ModeMode mode, char *input )
|
|
|
|
{
|
|
|
|
char *prompt = g_strdup_printf ( "%s:", mode_get_name ( modi[mode] ) );
|
|
|
|
curr_switcher = mode;
|
|
|
|
RofiViewState * state = rofi_view_create ( modi[mode], input, prompt, NULL, MENU_NORMAL );
|
|
|
|
state->finalize = process_result;
|
|
|
|
rofi_view_set_active ( state );
|
|
|
|
g_free ( prompt );
|
|
|
|
}
|
2015-11-25 08:26:38 +00:00
|
|
|
static void run_switcher ( ModeMode mode )
|
2014-01-20 21:58:10 +00:00
|
|
|
{
|
2016-01-20 19:57:26 +00:00
|
|
|
pfd = setup ();
|
2015-07-30 06:57:09 +00:00
|
|
|
if ( pfd < 0 ) {
|
|
|
|
return;
|
|
|
|
}
|
2014-07-21 19:39:24 +00:00
|
|
|
// Otherwise check if requested mode is enabled.
|
2015-11-25 08:26:38 +00:00
|
|
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
if ( !mode_init ( modi[i] ) ) {
|
2016-01-08 08:16:59 +00:00
|
|
|
error_dialog ( ERROR_MSG ( "Failed to initialize all the modi." ), ERROR_MSG_MARKUP );
|
|
|
|
teardown ( pfd );
|
|
|
|
return;
|
|
|
|
}
|
2015-03-27 19:28:53 +00:00
|
|
|
}
|
2016-02-07 11:31:17 +00:00
|
|
|
char *input = g_strdup ( config.filter );
|
|
|
|
__run_switcher_internal ( mode, input );
|
|
|
|
g_free ( input );
|
2016-01-20 19:57:26 +00:00
|
|
|
}
|
2016-02-06 12:06:58 +00:00
|
|
|
static void process_result ( RofiViewState *state )
|
2016-01-20 19:57:26 +00:00
|
|
|
{
|
2016-02-06 12:06:58 +00:00
|
|
|
unsigned int selected_line = rofi_view_get_selected_line ( state );;
|
|
|
|
MenuReturn mretv = rofi_view_get_return_value ( state );
|
|
|
|
char *input = g_strdup ( rofi_view_get_user_input ( state ) );
|
|
|
|
rofi_view_set_active ( NULL );
|
|
|
|
rofi_view_free ( state );
|
2016-02-06 12:40:25 +00:00
|
|
|
ModeMode retv = mode_result ( modi[curr_switcher], mretv, &input, selected_line );
|
2015-03-27 19:28:53 +00:00
|
|
|
|
2016-01-20 19:57:26 +00:00
|
|
|
ModeMode mode = curr_switcher;
|
|
|
|
// Find next enabled
|
|
|
|
if ( retv == NEXT_DIALOG ) {
|
|
|
|
mode = ( mode + 1 ) % num_modi;
|
|
|
|
}
|
|
|
|
else if ( retv == PREVIOUS_DIALOG ) {
|
|
|
|
if ( mode == 0 ) {
|
|
|
|
mode = num_modi - 1;
|
2015-03-27 19:28:53 +00:00
|
|
|
}
|
|
|
|
else {
|
2016-01-20 19:57:26 +00:00
|
|
|
mode = ( mode - 1 ) % num_modi;
|
2015-03-27 19:28:53 +00:00
|
|
|
}
|
2016-01-20 19:57:26 +00:00
|
|
|
}
|
|
|
|
else if ( retv == RELOAD_DIALOG ) {
|
|
|
|
// do nothing.
|
|
|
|
}
|
|
|
|
else if ( retv < MODE_EXIT ) {
|
|
|
|
mode = ( retv ) % num_modi;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mode = retv;
|
|
|
|
}
|
|
|
|
if ( mode != MODE_EXIT ) {
|
2016-02-07 11:31:17 +00:00
|
|
|
/**
|
|
|
|
* Load in the new mode.
|
|
|
|
*/
|
|
|
|
__run_switcher_internal ( mode, input );
|
2016-01-20 19:57:26 +00:00
|
|
|
g_free ( input );
|
2016-02-06 12:40:25 +00:00
|
|
|
main_loop_x11_event_handler ( NULL );
|
2016-01-20 19:57:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Cleanup
|
2015-03-27 19:28:53 +00:00
|
|
|
g_free ( input );
|
2015-11-25 08:26:38 +00:00
|
|
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
mode_destroy ( modi[i] );
|
2014-07-21 19:39:24 +00:00
|
|
|
}
|
2015-07-30 06:57:09 +00:00
|
|
|
// cleanup
|
|
|
|
teardown ( pfd );
|
2016-01-20 19:57:26 +00:00
|
|
|
if ( !daemon_mode ) {
|
|
|
|
g_main_loop_quit ( main_loop );
|
|
|
|
}
|
2015-07-30 06:57:09 +00:00
|
|
|
}
|
2014-01-16 17:47:19 +00:00
|
|
|
|
2015-07-30 06:57:09 +00:00
|
|
|
int show_error_message ( const char *msg, int markup )
|
|
|
|
{
|
|
|
|
int pfd = setup ();
|
|
|
|
if ( pfd < 0 ) {
|
|
|
|
return EXIT_FAILURE;
|
2014-01-20 21:58:10 +00:00
|
|
|
}
|
2015-07-30 06:57:09 +00:00
|
|
|
error_dialog ( msg, markup );
|
|
|
|
teardown ( pfd );
|
2016-01-26 07:36:44 +00:00
|
|
|
// TODO this looks incorrect.
|
2016-01-22 17:18:26 +00:00
|
|
|
g_main_loop_quit ( main_loop );
|
2015-07-30 06:57:09 +00:00
|
|
|
return EXIT_SUCCESS;
|
2012-06-29 17:10:13 +00:00
|
|
|
}
|
|
|
|
|
2015-01-08 12:16:44 +00:00
|
|
|
/**
|
|
|
|
* Function that listens for global key-presses.
|
|
|
|
* This is only used when in daemon mode.
|
|
|
|
*/
|
2014-05-25 09:04:45 +00:00
|
|
|
static void handle_keypress ( XEvent *ev )
|
2012-06-29 17:10:13 +00:00
|
|
|
{
|
2015-02-16 01:03:26 +00:00
|
|
|
int index;
|
2015-02-17 09:31:59 +00:00
|
|
|
KeySym key = XkbKeycodeToKeysym ( display, ev->xkey.keycode, 0, 0 );
|
|
|
|
index = locate_switcher ( key, ev->xkey.state );
|
|
|
|
if ( index >= 0 ) {
|
2015-07-28 20:22:18 +00:00
|
|
|
run_switcher ( index );
|
2014-01-21 09:13:42 +00:00
|
|
|
}
|
2015-02-16 01:03:26 +00:00
|
|
|
else {
|
2015-09-19 10:21:30 +00:00
|
|
|
fprintf ( stderr,
|
|
|
|
"Warning: Unhandled keypress in global keyhandler, keycode = %u mask = %u\n",
|
|
|
|
ev->xkey.keycode,
|
|
|
|
ev->xkey.state );
|
2015-02-16 01:03:26 +00:00
|
|
|
}
|
2012-06-29 17:10:13 +00:00
|
|
|
}
|
|
|
|
|
2014-01-19 12:57:54 +00:00
|
|
|
/**
|
2015-10-21 07:42:55 +00:00
|
|
|
* Help function.
|
2014-01-19 12:57:54 +00:00
|
|
|
*/
|
2015-10-21 07:42:55 +00:00
|
|
|
static void print_main_application_options ( void )
|
|
|
|
{
|
|
|
|
int is_term = isatty ( fileno ( stdout ) );
|
2015-11-15 12:12:43 +00:00
|
|
|
print_help_msg ( "-no-config", "", "Do not load configuration, use default values.", NULL, is_term );
|
|
|
|
print_help_msg ( "-quiet", "", "Suppress information messages.", NULL, is_term );
|
|
|
|
print_help_msg ( "-v,-version", "", "Print the version number and exit.", NULL, is_term );
|
|
|
|
print_help_msg ( "-dmenu", "", "Start in dmenu mode.", NULL, is_term );
|
|
|
|
print_help_msg ( "-display", "[string]", "X server to contact.", "${DISPLAY}", is_term );
|
|
|
|
print_help_msg ( "-h,-help", "", "This help message.", NULL, is_term );
|
|
|
|
print_help_msg ( "-dump-xresources", "", "Dump the current configuration in Xresources format and exit.", NULL, is_term );
|
2015-12-10 17:20:04 +00:00
|
|
|
print_help_msg ( "-dump-xresources-theme", "", "Dump the current color scheme in Xresources format and exit.", NULL, is_term );
|
2015-11-15 12:12:43 +00:00
|
|
|
print_help_msg ( "-e", "[string]", "Show a dialog displaying the passed message and exit.", NULL, is_term );
|
|
|
|
print_help_msg ( "-markup", "", "Enable pango markup where possible.", NULL, is_term );
|
|
|
|
print_help_msg ( "-normal-window", "", "In dmenu mode, behave as a normal window. (experimental)", NULL, is_term );
|
2015-11-14 18:59:56 +00:00
|
|
|
print_help_msg ( "-show", "[mode]", "Show the mode 'mode' and exit. The mode has to be enabled.", NULL, is_term );
|
2015-10-21 07:42:55 +00:00
|
|
|
}
|
2015-10-15 20:33:44 +00:00
|
|
|
static void help ( G_GNUC_UNUSED int argc, char **argv )
|
2014-01-19 12:57:54 +00:00
|
|
|
{
|
2015-10-15 20:33:44 +00:00
|
|
|
printf ( "%s usage:\n", argv[0] );
|
|
|
|
printf ( "\t%s [-options ...]\n\n", argv[0] );
|
2015-10-21 16:58:01 +00:00
|
|
|
printf ( "Command line only options:\n" );
|
2015-10-21 07:42:55 +00:00
|
|
|
print_main_application_options ();
|
2015-10-21 16:58:01 +00:00
|
|
|
printf ( "DMENU command line options:\n" );
|
|
|
|
print_dmenu_options ();
|
|
|
|
printf ( "Global options:\n" );
|
2015-10-15 20:33:44 +00:00
|
|
|
print_options ();
|
|
|
|
printf ( "\n" );
|
|
|
|
printf ( "For more information see: man rofi\n" );
|
2015-10-16 06:42:01 +00:00
|
|
|
printf ( "Version: "VERSION "\n" );
|
|
|
|
printf ( "Bugreports: "PACKAGE_BUGREPORT "\n" );
|
2014-01-19 12:57:54 +00:00
|
|
|
}
|
|
|
|
|
2016-01-22 17:18:26 +00:00
|
|
|
static void release_global_keybindings ()
|
|
|
|
{
|
|
|
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
mode_ungrab_key ( modi[i], display );
|
2016-01-22 17:18:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
static int grab_global_keybindings ()
|
|
|
|
{
|
|
|
|
int key_bound = FALSE;
|
|
|
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
if ( mode_grab_key ( modi[i], display ) ) {
|
2016-01-22 17:18:26 +00:00
|
|
|
key_bound = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return key_bound;
|
|
|
|
}
|
|
|
|
|
2014-09-23 07:24:24 +00:00
|
|
|
/**
|
|
|
|
* Function bound by 'atexit'.
|
|
|
|
* Cleanup globally allocated memory.
|
|
|
|
*/
|
2014-05-19 19:58:13 +00:00
|
|
|
static void cleanup ()
|
2014-05-19 19:02:05 +00:00
|
|
|
{
|
2015-11-14 12:47:45 +00:00
|
|
|
if ( tpool ) {
|
|
|
|
g_thread_pool_free ( tpool, TRUE, FALSE );
|
|
|
|
tpool = NULL;
|
|
|
|
}
|
2016-01-22 17:18:26 +00:00
|
|
|
if ( main_loop != NULL ) {
|
2016-02-06 12:06:58 +00:00
|
|
|
if ( main_loop_source ) {
|
2016-01-27 22:49:56 +00:00
|
|
|
g_source_destroy ( main_loop_source );
|
|
|
|
}
|
2016-01-22 17:18:26 +00:00
|
|
|
g_main_loop_unref ( main_loop );
|
|
|
|
main_loop = NULL;
|
|
|
|
}
|
|
|
|
if ( daemon_mode ) {
|
|
|
|
release_global_keybindings ();
|
|
|
|
if ( !quiet ) {
|
|
|
|
fprintf ( stdout, "Quit from daemon mode.\n" );
|
|
|
|
}
|
|
|
|
}
|
2014-05-19 19:02:05 +00:00
|
|
|
// Cleanup
|
2014-06-04 19:29:23 +00:00
|
|
|
if ( display != NULL ) {
|
2015-09-13 15:29:50 +00:00
|
|
|
if ( sncontext != NULL ) {
|
|
|
|
sn_launchee_context_unref ( sncontext );
|
|
|
|
sncontext = NULL;
|
|
|
|
}
|
|
|
|
if ( sndisplay != NULL ) {
|
|
|
|
sn_display_unref ( sndisplay );
|
|
|
|
sndisplay = NULL;
|
|
|
|
}
|
2015-07-29 07:37:40 +00:00
|
|
|
XCloseDisplay ( display );
|
|
|
|
display = NULL;
|
2014-05-19 19:02:05 +00:00
|
|
|
}
|
2015-07-28 20:22:18 +00:00
|
|
|
|
2014-05-19 19:58:13 +00:00
|
|
|
// Cleaning up memory allocated by the Xresources file.
|
2015-02-03 07:21:59 +00:00
|
|
|
config_xresource_free ();
|
2015-11-25 08:26:38 +00:00
|
|
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
mode_free ( &( modi[i] ) );
|
2014-07-21 19:39:24 +00:00
|
|
|
}
|
2015-11-25 08:26:38 +00:00
|
|
|
g_free ( modi );
|
2015-04-30 20:42:04 +00:00
|
|
|
|
|
|
|
// Cleanup the custom keybinding
|
|
|
|
cleanup_abe ();
|
2015-11-14 12:47:45 +00:00
|
|
|
|
2016-01-03 12:30:43 +00:00
|
|
|
g_free ( config_path );
|
|
|
|
|
2015-11-24 21:53:40 +00:00
|
|
|
TIMINGS_STOP ();
|
2014-05-19 19:02:05 +00:00
|
|
|
}
|
2014-05-20 09:41:39 +00:00
|
|
|
|
2014-09-23 07:24:24 +00:00
|
|
|
/**
|
2015-11-25 08:26:38 +00:00
|
|
|
* Parse the switcher string, into internal array of type Mode.
|
2014-09-23 07:24:24 +00:00
|
|
|
*
|
|
|
|
* String is split on separator ','
|
|
|
|
* First the three build-in modi are checked: window, run, ssh
|
|
|
|
* if that fails, a script-switcher is created.
|
|
|
|
*/
|
2016-02-04 08:20:10 +00:00
|
|
|
static int add_mode ( const char * token )
|
|
|
|
{
|
|
|
|
unsigned int index = num_modi;
|
|
|
|
// Resize and add entry.
|
2016-02-06 12:40:25 +00:00
|
|
|
modi = (Mode * *) g_realloc ( modi, sizeof ( Mode* ) * ( num_modi + 1 ) );
|
2016-02-04 08:20:10 +00:00
|
|
|
|
|
|
|
// Window switcher.
|
|
|
|
#ifdef WINDOW_MODE
|
|
|
|
if ( strcasecmp ( token, "window" ) == 0 ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
modi[num_modi] = &window_mode;
|
2016-02-04 08:20:10 +00:00
|
|
|
num_modi++;
|
|
|
|
}
|
|
|
|
else if ( strcasecmp ( token, "windowcd" ) == 0 ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
modi[num_modi] = &window_mode_cd;
|
2016-02-04 08:20:10 +00:00
|
|
|
num_modi++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif // WINDOW_MODE
|
|
|
|
// SSh dialog
|
|
|
|
if ( strcasecmp ( token, "ssh" ) == 0 ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
modi[num_modi] = &ssh_mode;
|
2016-02-04 08:20:10 +00:00
|
|
|
num_modi++;
|
|
|
|
}
|
|
|
|
// Run dialog
|
|
|
|
else if ( strcasecmp ( token, "run" ) == 0 ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
modi[num_modi] = &run_mode;
|
2016-02-04 08:20:10 +00:00
|
|
|
num_modi++;
|
|
|
|
}
|
|
|
|
else if ( strcasecmp ( token, "drun" ) == 0 ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
modi[num_modi] = &drun_mode;
|
2016-02-04 08:20:10 +00:00
|
|
|
num_modi++;
|
|
|
|
}
|
|
|
|
// combi dialog
|
|
|
|
else if ( strcasecmp ( token, "combi" ) == 0 ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
modi[num_modi] = &combi_mode;
|
2016-02-04 08:20:10 +00:00
|
|
|
num_modi++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// If not build in, use custom modi.
|
|
|
|
Mode *sw = script_switcher_parse_setup ( token );
|
|
|
|
if ( sw != NULL ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
modi[num_modi] = sw;
|
2016-02-04 08:20:10 +00:00
|
|
|
mode_set_config ( sw );
|
|
|
|
num_modi++;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
// Report error, don't continue.
|
|
|
|
fprintf ( stderr, "Invalid script switcher: %s\n", token );
|
|
|
|
token = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ( index == num_modi ) ? -1 : (int) index;
|
|
|
|
}
|
2015-11-25 08:26:38 +00:00
|
|
|
static void setup_modi ( void )
|
2014-07-21 19:39:24 +00:00
|
|
|
{
|
2015-01-09 14:54:34 +00:00
|
|
|
char *savept = NULL;
|
2015-01-08 12:16:44 +00:00
|
|
|
// Make a copy, as strtok will modify it.
|
2015-11-25 08:26:38 +00:00
|
|
|
char *switcher_str = g_strdup ( config.modi );
|
2014-12-02 07:11:53 +00:00
|
|
|
// Split token on ','. This modifies switcher_str.
|
2015-09-19 10:57:48 +00:00
|
|
|
for ( char *token = strtok_r ( switcher_str, ",", &savept ); token != NULL; token = strtok_r ( NULL, ",", &savept ) ) {
|
2016-02-04 08:20:10 +00:00
|
|
|
add_mode ( token );
|
2014-07-21 19:39:24 +00:00
|
|
|
}
|
2014-12-02 07:11:53 +00:00
|
|
|
// Free string that was modified by strtok_r
|
2014-08-09 09:40:42 +00:00
|
|
|
g_free ( switcher_str );
|
2015-02-15 20:15:16 +00:00
|
|
|
// We cannot do this in main loop, as we create pointer to string,
|
|
|
|
// and re-alloc moves that pointer.
|
2015-11-25 08:26:38 +00:00
|
|
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
mode_setup_keybinding ( modi[i] );
|
2015-02-15 20:15:16 +00:00
|
|
|
}
|
2016-01-12 21:17:53 +00:00
|
|
|
mode_set_config ( &ssh_mode );
|
|
|
|
mode_set_config ( &run_mode );
|
|
|
|
mode_set_config ( &drun_mode );
|
|
|
|
|
|
|
|
#ifdef WINDOW_MODE
|
|
|
|
mode_set_config ( &window_mode );
|
|
|
|
mode_set_config ( &window_mode_cd );
|
|
|
|
#endif // WINDOW_MODE
|
|
|
|
mode_set_config ( &combi_mode );
|
2014-07-21 19:39:24 +00:00
|
|
|
}
|
|
|
|
|
2014-11-05 09:52:10 +00:00
|
|
|
/**
|
|
|
|
* @param display Pointer to the X connection to use.
|
|
|
|
* Load configuration.
|
|
|
|
* Following priority: (current), X, commandline arguments
|
|
|
|
*/
|
|
|
|
static inline void load_configuration ( Display *display )
|
|
|
|
{
|
|
|
|
// Load in config from X resources.
|
2015-02-03 07:21:59 +00:00
|
|
|
config_parse_xresource_options ( display );
|
2016-01-03 12:30:43 +00:00
|
|
|
config_parse_xresource_options_file ( config_path );
|
2014-11-05 09:52:10 +00:00
|
|
|
|
|
|
|
// Parse command line for settings.
|
2015-03-11 17:32:37 +00:00
|
|
|
config_parse_cmd_options ( );
|
2015-02-15 20:15:16 +00:00
|
|
|
}
|
|
|
|
static inline void load_configuration_dynamic ( Display *display )
|
|
|
|
{
|
|
|
|
// Load in config from X resources.
|
|
|
|
config_parse_xresource_options_dynamic ( display );
|
2016-01-03 12:30:43 +00:00
|
|
|
config_parse_xresource_options_dynamic_file ( config_path );
|
2015-03-11 17:32:37 +00:00
|
|
|
config_parse_cmd_options_dynamic ( );
|
2014-11-05 09:52:10 +00:00
|
|
|
}
|
|
|
|
|
2015-07-29 15:55:26 +00:00
|
|
|
static void print_global_keybindings ()
|
|
|
|
{
|
|
|
|
fprintf ( stdout, "listening to the following keys:\n" );
|
2015-11-25 08:26:38 +00:00
|
|
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
mode_print_keybindings ( modi[i] );
|
2015-07-29 15:55:26 +00:00
|
|
|
}
|
|
|
|
}
|
2015-07-28 20:22:18 +00:00
|
|
|
|
|
|
|
static void reload_configuration ()
|
|
|
|
{
|
|
|
|
if ( find_arg ( "-no-config" ) < 0 ) {
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK ();
|
2015-10-10 12:15:27 +00:00
|
|
|
// Reset the color cache
|
|
|
|
color_cache_reset ();
|
2015-07-28 20:22:18 +00:00
|
|
|
// We need to open a new connection to X11, otherwise we get old
|
|
|
|
// configuration
|
2015-07-29 07:37:40 +00:00
|
|
|
Display *temp_display = XOpenDisplay ( display_str );
|
|
|
|
if ( temp_display ) {
|
|
|
|
load_configuration ( temp_display );
|
|
|
|
load_configuration_dynamic ( temp_display );
|
2015-07-28 20:22:18 +00:00
|
|
|
|
|
|
|
// Sanity check
|
2015-10-18 11:40:39 +00:00
|
|
|
config_sanity_check ( temp_display );
|
2015-07-28 20:22:18 +00:00
|
|
|
parse_keys_abe ();
|
2015-07-29 07:37:40 +00:00
|
|
|
XCloseDisplay ( temp_display );
|
|
|
|
}
|
|
|
|
else {
|
2015-09-19 10:57:48 +00:00
|
|
|
fprintf ( stderr, "Failed to get a new connection to the X11 server. No point in continuing.\n" );
|
2015-07-29 07:37:40 +00:00
|
|
|
abort ();
|
2015-07-28 20:22:18 +00:00
|
|
|
}
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK_N ( "Load config" );
|
2015-07-28 20:22:18 +00:00
|
|
|
}
|
2015-02-03 07:21:59 +00:00
|
|
|
}
|
|
|
|
|
2015-08-01 14:10:52 +00:00
|
|
|
/**
|
|
|
|
* Process X11 events in the main-loop (gui-thread) of the application.
|
|
|
|
*/
|
2016-02-06 12:40:25 +00:00
|
|
|
gboolean main_loop_x11_event_handler ( G_GNUC_UNUSED gpointer data )
|
2015-08-01 14:10:52 +00:00
|
|
|
{
|
2016-01-20 19:57:26 +00:00
|
|
|
if ( current_active_menu != NULL ) {
|
|
|
|
while ( XPending ( display ) ) {
|
|
|
|
XEvent ev;
|
|
|
|
// Read event, we know this won't block as we checked with XPending.
|
|
|
|
XNextEvent ( display, &ev );
|
2016-02-06 12:06:58 +00:00
|
|
|
rofi_view_itterrate ( current_active_menu, &ev );
|
2016-01-20 19:57:26 +00:00
|
|
|
}
|
2016-02-06 12:06:58 +00:00
|
|
|
if ( rofi_view_get_completed ( current_active_menu ) ) {
|
2016-01-20 19:57:26 +00:00
|
|
|
// This menu is done.
|
2016-02-06 12:06:58 +00:00
|
|
|
rofi_view_finalize ( current_active_menu );
|
2016-01-20 19:57:26 +00:00
|
|
|
}
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
|
|
}
|
2015-08-01 14:10:52 +00:00
|
|
|
// X11 produced an event. Consume them.
|
|
|
|
while ( XPending ( display ) ) {
|
2015-08-31 15:47:26 +00:00
|
|
|
XEvent ev;
|
2015-08-01 14:10:52 +00:00
|
|
|
// Read event, we know this won't block as we checked with XPending.
|
|
|
|
XNextEvent ( display, &ev );
|
2015-09-13 15:29:50 +00:00
|
|
|
if ( sndisplay != NULL ) {
|
|
|
|
sn_display_process_event ( sndisplay, &ev );
|
|
|
|
}
|
2015-08-01 14:10:52 +00:00
|
|
|
// If we get an event that does not belong to a window:
|
|
|
|
// Ignore it.
|
|
|
|
if ( ev.xany.window == None ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// If keypress, handle it.
|
|
|
|
if ( ev.type == KeyPress ) {
|
|
|
|
handle_keypress ( &ev );
|
|
|
|
}
|
|
|
|
}
|
2016-01-18 20:43:33 +00:00
|
|
|
return G_SOURCE_CONTINUE;
|
2015-08-01 14:10:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Process signals in the main-loop (gui-thread) of the application.
|
|
|
|
*
|
|
|
|
* returns TRUE when mainloop should be stopped.
|
|
|
|
*/
|
2016-01-18 19:51:35 +00:00
|
|
|
static gboolean main_loop_signal_handler_hup ( G_GNUC_UNUSED gpointer data )
|
2015-08-01 14:10:52 +00:00
|
|
|
{
|
2016-01-18 19:51:35 +00:00
|
|
|
fprintf ( stdout, "Reload configuration\n" );
|
|
|
|
// Release the keybindings.
|
|
|
|
release_global_keybindings ();
|
|
|
|
// Reload config
|
|
|
|
reload_configuration ();
|
|
|
|
// Grab the possibly new keybindings.
|
|
|
|
grab_global_keybindings ();
|
|
|
|
// We need to flush, otherwise the first key presses are not caught.
|
|
|
|
XFlush ( display );
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
|
|
}
|
2016-01-19 07:10:17 +00:00
|
|
|
static gboolean main_loop_signal_handler_int ( G_GNUC_UNUSED gpointer data )
|
2016-01-18 19:51:35 +00:00
|
|
|
{
|
|
|
|
// Break out of loop.
|
|
|
|
g_main_loop_quit ( main_loop );
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean main_loop_signal_handler_usr1 ( G_GNUC_UNUSED gpointer data )
|
|
|
|
{
|
|
|
|
config_parse_xresource_dump ();
|
|
|
|
return G_SOURCE_CONTINUE;
|
2015-08-01 14:10:52 +00:00
|
|
|
}
|
|
|
|
|
2016-01-18 19:51:35 +00:00
|
|
|
static int error_trap_depth = 0;
|
|
|
|
static void error_trap_push ( G_GNUC_UNUSED SnDisplay *display, G_GNUC_UNUSED Display *xdisplay )
|
|
|
|
{
|
|
|
|
++error_trap_depth;
|
|
|
|
}
|
|
|
|
|
2015-09-13 15:29:50 +00:00
|
|
|
static void error_trap_pop ( G_GNUC_UNUSED SnDisplay *display, Display *xdisplay )
|
|
|
|
{
|
|
|
|
if ( error_trap_depth == 0 ) {
|
|
|
|
fprintf ( stderr, "Error trap underflow!\n" );
|
2015-11-14 18:52:15 +00:00
|
|
|
exit ( EXIT_FAILURE );
|
2015-09-13 15:29:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
XSync ( xdisplay, False ); /* get all errors out of the queue */
|
|
|
|
--error_trap_depth;
|
|
|
|
}
|
2016-01-22 17:18:26 +00:00
|
|
|
static gboolean delayed_start ( G_GNUC_UNUSED gpointer data )
|
2016-01-20 19:57:26 +00:00
|
|
|
{
|
2016-01-20 22:08:19 +00:00
|
|
|
// Force some X Events to be handled.. seems the only way to get a reliable startup.
|
|
|
|
main_loop_x11_event_handler ( NULL );
|
2016-01-20 19:57:26 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2014-05-22 07:33:32 +00:00
|
|
|
int main ( int argc, char *argv[] )
|
|
|
|
{
|
2015-11-24 21:53:40 +00:00
|
|
|
TIMINGS_START ();
|
2015-11-14 12:47:45 +00:00
|
|
|
|
2015-03-11 17:32:37 +00:00
|
|
|
cmd_set_arguments ( argc, argv );
|
2015-04-05 20:29:26 +00:00
|
|
|
// Quiet flag
|
2016-01-22 17:18:26 +00:00
|
|
|
quiet = ( find_arg ( "-quiet" ) >= 0 );
|
2015-02-03 07:21:59 +00:00
|
|
|
// Version
|
2015-03-11 17:32:37 +00:00
|
|
|
if ( find_arg ( "-v" ) >= 0 || find_arg ( "-version" ) >= 0 ) {
|
2015-02-03 07:21:59 +00:00
|
|
|
fprintf ( stdout, "Version: "VERSION "\n" );
|
|
|
|
exit ( EXIT_SUCCESS );
|
|
|
|
}
|
|
|
|
|
2015-02-17 09:31:59 +00:00
|
|
|
// Detect if we are in dmenu mode.
|
|
|
|
// This has two possible causes.
|
|
|
|
// 1 the user specifies it on the command-line.
|
2015-09-05 17:04:36 +00:00
|
|
|
int dmenu_mode = FALSE;
|
2015-03-11 17:32:37 +00:00
|
|
|
if ( find_arg ( "-dmenu" ) >= 0 ) {
|
2015-02-17 09:31:59 +00:00
|
|
|
dmenu_mode = TRUE;
|
|
|
|
}
|
|
|
|
// 2 the binary that executed is called dmenu (e.g. symlink to rofi)
|
|
|
|
else{
|
|
|
|
// Get the base name of the executable called.
|
|
|
|
char *base_name = g_path_get_basename ( argv[0] );
|
|
|
|
dmenu_mode = ( strcmp ( base_name, "dmenu" ) == 0 );
|
|
|
|
// Free the basename for dmenu detection.
|
|
|
|
g_free ( base_name );
|
|
|
|
}
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK ();
|
2014-05-20 09:41:39 +00:00
|
|
|
// Get the path to the cache dir.
|
2014-08-09 09:44:06 +00:00
|
|
|
cache_dir = g_get_user_cache_dir ();
|
2014-02-02 09:54:01 +00:00
|
|
|
|
2015-01-31 17:23:17 +00:00
|
|
|
// Create pid file path.
|
2015-02-17 09:31:59 +00:00
|
|
|
const char *path = g_get_user_runtime_dir ();
|
|
|
|
if ( path ) {
|
|
|
|
pidfile = g_build_filename ( path, "rofi.pid", NULL );
|
2015-01-31 17:23:17 +00:00
|
|
|
}
|
2015-10-16 06:42:01 +00:00
|
|
|
config_parser_add_option ( xrm_String, "pid", (void * *) &pidfile, "Pidfile location" );
|
2015-01-31 17:23:17 +00:00
|
|
|
|
2016-01-03 12:30:43 +00:00
|
|
|
if ( find_arg ( "-config" ) < 0 ) {
|
|
|
|
const char *cpath = g_get_user_config_dir ();
|
|
|
|
if ( cpath ) {
|
|
|
|
config_path = g_build_filename ( cpath, "rofi", "config", NULL );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
char *c = NULL;
|
|
|
|
find_arg_str ( "-config", &c );
|
|
|
|
config_path = rofi_expand_path ( c );
|
|
|
|
}
|
|
|
|
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK ();
|
2014-05-20 09:41:39 +00:00
|
|
|
// Register cleanup function.
|
|
|
|
atexit ( cleanup );
|
2014-05-19 19:02:05 +00:00
|
|
|
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK ();
|
2015-02-09 18:35:51 +00:00
|
|
|
// Get DISPLAY, first env, then argument.
|
2014-11-04 15:37:05 +00:00
|
|
|
display_str = getenv ( "DISPLAY" );
|
2015-03-11 17:32:37 +00:00
|
|
|
find_arg_str ( "-display", &display_str );
|
2014-01-15 08:27:03 +00:00
|
|
|
|
2015-11-22 20:10:39 +00:00
|
|
|
if ( setlocale ( LC_ALL, "" ) == NULL ) {
|
|
|
|
fprintf ( stderr, "Failed to set locale.\n" );
|
2015-11-22 12:57:51 +00:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
2015-11-22 20:10:39 +00:00
|
|
|
|
2015-04-23 20:14:31 +00:00
|
|
|
if ( !XSupportsLocale () ) {
|
|
|
|
fprintf ( stderr, "X11 does not support locales\n" );
|
2016-01-29 20:56:52 +00:00
|
|
|
return EXIT_FAILURE;
|
2015-04-23 20:14:31 +00:00
|
|
|
}
|
|
|
|
if ( XSetLocaleModifiers ( "@im=none" ) == NULL ) {
|
|
|
|
fprintf ( stderr, "Failed to set locale modifier.\n" );
|
2016-01-29 20:56:52 +00:00
|
|
|
return EXIT_FAILURE;
|
2015-04-23 20:14:31 +00:00
|
|
|
}
|
2014-06-04 19:29:23 +00:00
|
|
|
if ( !( display = XOpenDisplay ( display_str ) ) ) {
|
2014-03-22 20:04:19 +00:00
|
|
|
fprintf ( stderr, "cannot open display!\n" );
|
2014-01-10 09:35:38 +00:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK_N ( "Open Display" );
|
2016-01-22 17:18:26 +00:00
|
|
|
|
|
|
|
main_loop = g_main_loop_new ( NULL, FALSE );
|
|
|
|
|
|
|
|
TICK_N ( "Setup mainloop" );
|
2015-09-13 15:29:50 +00:00
|
|
|
// startup not.
|
|
|
|
sndisplay = sn_display_new ( display, error_trap_push, error_trap_pop );
|
|
|
|
|
|
|
|
if ( sndisplay != NULL ) {
|
|
|
|
sncontext = sn_launchee_context_new_from_environment ( sndisplay, DefaultScreen ( display ) );
|
|
|
|
}
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK_N ( "Startup Notification" );
|
2016-01-04 06:59:30 +00:00
|
|
|
|
|
|
|
// Initialize Xresources subsystem.
|
|
|
|
config_parse_xresource_init ();
|
|
|
|
TICK_N ( "Initialize Xresources system" );
|
2015-04-30 20:42:04 +00:00
|
|
|
// Setup keybinding
|
|
|
|
setup_abe ();
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK_N ( "Setup abe" );
|
2015-04-30 20:42:04 +00:00
|
|
|
|
2015-05-31 07:46:39 +00:00
|
|
|
if ( find_arg ( "-no-config" ) < 0 ) {
|
|
|
|
load_configuration ( display );
|
|
|
|
}
|
2015-02-17 09:31:59 +00:00
|
|
|
if ( !dmenu_mode ) {
|
2015-11-25 08:26:38 +00:00
|
|
|
// setup_modi
|
|
|
|
setup_modi ();
|
2015-02-17 09:31:59 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Add dmenu options.
|
2015-11-14 18:52:15 +00:00
|
|
|
config_parser_add_option ( xrm_Char, "sep", (void * *) &( config.separator ), "Element separator" );
|
2015-02-17 09:31:59 +00:00
|
|
|
}
|
2015-05-31 07:46:39 +00:00
|
|
|
if ( find_arg ( "-no-config" ) < 0 ) {
|
|
|
|
// Reload for dynamic part.
|
|
|
|
load_configuration_dynamic ( display );
|
|
|
|
}
|
2015-07-28 20:22:18 +00:00
|
|
|
|
|
|
|
x11_setup ( display );
|
|
|
|
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK_N ( "X11 Setup " );
|
2015-05-31 07:46:39 +00:00
|
|
|
// Sanity check
|
2015-10-18 11:40:39 +00:00
|
|
|
config_sanity_check ( display );
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK_N ( "Config sanity check" );
|
2015-01-12 18:14:46 +00:00
|
|
|
// Dump.
|
2015-10-15 20:33:44 +00:00
|
|
|
// catch help request
|
|
|
|
if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) {
|
|
|
|
help ( argc, argv );
|
|
|
|
exit ( EXIT_SUCCESS );
|
|
|
|
}
|
2015-03-11 17:32:37 +00:00
|
|
|
if ( find_arg ( "-dump-xresources" ) >= 0 ) {
|
2016-01-07 12:32:33 +00:00
|
|
|
config_parse_xresource_dump ();
|
2015-01-12 18:14:46 +00:00
|
|
|
exit ( EXIT_SUCCESS );
|
|
|
|
}
|
2015-12-10 17:20:04 +00:00
|
|
|
if ( find_arg ( "-dump-xresources-theme" ) >= 0 ) {
|
2016-01-07 12:32:33 +00:00
|
|
|
config_parse_xresources_theme_dump ();
|
2015-12-10 17:20:04 +00:00
|
|
|
exit ( EXIT_SUCCESS );
|
|
|
|
}
|
2016-01-22 17:18:26 +00:00
|
|
|
main_loop_source = x11_event_source_new ( display );
|
|
|
|
x11_event_source_set_callback ( main_loop_source, main_loop_x11_event_handler );
|
2015-04-30 20:42:04 +00:00
|
|
|
// Parse the keybindings.
|
|
|
|
parse_keys_abe ();
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK_N ( "Parse ABE" );
|
2014-09-03 11:07:26 +00:00
|
|
|
char *msg = NULL;
|
2015-03-11 17:32:37 +00:00
|
|
|
if ( find_arg_str ( "-e", &( msg ) ) ) {
|
2015-06-08 21:22:35 +00:00
|
|
|
int markup = FALSE;
|
|
|
|
if ( find_arg ( "-markup" ) >= 0 ) {
|
|
|
|
markup = TRUE;
|
|
|
|
}
|
2015-07-30 06:57:09 +00:00
|
|
|
return show_error_message ( msg, markup );
|
2014-08-27 17:44:15 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 12:47:45 +00:00
|
|
|
// Create thread pool
|
2015-11-14 17:57:21 +00:00
|
|
|
GError *error = NULL;
|
2016-02-06 13:27:36 +00:00
|
|
|
tpool = g_thread_pool_new ( rofi_view_call_thread, NULL, config.threads, FALSE, &error );
|
2015-11-14 17:57:21 +00:00
|
|
|
if ( error == NULL ) {
|
|
|
|
// Idle threads should stick around for a max of 60 seconds.
|
|
|
|
g_thread_pool_set_max_idle_time ( 60000 );
|
|
|
|
// We are allowed to have
|
|
|
|
g_thread_pool_set_max_threads ( tpool, config.threads, &error );
|
|
|
|
}
|
|
|
|
// If error occured during setup of pool, tell user and exit.
|
|
|
|
if ( error != NULL ) {
|
|
|
|
char *msg = g_strdup_printf ( "Failed to setup thread pool: '%s'", error->message );
|
|
|
|
show_error_message ( msg, FALSE );
|
|
|
|
g_free ( msg );
|
|
|
|
g_error_free ( error );
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
2015-11-14 12:47:45 +00:00
|
|
|
|
2015-11-24 21:53:40 +00:00
|
|
|
TICK_N ( "Setup Threadpool" );
|
2015-02-01 19:15:21 +00:00
|
|
|
// Dmenu mode.
|
|
|
|
if ( dmenu_mode == TRUE ) {
|
2015-09-09 18:01:19 +00:00
|
|
|
normal_window_mode = find_arg ( "-normal-window" ) >= 0;
|
2014-11-09 12:10:24 +00:00
|
|
|
// force off sidebar mode:
|
|
|
|
config.sidebar_mode = FALSE;
|
2014-11-05 09:27:46 +00:00
|
|
|
int retv = run_dmenu ();
|
2014-12-16 20:08:12 +00:00
|
|
|
|
2014-11-10 07:59:39 +00:00
|
|
|
// User canceled the operation.
|
2014-11-05 09:27:46 +00:00
|
|
|
if ( retv == FALSE ) {
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
2015-05-04 08:37:50 +00:00
|
|
|
else if ( retv >= 10 ) {
|
|
|
|
return retv;
|
2015-05-03 11:04:03 +00:00
|
|
|
}
|
2015-02-01 19:15:21 +00:00
|
|
|
return EXIT_SUCCESS;
|
2014-11-05 09:27:46 +00:00
|
|
|
}
|
2015-02-01 19:15:21 +00:00
|
|
|
|
2016-01-22 17:18:26 +00:00
|
|
|
// Setup signal handling sources.
|
|
|
|
// SIGHup signal.
|
|
|
|
g_unix_signal_add ( SIGHUP, main_loop_signal_handler_hup, NULL );
|
2016-01-26 07:36:44 +00:00
|
|
|
// SIGINT
|
2016-01-22 17:18:26 +00:00
|
|
|
g_unix_signal_add ( SIGINT, main_loop_signal_handler_int, NULL );
|
|
|
|
// SIGUSR1
|
|
|
|
g_unix_signal_add ( SIGUSR1, main_loop_signal_handler_usr1, NULL );
|
2015-02-01 19:15:21 +00:00
|
|
|
// flags to run immediately and exit
|
|
|
|
char *sname = NULL;
|
2015-03-11 17:32:37 +00:00
|
|
|
if ( find_arg_str ( "-show", &sname ) == TRUE ) {
|
2014-07-21 19:39:24 +00:00
|
|
|
int index = switcher_get ( sname );
|
2016-02-04 08:20:10 +00:00
|
|
|
if ( index < 0 ) {
|
|
|
|
// Add it to the list
|
|
|
|
index = add_mode ( sname );
|
|
|
|
// Complain
|
|
|
|
if ( index >= 0 ) {
|
|
|
|
fprintf ( stdout, "Mode %s not enabled. Please add it to the list of enabled modi: %s\n",
|
|
|
|
sname, config.modi );
|
|
|
|
fprintf ( stdout, "Adding mode: %s\n", sname );
|
|
|
|
}
|
|
|
|
// Run it anyway if found.
|
|
|
|
}
|
2014-07-21 19:39:24 +00:00
|
|
|
if ( index >= 0 ) {
|
2015-07-28 20:22:18 +00:00
|
|
|
run_switcher ( index );
|
2016-01-20 19:57:26 +00:00
|
|
|
g_idle_add ( delayed_start, GINT_TO_POINTER ( index ) );
|
2014-07-21 19:39:24 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf ( stderr, "The %s switcher has not been enabled\n", sname );
|
2016-01-22 17:18:26 +00:00
|
|
|
return EXIT_FAILURE;
|
2014-07-21 19:39:24 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-04 19:29:23 +00:00
|
|
|
else{
|
2014-01-23 19:33:13 +00:00
|
|
|
// Daemon mode, Listen to key presses..
|
2015-07-29 07:37:40 +00:00
|
|
|
if ( !grab_global_keybindings () ) {
|
2015-11-14 17:57:21 +00:00
|
|
|
fprintf ( stderr, "Rofi was launched in daemon mode, but no key-binding was specified.\n" );
|
2015-04-05 20:29:26 +00:00
|
|
|
fprintf ( stderr, "Please check the manpage on how to specify a key-binding.\n" );
|
|
|
|
fprintf ( stderr, "The following modi are enabled and keys can be specified:\n" );
|
2015-11-25 08:26:38 +00:00
|
|
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
2016-02-06 12:40:25 +00:00
|
|
|
const char *name = mode_get_name ( modi[i] );
|
2016-01-07 20:27:20 +00:00
|
|
|
fprintf ( stderr, "\t* "color_bold "%s"color_reset ": -key-%s <key>\n", name, name );
|
2015-04-05 20:29:26 +00:00
|
|
|
}
|
2016-01-22 17:18:26 +00:00
|
|
|
// Cleanup
|
2015-04-05 20:29:26 +00:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
if ( !quiet ) {
|
2015-07-29 16:16:06 +00:00
|
|
|
fprintf ( stdout, "Rofi is launched in daemon mode.\n" );
|
2015-07-29 15:55:26 +00:00
|
|
|
print_global_keybindings ();
|
2014-07-21 19:39:24 +00:00
|
|
|
}
|
2014-11-05 09:52:10 +00:00
|
|
|
|
2015-09-13 15:29:50 +00:00
|
|
|
// done starting deamon.
|
|
|
|
|
|
|
|
if ( sncontext != NULL ) {
|
|
|
|
sn_launchee_context_complete ( sncontext );
|
|
|
|
}
|
2016-01-20 19:57:26 +00:00
|
|
|
daemon_mode = TRUE;
|
2015-07-28 20:22:18 +00:00
|
|
|
XSelectInput ( display, DefaultRootWindow ( display ), KeyPressMask );
|
|
|
|
XFlush ( display );
|
2014-01-23 17:24:28 +00:00
|
|
|
}
|
2014-01-23 19:33:13 +00:00
|
|
|
|
2016-01-22 17:18:26 +00:00
|
|
|
// Start mainloop.
|
|
|
|
g_main_loop_run ( main_loop );
|
|
|
|
|
2014-01-23 17:24:28 +00:00
|
|
|
return EXIT_SUCCESS;
|
2012-09-01 13:49:31 +00:00
|
|
|
}
|