OO-ify the Switchers.

This commit is contained in:
QC 2015-03-27 20:28:53 +01:00
parent f52b697dd4
commit b21368c005
14 changed files with 571 additions and 423 deletions

View File

@ -12,6 +12,7 @@
- Improve rendering of boxes (fixed height and margins) - Improve rendering of boxes (fixed height and margins)
- Fix modi switcher boxes size+layout. - Fix modi switcher boxes size+layout.
- Reduce work on redraws (do not always calculate new size/position), set text, etc. - Reduce work on redraws (do not always calculate new size/position), set text, etc.
- OO-ify the switchers.
Cleanup: Cleanup:
- Do not lug argc,argv around everywhere. - Do not lug argc,argv around everywhere.

View File

@ -1,14 +1,5 @@
#ifndef __RUN_DIALOG_H__ #ifndef __RUN_DIALOG_H__
#define __RUN_DIALOG_H__ #define __RUN_DIALOG_H__
/** extern Switcher run_mode;
* @param input Pointer to the user-input string.
* @param data Custom data pointer for callback.
*
* Run the run dialog
*
* @returns SwitcherMode selected by user.
*/
SwitcherMode run_switcher_dialog ( char **input, void *data );
#endif #endif

View File

@ -1,27 +1,6 @@
#ifndef __SCRIPT_DIALOG_H__ #ifndef __SCRIPT_DIALOG_H__
#define __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;
/**
* @param input Pointer to the user-input string.
* @param data Custom data pointer for callback.
*
* Run the script dialog
*
* @returns SwitcherMode selected by user.
*/
SwitcherMode script_switcher_dialog ( char **input, void *data );
/** /**
* @param str The input string to parse * @param str The input string to parse
@ -31,12 +10,5 @@ SwitcherMode script_switcher_dialog ( char **input, void *data );
* *
* @returns NULL when it fails, a newly allocated ScriptOptions when successful. * @returns NULL when it fails, a newly allocated ScriptOptions when successful.
*/ */
ScriptOptions *script_switcher_parse_setup ( const char *str ); Switcher *script_switcher_parse_setup ( const char *str );
/**
* @param sw Handle to the ScriptOption
*
* Free the ScriptOptions block.
*/
void script_switcher_free_options ( void *data );
#endif #endif

View File

@ -1,14 +1,5 @@
#ifndef __SSH_DIALOG_H__ #ifndef __SSH_DIALOG_H__
#define __SSH_DIALOG_H__ #define __SSH_DIALOG_H__
/** extern Switcher ssh_mode;
* @param input Pointer to the user-input string.
* @param data Custom data pointer for callback.
*
* Run the ssh dialog
*
* @returns SwitcherMode selected by user.
*/
SwitcherMode ssh_switcher_dialog ( char **input, void *data );
#endif #endif

View File

@ -1,6 +1,5 @@
#ifndef __WINDOW_DIALOG_H__ #ifndef __WINDOW_DIALOG_H__
#define __WINDOW_DIALOG_H__ #define __WINDOW_DIALOG_H__
SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data ); extern Switcher window_mode;
#endif // __WINDOW_DIALOG_H__ #endif // __WINDOW_DIALOG_H__

View File

@ -1,6 +1,6 @@
#ifndef __HELPER_H__ #ifndef __HELPER_H__
#define __HELPER_H__ #define __HELPER_H__
#include "rofi.h"
/** /**
* @param string The input string. * @param string The input string.
* @param output Pointer to 2 dimensional array with parsed string. * @param output Pointer to 2 dimensional array with parsed string.
@ -105,7 +105,7 @@ int find_arg ( const char * const key );
*/ */
int token_match ( char **tokens, const char *input, int case_sensitive, int token_match ( char **tokens, const char *input, int case_sensitive,
__attribute__( ( unused ) ) int index, __attribute__( ( unused ) ) int index,
__attribute__( ( unused ) ) void *data ); __attribute__( ( unused ) ) Switcher * data );
/** /**
* @param cmd The command to execute. * @param cmd The command to execute.
@ -115,7 +115,7 @@ int token_match ( char **tokens, const char *input, int case_sensitive,
* *
* @returns a valid file descriptor on success, or -1 on failure. * @returns a valid file descriptor on success, or -1 on failure.
*/ */
int execute_generator ( char * cmd ) __attribute__( ( nonnull ) ); int execute_generator ( const char * cmd ) __attribute__( ( nonnull ) );
/** /**
* @param pidfile The pidfile to create. * @param pidfile The pidfile to create.

View File

@ -2,6 +2,7 @@
#define __SIMPLESWITCHER_H__ #define __SIMPLESWITCHER_H__
#include <X11/X.h> #include <X11/X.h>
#include <glib.h> #include <glib.h>
#include <textbox.h>
/** /**
@ -9,7 +10,7 @@
*/ */
extern const char *cache_dir; extern const char *cache_dir;
typedef struct _Switcher Switcher;
/** /**
* Enum used to sum the possible states of ROFI. * Enum used to sum the possible states of ROFI.
*/ */
@ -34,7 +35,7 @@ typedef enum
* @returns SwitcherMode * @returns SwitcherMode
*/ */
typedef SwitcherMode ( *switcher_callback )( char **input, void *data ); typedef SwitcherMode ( *switcher_callback )( char **input, void *data );
typedef void ( *switcher_callback_free_data )( void *data ); typedef void ( *switcher_free )( Switcher *data );
/** /**
* State returned by the rofi window. * State returned by the rofi window.
@ -42,19 +43,21 @@ typedef void ( *switcher_callback_free_data )( void *data );
typedef enum typedef enum
{ {
/** Entry is selected. */ /** Entry is selected. */
MENU_OK = 0, MENU_OK = 0x1,
/** User canceled the operation. (e.g. pressed escape) */ /** User canceled the operation. (e.g. pressed escape) */
MENU_CANCEL = -1, MENU_CANCEL = 0x2,
/** User requested a mode switch */ /** User requested a mode switch */
MENU_NEXT = -2, MENU_NEXT = 0x4,
/** Custom (non-matched) input was entered. */ /** Custom (non-matched) input was entered. */
MENU_CUSTOM_INPUT = -3, MENU_CUSTOM_INPUT = 0x8,
/** User wanted to delete entry from history. */ /** User wanted to delete entry from history. */
MENU_ENTRY_DELETE = -4, MENU_ENTRY_DELETE = 0x10,
/** User wants to jump to another switcher. */ /** User wants to jump to another switcher. */
MENU_QUICK_SWITCH = -5, MENU_QUICK_SWITCH = 0x20,
/** Go to the previous menu. */ /** Go to the previous menu. */
MENU_PREVIOUS = -6 MENU_PREVIOUS = 0x40,
/** Modifiers */
MENU_SHIFT = 0x1000
} MenuReturn; } MenuReturn;
@ -69,7 +72,7 @@ typedef enum
* *
* @returns 1 when it matches, 0 if not. * @returns 1 when it matches, 0 if not.
*/ */
typedef int ( *menu_match_cb )( char **tokens, const char *input, int case_sensitive, int index, void *data ); typedef int ( *menu_match_cb )( char **tokens, const char *input, int case_sensitive, int index, Switcher *data );
/** /**
* @param lines An array of strings to display. * @param lines An array of strings to display.
@ -87,9 +90,9 @@ typedef int ( *menu_match_cb )( char **tokens, const char *input, int case_sensi
* @returns The command issued (see MenuReturn) * @returns The command issued (see MenuReturn)
*/ */
MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prompt, MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prompt,
Time *time, int *shift, Time *time,
menu_match_cb mmc, void *mmc_data, menu_match_cb mmc, void *mmc_data,
int *selected_line, int sorting ) __attribute__ ( ( nonnull ( 1, 3, 4, 9 ) ) ); int *selected_line, int sorting ) __attribute__ ( ( nonnull ( 1, 3, 4, 8 ) ) );
/** /**
* @param sig The caught signal * @param sig The caught signal
* *
@ -212,4 +215,42 @@ extern Settings config;
*/ */
void error_dialog ( const char *msg ); void error_dialog ( const char *msg );
/**
* Structure defining a switcher.
* It consists of a name, callback and if enabled
* a textbox for the sidebar-mode.
*/
struct _Switcher
{
// Name (max 31 char long)
char name[32];
// Textbox used in the sidebar-mode.
textbox *tb;
// Keybindings (keysym and modmask)
char * keycfg;
char * keystr;
KeySym keysym;
unsigned int modmask;
/**
* A switcher normally consists of the following parts:
*/
void ( *init )( struct _Switcher *sw );
char ** ( *get_data )( unsigned int *length, struct _Switcher *pd );
int ( *match )( char **tokens, const char *input, int case_sensitive, int index, struct _Switcher *data );
SwitcherMode ( *result )( int menu_retv, char **input, unsigned int selected_line, struct _Switcher *pd );
void ( *destroy )( struct _Switcher *pd );
// Token match.
menu_match_cb token_match;
// Pointer to private data.
void *private_data;
// Extra fields for script
void *ed;
// Free SWitcher
switcher_free free;
};
#endif #endif

