1
0
Fork 0
mirror of https://github.com/davatorium/rofi.git synced 2024-11-25 13:55:34 -05:00

Fix #128: Better handling of keybindings and remove deprecated launching.

See manpage.
This commit is contained in:
QC 2015-02-15 21:15:16 +01:00
parent b6652a0221
commit dee0bfb821
11 changed files with 251 additions and 263 deletions

View file

@ -1,9 +1,11 @@
0.15.2: (unreleased) 0.15.2: (unreleased)
Removed features: Removed features:
- Remove (broken) hmode - Remove (broken) hmode
- Old style key binding and mode launcher.
New features: New features:
- Word movement in entry box. (#126) - Word movement in entry box. (#126)
- PID file to avoid duplicate Rofi. - PID file to avoid duplicate Rofi.
- Generic keybinding and launching for modi. (#128)
Bug fixes: Bug fixes:
- Shift left/right movement between swtichers (#125) - Shift left/right movement between swtichers (#125)
- Document updates (#123,#116,#124,etc.) - Document updates (#123,#116,#124,etc.)

View file

@ -69,12 +69,6 @@ Settings config = {
.run_list_command = "", .run_list_command = "",
/** Command executed when running application in terminal */ /** Command executed when running application in terminal */
.run_shell_command = "{terminal} -e {cmd}", .run_shell_command = "{terminal} -e {cmd}",
/** Key binding */
.window_key = "F12",
/** Key to open run dialog */
.run_key = "mod1+F2",
/** Key to open ssh dialog */
.ssh_key = "mod1+F3",
/** /**
* Location of the window. * Location of the window.
* Enumeration indicating location or gravity of window. * Enumeration indicating location or gravity of window.

View file

@ -16,9 +16,7 @@ rofi - A window switcher, run dialog and dmenu replacement
[ -bgalt *color* ] [ -bgalt *color* ]
[ -hlfg *color* ] [ -hlfg *color* ]
[ -hlbg *color* ] [ -hlbg *color* ]
[ -key *combo* ] [ -key-**mode** *combo* ]
[ -dkey *comdo* ]
[ -rkey *comdo* ]
[ -terminal *terminal* ] [ -terminal *terminal* ]
[ -location *position* ] [ -location *position* ]
[ -fixed-num-lines ] [ -fixed-num-lines ]
@ -79,51 +77,14 @@ The default key combinations are:
## OPTIONS ## OPTIONS
`-key` `-key-**mode**` **KEY**
Change the key combination to display all windows. Change the key combination to display a **mode**
rofi -key F12 rofi -key-run F12
rofi -key control+shift+s rofi -key-ssh control+shift+s
rofi -key mod1+Tab rofi -key-window mod1+Tab
Default: *F12*
`-rkey`
Change the key combination to display the run dialog.
rofi -rkey F11
rofi -rkey control+shift+d
rofi -rkey mod1+grave (grave=backtick)
Default: *Alt-F2*
`-skey`
Change the key combination to display the ssh dialog.
rofi -skey F10
rofi -skey control+shift+s
rofi -skey mod1+grave (grave=backtick)
Default: *Alt-F3*
`-now`
Run rofi in all-windows mode once then exit. Does not bind any keys.
`-rnow`
Run rofi in run-dialog mode once then exit. Does not bind any keys.
`-snow`
Run rofi in ssh mode once then exit. Does not bind any keys.
`-dmenu` `-dmenu`

View file

@ -14,9 +14,7 @@ rofi \- A window switcher, run dialog and dmenu replacement
[ \-bgalt \fIcolor\fP ] [ \-bgalt \fIcolor\fP ]
[ \-hlfg \fIcolor\fP ] [ \-hlfg \fIcolor\fP ]
[ \-hlbg \fIcolor\fP ] [ \-hlbg \fIcolor\fP ]
[ \-key \fIcombo\fP ] [ \-key\-\fBmode\fP \fIcombo\fP ]
[ \-dkey \fIcomdo\fP ]
[ \-rkey \fIcomdo\fP ]
[ \-terminal \fIterminal\fP ] [ \-terminal \fIterminal\fP ]
[ \-location \fIposition\fP ] [ \-location \fIposition\fP ]
[ \-fixed\-num\-lines ] [ \-fixed\-num\-lines ]
@ -77,59 +75,17 @@ The default key combinations are:
Show ssh\-dialog. Show ssh\-dialog.
.SH OPTIONS .SH OPTIONS
.PP .PP
\fB\fC\-key\fR \fB\fC\-key\-**mode**\fR \fBKEY\fP
.IP .IP
Change the key combination to display all windows. Change the key combination to display a \fBmode\fP
.PP .PP
.RS .RS
.nf .nf
rofi \-key F12 rofi \-key\-run F12
rofi \-key control+shift+s rofi \-key\-ssh control+shift+s
rofi \-key mod1+Tab rofi \-key\-window mod1+Tab
.fi .fi
.RE .RE
.IP
Default: \fIF12\fP
.PP
\fB\fC\-rkey\fR
.IP
Change the key combination to display the run dialog.
.PP
.RS
.nf
rofi \-rkey F11
rofi \-rkey control+shift+d
rofi \-rkey mod1+grave (grave=backtick)
.fi
.RE
.IP
Default: \fIAlt\-F2\fP
.PP
\fB\fC\-skey\fR
.IP
Change the key combination to display the ssh dialog.
.PP
.RS
.nf
rofi \-skey F10
rofi \-skey control+shift+s
rofi \-skey mod1+grave (grave=backtick)
.fi
.RE
.IP
Default: \fIAlt\-F3\fP
.PP
\fB\fC\-now\fR
.IP
Run rofi in all\-windows mode once then exit. Does not bind any keys.
.PP
\fB\fC\-rnow\fR
.IP
Run rofi in run\-dialog mode once then exit. Does not bind any keys.
.PP
\fB\fC\-snow\fR
.IP
Run rofi in ssh mode once then exit. Does not bind any keys.
.PP .PP
\fB\fC\-dmenu\fR \fB\fC\-dmenu\fR
.IP .IP
@ -649,14 +605,18 @@ Check quotes used on the commandline: e.g. used “ instead of ".
.SH WEBSITE .SH WEBSITE
.PP .PP
\fBrofi\fP website can be found at here \fBrofi\fP website can be found at here
\[la]https://davedavenport.github.io/rofi/\[ra] .UR https://davedavenport.github.io/rofi/
.UE
.PP .PP
\fBrofi\fP bugtracker can be found here \fBrofi\fP bugtracker can be found here
\[la]https://github.com/DaveDavenport/rofi/issues\[ra] .UR https://github.com/DaveDavenport/rofi/issues
.UE
.SH AUTHOR .SH AUTHOR
.PP .PP
Qball Cow Qball Cow
\[la]qball@gmpclient.org\[ra] .MT qball@gmpclient.org
.ME
.PP .PP
Original code based on work by: Sean Pringle Original code based on work by: Sean Pringle
\[la]sean.pringle@gmail.com\[ra] .MT sean.pringle@gmail.com
.ME

View file

@ -174,12 +174,6 @@ typedef struct _Settings
/** Command for listing executables */ /** Command for listing executables */
char * run_list_command; char * run_list_command;
/** Key to open window switcher */
char * window_key;
/** Key to open run dialog */
char * run_key;
/** Key to open ssh dialog */
char * ssh_key;
/** Windows location/gravity */ /** Windows location/gravity */
WindowLocation location; WindowLocation location;
/** Padding between elements */ /** Padding between elements */

View file

@ -1,6 +1,16 @@
#ifndef __XRMOPTIONS_H__ #ifndef __XRMOPTIONS_H__
#define __XRMOPTIONS_H__ #define __XRMOPTIONS_H__
// Big thanks to Sean Pringle for this code.
// This maps xresource options to config structure.
typedef enum
{
xrm_String = 0,
xrm_Number = 1,
xrm_SNumber = 2,
xrm_Boolean = 3
} XrmOptionType;
/** /**
* @param display Handler of the display to fetch the settings from. * @param display Handler of the display to fetch the settings from.
* *
@ -9,6 +19,14 @@
*/ */
void config_parse_xresource_options ( Display *display ); void config_parse_xresource_options ( Display *display );
/**
* @param display Handler of the display to fetch the settings from.
*
* Parse the rofi related X resource options of the
* connected X server.
*/
void config_parse_xresource_options_dynamic ( Display *display );
/** /**
* Free any allocated memory. * Free any allocated memory.
*/ */
@ -20,4 +38,5 @@ void config_xresource_free ( void );
*/ */
void xresource_dump ( void ); void xresource_dump ( void );
void config_parser_add_option ( XrmOptionType type, const char *key, void **value );
#endif #endif

View file

@ -452,16 +452,8 @@ void config_parse_cmd_options ( int argc, char ** argv )
find_arg_str ( argc, argv, "-run-list-command", &( config.run_list_command ) ); find_arg_str ( argc, argv, "-run-list-command", &( config.run_list_command ) );
find_arg_str ( argc, argv, "-run-shell-command", &( config.run_shell_command ) ); find_arg_str ( argc, argv, "-run-shell-command", &( config.run_shell_command ) );
// Keybindings
find_arg_str ( argc, argv, "-key", &( config.window_key ) );
find_arg_str ( argc, argv, "-rkey", &( config.run_key ) );
find_arg_str ( argc, argv, "-skey", &( config.ssh_key ) );
find_arg_char ( argc, argv, "-sep", &( config.separator ) ); find_arg_char ( argc, argv, "-sep", &( config.separator ) );
find_arg_int ( argc, argv, "-eh", &( config.element_height ) ); find_arg_int ( argc, argv, "-eh", &( config.element_height ) );
find_arg_uint ( argc, argv, "-lazy-filter-limit", &( config.lazy_filter_limit ) ); find_arg_uint ( argc, argv, "-lazy-filter-limit", &( config.lazy_filter_limit ) );

View file

@ -65,17 +65,13 @@ typedef enum _MainLoopEvent
} MainLoopEvent; } MainLoopEvent;
// Pidfile. // Pidfile.
char *pidfile = NULL; char *pidfile = NULL;
const char *cache_dir = NULL; const char *cache_dir = NULL;
Display *display = NULL; Display *display = NULL;
char *display_str = NULL; char *display_str = NULL;
const char *netatom_names[] = { EWMH_ATOMS ( ATOM_CHAR ) };
Atom netatoms[NUM_NETATOMS];
unsigned int windows_modmask, rundialog_modmask, sshdialog_modmask;
KeySym rundialog_keysym, sshdialog_keysym, windows_keysym;
const char *netatom_names[] = { EWMH_ATOMS ( ATOM_CHAR ) };
Atom netatoms[NUM_NETATOMS];
/** /**
* Structure defining a switcher. * Structure defining a switcher.
@ -93,6 +89,11 @@ typedef struct _Switcher
switcher_callback_free_data cb_data_free; switcher_callback_free_data cb_data_free;
// Textbox used in the sidebar-mode. // Textbox used in the sidebar-mode.
textbox *tb; textbox *tb;
// Keybindings (keysym and modmask)
char * keycfg;
char * keystr;
KeySym keysym;
unsigned int modmask;
} Switcher; } Switcher;
// Array of switchers. // Array of switchers.
@ -551,12 +552,20 @@ inline static void menu_nav_down ( MenuState *state )
*/ */
static void menu_keyboard_navigation ( MenuState *state, KeySym key, unsigned int modstate ) static void menu_keyboard_navigation ( MenuState *state, KeySym key, unsigned int modstate )
{ {
if ( key == XK_Escape // pressing one of the global key bindings closes the switcher. this allows fast closing of the
// pressing one of the global key bindings closes the switcher. this allows fast closing of the menu if an item is not selected // menu if an item is not selected
|| ( ( windows_modmask == AnyModifier || modstate & windows_modmask ) && key == windows_keysym ) for ( unsigned int i = 0; i < num_switchers; i++ ) {
|| ( ( rundialog_modmask == AnyModifier || modstate & rundialog_modmask ) && key == rundialog_keysym ) if ( switchers[i].keystr != NULL ) {
|| ( ( sshdialog_modmask == AnyModifier || modstate & sshdialog_modmask ) && key == sshdialog_keysym ) if ( ( switchers[i].modmask == AnyModifier || modstate & ( switchers[i].keysym ) ) &&
) { switchers[i].keysym == key ) {
state->retv = MENU_CANCEL;
state->quit = TRUE;
state->prev_key = key;
return;
}
}
}
if ( key == XK_Escape ) {
state->retv = MENU_CANCEL; state->retv = MENU_CANCEL;
state->quit = TRUE; state->quit = TRUE;
} }
@ -1418,19 +1427,13 @@ static void handle_keypress ( XEvent *ev )
{ {
int index = -1; int index = -1;
KeySym key = XkbKeycodeToKeysym ( display, ev->xkey.keycode, 0, 0 ); KeySym key = XkbKeycodeToKeysym ( display, ev->xkey.keycode, 0, 0 );
if ( ( windows_modmask == AnyModifier || ev->xkey.state & windows_modmask ) && for ( unsigned int i = 0; i < num_switchers; i++ ) {
key == windows_keysym ) { if ( switchers[i].keystr != NULL ) {
index = switcher_get ( "window" ); if ( ( switchers[i].modmask == AnyModifier || ( ev->xkey.state ) & ( switchers[i].keysym ) ) &&
} switchers[i].keysym == key ) {
index = i;
if ( ( rundialog_modmask == AnyModifier || ev->xkey.state & rundialog_modmask ) && }
key == rundialog_keysym ) { }
index = switcher_get ( "run" );
}
if ( ( sshdialog_modmask == AnyModifier || ev->xkey.state & sshdialog_modmask ) &&
key == sshdialog_keysym ) {
index = switcher_get ( "ssh" );
} }
if ( index >= 0 ) { if ( index >= 0 ) {
run_switcher ( TRUE, index ); run_switcher ( TRUE, index );
@ -1468,12 +1471,19 @@ static void cleanup ()
// Cleaning up memory allocated by the Xresources file. // Cleaning up memory allocated by the Xresources file.
config_xresource_free (); config_xresource_free ();
for ( unsigned int i = 0; i < num_switchers; i++ ) { for ( unsigned int i = 0; i < num_switchers; i++ ) {
// only used for script dialog. // only used for script dialog.
if ( switchers[i].cb_data_free != NULL ) { if ( switchers[i].cb_data_free != NULL ) {
switchers[i].cb_data_free ( switchers[i].cb_data ); switchers[i].cb_data_free ( switchers[i].cb_data );
} }
if ( switchers[i].keystr != NULL ) {
g_free ( switchers[i].keystr );
switchers[i].keystr = NULL;
}
if ( switchers[i].keycfg != NULL ) {
g_free ( switchers[i].keycfg );
switchers[i].keycfg = NULL;
}
} }
g_free ( switchers ); g_free ( switchers );
@ -1501,9 +1511,14 @@ static void setup_switchers ( void )
token != NULL; token != NULL;
token = strtok_r ( NULL, ",", &savept ) ) { token = strtok_r ( NULL, ",", &savept ) ) {
// Resize and add entry. // Resize and add entry.
switchers = (Switcher *) g_realloc ( switchers, sizeof ( Switcher ) * ( num_switchers + 1 ) ); switchers = (Switcher *) g_realloc ( switchers,
sizeof ( Switcher ) * ( num_switchers + 1 ) );
switchers[num_switchers].cb_data = NULL; switchers[num_switchers].cb_data = NULL;
switchers[num_switchers].cb_data_free = NULL; switchers[num_switchers].cb_data_free = NULL;
switchers[num_switchers].keystr = NULL;
switchers[num_switchers].keycfg = NULL;
switchers[num_switchers].keysym = None;
switchers[num_switchers].modmask = AnyModifier;
// Window switcher. // Window switcher.
if ( strcasecmp ( token, "window" ) == 0 ) { if ( strcasecmp ( token, "window" ) == 0 ) {
@ -1540,9 +1555,19 @@ static void setup_switchers ( void )
token = NULL; token = NULL;
} }
} }
// Keybinding.
} }
// Free string that was modified by strtok_r // Free string that was modified by strtok_r
g_free ( switcher_str ); g_free ( switcher_str );
// We cannot do this in main loop, as we create pointer to string,
// and re-alloc moves that pointer.
for ( unsigned int i = 0; i < num_switchers; i++ ) {
switchers[i].keycfg = g_strdup_printf ( "key-%s",
switchers[i].name );
config_parser_add_option ( xrm_String,
switchers[i].keycfg,
(void * *) &( switchers[i].keystr ) );
}
} }
/** /**
@ -1563,11 +1588,24 @@ static inline void load_configuration ( Display *display )
// Parse command line for settings. // Parse command line for settings.
config_parse_cmd_options ( stored_argc, stored_argv ); config_parse_cmd_options ( stored_argc, stored_argv );
}
static inline void load_configuration_dynamic ( Display *display )
{
// Load in config from X resources.
config_parse_xresource_options_dynamic ( display );
for ( unsigned int i = 0; i < num_switchers; i++ ) {
if ( switchers[i].keycfg != NULL ) {
char *flag = g_strdup_printf ( "-%s", switchers[i].keycfg );
find_arg_str_alloc ( stored_argc, stored_argv, flag, &( switchers[i].keystr ) );
g_free ( flag );
}
}
// Sanity check // Sanity check
config_sanity_check (); config_sanity_check ();
} }
/** /**
* Handle sighub request. * Handle sighub request.
* Currently we just reload the configuration. * Currently we just reload the configuration.
@ -1582,6 +1620,7 @@ static void hup_action_handler ( int num )
Display *display = XOpenDisplay ( display_str ); Display *display = XOpenDisplay ( display_str );
if ( display ) { if ( display ) {
load_configuration ( display ); load_configuration ( display );
load_configuration_dynamic ( display );
XCloseDisplay ( display ); XCloseDisplay ( display );
} }
} }
@ -1647,6 +1686,10 @@ int main ( int argc, char *argv[] )
load_configuration ( display ); load_configuration ( display );
// setup_switchers
setup_switchers ();
// Reload for dynamic part.
load_configuration_dynamic ( display );
// Dump. // Dump.
if ( find_arg ( argc, argv, "-dump-xresources" ) >= 0 ) { if ( find_arg ( argc, argv, "-dump-xresources" ) >= 0 ) {
@ -1654,9 +1697,6 @@ int main ( int argc, char *argv[] )
exit ( EXIT_SUCCESS ); exit ( EXIT_SUCCESS );
} }
// setup_switchers
setup_switchers ();
// Set up X interaction. // Set up X interaction.
signal ( SIGCHLD, catch_exit ); signal ( SIGCHLD, catch_exit );
@ -1711,51 +1751,14 @@ int main ( int argc, char *argv[] )
fprintf ( stderr, "The %s switcher has not been enabled\n", sname ); fprintf ( stderr, "The %s switcher has not been enabled\n", sname );
} }
} }
// Old modi.
else if ( find_arg ( argc, argv, "-now" ) >= 0 ) {
int index = switcher_get ( "window" );
if ( index >= 0 ) {
run_switcher ( FALSE, index );
}
else {
fprintf ( stderr, "The window switcher has not been enabled\n" );
}
}
else if ( find_arg ( argc, argv, "-rnow" ) >= 0 ) {
int index = switcher_get ( "run" );
if ( index >= 0 ) {
run_switcher ( FALSE, index );
}
else {
fprintf ( stderr, "The run dialog has not been enabled\n" );
}
}
else if ( find_arg ( argc, argv, "-snow" ) >= 0 ) {
int index = switcher_get ( "ssh" );
if ( index >= 0 ) {
run_switcher ( FALSE, index );
}
else {
fprintf ( stderr, "The ssh dialog has not been enabled\n" );
}
}
else{ else{
// Daemon mode, Listen to key presses.. // Daemon mode, Listen to key presses..
if ( switcher_get ( "window" ) >= 0 ) { for ( unsigned int i = 0; i < num_switchers; i++ ) {
x11_parse_key ( config.window_key, &windows_modmask, &windows_keysym ); if ( switchers[i].keystr != NULL ) {
x11_grab_key ( display, windows_modmask, windows_keysym ); x11_parse_key ( switchers[i].keystr, &( switchers[i].modmask ), &( switchers[i].keysym ) );
x11_grab_key ( display, switchers[i].modmask, switchers[i].keysym );
}
} }
if ( switcher_get ( "run" ) >= 0 ) {
x11_parse_key ( config.run_key, &rundialog_modmask, &rundialog_keysym );
x11_grab_key ( display, rundialog_modmask, rundialog_keysym );
}
if ( switcher_get ( "ssh" ) >= 0 ) {
x11_parse_key ( config.ssh_key, &sshdialog_modmask, &sshdialog_keysym );
x11_grab_key ( display, sshdialog_modmask, sshdialog_keysym );
}
// Setup handler for sighub (reload config) // Setup handler for sighub (reload config)
const struct sigaction hup_action = { const struct sigaction hup_action = {
.sa_handler = hup_action_handler .sa_handler = hup_action_handler

View file

@ -312,7 +312,7 @@ void textbox_draw ( textbox *tb )
// cursor handling for edit mode // cursor handling for edit mode
void textbox_cursor ( textbox *tb, int pos ) void textbox_cursor ( textbox *tb, int pos )
{ {
int length = (tb->text == NULL)? 0: strlen(tb->text); int length = ( tb->text == NULL ) ? 0 : strlen ( tb->text );
tb->cursor = MAX ( 0, MIN ( length, pos ) ); tb->cursor = MAX ( 0, MIN ( length, pos ) );
} }
@ -333,7 +333,7 @@ void textbox_cursor_dec ( textbox *tb )
// Move word right // Move word right
void textbox_cursor_inc_word ( textbox *tb ) void textbox_cursor_inc_word ( textbox *tb )
{ {
if(tb->text == NULL) { if ( tb->text == NULL ) {
return; return;
} }
// Find word boundaries, with pango_Break? // Find word boundaries, with pango_Break?
@ -351,7 +351,7 @@ void textbox_cursor_inc_word ( textbox *tb )
break; break;
} }
} }
if(c == NULL) { if ( c == NULL ) {
return; return;
} }
while ( ( c = g_utf8_next_char ( c ) ) ) { while ( ( c = g_utf8_next_char ( c ) ) ) {
@ -452,7 +452,7 @@ void textbox_delete ( textbox *tb, int pos, int dlen )
// delete on character // delete on character
void textbox_cursor_del ( textbox *tb ) void textbox_cursor_del ( textbox *tb )
{ {
if(tb->text == NULL) { if ( tb->text == NULL ) {
return; return;
} }
int index = g_utf8_next_char ( &( tb->text[tb->cursor] ) ) - tb->text; int index = g_utf8_next_char ( &( tb->text[tb->cursor] ) ) - tb->text;

View file

@ -412,7 +412,7 @@ void x11_setup ( Display *display )
extern Colormap map; extern Colormap map;
extern XVisualInfo vinfo; extern XVisualInfo vinfo;
int truecolor = FALSE; int truecolor = FALSE;
void create_visual_and_colormap ( Display *display ) void create_visual_and_colormap ( Display *display )
{ {
int screen = DefaultScreen ( display ); int screen = DefaultScreen ( display );

View file

@ -33,25 +33,16 @@
#include "rofi.h" #include "rofi.h"
#include "xrmoptions.h" #include "xrmoptions.h"
// Big thanks to Sean Pringle for this code.
// This maps xresource options to config structure.
typedef enum
{
xrm_String = 0,
xrm_Number = 1,
xrm_SNumber = 2,
xrm_Boolean = 3
} XrmOptionType;
typedef struct typedef struct
{ {
int type; int type;
char * name; const char * name;
union union
{ {
unsigned int * num; unsigned int * num;
int * snum; int * snum;
char ** str; char ** str;
void *pointer;
}; };
char *mem; char *mem;
} XrmOption; } XrmOption;
@ -108,13 +99,58 @@ static XrmOption xrmOptions[] = {
{ xrm_Boolean, "levenshtein-sort", { .num = &config.levenshtein_sort }, NULL }, { xrm_Boolean, "levenshtein-sort", { .num = &config.levenshtein_sort }, NULL },
{ xrm_Boolean, "case-sensitive", { .num = &config.case_sensitive }, NULL }, { xrm_Boolean, "case-sensitive", { .num = &config.case_sensitive }, NULL },
/* Key bindings */ /* Key bindings */
{ xrm_String, "key", { .str = &config.window_key }, NULL },
{ xrm_String, "rkey", { .str = &config.run_key }, NULL },
{ xrm_String, "skey", { .str = &config.ssh_key }, NULL },
{ xrm_Boolean, "sidebar-mode", { .num = &config.sidebar_mode }, NULL }, { xrm_Boolean, "sidebar-mode", { .num = &config.sidebar_mode }, NULL },
{ xrm_Number, "lazy-filter-limit", { .num = &config.lazy_filter_limit }, NULL } { xrm_Number, "lazy-filter-limit", { .num = &config.lazy_filter_limit }, NULL }
}; };
// Dynamic options.
XrmOption *extra_options = NULL;
unsigned int num_extra_options = 0;
void config_parser_add_option ( XrmOptionType type, const char *key, void **value )
{
extra_options = g_realloc ( extra_options, ( num_extra_options + 1 ) * sizeof ( XrmOption ) );
extra_options[num_extra_options].type = type;
extra_options[num_extra_options].name = key;
extra_options[num_extra_options].pointer = value;
if ( type == xrm_String ) {
extra_options[num_extra_options].mem = ( (char *) ( *value ) );
}
else {
extra_options[num_extra_options].mem = NULL;
}
num_extra_options++;
}
static void config_parser_set ( XrmOption *option, XrmValue *xrmValue )
{
if ( option->type == xrm_String ) {
if ( ( option )->mem != NULL ) {
g_free ( option->mem );
option->mem = NULL;
}
*( option->str ) = g_strndup ( xrmValue->addr, xrmValue->size );
// Memory
( option )->mem = *( option->str );
}
else if ( option->type == xrm_Number ) {
*( option->num ) = (unsigned int) strtoul ( xrmValue->addr, NULL, 10 );
}
else if ( option->type == xrm_SNumber ) {
*( option->snum ) = (int) strtol ( xrmValue->addr, NULL, 10 );
}
else if ( option->type == xrm_Boolean ) {
if ( xrmValue->size > 0 && g_ascii_strncasecmp ( xrmValue->addr, "true", xrmValue->size ) == 0 ) {
*( option->num ) = TRUE;
}
else{
*( option->num ) = FALSE;
}
}
}
void config_parse_xresource_options ( Display *display ) void config_parse_xresource_options ( Display *display )
{ {
@ -133,37 +169,46 @@ void config_parse_xresource_options ( Display *display )
const char * namePrefix = "rofi"; const char * namePrefix = "rofi";
const char * classPrefix = "rofi"; const char * classPrefix = "rofi";
for ( unsigned int i = 0; i < sizeof ( xrmOptions ) / sizeof ( *xrmOptions ); ++i ) { for ( unsigned int i = 0; i < sizeof ( xrmOptions ) / sizeof ( XrmOption ); ++i ) {
char *name, *class; char *name, *class;
name = g_strdup_printf ( "%s.%s", namePrefix, xrmOptions[i].name ); name = g_strdup_printf ( "%s.%s", namePrefix, xrmOptions[i].name );
class = g_strdup_printf ( "%s.%s", classPrefix, xrmOptions[i].name ); class = g_strdup_printf ( "%s.%s", classPrefix, xrmOptions[i].name );
if ( XrmGetResource ( xDB, name, class, &xrmType, &xrmValue ) ) { if ( XrmGetResource ( xDB, name, class, &xrmType, &xrmValue ) ) {
if ( xrmOptions[i].type == xrm_String ) { config_parser_set ( &( xrmOptions[i] ), &xrmValue );
if ( xrmOptions[i].mem != NULL ) { }
g_free ( xrmOptions[i].mem );
xrmOptions[i].mem = NULL;
}
*xrmOptions[i].str = g_strndup ( xrmValue.addr, xrmValue.size );
// Memory g_free ( class );
xrmOptions[i].mem = ( *xrmOptions[i].str ); g_free ( name );
} }
else if ( xrmOptions[i].type == xrm_Number ) { XrmDestroyDatabase ( xDB );
*xrmOptions[i].num = (unsigned int) strtoul ( xrmValue.addr, NULL, 10 ); }
}
else if ( xrmOptions[i].type == xrm_SNumber ) { void config_parse_xresource_options_dynamic ( Display *display )
*xrmOptions[i].snum = (int) strtol ( xrmValue.addr, NULL, 10 ); {
} char *xRMS;
else if ( xrmOptions[i].type == xrm_Boolean ) { // Map Xresource entries to rofi config options.
if ( xrmValue.size > 0 && g_ascii_strncasecmp ( xrmValue.addr, "true", xrmValue.size ) == 0 ) { XrmInitialize ();
*xrmOptions[i].num = TRUE; xRMS = XResourceManagerString ( display );
}
else{ if ( xRMS == NULL ) {
*xrmOptions[i].num = FALSE; return;
} }
} XrmDatabase xDB = XrmGetStringDatabase ( xRMS );
char * xrmType;
XrmValue xrmValue;
const char * namePrefix = "rofi";
const char * classPrefix = "rofi";
for ( unsigned int i = 0; i < num_extra_options; ++i ) {
char *name, *class;
name = g_strdup_printf ( "%s.%s", namePrefix, extra_options[i].name );
class = g_strdup_printf ( "%s.%s", classPrefix, extra_options[i].name );
if ( XrmGetResource ( xDB, name, class, &xrmType, &xrmValue ) ) {
config_parser_set ( &( extra_options[i] ), &xrmValue );
} }
g_free ( class ); g_free ( class );
@ -174,12 +219,47 @@ void config_parse_xresource_options ( Display *display )
void config_xresource_free ( void ) void config_xresource_free ( void )
{ {
for ( unsigned int i = 0; i < sizeof ( xrmOptions ) / sizeof ( *xrmOptions ); ++i ) { for ( unsigned int i = 0; i < ( sizeof ( xrmOptions ) / sizeof ( *xrmOptions ) ); ++i ) {
if ( xrmOptions[i].mem != NULL ) { if ( xrmOptions[i].mem != NULL ) {
g_free ( xrmOptions[i].mem ); g_free ( xrmOptions[i].mem );
xrmOptions[i].mem = NULL; xrmOptions[i].mem = NULL;
} }
} }
for ( unsigned int i = 0; i < num_extra_options; ++i ) {
if ( extra_options[i].mem != NULL ) {
g_free ( extra_options[i].mem );
extra_options[i].mem = NULL;
}
}
if ( extra_options != NULL ) {
g_free ( extra_options );
}
}
void xresource_dump_entry ( const char *namePrefix, XrmOption *option )
{
printf ( "%s.%s: %*s", namePrefix, option->name,
(int) ( 20 - strlen ( option->name ) ), "" );
switch ( option->type )
{
case xrm_Number:
printf ( "%u", *( option->num ) );
break;
case xrm_SNumber:
printf ( "%i", *( option->snum ) );
break;
case xrm_String:
if ( ( *( option->str ) ) != NULL ) {
printf ( "%s", *( option->str ) );
}
break;
case xrm_Boolean:
printf ( "%s", ( *( option->num ) == TRUE ) ? "true" : "false" );
break;
default:
break;
}
printf ( "\n" );
} }
void xresource_dump ( void ) void xresource_dump ( void )
@ -193,26 +273,9 @@ void xresource_dump ( void )
continue; continue;
} }
} }
xresource_dump_entry ( namePrefix, &( xrmOptions[i] ) );
printf ( "%s.%s: %*s", namePrefix, xrmOptions[i].name, (int) ( 20 - strlen ( xrmOptions[i].name ) ), }
"" ); for ( unsigned int i = 0; i < num_extra_options; i++ ) {
switch ( xrmOptions[i].type ) xresource_dump_entry ( namePrefix, &( extra_options[i] ) );
{
case xrm_Number:
printf ( "%u", *xrmOptions[i].num );
break;
case xrm_SNumber:
printf ( "%i", *xrmOptions[i].snum );
break;
case xrm_String:
printf ( "%s", *xrmOptions[i].str );
break;
case xrm_Boolean:
printf ( "%s", ( ( *xrmOptions[i].num ) == TRUE ) ? "true" : "false" );
break;
default:
break;
}
printf ( "\n" );
} }
} }