diff options
author | QC <qball@gmpclient.org> | 2014-07-21 21:39:24 +0200 |
---|---|---|
committer | QC <qball@gmpclient.org> | 2014-07-21 21:39:24 +0200 |
commit | cd4888a5cfc912720f230c3a550526f4428f83b4 (patch) | |
tree | e4f2b79f8f9968197e9547ec8c8e19a6cfa931e2 | |
parent | d584987c819ce85fc93fe9e8e3c3973f7b9e99cf (diff) |
Fix #65, Fix #63 Allow user to select list of modi's
* Add script_dialog, so user can add dialogs using a script.
* Add a way to disable modi's
* Add -show <modi> option.
-rwxr-xr-x | Examples/i3_switch_workspaces.sh | 22 | ||||
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | config/config.c | 3 | ||||
-rw-r--r-- | doc/rofi-manpage.markdown | 33 | ||||
-rw-r--r-- | doc/rofi.1 | 49 | ||||
-rw-r--r-- | include/dmenu-dialog.h | 2 | ||||
-rw-r--r-- | include/rofi.h | 20 | ||||
-rw-r--r-- | include/run-dialog.h | 2 | ||||
-rw-r--r-- | include/script-dialog.h | 28 | ||||
-rw-r--r-- | include/ssh-dialog.h | 2 | ||||
-rw-r--r-- | include/textbox.h | 12 | ||||
-rw-r--r-- | source/dmenu-dialog.c | 4 | ||||
-rw-r--r-- | source/rofi.c | 227 | ||||
-rw-r--r-- | source/run-dialog.c | 4 | ||||
-rw-r--r-- | source/script-dialog.c | 201 | ||||
-rw-r--r-- | source/ssh-dialog.c | 4 | ||||
-rw-r--r-- | source/xrmoptions.c | 1 |
17 files changed, 544 insertions, 73 deletions
diff --git a/Examples/i3_switch_workspaces.sh b/Examples/i3_switch_workspaces.sh new file mode 100755 index 00000000..a5920567 --- /dev/null +++ b/Examples/i3_switch_workspaces.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +if [ -z $@ ] +then +function gen_workspaces() +{ + i3-msg -t get_workspaces | tr ',' '\n' | grep "name" | sed 's/"name":"\(.*\)"/\1/g' | sort -n +} + + +echo empty; gen_workspaces +else + WORKSPACE=$@ + + if [ x"empty" = x"${WORKSPACE}" ] + then + i3_empty_workspace.sh >/dev/null + elif [ -n "${WORKSPACE}" ] + then + i3-msg workspace "${WORKSPACE}" >/dev/null + fi +fi diff --git a/Makefile.am b/Makefile.am index 9d416647..5e95f8d2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,12 +26,14 @@ rofi_SOURCES=\ source/dmenu-dialog.c\ source/run-dialog.c\ source/ssh-dialog.c\ + source/script-dialog.c\ source/history.c\ config/config.c\ include/rofi.h\ include/run-dialog.h\ include/ssh-dialog.h\ include/dmenu-dialog.h\ + include/script-dialog.h\ include/xrmoptions.h\ include/history.h\ include/textbox.h @@ -66,6 +68,7 @@ EXTRA_DIST=\ $(man1_MANS)\ $(markdown_FILES)\ $(markdown_SC_FILES)\ + Examples/i3_switch_workspaces.sh\ INSTALL.md ## diff --git a/config/config.c b/config/config.c index 54590735..7037599d 100644 --- a/config/config.c +++ b/config/config.c @@ -29,6 +29,9 @@ #include "rofi.h" Settings config = { + // List of enabled switchers. + // -switchers + .switchers = "window,run,ssh", // Set the default window opacity. // This option only works when running a composite manager. // -o diff --git a/doc/rofi-manpage.markdown b/doc/rofi-manpage.markdown index d1a3599b..f2364edd 100644 --- a/doc/rofi-manpage.markdown +++ b/doc/rofi-manpage.markdown @@ -14,11 +14,11 @@ SYNOPSIS [ -terminal *terminal* ] [ -loc *position* ] [ -hmode ] [ -fixed-num-lines ] [ -padding *padding* ] [ -opacity *opacity%* ] [ -display *display* ] [ -bc *color* ] [ -bw *width* ] [ -dmenu [ -p *prompt* ] ] [ -ssh-set-title *true|false* ] [ -now ] [ -rnow ] [ -snow ] [ -version ] [ -help] [ -dump-xresources ] -[ -disable-history ] [ -levenshtein-sort ] +[ -disable-history ] [ -levenshtein-sort ] [ -show *mode* ] [ -switcher *mode1,mode2* ] DESCRIPTION ----------- -`rofi` is an X11 popup window switcher. A list is displayed center-screen showing open window titles, WM_CLASS, and desktop number. +`rofi` is an X11 popup window switcher. A list is displayed center-screen showing open window titles, WM_CLASS, and desktop number. The user may filter the list by typing, navigate with Up/Down or Tab keys, and select a window with Return (Enter). Escape cancels. License @@ -219,11 +219,38 @@ OPTIONS When searching sort the result based on levenshtein distance. +`-show` *mode* + + Open rofi in a certain mode. + + For example to show the run-dialog: + + rofi -show run + + This function deprecates -rnow,-snow and -now + +`-switchers` *mode1,mode1* + + Give a comma separated list of modes to enable, in what order. + + For example to only show the run and ssh dialog (in that order): + + rofi -switchers "run,ssh" -show run + + Custom modes can be added using the internal 'script' mode. Each mode has two parameters: + + <name>:<script> + + So to have a mode 'Workspaces' using the `i3_switch_workspace.sh` script type: + + rofi -switchers "window,run,ssh,Workspaces:i3_switch_workspaces.sh" -show Workspaces + Switch between modi ------------------- -Type '?' *enter* to switch between window list, run and ssh mode. +Type '?' *enter* to switch between window list, run and ssh mode. The list can be customized with +the `-switchers` argument. WEBSITE ------- @@ -9,10 +9,10 @@ rofi \- A window switcher, run dialog and dmenu replacement [ \-terminal \fIterminal\fP ] [ \-loc \fIposition\fP ] [ \-hmode ] [ \-fixed\-num\-lines ] [ \-padding \fIpadding\fP ] [ \-opacity \fIopacity%\fP ] [ \-display \fIdisplay\fP ] [ \-bc \fIcolor\fP ] [ \-bw \fIwidth\fP ] [ \-dmenu [ \-p \fIprompt\fP ] ] [ \-ssh\-set\-title \fItrue|false\fP ] [ \-now ] [ \-rnow ] [ \-snow ] [ \-version ] [ \-help] [ \-dump\-xresources ] -[ \-disable\-history ] [ \-levenshtein\-sort ] +[ \-disable\-history ] [ \-levenshtein\-sort ] [ \-show \fImode\fP ] [ \-switcher \fImode1,mode2\fP ] .SH DESCRIPTION .PP -\fB\fCrofi\fR is an X11 popup window switcher. A list is displayed center\-screen showing open window titles, WM_CLASS, and desktop number. +\fB\fCrofi\fR is an X11 popup window switcher. A list is displayed center\-screen showing open window titles, WM_CLASS, and desktop number. The user may filter the list by typing, navigate with Up/Down or Tab keys, and select a window with Return (Enter). Escape cancels. .SH License .PP @@ -262,9 +262,52 @@ Disable history \fB\fC\-levenshtein\-sort\fR .IP When searching sort the result based on levenshtein distance. +.PP +\fB\fC\-show\fR \fImode\fP +.IP +Open rofi in a certain mode. +.IP +For example to show the run\-dialog: +.PP +.RS +.nf + rofi \-show run +.fi +.RE +.IP +This function deprecates \-rnow,\-snow and \-now +.PP +\fB\fC\-switchers\fR \fImode1,mode1\fP +.IP +Give a comma separated list of modes to enable, in what order. +.IP +For example to only show the run and ssh dialog (in that order): +.PP +.RS +.nf + rofi \-switchers "run,ssh" \-show run +.fi +.RE +.IP +Custom modes can be added using the internal 'script' mode. Each mode has two parameters: +.PP +.RS +.nf + <name>:<script> +.fi +.RE +.IP +So to have a mode 'Workspaces' using the \fB\fCi3_switch_workspace.sh\fR script type: +.PP +.RS +.nf + rofi \-switchers "window,run,ssh,Workspaces:i3_switch_workspaces.sh" \-show Workspaces +.fi +.RE .SH Switch between modi .PP -Type '?' \fIenter\fP to switch between window list, run and ssh mode. +Type '?' \fIenter\fP to switch between window list, run and ssh mode. The list can be customized with +the \fB\fC\-switchers\fR argument. .SH WEBSITE .PP \fB\fCrofi\fR website can be found at here diff --git a/include/dmenu-dialog.h b/include/dmenu-dialog.h index ff04a66a..4c22a2e0 100644 --- a/include/dmenu-dialog.h +++ b/include/dmenu-dialog.h @@ -2,6 +2,6 @@ #define __DMENU_DIALOG_H__ extern char *dmenu_prompt; -SwitcherMode dmenu_switcher_dialog ( char **input ); +SwitcherMode dmenu_switcher_dialog ( char **input, void *data ); #endif diff --git a/include/rofi.h b/include/rofi.h index 8fd61b13..f6854636 100644 --- a/include/rofi.h +++ b/include/rofi.h @@ -19,27 +19,24 @@ extern const char *cache_dir; + /** * Enum used to sum the possible states of ROFI. */ typedef enum { - /** Show the window switcher */ - WINDOW_SWITCHER, - /** Show the run dialog */ - RUN_DIALOG, - /** Show the ssh dialog */ - SSH_DIALOG, - /** Number of cycle-able dialogs */ - NUM_DIALOGS, /** Dmenu mode */ - DMENU_DIALOG, + DMENU_DIALOG = 999, /** Exit. */ - MODE_EXIT, + MODE_EXIT = 1000, /** Skip to the next cycle-able dialog. */ - NEXT_DIALOG + NEXT_DIALOG = 1001, + /** Reload current DIALOG */ + RELOAD_DIALOG = 1002 } SwitcherMode; +// switcher callback +typedef SwitcherMode ( *switcher_callback )( char **input, void *data ); /** * State returned by the rofi window. @@ -105,6 +102,7 @@ typedef enum _WindowLocation typedef struct _Settings { + char *switchers; // Window settings unsigned int window_opacity; // Menu settings diff --git a/include/run-dialog.h b/include/run-dialog.h index cbbce06c..d481ca5d 100644 --- a/include/run-dialog.h +++ b/include/run-dialog.h @@ -3,6 +3,6 @@ -SwitcherMode run_switcher_dialog ( char **input ); +SwitcherMode run_switcher_dialog ( char **input, void *data ); #endif diff --git a/include/script-dialog.h b/include/script-dialog.h new file mode 100644 index 00000000..94d66f2e --- /dev/null +++ b/include/script-dialog.h @@ -0,0 +1,28 @@ +#ifndef __SCRIPT_DIALOG_H__ +#define __SCRIPT_DIALOG_H__ + +/** + * Structure holds the arguments for the script_switcher. + */ +typedef struct +{ + // Prompt to display. + char *name; + // The script + char *script_path; +} ScriptOptions; + +SwitcherMode script_switcher_dialog ( char **input, void *data ); + +/** + * Parse an argument string into the right ScriptOptions data object. + * This is off format: <Name>:<Script> + * Return NULL when it fails. + */ +ScriptOptions *script_switcher_parse_setup ( const char *str ); + +/** + * Free the ScriptOptions block. + */ +void script_switcher_free_options ( ScriptOptions *sw ); +#endif diff --git a/include/ssh-dialog.h b/include/ssh-dialog.h index 0539bc2f..6dffb1d9 100644 --- a/include/ssh-dialog.h +++ b/include/ssh-dialog.h @@ -3,6 +3,6 @@ -SwitcherMode ssh_switcher_dialog ( char **input ); +SwitcherMode ssh_switcher_dialog ( char **input, void *data ); #endif diff --git a/include/textbox.h b/include/textbox.h index e3b7b87c..18681acd 100644 --- a/include/textbox.h +++ b/include/textbox.h @@ -19,12 +19,12 @@ typedef struct typedef enum { - TB_AUTOHEIGHT = 1 << 0, - TB_AUTOWIDTH = 1 << 1, - TB_LEFT = 1 << 16, - TB_RIGHT = 1 << 17, - TB_CENTER = 1 << 18, - TB_EDITABLE = 1 << 19, + TB_AUTOHEIGHT = 1 << 0, + TB_AUTOWIDTH = 1 << 1, + TB_LEFT = 1 << 16, + TB_RIGHT = 1 << 17, + TB_CENTER = 1 << 18, + TB_EDITABLE = 1 << 19, } TextboxFlags; typedef enum diff --git a/source/dmenu-dialog.c b/source/dmenu-dialog.c index 92b7eb09..70907bdb 100644 --- a/source/dmenu-dialog.c +++ b/source/dmenu-dialog.c @@ -65,7 +65,7 @@ static char **get_dmenu ( unsigned int *length ) return retv; } -SwitcherMode dmenu_switcher_dialog ( char **input ) +SwitcherMode dmenu_switcher_dialog ( char **input, void *data ) { int selected_line = 0; SwitcherMode retv = MODE_EXIT; @@ -76,7 +76,7 @@ SwitcherMode dmenu_switcher_dialog ( char **input ) token_match, NULL, &selected_line ); if ( mretv == MENU_NEXT ) { - retv = DMENU_DIALOG; + retv = RELOAD_DIALOG; } else if ( mretv == MENU_OK && list[selected_line] != NULL ) { fputs ( list[selected_line], stdout ); diff --git a/source/rofi.c b/source/rofi.c index 57091de2..b1b705d3 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -65,6 +65,7 @@ #include "run-dialog.h" #include "ssh-dialog.h" #include "dmenu-dialog.h" +#include "script-dialog.h" #include "xrmoptions.h" @@ -85,6 +86,48 @@ char *active_font = NULL; unsigned int NumlockMask = 0; Display *display = NULL; + +typedef struct _Switcher +{ + char name[32]; + switcher_callback cb; + void *cb_data; +} Switcher; + +Switcher *switchers = NULL; +int num_switchers = 0; + +int switcher_get ( const char *name ) +{ + for ( int i = 0; i < num_switchers; i++ ) { + if ( strcmp ( switchers[i].name, name ) == 0 ) { + return i; + } + } + return -1; +} + + +/** + * Not every platform has strlcpy. (Why god why?) + * So a quick implementation to fix this. + */ +static size_t copy_string ( char *dest, const char *src, size_t len ) +{ + size_t size; + + if ( !len ) { + return 0; + } + size = strlen ( src ); + if ( size >= len ) { + size = len - 1; + } + memcpy ( dest, src, size ); + dest[size] = '\0'; + return size; +} + /** * Shared 'token_match' function. * Matches tokenized. @@ -219,22 +262,26 @@ static int find_arg ( const int argc, char * const argv[], const char * const ke return i < argc ? i : -1; } -static void find_arg_str ( int argc, char *argv[], char *key, char** val ) +static int find_arg_str ( int argc, char *argv[], char *key, char** val ) { int i = find_arg ( argc, argv, key ); if ( val != NULL && i > 0 && i < argc - 1 ) { *val = argv[i + 1]; + return TRUE; } + return FALSE; } -static void find_arg_int ( int argc, char *argv[], char *key, unsigned int *val ) +static int find_arg_int ( int argc, char *argv[], char *key, unsigned int *val ) { int i = find_arg ( argc, argv, key ); if ( val != NULL && i > 0 && i < ( argc - 1 ) ) { *val = strtol ( argv[i + 1], NULL, 10 ); + return TRUE; } + return FALSE; } @@ -1333,8 +1380,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom if ( shift != NULL ) { ( *shift ) = ( ( ev.xkey.state & ShiftMask ) == ShiftMask ); } - - if ( filtered && filtered[selected] ) { + if ( filtered[selected] != NULL ) { retv = MENU_OK; *selected_line = line_map[selected]; } @@ -1490,7 +1536,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom return retv; } -SwitcherMode run_switcher_window ( char **input ) +SwitcherMode run_switcher_window ( char **input, void *data ) { Screen *screen = DefaultScreenOfDisplay ( display ); Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) ); @@ -1662,31 +1708,29 @@ static void run_switcher ( int do_fork, SwitcherMode mode ) config.menu_hlbg, config.menu_hlfg ); char *input = NULL; + // Dmenu is a special mode. You can cycle away from it. + if ( mode == DMENU_DIALOG ) { + dmenu_switcher_dialog ( &input, NULL ); + } + // Otherwise check if requested mode is enabled. + else if ( switchers[mode].cb != NULL ) { + do { + SwitcherMode retv = MODE_EXIT; - do { - SwitcherMode retv = MODE_EXIT; - - if ( mode == WINDOW_SWITCHER ) { - retv = run_switcher_window ( &input ); - } - else if ( mode == RUN_DIALOG ) { - retv = run_switcher_dialog ( &input ); - } - else if ( mode == SSH_DIALOG ) { - retv = ssh_switcher_dialog ( &input ); - } - else if ( mode == DMENU_DIALOG ) { - retv = dmenu_switcher_dialog ( &input ); - } - - if ( retv == NEXT_DIALOG ) { - mode = ( mode + 1 ) % NUM_DIALOGS; - } - else{ - mode = retv; - } - } while ( mode != MODE_EXIT ); + retv = switchers[mode].cb ( &input, switchers[mode].cb_data ); + // Find next enabled + if ( retv == NEXT_DIALOG ) { + mode = ( mode + 1 ) % num_switchers; + } + else if ( retv == RELOAD_DIALOG ) { + // do nothing. + } + else { + mode = retv; + } + } while ( mode != MODE_EXIT ); + } free ( input ); // Cleanup font setup. @@ -1704,17 +1748,26 @@ static void handle_keypress ( XEvent *ev ) if ( ( windows_modmask == AnyModifier || ev->xkey.state & windows_modmask ) && key == windows_keysym ) { - run_switcher ( TRUE, WINDOW_SWITCHER ); + int index = switcher_get ( "window" ); + if ( index >= 0 ) { + run_switcher ( TRUE, index ); + } } if ( ( rundialog_modmask == AnyModifier || ev->xkey.state & rundialog_modmask ) && key == rundialog_keysym ) { - run_switcher ( TRUE, RUN_DIALOG ); + int index = switcher_get ( "run" ); + if ( index >= 0 ) { + run_switcher ( TRUE, index ); + } } if ( ( sshdialog_modmask == AnyModifier || ev->xkey.state & sshdialog_modmask ) && key == sshdialog_keysym ) { - run_switcher ( TRUE, SSH_DIALOG ); + int index = switcher_get ( "ssh" ); + if ( index >= 0 ) { + run_switcher ( TRUE, index ); + } } } @@ -1836,6 +1889,7 @@ static void parse_cmd_options ( int argc, char ** argv ) exit ( EXIT_SUCCESS ); } + find_arg_str ( argc, argv, "-switchers", &( config.switchers ) ); // Parse commandline arguments about the looks. find_arg_int ( argc, argv, "-opacity", &( config.window_opacity ) ); @@ -1933,6 +1987,14 @@ static void cleanup () xdgWipeHandle ( &xdg_handle ); free ( active_font ); + + for ( unsigned int i = 0; i < num_switchers; i++ ) { + // only used for script dialog. + if ( switchers[i].cb_data != NULL ) { + script_switcher_free_options ( switchers[i].cb_data ); + } + } + free ( switchers ); } /** @@ -1966,6 +2028,51 @@ static void config_sanity_check ( void ) } } +static void setup_switchers ( void ) +{ + char *switcher_str = strdup ( config.switchers ); + char *token; + for ( token = strtok ( switcher_str, "," ); token != NULL; token = strtok ( NULL, "," ) ) { + if ( strcasecmp ( token, "window" ) == 0 ) { + switchers = (Switcher *) realloc ( switchers, sizeof ( Switcher ) * ( num_switchers + 1 ) ); + copy_string ( switchers[num_switchers].name, "window", 32 ); + switchers[num_switchers].cb = run_switcher_window; + switchers[num_switchers].cb_data = NULL; + num_switchers++; + } + else if ( strcasecmp ( token, "ssh" ) == 0 ) { + switchers = (Switcher *) realloc ( switchers, sizeof ( Switcher ) * ( num_switchers + 1 ) ); + copy_string ( switchers[num_switchers].name, "ssh", 32 ); + switchers[num_switchers].cb = ssh_switcher_dialog; + switchers[num_switchers].cb_data = NULL; + num_switchers++; + } + else if ( strcasecmp ( token, "run" ) == 0 ) { + switchers = (Switcher *) realloc ( switchers, sizeof ( Switcher ) * ( num_switchers + 1 ) ); + copy_string ( switchers[num_switchers].name, "run", 32 ); + switchers[num_switchers].cb = run_switcher_dialog; + switchers[num_switchers].cb_data = NULL; + num_switchers++; + } + else { + ScriptOptions *sw = script_switcher_parse_setup ( token ); + if ( sw != NULL ) { + switchers = (Switcher *) realloc ( switchers, sizeof ( Switcher ) * ( num_switchers + 1 ) ); + copy_string ( switchers[num_switchers].name, sw->name, 32 ); + switchers[num_switchers].cb = script_switcher_dialog; + switchers[num_switchers].cb_data = sw; + num_switchers++; + } + else{ + fprintf ( stderr, "Invalid script switcher: %s\n", token ); + token = NULL; + } + } + } + + free ( switcher_str ); +} + int main ( int argc, char *argv[] ) { @@ -1999,6 +2106,9 @@ int main ( int argc, char *argv[] ) // Sanity check config_sanity_check (); + // setup_switchers + setup_switchers (); + // Generate the font string for the line that indicates a selected item. if ( asprintf ( &active_font, "%s:slant=italic", config.menu_font ) < 0 ) { fprintf ( stderr, "Failed to construct active string: %s\n", strerror ( errno ) ); @@ -2043,14 +2153,43 @@ int main ( int argc, char *argv[] ) // flags to run immediately and exit - if ( find_arg ( argc, argv, "-now" ) >= 0 ) { - run_switcher ( FALSE, WINDOW_SWITCHER ); + char *sname = NULL; + if ( find_arg_str ( argc, argv, "-show", &sname ) == TRUE ) { + int index = switcher_get ( sname ); + if ( index >= 0 ) { + run_switcher ( FALSE, index ); + } + else { + 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 ) { - run_switcher ( FALSE, RUN_DIALOG ); + 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 ) { - run_switcher ( FALSE, SSH_DIALOG ); + int index = switcher_get ( "ssh" ); + if ( index >= 0 ) { + run_switcher ( FALSE, index ); + } + else { + fprintf ( stderr, "The ssh dialog has not been enabled\n" ); + } } else if ( find_arg ( argc, argv, "-dmenu" ) >= 0 ) { find_arg_str ( argc, argv, "-p", &dmenu_prompt ); @@ -2058,14 +2197,20 @@ int main ( int argc, char *argv[] ) } else{ // Daemon mode, Listen to key presses.. - parse_key ( display, config.window_key, &windows_modmask, &windows_keysym ); - grab_key ( display, windows_modmask, windows_keysym ); + if ( switcher_get ( "window" ) >= 0 ) { + parse_key ( display, config.window_key, &windows_modmask, &windows_keysym ); + grab_key ( display, windows_modmask, windows_keysym ); + } - parse_key ( display, config.run_key, &rundialog_modmask, &rundialog_keysym ); - grab_key ( display, rundialog_modmask, rundialog_keysym ); + if ( switcher_get ( "run" ) >= 0 ) { + parse_key ( display, config.run_key, &rundialog_modmask, &rundialog_keysym ); + grab_key ( display, rundialog_modmask, rundialog_keysym ); + } - parse_key ( display, config.ssh_key, &sshdialog_modmask, &sshdialog_keysym ); - grab_key ( display, sshdialog_modmask, sshdialog_keysym ); + if ( switcher_get ( "ssh" ) >= 0 ) { + parse_key ( display, config.ssh_key, &sshdialog_modmask, &sshdialog_keysym ); + grab_key ( display, sshdialog_modmask, sshdialog_keysym ); + } // Main loop for (;; ) { diff --git a/source/run-dialog.c b/source/run-dialog.c index 70712078..3237201b 100644 --- a/source/run-dialog.c +++ b/source/run-dialog.c @@ -198,7 +198,7 @@ static char ** get_apps ( unsigned int *length ) return retv; } -SwitcherMode run_switcher_dialog ( char **input ) +SwitcherMode run_switcher_dialog ( char **input, void *data ) { int shift = 0; int selected_line = 0; @@ -226,7 +226,7 @@ SwitcherMode run_switcher_dialog ( char **input ) } else if ( mretv == MENU_ENTRY_DELETE && cmd_list[selected_line] ) { delete_entry ( cmd_list[selected_line] ); - retv = RUN_DIALOG; + retv = RELOAD_DIALOG; } for ( int i = 0; cmd_list != NULL && cmd_list[i] != NULL; i++ ) { diff --git a/source/script-dialog.c b/source/script-dialog.c new file mode 100644 index 00000000..a43234e1 --- /dev/null +++ b/source/script-dialog.c @@ -0,0 +1,201 @@ +/** + * rofi + * + * MIT/X11 License + * Copyright 2013-2014 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. + * + */ + + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <strings.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include "rofi.h" +#include "script-dialog.h" + + + +pid_t execute_generator ( char * cmd ) +{ + int filedes[2]; + pid_t pid; + + + if ( -1 == pipe ( filedes ) ) { + perror ( "pipe failed" ); + return 0; + } + + switch ( pid = fork () ) + { + case -1: + perror ( "Failed to fork, executing generator failed" ); + pid = 0; + break; + + case 0: /* child */ + close ( 1 ); + dup ( filedes[1] ); + close ( filedes[1] ); + execlp ( "/bin/sh", "sh", "-c", cmd, NULL ); + perror ( cmd ); + break; + + default: /* parent */ + close ( 0 ); + dup ( filedes[0] ); + close ( filedes[0] ); + close ( filedes[1] ); + break; + } + + return pid; +} + + +static char **get_script_output ( char *command, unsigned int *length ) +{ + char buffer[1024]; + char **retv = NULL; + + *length = 0; + execute_generator ( command ); + while ( fgets ( buffer, 1024, stdin ) != NULL ) { + char **tr = realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) ); + if ( tr == NULL ) { + return retv; + } + retv = tr; + retv[( *length )] = strdup ( buffer ); + retv[( *length ) + 1] = NULL; + + // Filter out line-end. + if ( retv[( *length )][strlen ( buffer ) - 1] == '\n' ) { + retv[( *length )][strlen ( buffer ) - 1] = '\0'; + } + + ( *length )++; + } + + return retv; +} + +char **execute_executor ( ScriptOptions *options, const char *result, unsigned int *length ) +{ + char **retv = NULL; + char *command; + if ( asprintf ( &command, "%s %s", options->script_path, result ) > 0 ) { + retv = get_script_output ( command, length ); + free ( command ); + } + return retv; +} + +SwitcherMode script_switcher_dialog ( char **input, void *data ) +{ + ScriptOptions *options = (ScriptOptions *) data; + assert ( options != NULL ); + int selected_line = 0; + SwitcherMode retv = MODE_EXIT; + unsigned int length = 0; + char **list = get_script_output ( options->script_path, &length ); + + + do { + unsigned int new_length = 0; + char **new_list = NULL; + int mretv = menu ( list, length, input, options->name, NULL, NULL, + token_match, NULL, &selected_line ); + + if ( mretv == MENU_NEXT ) { + retv = NEXT_DIALOG; + } + else if ( mretv == MENU_OK && list[selected_line] != NULL ) { + new_list = execute_executor ( options, list[selected_line], &new_length ); + } + else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' ) { + new_list = execute_executor ( options, *input, &new_length ); + } + + // Free old list. + for ( unsigned int i = 0; i < length; i++ ) { + free ( list[i] ); + } + + if ( list != NULL ) { + free ( list ); + list = NULL; + } + // If a new list was generated, use that an loop around. + if ( new_list != NULL ) { + list = new_list; + length = new_leng |