1
0
Fork 0
mirror of https://github.com/davatorium/rofi.git synced 2025-04-14 17:43:01 -04:00

Improve run-dialog options.

This commit is contained in:
Qball Cow 2014-01-14 06:36:12 +01:00
parent eaee941bfd
commit b1d5e6a686
3 changed files with 168 additions and 105 deletions

View file

@ -7,8 +7,8 @@ Pringle](http://github.com/seanpringle/simpleswitcher). All credit for this grea
* Switcher centered on screen (or monitor for multi-head).
* Vertical list with two columns:
2. Window class.
3. Window title.
1. Window class.
2. Window title.
* Controls like dmenu:
* Type to filter windows.
@ -16,6 +16,12 @@ Pringle](http://github.com/seanpringle/simpleswitcher). All credit for this grea
* Arrows to highlight selections.
* Return to select.
* Rudimentary run dialog
* Type to filter.
* Tokonized filter. Type any word in any order to filter.
* Arrows to highlight selections.
* Return to select.
* Runs in background or once-off.
If compiled with I3 support, it should autodetect if I3 window manager is running.

View file

@ -22,6 +22,7 @@ simpleswitcher \- a simple EWMH window switcher
.RB [ \-dkey
.IR comdo ]
.RB [ \-now ]
.RB [ \-rnow ]
.SH DESCRIPTION
.I simpleswitcher
@ -34,8 +35,8 @@ See options below for custom key combinations. These are the defaults.
.B F12
Show all windows on all desktops.
.TP
.B F11
Show windows from the current desktop.
.B mod1-F2
Show run-dialog.
.SH OPTIONS
.TP
.B -key
@ -49,20 +50,23 @@ simpleswitcher -key control+shift+s
simpleswitcher -key mod1+Tab
.RE
.TP
.B -dkey
Change the key combination to display window on the current desktop (default: F11).
.B -rkey
Change the key combination to display the run dialog (default: mod1-F2).
.P
.RS
simpleswitcher -key F11
simpleswitcher -rkey F11
.br
simpleswitcher -key control+shift+d
simpleswitcher -rkey control+shift+d
.br
simpleswitcher -key mod1+grave (grave=backtick)
simpleswitcher -rkey mod1+grave (grave=backtick)
.RE
.TP
.B -now
Run simpleswitcher in all-windows mode once then exit. Does not bind any keys.
.TP
.B -rnow
Run simpleswitcher in run-dialog mode once then exit. Does not bind any keys.
.TP
.B -bg
Set the background text color (X11 named color or hex #rrggbb) for the menu (default: #222222).
.P
@ -136,3 +140,4 @@ simpleswitcher -width 60
.BR simpleswitcher (1)
.SH AUTHOR
Sean Pringle <sean.pringle@gmail.com>
Qball Cow <qball@gmpclient.org>

View file

@ -725,6 +725,8 @@ client* window_client( Window win )
unsigned int windows_modmask;
KeySym windows_keysym;
unsigned int rundialog_modmask;
KeySym rundialog_keysym;
// flags to set if we switch modes on the fly
Window main_window = None;
@ -930,6 +932,7 @@ int menu( char **lines, char **input, char *prompt, int selected, Time *time )
if ( key == XK_Escape
// pressing one of the global key bindings closes the switcher. this allows fast closing of the menu if an item is not selected
|| ( ( windows_modmask == AnyModifier || ev.xkey.state & windows_modmask ) && key == windows_keysym )
|| ( ( rundialog_modmask == AnyModifier || ev.xkey.state & rundialog_modmask ) && key == rundialog_keysym )
) {
aborted = 1;
break;
@ -994,31 +997,44 @@ int menu( char **lines, char **input, char *prompt, int selected, Time *time )
static char ** get_apps ( )
{
if(getenv("PATH") == NULL) return NULL;
char *path = strdup(getenv("PATH"));
if ( getenv( "PATH" ) == NULL ) return NULL;
char *path = strdup( getenv( "PATH" ) );
char **retv = NULL;
int index = 0;
for(const char *dirname = strtok(path, ":"); dirname != NULL; dirname = strtok(NULL, ":"))
{
DIR *dir = opendir(dirname);
if(dir != NULL) {
for ( const char *dirname = strtok( path, ":" ); dirname != NULL; dirname = strtok( NULL, ":" ) ) {
DIR *dir = opendir( dirname );
if ( dir != NULL ) {
struct dirent *dent;
while((dent=readdir(dir))!=NULL)
{
if(dent->d_name[0] == '.') continue;
while ( ( dent=readdir( dir ) )!=NULL ) {
if ( dent->d_name[0] == '.' ) continue;
retv = realloc( retv, ( index+2 )*sizeof( char* ) );
retv[index] = strdup( dent->d_name );
retv[index+1] = NULL;
index++;
}
closedir(dir);
closedir( dir );
}
}
free(path);
free( path );
return retv;
}
typedef enum {
WINDOW_SWITCHER,
RUN_DIALOG,
MODE_EXIT
} SwitcherMode;
SwitcherMode mode = WINDOW_SWITCHER;
void run_switcher( int fmode )
{
// TODO: this whole function is messy. build a nicer solution
@ -1035,121 +1051,133 @@ void run_switcher( int fmode )
XSync( display, True );
}
{
do {
if ( mode == WINDOW_SWITCHER ) {
char pattern[50], **list = NULL;
int i, plen = 0, lines = 0;
unsigned int classfield = 0;
unsigned long desktops = 0, current_desktop = 0;
Window w;
client *c;
char pattern[50], **list = NULL;
int i, plen = 0, lines = 0;
unsigned int classfield = 0;
unsigned long desktops = 0, current_desktop = 0;
Window w;
client *c;
// windows we actually display. may be slightly different to _NET_CLIENT_LIST_STACKING
// if we happen to have a window destroyed while we're working...
winlist *ids = winlist_new();
mode = MODE_EXIT;
// windows we actually display. may be slightly different to _NET_CLIENT_LIST_STACKING
// if we happen to have a window destroyed while we're working...
winlist *ids = winlist_new();
if ( !window_get_cardinal_prop( root, netatoms[_NET_CURRENT_DESKTOP], &current_desktop, 1 ) )
current_desktop = 0;
if ( !window_get_cardinal_prop( root, netatoms[_NET_CURRENT_DESKTOP], &current_desktop, 1 ) )
current_desktop = 0;
// find window list
Atom type;
int nwins;
unsigned long *wins = allocate_clear( sizeof( unsigned long ) * 100 );
// find window list
Atom type;
int nwins;
unsigned long *wins = allocate_clear( sizeof( unsigned long ) * 100 );
if ( window_get_prop( root, netatoms[_NET_CLIENT_LIST_STACKING], &type, &nwins, wins, 100 * sizeof( unsigned long ) )
&& type == XA_WINDOW ) {
// calc widths of fields
for ( i = nwins-1; i > -1; i-- ) {
if ( ( c = window_client( wins[i] ) )
&& !c->xattr.override_redirect
&& !client_has_state( c, netatoms[_NET_WM_STATE_SKIP_PAGER] )
&& !client_has_state( c, netatoms[_NET_WM_STATE_SKIP_TASKBAR] ) ) {
classfield = MAX( classfield, strlen( c->class ) );
if ( window_get_prop( root, netatoms[_NET_CLIENT_LIST_STACKING], &type, &nwins, wins, 100 * sizeof( unsigned long ) )
&& type == XA_WINDOW ) {
// calc widths of fields
for ( i = nwins-1; i > -1; i-- ) {
if ( ( c = window_client( wins[i] ) )
&& !c->xattr.override_redirect
&& !client_has_state( c, netatoms[_NET_WM_STATE_SKIP_PAGER] )
&& !client_has_state( c, netatoms[_NET_WM_STATE_SKIP_TASKBAR] ) ) {
classfield = MAX( classfield, strlen( c->class ) );
#ifdef I3
// In i3 mode, skip the i3bar completely.
if ( config_i3_mode && strstr( c->class, "i3bar" ) != NULL ) continue;
// In i3 mode, skip the i3bar completely.
if ( config_i3_mode && strstr( c->class, "i3bar" ) != NULL ) continue;
#endif
winlist_append( ids, c->window, NULL );
winlist_append( ids, c->window, NULL );
}
}
}
if ( !window_get_cardinal_prop( root, netatoms[_NET_NUMBER_OF_DESKTOPS], &desktops, 1 ) )
desktops = 1;
if ( !window_get_cardinal_prop( root, netatoms[_NET_NUMBER_OF_DESKTOPS], &desktops, 1 ) )
desktops = 1;
plen += sprintf( pattern+plen, "%%-%ds %%s", MAX( 5, classfield ) );
list = allocate_clear( sizeof( char* ) * ( ids->len+1 ) );
lines = 0;
plen += sprintf( pattern+plen, "%%-%ds %%s", MAX( 5, classfield ) );
list = allocate_clear( sizeof( char* ) * ( ids->len+1 ) );
lines = 0;
// build the actual list
winlist_ascend( ids, i, w ) {
if ( ( c = window_client( w ) ) ) {
// final line format
char *line = allocate( strlen( c->title ) + strlen( c->class ) + classfield + 50 );
// build the actual list
winlist_ascend( ids, i, w ) {
if ( ( c = window_client( w ) ) ) {
// final line format
char *line = allocate( strlen( c->title ) + strlen( c->class ) + classfield + 50 );
sprintf( line, pattern, c->class, c->title );
sprintf( line, pattern, c->class, c->title );
list[lines++] = line;
list[lines++] = line;
}
}
}
char *input = NULL;
Time time;
int n = menu( list, &input, "> ", 1, &time );
char *input = NULL;
Time time;
int n = menu( list, &input, "> ", 1, &time );
if ( n >= 0 && list[n] ) {
if ( input != NULL && input[0] == '!' ) {
mode = RUN_DIALOG;
} else if ( n >= 0 && list[n] ) {
// Normally we want to exit.
#ifdef I3
if ( config_i3_mode ) {
// Hack for i3.
focus_window_i3( i3_socket_path,ids->array[n] );
} else
if ( config_i3_mode ) {
// Hack for i3.
focus_window_i3( i3_socket_path,ids->array[n] );
} else
#endif
{
if ( isdigit( list[n][0] ) ) {
// TODO: get rid of strtol
window_send_message( root, root, netatoms[_NET_CURRENT_DESKTOP], strtol( list[n], NULL, 10 )-1,
{
if ( isdigit( list[n][0] ) ) {
// TODO: get rid of strtol
window_send_message( root, root, netatoms[_NET_CURRENT_DESKTOP], strtol( list[n], NULL, 10 )-1,
SubstructureNotifyMask | SubstructureRedirectMask, time );
XSync( display, False );
}
window_send_message( root, ids->array[n], netatoms[_NET_ACTIVE_WINDOW], 2, // 2 = pager
SubstructureNotifyMask | SubstructureRedirectMask, time );
XSync( display, False );
}
window_send_message( root, ids->array[n], netatoms[_NET_ACTIVE_WINDOW], 2, // 2 = pager
SubstructureNotifyMask | SubstructureRedirectMask, time );
}
} else
// act as a launcher
if ( input ) {
char **cmd_list = get_apps( );
if(cmd_list == NULL) {
cmd_list = allocate(2*sizeof(char *));
cmd_list[0] = strdup("No applications found");
cmd_list[1] = NULL;
}
int n = menu( cmd_list, &input, "$ ", 0, &time );
if ( n >=0 && cmd_list[n] != NULL ) {
exec_cmd( cmd_list[n] );
}
for ( i=0; cmd_list[i] != NULL; i++ ) {
free( cmd_list[i] );
}
free( cmd_list );
}
}
for ( i = 0; i < lines; i++ )
free( list[i] );
free( list );
}
free( wins );
winlist_free( ids );
}
free( wins );
winlist_free( ids );
} else if ( mode == RUN_DIALOG ) {
Time time;
char *input = NULL;
mode = MODE_EXIT;
// act as a launcher
char **cmd_list = get_apps( );
if ( cmd_list == NULL ) {
cmd_list = allocate( 2*sizeof( char * ) );
cmd_list[0] = strdup( "No applications found" );
cmd_list[1] = NULL;
}
int n = menu( cmd_list, &input, "$ ", 0, &time );
if ( input != NULL && *input == '>' ) {
mode = WINDOW_SWITCHER;
} else if ( n >=0 && cmd_list[n] != NULL ) {
exec_cmd( cmd_list[n] );
}
for ( int i=0; cmd_list[i] != NULL; i++ ) {
free( cmd_list[i] );
}
free( cmd_list );
}
} while ( mode != MODE_EXIT );
if ( fmode == FORK )
exit( EXIT_SUCCESS );
@ -1160,8 +1188,17 @@ void handle_keypress( XEvent *ev )
{
KeySym key = XkbKeycodeToKeysym( display, ev->xkey.keycode, 0, 0 );
if ( ( windows_modmask == AnyModifier || ev->xkey.state & windows_modmask ) && key == windows_keysym )
if ( ( windows_modmask == AnyModifier || ev->xkey.state & windows_modmask ) &&
key == windows_keysym ) {
mode = WINDOW_SWITCHER;
run_switcher( FORK );
}
if ( ( rundialog_modmask == AnyModifier || ev->xkey.state & rundialog_modmask ) &&
key == rundialog_keysym ) {
mode = RUN_DIALOG;
run_switcher( FORK );
}
}
// convert a Mod+key arg to mod mask and keysym
@ -1175,6 +1212,8 @@ void parse_key( char *combo, unsigned int *mod, KeySym *key )
if ( strcasestr( combo, "mod1" ) ) modmask |= Mod1Mask;
if ( strcasestr( combo, "alt" ) ) modmask |= Mod1Mask;
if ( strcasestr( combo, "mod2" ) ) modmask |= Mod2Mask;
if ( strcasestr( combo, "mod3" ) ) modmask |= Mod3Mask;
@ -1303,6 +1342,17 @@ int main( int argc, char *argv[] )
if ( i3_socket_path != NULL ) free( i3_socket_path );
#endif
exit( EXIT_SUCCESS );
}
if ( find_arg( ac, av, "-rnow" ) >= 0 ) {
mode = RUN_DIALOG;
run_switcher( NOFORK );
#ifdef I3
if ( i3_socket_path != NULL ) free( i3_socket_path );
#endif
exit( EXIT_SUCCESS );
}
@ -1311,10 +1361,12 @@ int main( int argc, char *argv[] )
// key combination to display all windows from all desktops
parse_key( find_arg_str( ac, av, "-key", "F12" ), &windows_modmask, &windows_keysym );
parse_key( find_arg_str( ac, av, "-rkey", "mod1+F2" ), &rundialog_modmask, &rundialog_keysym );
// bind key combos
grab_key( windows_modmask, windows_keysym );
grab_key( rundialog_modmask, rundialog_keysym );
XEvent ev;