mirror of
https://github.com/lbonn/rofi
synced 2024-11-10 14:24:27 +00:00
* Add script_dialog, so user can add dialogs using a script. * Add a way to disable modi's * Add -show <modi> option.
This commit is contained in:
parent
d584987c81
commit
cd4888a5cf
17 changed files with 544 additions and 73 deletions
22
Examples/i3_switch_workspaces.sh
Executable file
22
Examples/i3_switch_workspaces.sh
Executable file
|
@ -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
|
|
@ -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
|
||||
|
||||
##
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -14,7 +14,7 @@ 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
|
||||
-----------
|
||||
|
@ -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
|
||||
-------
|
||||
|
|
47
doc/rofi.1
47
doc/rofi.1
|
@ -9,7 +9,7 @@ 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.
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
|
||||
|
||||
|
||||
SwitcherMode run_switcher_dialog ( char **input );
|
||||
SwitcherMode run_switcher_dialog ( char **input, void *data );
|
||||
|
||||
#endif
|
||||
|
|
28
include/script-dialog.h
Normal file
28
include/script-dialog.h
Normal file
|
@ -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
|
|
@ -3,6 +3,6 @@
|
|||
|
||||
|
||||
|
||||
SwitcherMode ssh_switcher_dialog ( char **input );
|
||||
SwitcherMode ssh_switcher_dialog ( char **input, void *data );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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 );
|
||||
|
|
199
source/rofi.c
199
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;
|
||||
|
||||
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 );
|
||||
}
|
||||
retv = switchers[mode].cb ( &input, switchers[mode].cb_data );
|
||||
|
||||
// Find next enabled
|
||||
if ( retv == NEXT_DIALOG ) {
|
||||
mode = ( mode + 1 ) % NUM_DIALOGS;
|
||||
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..
|
||||
if ( switcher_get ( "window" ) >= 0 ) {
|
||||
parse_key ( display, config.window_key, &windows_modmask, &windows_keysym );
|
||||
grab_key ( display, windows_modmask, windows_keysym );
|
||||
}
|
||||
|
||||
if ( switcher_get ( "run" ) >= 0 ) {
|
||||
parse_key ( display, config.run_key, &rundialog_modmask, &rundialog_keysym );
|
||||
grab_key ( display, rundialog_modmask, rundialog_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 (;; ) {
|
||||
|
|
|
@ -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++ ) {
|
||||
|
|
201
source/script-dialog.c
Normal file
201
source/script-dialog.c
Normal file
|
@ -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 ) ) {
|
||||
if ( index == 0 ) {
|
||||
sw->name = strdup ( token );
|
||||
}
|
||||
else if ( index == 1 ) {
|
||||
sw->script_path = strdup ( token );
|
||||
}
|
||||
index++;
|
||||
}
|
||||
free ( parse );
|
||||
if ( index == 2 ) {
|
||||
return sw;
|
||||
}
|
||||
fprintf ( stderr, "The script command '%s' has %d options, but needs 2: <name>:<script>.\n",
|
||||
str, index );
|
||||
script_switcher_free_options ( sw );
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -215,7 +215,7 @@ static char ** get_ssh ( unsigned int *length )
|
|||
return retv;
|
||||
}
|
||||
|
||||
SwitcherMode ssh_switcher_dialog ( char **input )
|
||||
SwitcherMode ssh_switcher_dialog ( char **input, void *data )
|
||||
{
|
||||
SwitcherMode retv = MODE_EXIT;
|
||||
// act as a launcher
|
||||
|
@ -244,7 +244,7 @@ SwitcherMode ssh_switcher_dialog ( char **input )
|
|||
else if ( mretv == MENU_ENTRY_DELETE && cmd_list[selected_line] ) {
|
||||
delete_ssh ( cmd_list[selected_line] );
|
||||
// Stay
|
||||
retv = SSH_DIALOG;
|
||||
retv = RELOAD_DIALOG;
|
||||
}
|
||||
|
||||
for ( int i = 0; cmd_list[i] != NULL; i++ ) {
|
||||
|
|
|
@ -58,6 +58,7 @@ typedef struct
|
|||
* Currently supports string and number.
|
||||
*/
|
||||
static XrmOption xrmOptions[] = {
|
||||
{ xrm_String, "switchers", { .str = &config.switchers }, NULL },
|
||||
{ xrm_Number, "opacity", { .num = &config.window_opacity }, NULL },
|
||||
|
||||
{ xrm_Number, "width", { .num = &config.menu_width }, NULL },
|
||||
|
|
Loading…
Reference in a new issue