View File

@ -83,13 +83,12 @@ int dmenu_switcher_dialog ( char **input )
find_arg_int ( "-l", &selected_line ); find_arg_int ( "-l", &selected_line );
do { do {
int shift = 0; int mretv = menu ( list, length, input, dmenu_prompt, NULL,
int mretv = menu ( list, length, input, dmenu_prompt, NULL, &shift,
token_match, NULL, &selected_line, FALSE ); token_match, NULL, &selected_line, FALSE );
// We normally do not want to restart the loop. // We normally do not want to restart the loop.
restart = FALSE; restart = FALSE;
if ( mretv == MENU_OK && list[selected_line] != NULL ) { if ( ( mretv & MENU_OK ) && list[selected_line] != NULL ) {
if ( number_mode ) { if ( number_mode ) {
fprintf ( stdout, "%d", selected_line ); fprintf ( stdout, "%d", selected_line );
} }
@ -98,20 +97,20 @@ int dmenu_switcher_dialog ( char **input )
} }
fputc ( '\n', stdout ); fputc ( '\n', stdout );
fflush ( stdout ); fflush ( stdout );
if ( shift ) { if ( ( mretv & MENU_SHIFT ) ) {
restart = TRUE; restart = TRUE;
// Move to next line. // Move to next line.
selected_line = MIN ( selected_line + 1, length - 1 ); selected_line = MIN ( selected_line + 1, length - 1 );
} }
retv = TRUE; retv = TRUE;
} }
else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' ) { else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) {
if ( !number_mode ) { if ( !number_mode ) {
fputs ( *input, stdout ); fputs ( *input, stdout );
fputc ( '\n', stdout ); fputc ( '\n', stdout );
fflush ( stdout ); fflush ( stdout );
} }
if ( shift ) { if ( ( mretv & MENU_SHIFT ) ) {
restart = TRUE; restart = TRUE;
// Move to next line. // Move to next line.
selected_line = MIN ( selected_line + 1, length - 1 ); selected_line = MIN ( selected_line + 1, length - 1 );

View File

@ -154,7 +154,6 @@ static char ** get_apps_external ( char **retv, unsigned int *length, unsigned i
// No duplicate, add it. // No duplicate, add it.
retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) ); retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) );
retv[( *length )] = g_strdup ( buffer ); retv[( *length )] = g_strdup ( buffer );
retv[( *length ) + 1] = NULL;
( *length )++; ( *length )++;
@ -162,14 +161,16 @@ static char ** get_apps_external ( char **retv, unsigned int *length, unsigned i
fclose ( inp ); fclose ( inp );
} }
} }
retv[( *length ) ] = NULL;
return retv; return retv;
} }
/** /**
* Internal spider used to get list of executables. * Internal spider used to get list of executables.
*/ */
static char ** get_apps ( char **retv, unsigned int *length ) static char ** get_apps ( unsigned int *length )
{ {
char **retv = NULL;
unsigned int num_favorites = 0; unsigned int num_favorites = 0;
char *path; char *path;
@ -263,47 +264,85 @@ static char ** get_apps ( char **retv, unsigned int *length )
return retv; return retv;
} }
SwitcherMode run_switcher_dialog ( char **input, G_GNUC_UNUSED void *data ) typedef struct _RunModePrivateData
{ {
int shift = 0; unsigned int id;
int selected_line = 0; char **cmd_list;
SwitcherMode retv = MODE_EXIT; unsigned int cmd_list_length;
// act as a launcher } RunModePrivateData;
unsigned int cmd_list_length = 0;
char **cmd_list = NULL;
cmd_list = get_apps ( cmd_list, &cmd_list_length );
if ( cmd_list == NULL ) {
cmd_list = g_malloc_n ( 2, sizeof ( char * ) ); static void run_mode_init ( Switcher *sw )
cmd_list[0] = g_strdup ( "No applications found" ); {
cmd_list[1] = NULL; if ( sw->private_data == NULL ) {
RunModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
sw->private_data = (void *) pd;
} }
}
int mretv = menu ( cmd_list, cmd_list_length, input, "run:", static char ** run_mode_get_data ( unsigned int *length, Switcher *sw )
NULL, &shift, token_match, NULL, &selected_line, {
config.levenshtein_sort ); RunModePrivateData *rmpd = (RunModePrivateData *) sw->private_data;
if ( rmpd->cmd_list == NULL ) {
rmpd->cmd_list_length = 0;
rmpd->cmd_list = get_apps ( &( rmpd->cmd_list_length ) );
}
*length = rmpd->cmd_list_length;
return rmpd->cmd_list;
}
if ( mretv == MENU_NEXT ) { static SwitcherMode run_mode_result ( int mretv, char **input, unsigned int selected_line, Switcher *sw )
{
RunModePrivateData *rmpd = (RunModePrivateData *) sw->private_data;
SwitcherMode retv = MODE_EXIT;
int shift = ( ( mretv & MENU_SHIFT ) == MENU_SHIFT );
if ( mretv & MENU_NEXT ) {
retv = NEXT_DIALOG; retv = NEXT_DIALOG;
} }
else if ( mretv == MENU_PREVIOUS ) { else if ( mretv & MENU_PREVIOUS ) {
retv = PREVIOUS_DIALOG; retv = PREVIOUS_DIALOG;
} }
else if ( mretv == MENU_QUICK_SWITCH ) { else if ( mretv & MENU_QUICK_SWITCH ) {
retv = selected_line; retv = selected_line;
} }
else if ( mretv == MENU_OK && cmd_list[selected_line] != NULL ) { else if ( ( mretv & MENU_OK ) && rmpd->cmd_list[selected_line] != NULL ) {
exec_cmd ( cmd_list[selected_line], shift ); exec_cmd ( rmpd->cmd_list[selected_line], shift );
} }
else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' ) { else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) {
exec_cmd ( *input, shift ); exec_cmd ( *input, shift );
} }
else if ( mretv == MENU_ENTRY_DELETE && cmd_list[selected_line] ) { else if ( ( mretv & MENU_ENTRY_DELETE ) && rmpd->cmd_list[selected_line] ) {
delete_entry ( cmd_list[selected_line] ); delete_entry ( rmpd->cmd_list[selected_line] );
retv = RELOAD_DIALOG; retv = RELOAD_DIALOG;
} }
g_strfreev ( cmd_list );
return retv; return retv;
} }
static void run_mode_destroy ( Switcher *sw )
{
RunModePrivateData *rmpd = (RunModePrivateData *) sw->private_data;
if ( rmpd != NULL ) {
g_strfreev ( rmpd->cmd_list );
g_free ( rmpd );
sw->private_data = NULL;
}
}
Switcher run_mode =
{
.name = "run",
.tb = NULL,
.keycfg = NULL,
.keystr = NULL,
.modmask = AnyModifier,
.init = run_mode_init,
.get_data = run_mode_get_data,
.result = run_mode_result,
.destroy = run_mode_destroy,
.token_match = token_match,
.private_data = NULL,
.free = NULL
};

View File

@ -42,7 +42,7 @@
static char **get_script_output ( char *command, unsigned int *length ) static char **get_script_output ( const char *command, unsigned int *length )
{ {
char **retv = NULL; char **retv = NULL;
@ -70,101 +70,131 @@ static char **get_script_output ( char *command, unsigned int *length )
return retv; return retv;
} }
static char **execute_executor ( ScriptOptions *options, const char *result, unsigned int *length ) static char **execute_executor ( Switcher *sw, const char *result, unsigned int *length )
{ {
char **retv = NULL; char **retv = NULL;
char *arg = g_shell_quote ( result ); char *arg = g_shell_quote ( result );
char *command = g_strdup_printf ( "%s %s", options->script_path, arg ); char *command = g_strdup_printf ( "%s %s", (const char *) sw->ed, arg );
retv = get_script_output ( command, length ); retv = get_script_output ( command, length );
g_free ( command ); g_free ( command );
g_free ( arg ); g_free ( arg );
return retv; return retv;
} }
SwitcherMode script_switcher_dialog ( char **input, void *data ) static void script_switcher_free ( Switcher *sw )
{ {
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 );
char *prompt = g_strdup_printf ( "%s:", options->name );
do {
unsigned int new_length = 0;
char **new_list = NULL;
int mretv = menu ( list, length, input, prompt, NULL, NULL,
token_match, NULL, &selected_line, FALSE );
if ( mretv == MENU_NEXT ) {
retv = NEXT_DIALOG;
}
else if ( mretv == MENU_PREVIOUS ) {
retv = PREVIOUS_DIALOG;
}
else if ( mretv == MENU_QUICK_SWITCH ) {
retv = selected_line;
}
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.
g_strfreev ( list );
list = NULL;
// If a new list was generated, use that an loop around.
if ( new_list != NULL ) {
list = new_list;
length = new_length;
g_free ( *input );
*input = NULL;
}
} while ( list != NULL );
g_free ( prompt );
return retv;
}
void script_switcher_free_options ( void *data )
{
ScriptOptions *sw = (ScriptOptions *) data;
if ( sw == NULL ) { if ( sw == NULL ) {
return; return;
} }
g_free ( sw->name ); g_free ( sw->ed );
g_free ( sw->script_path );
g_free ( sw ); g_free ( sw );
} }
typedef struct _ScriptModePrivateData
ScriptOptions *script_switcher_parse_setup ( const char *str )
{ {
ScriptOptions *sw = g_malloc0 ( sizeof ( *sw ) ); unsigned int id;
char **cmd_list;
unsigned int cmd_list_length;
} ScriptModePrivateData;
static void script_mode_init ( Switcher *sw )
{
if ( sw->private_data == NULL ) {
ScriptModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
sw->private_data = (void *) pd;
}
}
static char ** script_mode_get_data ( unsigned int *length, Switcher *sw )
{
ScriptModePrivateData *rmpd = (ScriptModePrivateData *) sw->private_data;
if ( rmpd->cmd_list == NULL ) {
rmpd->cmd_list_length = 0;
rmpd->cmd_list = get_script_output ( (const char *) sw->ed, &( rmpd->cmd_list_length ) );
}
*length = rmpd->cmd_list_length;
return rmpd->cmd_list;
}
static SwitcherMode script_mode_result ( int mretv, char **input, unsigned int selected_line, Switcher *sw )
{
ScriptModePrivateData *rmpd = (ScriptModePrivateData *) sw->private_data;
SwitcherMode retv = MODE_EXIT;
char **new_list = NULL;
unsigned int new_length = 0;
if ( ( mretv & MENU_NEXT ) ) {
retv = NEXT_DIALOG;
}
else if ( ( mretv & MENU_PREVIOUS ) ) {
retv = PREVIOUS_DIALOG;
}
else if ( ( mretv & MENU_QUICK_SWITCH ) ) {
retv = selected_line;
}
else if ( ( mretv & MENU_OK ) && rmpd->cmd_list[selected_line] != NULL ) {
new_list = execute_executor ( sw, rmpd->cmd_list[selected_line], &new_length );
}
else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) {
new_list = execute_executor ( sw, *input, &new_length );
}
// If a new list was generated, use that an loop around.
if ( new_list != NULL ) {
g_strfreev ( rmpd->cmd_list );
rmpd->cmd_list = new_list;
rmpd->cmd_list_length = new_length;
g_free ( *input );
*input = NULL;
retv = RELOAD_DIALOG;
}
return retv;
}
static void script_mode_destroy ( Switcher *sw )
{
ScriptModePrivateData *rmpd = (ScriptModePrivateData *) sw->private_data;
if ( rmpd != NULL ) {
g_strfreev ( rmpd->cmd_list );
g_free ( rmpd );
sw->private_data = NULL;
}
}
Switcher *script_switcher_parse_setup ( const char *str )
{
Switcher *sw = g_malloc0 ( sizeof ( *sw ) );
char *endp = NULL; char *endp = NULL;
char *parse = g_strdup ( str ); char *parse = g_strdup ( str );
unsigned int index = 0; unsigned int index = 0;
for ( char *token = strtok_r ( parse, ":", &endp ); token != NULL; token = strtok_r ( NULL, ":", &endp ) ) { for ( char *token = strtok_r ( parse, ":", &endp ); token != NULL; token = strtok_r ( NULL, ":", &endp ) ) {
if ( index == 0 ) { if ( index == 0 ) {
sw->name = g_strdup ( token ); g_strlcpy ( sw->name, token, 32 );
} }
else if ( index == 1 ) { else if ( index == 1 ) {
sw->script_path = g_strdup ( token ); sw->ed = (void *) g_strdup ( token );
} }
index++; index++;
} }
g_free ( parse ); g_free ( parse );
if ( index == 2 ) { if ( index == 2 ) {
sw->free = script_switcher_free;
sw->keysym = None;
sw->modmask = AnyModifier;
sw->init = script_mode_init;
sw->get_data = script_mode_get_data;
sw->result = script_mode_result;
sw->destroy = script_mode_destroy;
sw->token_match = token_match;
return sw; return sw;
} }
fprintf ( stderr, "The script command '%s' has %u options, but needs 2: <name>:<script>.\n", fprintf ( stderr, "The script command '%s' has %u options, but needs 2: <name>:<script>.\n",
str, index ); str, index );
script_switcher_free_options ( sw ); script_switcher_free ( sw );
return NULL; return NULL;
} }

View File

@ -111,9 +111,9 @@ static int ssh_sort_func ( const void *a, const void *b )
} }
static char ** get_ssh ( unsigned int *length ) static char ** get_ssh ( unsigned int *length )
{ {
char **retv = NULL;
unsigned int num_favorites = 0; unsigned int num_favorites = 0;
char *path; char *path;
char **retv = NULL;
if ( getenv ( "HOME" ) == NULL ) { if ( getenv ( "HOME" ) == NULL ) {
return NULL; return NULL;
@ -191,47 +191,80 @@ static char ** get_ssh ( unsigned int *length )
return retv; return retv;
} }
SwitcherMode ssh_switcher_dialog ( char **input, G_GNUC_UNUSED void *data ) typedef struct _SSHModePrivateData
{
unsigned int id;
char **cmd_list;
unsigned int cmd_list_length;
} SSHModePrivateData;
static void ssh_mode_init ( Switcher *sw )
{
if ( sw->private_data == NULL ) {
SSHModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
sw->private_data = (void *) pd;
}
}
static char ** ssh_mode_get_data ( unsigned int *length, Switcher *sw )
{
SSHModePrivateData *rmpd = (SSHModePrivateData *) sw->private_data;
if ( rmpd->cmd_list == NULL ) {
rmpd->cmd_list_length = 0;
rmpd->cmd_list = get_ssh ( &( rmpd->cmd_list_length ) );
}
*length = rmpd->cmd_list_length;
return rmpd->cmd_list;
}
static SwitcherMode ssh_mode_result ( int mretv, char **input, unsigned int selected_line, Switcher *sw )
{ {
SwitcherMode retv = MODE_EXIT; SwitcherMode retv = MODE_EXIT;
// act as a launcher SSHModePrivateData *rmpd = (SSHModePrivateData *) sw->private_data;
unsigned int cmd_list_length = 0; if ( mretv & MENU_NEXT ) {
char **cmd_list = get_ssh ( &cmd_list_length );
if ( cmd_list == NULL ) {
cmd_list = g_malloc_n ( 2, sizeof ( char * ) );
cmd_list[0] = g_strdup ( "No ssh hosts found" );
cmd_list[1] = NULL;
}
int shift = 0;
int selected_line = 0;
int mretv = menu ( cmd_list, cmd_list_length, input, "ssh:",
NULL, &shift, token_match, NULL, &selected_line,
config.levenshtein_sort );
if ( mretv == MENU_NEXT ) {
retv = NEXT_DIALOG; retv = NEXT_DIALOG;
} }
else if ( mretv == MENU_PREVIOUS ) { else if ( mretv & MENU_PREVIOUS ) {
retv = PREVIOUS_DIALOG; retv = PREVIOUS_DIALOG;
} }
else if ( mretv == MENU_QUICK_SWITCH ) { else if ( mretv & MENU_QUICK_SWITCH ) {
retv = selected_line; retv = selected_line;
} }
else if ( mretv == MENU_OK && cmd_list[selected_line] != NULL ) { else if ( ( mretv & MENU_OK ) && rmpd->cmd_list[selected_line] != NULL ) {
exec_ssh ( cmd_list[selected_line] ); exec_ssh ( rmpd->cmd_list[selected_line] );
} }
else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' ) { else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) {
exec_ssh ( *input ); exec_ssh ( *input );
} }
else if ( mretv == MENU_ENTRY_DELETE && cmd_list[selected_line] ) { else if ( ( mretv & MENU_ENTRY_DELETE ) && rmpd->cmd_list[selected_line] ) {
delete_ssh ( cmd_list[selected_line] ); delete_ssh ( rmpd->cmd_list[selected_line] );
// Stay // Stay
retv = RELOAD_DIALOG; retv = RELOAD_DIALOG;
} }
g_strfreev ( cmd_list );
return retv; return retv;
} }
static void ssh_mode_destroy ( Switcher *sw )
{
SSHModePrivateData *rmpd = (SSHModePrivateData *) sw->private_data;
if ( rmpd != NULL ) {
g_strfreev ( rmpd->cmd_list );
g_free ( rmpd );
sw->private_data = NULL;
}
}
Switcher ssh_mode =
{
.name = "ssh",
.tb = NULL,
.keycfg = NULL,
.keystr = NULL,
.modmask = AnyModifier,
.init = ssh_mode_init,
.get_data = ssh_mode_get_data,
.result = ssh_mode_result,
.destroy = ssh_mode_destroy,
.token_match = token_match,
.private_data = NULL,
.free = NULL
};

View File

@ -278,13 +278,22 @@ static client* window_client ( Display *display, Window win )
return c; return c;
} }
typedef struct _SwitcherModePrivateData
{
unsigned int id;
char **cmd_list;
unsigned int cmd_list_length;
winlist *ids;
int config_i3_mode;
int init;
} SwitcherModePrivateData;
static int window_match ( char **tokens, __attribute__( ( unused ) ) const char *input, static int window_match ( char **tokens, __attribute__( ( unused ) ) const char *input,
int case_sensitive, int index, void *data ) int case_sensitive, int index, Switcher *sw )
{ {
SwitcherModePrivateData *rmpd = (SwitcherModePrivateData *) sw->private_data;
int match = 1; int match = 1;
winlist *ids = ( winlist * ) data; winlist *ids = ( winlist * ) rmpd->ids;
client *c = window_client ( display, ids->array[index] ); client *c = window_client ( display, ids->array[index] );
if ( tokens ) { if ( tokens ) {
@ -324,13 +333,21 @@ static int window_match ( char **tokens, __attribute__( ( unused ) ) const char
return match; return match;
} }
static void window_mode_init ( Switcher *sw )
SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
{ {
if ( sw->private_data == NULL ) {
SwitcherModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
sw->private_data = (void *) pd;
pd->init = FALSE;
}
}
static char ** window_mode_get_data ( unsigned int *length, Switcher *sw )
{
SwitcherModePrivateData *pd = (SwitcherModePrivateData *) sw->private_data;
if ( !pd->init ) {
Screen *screen = DefaultScreenOfDisplay ( display ); Screen *screen = DefaultScreenOfDisplay ( display );
Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) ); Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) );
SwitcherMode retv = MODE_EXIT;
// find window list // find window list
Atom type; Atom type;
int nwins; int nwins;
@ -341,7 +358,7 @@ SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
x11_cache_create (); x11_cache_create ();
// Check for i3 // Check for i3
int config_i3_mode = i3_support_initialize ( display ); pd->config_i3_mode = i3_support_initialize ( display );
// Get the active window so we can highlight this. // Get the active window so we can highlight this.
if ( !( window_get_prop ( display, root, netatoms[_NET_ACTIVE_WINDOW], &type, if ( !( window_get_prop ( display, root, netatoms[_NET_ACTIVE_WINDOW], &type,
@ -359,7 +376,7 @@ SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
unsigned long desktops = 0; unsigned long desktops = 0;
// windows we actually display. May be slightly different to _NET_CLIENT_LIST_STACKING // 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... // if we happen to have a window destroyed while we're working...
winlist *ids = winlist_new (); pd->ids = winlist_new ();
@ -374,14 +391,14 @@ SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
classfield = MAX ( classfield, strlen ( c->class ) ); classfield = MAX ( classfield, strlen ( c->class ) );
// In i3 mode, skip the i3bar completely. // In i3 mode, skip the i3bar completely.
if ( config_i3_mode && strstr ( c->class, "i3bar" ) != NULL ) { if ( pd->config_i3_mode && strstr ( c->class, "i3bar" ) != NULL ) {
continue; continue;
} }
if ( c->window == curr_win_id ) { if ( c->window == curr_win_id ) {
c->active = TRUE; c->active = TRUE;
} }
winlist_append ( ids, c->window, NULL ); winlist_append ( pd->ids, c->window, NULL );
} }
} }
@ -389,18 +406,17 @@ SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
if ( !window_get_cardinal_prop ( display, root, netatoms[_NET_NUMBER_OF_DESKTOPS], &desktops, 1 ) ) { if ( !window_get_cardinal_prop ( display, root, netatoms[_NET_NUMBER_OF_DESKTOPS], &desktops, 1 ) ) {
desktops = 1; desktops = 1;
} }
if ( config_i3_mode ) { if ( pd->config_i3_mode ) {
sprintf ( pattern, "%%-%ds %%s", MAX ( 5, classfield ) ); sprintf ( pattern, "%%-%ds %%s", MAX ( 5, classfield ) );
} }
else{ else{
sprintf ( pattern, "%%-%ds %%-%ds %%s", desktops < 10 ? 1 : 2, MAX ( 5, classfield ) ); sprintf ( pattern, "%%-%ds %%-%ds %%s", desktops < 10 ? 1 : 2, MAX ( 5, classfield ) );
} }
char **list = g_malloc0_n ( ( ids->len + 1 ), sizeof ( char* ) ); pd->cmd_list = g_malloc0_n ( ( pd->ids->len + 1 ), sizeof ( char* ) );
unsigned int lines = 0;
// build the actual list // build the actual list
for ( i = 0; i < ( ids->len ); i++ ) { for ( i = 0; i < ( pd->ids->len ); i++ ) {
Window w = ids->array[i]; Window w = pd->ids->array[i];
client *c; client *c;
if ( ( c = window_client ( display, w ) ) ) { if ( ( c = window_client ( display, w ) ) ) {
@ -409,7 +425,7 @@ SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
char desktop[5]; char desktop[5];
desktop[0] = 0; desktop[0] = 0;
char *line = g_malloc ( strlen ( c->title ) + strlen ( c->class ) + classfield + 50 ); char *line = g_malloc ( strlen ( c->title ) + strlen ( c->class ) + classfield + 50 );
if ( !config_i3_mode ) { if ( !pd->config_i3_mode ) {
// find client's desktop. This is zero-based, so we adjust by since most // find client's desktop. This is zero-based, so we adjust by since most
// normal people don't think like this :-) // normal people don't think like this :-)
if ( !window_get_cardinal_prop ( display, c->window, netatoms[_NET_WM_DESKTOP], &wmdesktop, 1 ) ) { if ( !window_get_cardinal_prop ( display, c->window, netatoms[_NET_WM_DESKTOP], &wmdesktop, 1 ) ) {
@ -426,47 +442,77 @@ SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
sprintf ( line, pattern, c->class, c->title ); sprintf ( line, pattern, c->class, c->title );
} }
list[lines++] = line; pd->cmd_list[pd->cmd_list_length++] = line;
} }
} }
Time time; }
int selected_line = 0; pd->init = TRUE;
MenuReturn mretv = menu ( list, lines, input, "window:", &time, NULL, }
window_match, ids, &selected_line, config.levenshtein_sort ); *length = pd->cmd_list_length;
return pd->cmd_list;
if ( mretv == MENU_NEXT ) { }
static SwitcherMode window_mode_result ( int mretv, G_GNUC_UNUSED char **input, unsigned int selected_line, Switcher *sw )
{
SwitcherModePrivateData *rmpd = (SwitcherModePrivateData *) sw->private_data;
SwitcherMode retv = MODE_EXIT;
if ( mretv & MENU_NEXT ) {
retv = NEXT_DIALOG; retv = NEXT_DIALOG;
} }
else if ( mretv == MENU_PREVIOUS ) { else if ( mretv & MENU_PREVIOUS ) {
retv = PREVIOUS_DIALOG; retv = PREVIOUS_DIALOG;
} }
else if ( mretv == MENU_QUICK_SWITCH ) { else if ( mretv == MENU_QUICK_SWITCH ) {
retv = selected_line; retv = selected_line;
} }
else if ( ( mretv == MENU_OK || mretv == MENU_CUSTOM_INPUT ) && list[selected_line] ) { else if ( ( mretv & ( MENU_OK | MENU_CUSTOM_INPUT ) ) && rmpd->cmd_list[selected_line] ) {
if ( config_i3_mode ) { if ( rmpd->config_i3_mode ) {
// Hack for i3. // Hack for i3.
i3_support_focus_window ( ids->array[selected_line] ); i3_support_focus_window ( rmpd->ids->array[selected_line] );
} }
else{ else{
Screen *screen = DefaultScreenOfDisplay ( display );
Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) );
// Change to the desktop of the selected window/client. // Change to the desktop of the selected window/client.
// TODO: get rid of strtol // TODO: get rid of strtol
window_send_message ( display, root, root, netatoms[_NET_CURRENT_DESKTOP], window_send_message ( display, root, root, netatoms[_NET_CURRENT_DESKTOP],
strtol ( list[selected_line], NULL, 10 ) - 1, strtol ( rmpd->cmd_list[selected_line], NULL, 10 ) - 1,
SubstructureNotifyMask | SubstructureRedirectMask, time ); SubstructureNotifyMask | SubstructureRedirectMask, 0 );
XSync ( display, False ); XSync ( display, False );
window_send_message ( display, root, ids->array[selected_line], window_send_message ( display, root, rmpd->ids->array[selected_line],
netatoms[_NET_ACTIVE_WINDOW], 2, // 2 = pager netatoms[_NET_ACTIVE_WINDOW], 2, // 2 = pager
SubstructureNotifyMask | SubstructureRedirectMask, time ); SubstructureNotifyMask | SubstructureRedirectMask, 0 );
} }
} }
g_strfreev ( list );
winlist_free ( ids );
}
i3_support_free_internals ();
x11_cache_free ();
return retv; return retv;
} }
static void window_mode_destroy ( Switcher *sw )
{
SwitcherModePrivateData *rmpd = (SwitcherModePrivateData *) sw->private_data;
if ( rmpd != NULL ) {
g_strfreev ( rmpd->cmd_list );
winlist_free ( rmpd->ids );
i3_support_free_internals ();
x11_cache_free ();
g_free ( rmpd );
sw->private_data = NULL;
}
}
Switcher window_mode =
{
.name = "window",
.tb = NULL,
.keycfg = NULL,
.keystr = NULL,
.modmask = AnyModifier,
.init = window_mode_init,
.get_data = window_mode_get_data,
.result = window_mode_result,
.destroy = window_mode_destroy,
.token_match = window_match,
.private_data = NULL,
.free = NULL
};

View File

@ -318,7 +318,7 @@ int find_arg_char ( const char * const key, char *val )
*/ */
int token_match ( char **tokens, const char *input, int case_sensitive, int token_match ( char **tokens, const char *input, int case_sensitive,
__attribute__( ( unused ) ) int index, __attribute__( ( unused ) ) int index,
__attribute__( ( unused ) ) void *data ) __attribute__( ( unused ) ) Switcher *data )
{ {
int match = 1; int match = 1;
char *compk = token_collate_key ( input, case_sensitive ); char *compk = token_collate_key ( input, case_sensitive );
@ -333,7 +333,7 @@ int token_match ( char **tokens, const char *input, int case_sensitive,
return match; return match;
} }
int execute_generator ( char * cmd ) int execute_generator ( const char * cmd )
{ {
char **args = NULL; char **args = NULL;
int argv = 0; int argv = 0;

View File

@ -58,6 +58,10 @@
#define LINE_MARGIN 3 #define LINE_MARGIN 3
// TEMP
SwitcherMode switcher_run ( char **input, Switcher *sw );
typedef enum _MainLoopEvent typedef enum _MainLoopEvent
{ {
ML_XEVENT, ML_XEVENT,
@ -73,31 +77,9 @@ char *display_str = NULL;
const char *netatom_names[] = { EWMH_ATOMS ( ATOM_CHAR ) }; const char *netatom_names[] = { EWMH_ATOMS ( ATOM_CHAR ) };
Atom netatoms[NUM_NETATOMS]; Atom netatoms[NUM_NETATOMS];
/**
* Structure defining a switcher.
* It consists of a name, callback and if enabled
* a textbox for the sidebar-mode.
*/
typedef struct _Switcher
{
// Name (max 31 char long)
char name[32];
// Switcher callback.
switcher_callback cb;
// Callback data.
void *cb_data;
switcher_callback_free_data cb_data_free;
// Textbox used in the sidebar-mode.
textbox *tb;
// Keybindings (keysym and modmask)
char * keycfg;
char * keystr;
KeySym keysym;
unsigned int modmask;
} Switcher;
// Array of switchers. // Array of switchers.
Switcher *switchers = NULL; Switcher **switchers = NULL;
// Number of switchers. // Number of switchers.
unsigned int num_switchers = 0; unsigned int num_switchers = 0;
// Current selected switcher. // Current selected switcher.
@ -113,7 +95,7 @@ unsigned int curr_switcher = 0;
static int switcher_get ( const char *name ) static int switcher_get ( const char *name )
{ {
for ( unsigned int i = 0; i < num_switchers; i++ ) { for ( unsigned int i = 0; i < num_switchers; i++ ) {
if ( strcmp ( switchers[i].name, name ) == 0 ) { if ( strcmp ( switchers[i]->name, name ) == 0 ) {
return i; return i;
} }
} }
@ -561,9 +543,9 @@ static int locate_switcher ( KeySym key, unsigned int modstate )
// ignore annoying modifiers // ignore annoying modifiers
unsigned int modstate_filtered = modstate & ~( LockMask | NumlockMask ); unsigned int modstate_filtered = modstate & ~( LockMask | NumlockMask );
for ( unsigned int i = 0; i < num_switchers; i++ ) { for ( unsigned int i = 0; i < num_switchers; i++ ) {
if ( switchers[i].keystr != NULL ) { if ( switchers[i]->keystr != NULL ) {
if ( ( modstate_filtered == switchers[i].modmask ) && if ( ( modstate_filtered == switchers[i]->modmask ) &&
switchers[i].keysym == key ) { switchers[i]->keysym == key ) {
return i; return i;
} }
} }
@ -708,7 +690,7 @@ static void menu_mouse_navigation ( MenuState *state, XButtonEvent *xbe )
} }
else { else {
for ( unsigned int i = 0; config.sidebar_mode == TRUE && i < num_switchers; i++ ) { for ( unsigned int i = 0; config.sidebar_mode == TRUE && i < num_switchers; i++ ) {
if ( switchers[i].tb->window == ( xbe->window ) ) { if ( switchers[i]->tb->window == ( xbe->window ) ) {
*( state->selected_line ) = i; *( state->selected_line ) = i;
state->retv = MENU_QUICK_SWITCH; state->retv = MENU_QUICK_SWITCH;
state->quit = TRUE; state->quit = TRUE;
@ -905,7 +887,7 @@ static void menu_update ( MenuState *state )
state->w - ( ( config.padding ) ) - 1, state->w - ( ( config.padding ) ) - 1,
state->h - state->line_height - ( config.padding ) - LINE_MARGIN ); state->h - state->line_height - ( config.padding ) - LINE_MARGIN );
for ( unsigned int j = 0; j < num_switchers; j++ ) { for ( unsigned int j = 0; j < num_switchers; j++ ) {
textbox_draw ( switchers[j].tb ); textbox_draw ( switchers[j]->tb );
} }
} }
@ -941,8 +923,9 @@ static void menu_paste ( MenuState *state, XSelectionEvent *xse )
} }
MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prompt, Time *time, MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prompt, Time *time,
int *shift, menu_match_cb mmc, void *mmc_data, int *selected_line, int sorting ) menu_match_cb mmc, void *mmc_data, int *selected_line, int sorting )
{ {
int shift = FALSE;
MenuState state = { MenuState state = {
.selected_line = selected_line, .selected_line = selected_line,
.retv = MENU_CANCEL, .retv = MENU_CANCEL,
@ -1078,11 +1061,11 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
if ( config.sidebar_mode == TRUE ) { if ( config.sidebar_mode == TRUE ) {
int width = ( state.w - ( 2 * ( config.padding ) + ( num_switchers - 1 ) * LINE_MARGIN ) ) / num_switchers; int width = ( state.w - ( 2 * ( config.padding ) + ( num_switchers - 1 ) * LINE_MARGIN ) ) / num_switchers;
for ( unsigned int j = 0; j < num_switchers; j++ ) { for ( unsigned int j = 0; j < num_switchers; j++ ) {
switchers[j].tb = textbox_create ( main_window, &vinfo, map, TB_CENTER, switchers[j]->tb = textbox_create ( main_window, &vinfo, map, TB_CENTER,
config.padding + j * ( width + LINE_MARGIN ), config.padding + j * ( width + LINE_MARGIN ),
state.h - state.line_height - config.padding, state.h - state.line_height - config.padding,
width, state.line_height, ( j == curr_switcher ) ? HIGHLIGHT : NORMAL, switchers[j].name ); width, state.line_height, ( j == curr_switcher ) ? HIGHLIGHT : NORMAL, switchers[j]->name );
textbox_show ( switchers[j].tb ); textbox_show ( switchers[j]->tb );
} }
} }
@ -1243,9 +1226,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
int rc = textbox_keypress ( state.text, &ev ); int rc = textbox_keypress ( state.text, &ev );
// Row is accepted. // Row is accepted.
if ( rc < 0 ) { if ( rc < 0 ) {
if ( shift != NULL ) { shift = ( ( ev.xkey.state & ShiftMask ) == ShiftMask );
( *shift ) = ( ( ev.xkey.state & ShiftMask ) == ShiftMask );
}
// If a valid item is selected, return that.. // If a valid item is selected, return that..
if ( state.selected < state.filtered_lines && state.filtered[state.selected] != NULL ) { if ( state.selected < state.filtered_lines && state.filtered[state.selected] != NULL ) {
@ -1290,12 +1271,16 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
int retv = state.retv; int retv = state.retv;
menu_free_state ( &state ); menu_free_state ( &state );
if ( shift ) {
retv |= MENU_SHIFT;
}
// Free the switcher boxes. // Free the switcher boxes.
// When state is free'ed we should no longer need these. // When state is free'ed we should no longer need these.
if ( config.sidebar_mode == TRUE ) { if ( config.sidebar_mode == TRUE ) {
for ( unsigned int j = 0; j < num_switchers; j++ ) { for ( unsigned int j = 0; j < num_switchers; j++ ) {
textbox_free ( switchers[j].tb ); textbox_free ( switchers[j]->tb );
switchers[j].tb = NULL; switchers[j]->tb = NULL;
} }
} }
@ -1449,13 +1434,15 @@ static void run_switcher ( int do_fork, SwitcherMode mode )
config.menu_hlbg, config.menu_hlbg,
config.menu_hlfg ); config.menu_hlfg );
// Otherwise check if requested mode is enabled. // Otherwise check if requested mode is enabled.
if ( switchers[mode].cb != NULL ) {
char *input = NULL; char *input = NULL;
for ( unsigned int i = 0; i < num_switchers; i++ ) {
switchers[i]->init ( switchers[i] );
}
do { do {
SwitcherMode retv; SwitcherMode retv;
curr_switcher = mode; curr_switcher = mode;
retv = switchers[mode].cb ( &input, switchers[mode].cb_data ); retv = switcher_run ( &input, switchers[mode] );
// Find next enabled // Find next enabled
if ( retv == NEXT_DIALOG ) { if ( retv == NEXT_DIALOG ) {
mode = ( mode + 1 ) % num_switchers; mode = ( mode + 1 ) % num_switchers;
@ -1479,6 +1466,8 @@ static void run_switcher ( int do_fork, SwitcherMode mode )
} }
} while ( mode != MODE_EXIT ); } while ( mode != MODE_EXIT );
g_free ( input ); g_free ( input );
for ( unsigned int i = 0; i < num_switchers; i++ ) {
switchers[i]->destroy ( switchers[i] );
} }
// Cleanup font setup. // Cleanup font setup.
@ -1546,14 +1535,14 @@ static void cleanup ()
// Cleaning up memory allocated by the Xresources file. // Cleaning up memory allocated by the Xresources file.
config_xresource_free (); config_xresource_free ();
for ( unsigned int i = 0; i < num_switchers; i++ ) { for ( unsigned int i = 0; i < num_switchers; i++ ) {
// only used for script dialog.
if ( switchers[i].cb_data_free != NULL ) {
switchers[i].cb_data_free ( switchers[i].cb_data );
}
// Switcher keystr is free'ed when needed by config system. // Switcher keystr is free'ed when needed by config system.
if ( switchers[i].keycfg != NULL ) { if ( switchers[i]->keycfg != NULL ) {
g_free ( switchers[i].keycfg ); g_free ( switchers[i]->keycfg );
switchers[i].keycfg = NULL; switchers[i]->keycfg = NULL;
}
// only used for script dialog.
if ( switchers[i]->free != NULL ) {
switchers[i]->free ( switchers[i] );
} }
} }
g_free ( switchers ); g_free ( switchers );
@ -1576,42 +1565,29 @@ static void setup_switchers ( void )
token != NULL; token != NULL;
token = strtok_r ( NULL, ",", &savept ) ) { token = strtok_r ( NULL, ",", &savept ) ) {
// Resize and add entry. // Resize and add entry.
switchers = (Switcher *) g_realloc ( switchers, switchers = (Switcher * *) g_realloc ( switchers,
sizeof ( Switcher ) * ( num_switchers + 1 ) ); sizeof ( Switcher* ) * ( num_switchers + 1 ) );
switchers[num_switchers].cb_data = NULL;
switchers[num_switchers].cb_data_free = NULL;
switchers[num_switchers].keystr = NULL;
switchers[num_switchers].keycfg = NULL;
switchers[num_switchers].keysym = None;
switchers[num_switchers].modmask = AnyModifier;
// Window switcher. // Window switcher.
if ( strcasecmp ( token, "window" ) == 0 ) { if ( strcasecmp ( token, "window" ) == 0 ) {
g_strlcpy ( switchers[num_switchers].name, "window", 32 ); switchers[num_switchers] = &window_mode;
switchers[num_switchers].cb = run_switcher_window;
num_switchers++; num_switchers++;
} }
// SSh dialog // SSh dialog
else if ( strcasecmp ( token, "ssh" ) == 0 ) { else if ( strcasecmp ( token, "ssh" ) == 0 ) {
g_strlcpy ( switchers[num_switchers].name, "ssh", 32 ); switchers[num_switchers] = &ssh_mode;
switchers[num_switchers].cb = ssh_switcher_dialog;
num_switchers++; num_switchers++;
} }
// Run dialog // Run dialog
else if ( strcasecmp ( token, "run" ) == 0 ) { else if ( strcasecmp ( token, "run" ) == 0 ) {
g_strlcpy ( switchers[num_switchers].name, "run", 32 ); switchers[num_switchers] = &run_mode;
switchers[num_switchers].cb = run_switcher_dialog;
num_switchers++; num_switchers++;
} }
else { else {
// If not build in, use custom switchers. // If not build in, use custom switchers.
ScriptOptions *sw = script_switcher_parse_setup ( token ); Switcher *sw = script_switcher_parse_setup ( token );
if ( sw != NULL ) { if ( sw != NULL ) {
// Resize and add entry. switchers[num_switchers] = sw;
g_strlcpy ( switchers[num_switchers].name, sw->name, 32 );
switchers[num_switchers].cb = script_switcher_dialog;
switchers[num_switchers].cb_data = sw;
switchers[num_switchers].cb_data_free = script_switcher_free_options;
num_switchers++; num_switchers++;
} }
else{ else{
@ -1627,10 +1603,10 @@ static void setup_switchers ( void )
// We cannot do this in main loop, as we create pointer to string, // We cannot do this in main loop, as we create pointer to string,
// and re-alloc moves that pointer. // and re-alloc moves that pointer.
for ( unsigned int i = 0; i < num_switchers; i++ ) { for ( unsigned int i = 0; i < num_switchers; i++ ) {
switchers[i].keycfg = g_strdup_printf ( "key-%s", switchers[i].name ); switchers[i]->keycfg = g_strdup_printf ( "key-%s", switchers[i]->name );
config_parser_add_option ( xrm_String, config_parser_add_option ( xrm_String,
switchers[i].keycfg, switchers[i]->keycfg,
(void * *) &( switchers[i].keystr ) ); (void * *) &( switchers[i]->keystr ) );
} }
} }
@ -1809,9 +1785,9 @@ int main ( int argc, char *argv[] )
else{ else{
// Daemon mode, Listen to key presses.. // Daemon mode, Listen to key presses..
for ( unsigned int i = 0; i < num_switchers; i++ ) { for ( unsigned int i = 0; i < num_switchers; i++ ) {
if ( switchers[i].keystr != NULL ) { if ( switchers[i]->keystr != NULL ) {
x11_parse_key ( switchers[i].keystr, &( switchers[i].modmask ), &( switchers[i].keysym ) ); x11_parse_key ( switchers[i]->keystr, &( switchers[i]->modmask ), &( switchers[i]->keysym ) );
x11_grab_key ( display, switchers[i].modmask, switchers[i].keysym ); x11_grab_key ( display, switchers[i]->modmask, switchers[i]->keysym );
} }
} }
// Setup handler for sighup (reload config) // Setup handler for sighup (reload config)
@ -1843,3 +1819,33 @@ int main ( int argc, char *argv[] )
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
SwitcherMode switcher_run ( char **input, Switcher *sw )
{
int selected_line = 0;
SwitcherMode retv = MODE_EXIT;
unsigned int cmd_list_length = 0;
char **cmd_list = NULL;
cmd_list = sw->get_data ( &cmd_list_length, sw );
if ( cmd_list == NULL ) {
cmd_list = g_malloc_n ( 2, sizeof ( char * ) );
cmd_list[0] = g_strdup ( "No applications found" );
cmd_list[1] = NULL;
}
char *prompt = g_strdup_printf ( "%s:", sw->name );
int mretv = menu ( cmd_list, cmd_list_length, input, prompt,
NULL, sw->token_match, sw, &selected_line,
config.levenshtein_sort );
retv = sw->result ( mretv, input, selected_line, sw );
g_free ( prompt );
return retv;
}