diff --git a/doc/simpleswitcher.1 b/doc/simpleswitcher.1 index 211a60bb..c538bab0 100644 --- a/doc/simpleswitcher.1 +++ b/doc/simpleswitcher.1 @@ -26,8 +26,11 @@ simpleswitcher \- a simple EWMH window switcher .RB [ \-snow ] .RB [ \-term .IR terminal ] -.RB [ \-loc +.RB [ \-loc .IR position ] +.RB [ \-hmode ] +.RB [ \-padding +.IR padding ] .SH DESCRIPTION .I simpleswitcher @@ -40,7 +43,7 @@ See options below for custom key combinations. These are the defaults. .B F12 Show all windows on all desktops. .TP -.B mod1-F2 +.B mod1-F2 Show run-dialog. .SH OPTIONS .TP @@ -136,7 +139,7 @@ simpleswitcher -fg "#ffffff" .RE .TP .B -o -Set the window opacity (0-100). +Set the window opacity (0-100). .P .RS simpleswitcher -o "75" @@ -174,6 +177,19 @@ monitor: .TP 7 6 5 .RE +.TP +.B -hmode +Switch to horizontal mode (ala dmenu). You can specify the number of elements with the +.IR -lines +option. +.TP +.B -padding +Define the inner margin of the window. Default is 5 pixels. +.RS +To make simpleswitcher look like dmenu: +.TP +simpleswitcher -hmode -padding 0 +.RE .SH Switch between modi Type '?' to switch between window list and run mode. .SH SEE ALSO diff --git a/include/simpleswitcher.h b/include/simpleswitcher.h index 145b44b6..70c1adc8 100644 --- a/include/simpleswitcher.h +++ b/include/simpleswitcher.h @@ -21,6 +21,7 @@ typedef enum { } SwitcherMode; + typedef int ( *menu_match_cb )( char **tokens, const char *input, int index, void *data ); int menu( char **lines, char **input, char *prompt, Time *time, int *shift, menu_match_cb mmc, void *mmc_data ); @@ -48,33 +49,39 @@ typedef enum _WindowLocation { WEST = 8 } WindowLocation; +typedef enum { + VERTICAL = 0, + HORIZONTAL = 1 +} WindowMode; /** * Settings */ typedef struct _Settings { // Window settings - unsigned int window_opacity; + unsigned int window_opacity; // Menu settings - unsigned int menu_bw; - unsigned int menu_width; - unsigned int menu_lines; - char * menu_font; - char * menu_fg; - char * menu_bg; - char * menu_bgalt; - char * menu_hlfg; - char * menu_hlbg; - char * menu_bc; + unsigned int menu_bw; + unsigned int menu_width; + unsigned int menu_lines; + char * menu_font; + char * menu_fg; + char * menu_bg; + char * menu_bgalt; + char * menu_hlfg; + char * menu_hlbg; + char * menu_bc; // Behavior - unsigned int zeltak_mode; - char * terminal_emulator; - unsigned int i3_mode; + unsigned int zeltak_mode; + char * terminal_emulator; + unsigned int i3_mode; // Key bindings - char * window_key; - char * run_key; - char * ssh_key; - WindowLocation location; + char * window_key; + char * run_key; + char * ssh_key; + WindowLocation location; + WindowMode wmode; + unsigned int inner_margin; } Settings; extern Settings config; diff --git a/source/simpleswitcher.c b/source/simpleswitcher.c index ac2ef703..f2958d8c 100644 --- a/source/simpleswitcher.c +++ b/source/simpleswitcher.c @@ -64,7 +64,6 @@ #include "ssh-dialog.h" #define LINE_MARGIN 4 -#define INNER_MARGIN 5 #define OPAQUE 0xffffffff #define OPACITY "_NET_WM_WINDOW_OPACITY" @@ -96,7 +95,9 @@ Settings config = { .window_key = "F12", .run_key = "mod1+F2", .ssh_key = "mod1+F3", - .location = CENTER + .location = CENTER, + .wmode = VERTICAL, + .inner_margin = 5 }; @@ -201,23 +202,23 @@ static void focus_window_i3( const char *socket_path, int id ) // Formulate command - snprintf( command, 128, "[id=\"%d\"] focus", id ); - // Prepare header. - memcpy( head.magic, I3_IPC_MAGIC, 6 ); - head.size = strlen( command ); - head.type = I3_IPC_MESSAGE_TYPE_COMMAND; - // Send header. - send( s, &head, sizeof( head ),0 ); - // Send message - send( s, command, strlen( command ),0 ); - // Receive header. - t = recv( s, &head, sizeof( head ),0 ); + snprintf( command, 128, "[id=\"%d\"] focus", id ); + // Prepare header. + memcpy( head.magic, I3_IPC_MAGIC, 6 ); + head.size = strlen( command ); + head.type = I3_IPC_MESSAGE_TYPE_COMMAND; + // Send header. + send( s, &head, sizeof( head ),0 ); + // Send message + send( s, command, strlen( command ),0 ); + // Receive header. + t = recv( s, &head, sizeof( head ),0 ); - if ( t == sizeof( head ) ) { - t= recv( s, command, head.size, 0 ); - command[t] = '\0'; - printf( "%s\n", command ); - } + if ( t == sizeof( head ) ) { + t= recv( s, command, head.size, 0 ); + command[t] = '\0'; + printf( "%s\n", command ); + } close( s ); } @@ -776,8 +777,14 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, unsigned int max_lines = MIN( config.menu_lines, num_lines ); - int w = config.menu_width < 101 ? ( mon.w/100 )*config.menu_width: config.menu_width; + // Calculate as float to stop silly, big rounding down errors. + int w = config.menu_width < 101 ? ( mon.w/100.0f )*( float )config.menu_width: config.menu_width; int x = mon.x + ( mon.w - w )/2; + int element_width = w -( 2*( config.inner_margin ) ); + + if ( config.wmode == HORIZONTAL ) { + element_width = ( w-( 2*( config.inner_margin ) )-max_lines*LINE_MARGIN )/( max_lines+1 ); + } Window box; XWindowAttributes attr; @@ -813,23 +820,35 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, } // search text input - textbox *text = textbox_create( box, TB_AUTOHEIGHT|TB_EDITABLE, INNER_MARGIN, INNER_MARGIN, - w-( 2*INNER_MARGIN ), 1, + textbox *text = textbox_create( box, TB_AUTOHEIGHT|TB_EDITABLE, + ( config.inner_margin ), + ( config.inner_margin ), + element_width, 1, config.menu_font, config.menu_fg, config.menu_bg, ( input!= NULL )?*input:"", prompt ); textbox_show( text ); int line_height = text->font->ascent + text->font->descent; - //line_height += line_height/10; - int row_margin = line_height/10; - line_height+=row_margin; // filtered list display textbox **boxes = allocate_clear( sizeof( textbox* ) * max_lines ); + int columns = 1; + + if ( config.wmode == HORIZONTAL ) { + // Number of columns is the width of the screen - the inner margins + trailing line margin. + columns = ( w-2*( config.inner_margin )+LINE_MARGIN )/( element_width+LINE_MARGIN ); + } + for ( i = 0; i < max_lines; i++ ) { - boxes[i] = textbox_create( box, TB_AUTOHEIGHT, INNER_MARGIN, ( i+1 ) * line_height + - INNER_MARGIN+LINE_MARGIN, w-( 2*INNER_MARGIN ), 1, + int col = ( i+1 )%columns; + int line = ( i+1 )/columns; + boxes[i] = textbox_create( box, + 0, + ( config.inner_margin )+col*( element_width+LINE_MARGIN ), // X + line * line_height + config.inner_margin +( ( config.wmode == HORIZONTAL )?0:LINE_MARGIN ), // y + element_width, // w + line_height, // h config.menu_font, config.menu_fg, config.menu_bg, lines[i], NULL ); textbox_show( boxes[i] ); } @@ -868,31 +887,45 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, // resize window vertically to suit // Subtract the margin of the last row. - int h = line_height * ( max_lines+1 ) + INNER_MARGIN*2 - row_margin+LINE_MARGIN; + int h = line_height * ( max_lines+1 ) + ( config.inner_margin )*2 +LINE_MARGIN; + + if ( config.wmode == HORIZONTAL ) { + h = line_height+( config.inner_margin )*2; + } + + // Default location is center. int y = mon.y + ( mon.h - h )/2; - switch(config.location) - { + // Determine window location + switch ( config.location ) { case NORTH_WEST: x=mon.x; + case NORTH: y=mon.y; break; + case NORTH_EAST: y=mon.y; + case EAST: x=mon.x+mon.w-w; break; + case EAST_SOUTH: x=mon.x+mon.w-w; + case SOUTH: y=mon.y+mon.h-h; break; + case SOUTH_WEST: y=mon.y+mon.h-h; + case WEST: x=mon.x; break; + case CENTER: default: break; @@ -912,11 +945,14 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, while ( XCheckTypedEvent( display, Expose, &ev ) ); menu_draw( text, boxes, max_lines, selected, filtered ); + // Why do we need the specian -1? - XDrawLine( display, main_window, gc, INNER_MARGIN, - line_height+INNER_MARGIN+( LINE_MARGIN-2 )/2, - w-( INNER_MARGIN )-1, - line_height+INNER_MARGIN +( LINE_MARGIN-2 )/2 ); + if ( config.wmode == VERTICAL ) { + XDrawLine( display, main_window, gc, ( config.inner_margin ), + line_height+( config.inner_margin )+( LINE_MARGIN-2 )/2, + w-( ( config.inner_margin ) )-1, + line_height+( config.inner_margin ) +( LINE_MARGIN-2 )/2 ); + } } else if ( ev.type == KeyPress ) { while ( XCheckTypedEvent( display, KeyPress, &ev ) ); @@ -1295,13 +1331,13 @@ int main( int argc, char *argv[] ) return EXIT_FAILURE; } - if(xdgInitHandle(&xdg_handle) == NULL) { - fprintf(stderr, "Failed to initialize XDG\n"); + if ( xdgInitHandle( &xdg_handle ) == NULL ) { + fprintf( stderr, "Failed to initialize XDG\n" ); return EXIT_FAILURE; } - cache_dir = xdgCacheHome(&xdg_handle); - printf("Cache directory: %s\n", cache_dir); + cache_dir = xdgCacheHome( &xdg_handle ); + printf( "Cache directory: %s\n", cache_dir ); signal( SIGCHLD, catch_exit ); @@ -1347,6 +1383,9 @@ int main( int argc, char *argv[] ) find_arg_int( argc, argv, "-lines",&( config.menu_lines ) ); find_arg_int( argc, argv, "-loc", &( config.location ) ); + config.wmode = ( find_arg( argc, argv, "-hmode" ) >= 0 )?HORIZONTAL:VERTICAL; + + find_arg_int( argc, argv, "-padding", &( config.inner_margin ) ); #ifdef I3 // Check for i3 @@ -1422,6 +1461,6 @@ int main( int argc, char *argv[] ) if ( i3_socket_path != NULL ) free( i3_socket_path ); #endif - xdgWipeHandle(&xdg_handle); + xdgWipeHandle( &xdg_handle ); return EXIT_SUCCESS; } diff --git a/source/ssh-dialog.c b/source/ssh-dialog.c index fa154fb9..4c6d754e 100644 --- a/source/ssh-dialog.c +++ b/source/ssh-dialog.c @@ -163,7 +163,7 @@ static char ** get_ssh ( ) } free( path ); - const char *hd = getenv("HOME"); + const char *hd = getenv( "HOME" ); path = allocate( strlen( hd ) + strlen( ".ssh/config" )+3 ); sprintf( path, "%s/%s", hd, ".ssh/config" ); fd = fopen ( path, "r" );