summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xExamples/i3_switch_workspaces.sh22
-rw-r--r--Makefile.am3
-rw-r--r--config/config.c3
-rw-r--r--doc/rofi-manpage.markdown33
-rw-r--r--doc/rofi.149
-rw-r--r--include/dmenu-dialog.h2
-rw-r--r--include/rofi.h20
-rw-r--r--include/run-dialog.h2
-rw-r--r--include/script-dialog.h28
-rw-r--r--include/ssh-dialog.h2
-rw-r--r--include/textbox.h12
-rw-r--r--source/dmenu-dialog.c4
-rw-r--r--source/rofi.c227
-rw-r--r--source/run-dialog.c4
-rw-r--r--source/script-dialog.c201
-rw-r--r--source/ssh-dialog.c4
-rw-r--r--source/xrmoptions.c1
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
-------
diff --git a/doc/rofi.1 b/doc/rofi.1
index 6775f01e..574c7a17 100644
--- a/doc/rofi.1
+++ b/doc/rofi.1
@@ -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_length;
+ free ( *input );
+ *input = NULL;
+ }
+ } while ( list != NULL );
+
+ return retv;
+}
+
+void script_switcher_free_options ( ScriptOptions *sw )
+{
+ if ( sw == NULL ) {
+ return;
+ }
+ free ( sw->name );
+ free ( sw->script_path );
+ free ( sw );
+}
+
+
+ScriptOptions *script_switcher_parse_setup ( const char *str )
+{
+ ScriptOptions *sw = calloc ( 1, sizeof ( *sw ) );
+ char *endp = NULL;
+ char *parse = strdup ( str );
+ unsigned int index = 0;
+ // TODO: This is naive and can be improved.
+ for ( char *token = strtok_r ( parse, ":", &endp ); token != NULL; token = strtok_r ( NULL, ":", &endp ) )