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:
parent
eaee941bfd
commit
b1d5e6a686
3 changed files with 168 additions and 105 deletions
10
README.md
10
README.md
|
@ -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.
|
||||
|
|
|
@ -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>
|
||||
|
|
244
simpleswitcher.c
244
simpleswitcher.c
|
@ -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], ¤t_desktop, 1 ) )
|
||||
current_desktop = 0;
|
||||
if ( !window_get_cardinal_prop( root, netatoms[_NET_CURRENT_DESKTOP], ¤t_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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue