Indent the bunch with my astyle line.

This commit is contained in:
Qball Cow 2014-01-10 10:35:38 +01:00
parent bad311adab
commit b47f22ca51
3 changed files with 961 additions and 886 deletions

View File

@ -24,12 +24,16 @@ normal:
debug:
$(CC) -o simpleswitcher-debug simpleswitcher.c -std=c99 $(CFLAGS) -Wunused-parameter -g -DDEBUG $(LDADD)
install: install-man
install: normal install-man
install -Dm 755 simpleswitcher $(BINDIR)/simpleswitcher
install-man:
install -Dm 644 simpleswitcher.1 $(MANDIR)
gzip $(MANDIR)/simpleswitcher.1
gzip -f $(MANDIR)/simpleswitcher.1
clean:
rm -f simpleswitcher simpleswitcher-debug
indent:
@astyle --style=linux -S -C -D -N -H -L -W3 -f simpleswitcher.c textbox.c

View File

@ -61,11 +61,12 @@
static void* allocate( unsigned long bytes )
{
void *ptr = malloc( bytes );
if (!ptr)
{
if ( !ptr ) {
fprintf( stderr, "malloc failed!\n" );
exit( EXIT_FAILURE );
}
return ptr;
}
static void* allocate_clear( unsigned long bytes )
@ -77,17 +78,19 @@ static void* allocate_clear(unsigned long bytes)
static void* reallocate( void *ptr, unsigned long bytes )
{
ptr = realloc( ptr, bytes );
if (!ptr)
{
if ( !ptr ) {
fprintf( stderr, "realloc failed!\n" );
exit( EXIT_FAILURE );
}
return ptr;
}
static inline char **tokenize( const char *input )
{
if ( input == NULL ) return NULL;
char *saveptr = NULL, *token;
char **retv = NULL;
// First entry is always full (modified) stringtext.
@ -102,8 +105,7 @@ static inline char **tokenize(const char *input)
for (
token = strtok_r( retv[0], " ", &saveptr );
token != NULL;
token = strtok_r(NULL, " ", &saveptr))
{
token = strtok_r( NULL, " ", &saveptr ) ) {
retv = realloc( retv, sizeof( char* )*( num_tokens+2 ) );
retv[num_tokens+1] = NULL;
retv[num_tokens] = token;
@ -116,8 +118,10 @@ static inline char **tokenize(const char *input)
static inline void tokenize_free( char **ip )
{
if ( ip == NULL ) return;
if ( ip[0] )
free( ip[0] );
free( ip );
}
@ -136,21 +140,25 @@ int execsh(char *cmd)
pid_t exec_cmd( char *cmd )
{
if ( !cmd || !cmd[0] ) return -1;
signal( SIGCHLD, catch_exit );
pid_t pid = fork();
if (!pid)
{
if ( !pid ) {
setsid();
execsh( cmd );
exit( EXIT_FAILURE );
}
return pid;
}
// cli arg handling
static int find_arg( const int argc, char * const argv[], const char * const key )
{
int i;
for ( i = 0; i < argc && strcasecmp( argv[i], key ); i++ );
return i < argc ? i: -1;
}
static char* find_arg_str( int argc, char *argv[], char *key, char* def )
@ -165,7 +173,8 @@ static int find_arg_int(int argc, char *argv[], char *key, int def)
}
unsigned int NumlockMask = 0;
Display *display; Screen *screen;
Display *display;
Screen *screen;
Window root;
int screen_id;
@ -228,6 +237,7 @@ int oops(__attribute__((unused)) Display *d, XErrorEvent *ee)
|| ( ee->request_code == X_GrabButton && ee->error_code == BadAccess )
|| ( ee->request_code == X_GrabKey && ee->error_code == BadAccess )
) return 0;
fprintf( stderr, "error: request code=%d, error code=%d\n", ee->request_code, ee->error_code );
return xerror( display, ee );
}
@ -255,18 +265,19 @@ winlist *cache_xattr;
winlist* winlist_new()
{
winlist *l = allocate(sizeof(winlist)); l->len = 0;
winlist *l = allocate( sizeof( winlist ) );
l->len = 0;
l->array = allocate( sizeof( Window ) * ( WINLIST+1 ) );
l->data = allocate( sizeof( void* ) * ( WINLIST+1 ) );
return l;
}
int winlist_append( winlist *l, Window w, void *d )
{
if (l->len > 0 && !(l->len % WINLIST))
{
if ( l->len > 0 && !( l->len % WINLIST ) ) {
l->array = reallocate( l->array, sizeof( Window ) * ( l->len+WINLIST+1 ) );
l->data = reallocate( l->data, sizeof( void* ) * ( l->len+WINLIST+1 ) );
}
l->data[l->len] = d;
l->array[l->len++] = w;
return l->len-1;
@ -277,7 +288,10 @@ void winlist_empty(winlist *l)
}
void winlist_free( winlist *l )
{
winlist_empty(l); free(l->array); free(l->data); free(l);
winlist_empty( l );
free( l->array );
free( l->data );
free( l );
}
void winlist_empty_2d( winlist *l )
{
@ -287,18 +301,27 @@ int winlist_find(winlist *l, Window w)
{
// iterate backwards. theory is: windows most often accessed will be
// nearer the end. testing with kcachegrind seems to support this...
int i; Window o; winlist_descend(l, i, o) if (w == o) return i;
int i;
Window o;
winlist_descend( l, i, o ) if ( w == o ) return i;
return -1;
}
int winlist_forget( winlist *l, Window w )
{
int i, j;
for (i = 0, j = 0; i < l->len; i++, j++)
{
for ( i = 0, j = 0; i < l->len; i++, j++ ) {
l->array[j] = l->array[i];
l->data[j] = l->data[i];
if (l->array[i] == w) { free(l->data[i]); j--; }
if ( l->array[i] == w ) {
free( l->data[i] );
j--;
}
}
l->len -= ( i-j );
return j != i ?1:0;
}
@ -358,25 +381,32 @@ static unsigned int color_get(const char *const name)
// find mouse pointer location
int pointer_get( Window root, int *x, int *y )
{
*x = 0; *y = 0;
Window rr, cr; int rxr, ryr, wxr, wyr; unsigned int mr;
if (XQueryPointer(display, root, &rr, &cr, &rxr, &ryr, &wxr, &wyr, &mr))
{
*x = rxr; *y = ryr;
*x = 0;
*y = 0;
Window rr, cr;
int rxr, ryr, wxr, wyr;
unsigned int mr;
if ( XQueryPointer( display, root, &rr, &cr, &rxr, &ryr, &wxr, &wyr, &mr ) ) {
*x = rxr;
*y = ryr;
return 1;
}
return 0;
}
int take_keyboard( Window w )
{
int i;
for (i = 0; i < 1000; i++)
{
for ( i = 0; i < 1000; i++ ) {
if ( XGrabKeyboard( display, w, True, GrabModeAsync, GrabModeAsync, CurrentTime ) == GrabSuccess )
return 1;
usleep( 1000 );
}
return 0;
}
void release_keyboard()
@ -388,37 +418,51 @@ void release_keyboard()
XWindowAttributes* window_get_attributes( Window w )
{
int idx = winlist_find( cache_xattr, w );
if (idx < 0)
{
if ( idx < 0 ) {
XWindowAttributes *cattr = allocate( sizeof( XWindowAttributes ) );
if (XGetWindowAttributes(display, w, cattr))
{
if ( XGetWindowAttributes( display, w, cattr ) ) {
winlist_append( cache_xattr, w, cattr );
return cattr;
}
free( cattr );
return NULL;
}
return cache_xattr->data[idx];
}
// retrieve a property of any type from a window
int window_get_prop( Window w, Atom prop, Atom *type, int *items, void *buffer, unsigned int bytes )
{
Atom _type; if (!type) type = &_type;
int _items; if (!items) items = &_items;
int format; unsigned long nitems, nbytes; unsigned char *ret = NULL;
Atom _type;
if ( !type ) type = &_type;
int _items;
if ( !items ) items = &_items;
int format;
unsigned long nitems, nbytes;
unsigned char *ret = NULL;
memset( buffer, 0, bytes );
if ( XGetWindowProperty( display, w, prop, 0, bytes/4, False, AnyPropertyType, type,
&format, &nitems, &nbytes, &ret) == Success && ret && *type != None && format)
{
&format, &nitems, &nbytes, &ret ) == Success && ret && *type != None && format ) {
if ( format == 8 ) memmove( buffer, ret, MIN( bytes, nitems ) );
if ( format == 16 ) memmove( buffer, ret, MIN( bytes, nitems * sizeof( short ) ) );
if ( format == 32 ) memmove( buffer, ret, MIN( bytes, nitems * sizeof( long ) ) );
*items = (int)nitems; XFree(ret);
*items = ( int )nitems;
XFree( ret );
return 1;
}
return 0;
}
@ -426,30 +470,31 @@ int window_get_prop(Window w, Atom prop, Atom *type, int *items, void *buffer, u
// technically we could use window_get_prop(), but this is better for character set support
char* window_get_text_prop( Window w, Atom atom )
{
XTextProperty prop; char *res = NULL;
char **list = NULL; int count;
if (XGetTextProperty(display, w, &prop, atom) && prop.value && prop.nitems)
{
if (prop.encoding == XA_STRING)
{
XTextProperty prop;
char *res = NULL;
char **list = NULL;
int count;
if ( XGetTextProperty( display, w, &prop, atom ) && prop.value && prop.nitems ) {
if ( prop.encoding == XA_STRING ) {
res = allocate( strlen( ( char* )prop.value )+1 );
strcpy( res, ( char* )prop.value );
}
else
if (XmbTextPropertyToTextList(display, &prop, &list, &count) >= Success && count > 0 && *list)
{
} else if ( XmbTextPropertyToTextList( display, &prop, &list, &count ) >= Success && count > 0 && *list ) {
res = allocate( strlen( *list )+1 );
strcpy( res, *list );
XFreeStringList( list );
}
}
if ( prop.value ) XFree( prop.value );
return res;
}
int window_get_atom_prop( Window w, Atom atom, Atom *list, int count )
{
Atom type; int items;
Atom type;
int items;
return window_get_prop( w, atom, &type, &items, list, count*sizeof( Atom ) ) && type == XA_ATOM ? items:0;
}
@ -460,18 +505,23 @@ void window_set_atom_prop(Window w, Atom prop, Atom *atoms, int count)
int window_get_cardinal_prop( Window w, Atom atom, unsigned long *list, int count )
{
Atom type; int items;
Atom type;
int items;
return window_get_prop( w, atom, &type, &items, list, count*sizeof( unsigned long ) ) && type == XA_CARDINAL ? items:0;
}
// a ClientMessage
int window_send_message( Window target, Window subject, Atom atom, unsigned long protocol, unsigned long mask, Time time )
{
XEvent e; memset(&e, 0, sizeof(XEvent));
XEvent e;
memset( &e, 0, sizeof( XEvent ) );
e.xclient.type = ClientMessage;
e.xclient.message_type = atom; e.xclient.window = subject;
e.xclient.data.l[0] = protocol; e.xclient.data.l[1] = time;
e.xclient.send_event = True; e.xclient.format = 32;
e.xclient.message_type = atom;
e.xclient.window = subject;
e.xclient.data.l[0] = protocol;
e.xclient.data.l[1] = time;
e.xclient.send_event = True;
e.xclient.format = 32;
int r = XSendEvent( display, target, False, mask, &e ) ?1:0;
XFlush( display );
return r;
@ -485,19 +535,20 @@ void monitor_dimensions(Screen *screen, int x, int y, workarea *mon)
mon->h = HeightOfScreen( screen );
// locate the current monitor
if (XineramaIsActive(display))
{
if ( XineramaIsActive( display ) ) {
int monitors, i;
XineramaScreenInfo *info = XineramaQueryScreens( display, &monitors );
if (info) for (i = 0; i < monitors; i++)
{
if (INTERSECT(x, y, 1, 1, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
{
mon->x = info[i].x_org; mon->y = info[i].y_org;
mon->w = info[i].width; mon->h = info[i].height;
if ( info ) for ( i = 0; i < monitors; i++ ) {
if ( INTERSECT( x, y, 1, 1, info[i].x_org, info[i].y_org, info[i].width, info[i].height ) ) {
mon->x = info[i].x_org;
mon->y = info[i].y_org;
mon->w = info[i].width;
mon->h = info[i].height;
break;
}
}
XFree( info );
}
}
@ -507,20 +558,24 @@ void monitor_active(workarea *mon)
{
Window root = RootWindow( display, XScreenNumberOfScreen( screen ) );
unsigned long id; Atom type; int count;
unsigned long id;
Atom type;
int count;
if ( window_get_prop( root, netatoms[_NET_ACTIVE_WINDOW], &type, &count, &id, 1 )
&& type == XA_WINDOW && count > 0)
{
&& type == XA_WINDOW && count > 0 ) {
XWindowAttributes *attr = window_get_attributes( id );
monitor_dimensions( screen, attr->x, attr->y, mon );
return;
}
int x, y;
if (pointer_get(root, &x, &y))
{
if ( pointer_get( root, &x, &y ) ) {
monitor_dimensions( screen, x, y, mon );
return;
}
monitor_dimensions( screen, 0, 0, mon );
}
@ -528,8 +583,10 @@ void monitor_active(workarea *mon)
int client_has_state( client *c, Atom state )
{
int i;
for ( i = 0; i < c->states; i++ )
if ( c->state[i] == state ) return 1;
return 0;
}
@ -538,11 +595,14 @@ int client_has_state(client *c, Atom state)
client* window_client( Window win )
{
if ( win == None ) return NULL;
int idx = winlist_find( cache_client, win );
if ( idx >= 0 ) return cache_client->data[idx];
// if this fails, we're up that creek
XWindowAttributes *attr = window_get_attributes( win );
if ( !attr ) return NULL;
client *c = allocate_clear( sizeof( client ) );
@ -561,24 +621,24 @@ client* window_client(Window win)
: netatoms[_NET_WM_WINDOW_TYPE_NORMAL];
char *name;
if ((name = window_get_text_prop(c->window, netatoms[_NET_WM_NAME])) && name)
{
if ( ( name = window_get_text_prop( c->window, netatoms[_NET_WM_NAME] ) ) && name ) {
snprintf( c->title, CLIENTTITLE, "%s", name );
free( name );
}
else
if (XFetchName(display, c->window, &name))
{
} else if ( XFetchName( display, c->window, &name ) ) {
snprintf( c->title, CLIENTTITLE, "%s", name );
XFree( name );
}
XClassHint chint;
if (XGetClassHint(display, c->window, &chint))
{
if ( XGetClassHint( display, c->window, &chint ) ) {
snprintf( c->class, CLIENTCLASS, "%s", chint.res_class );
snprintf( c->name, CLIENTNAME, "%s", chint.res_name );
XFree(chint.res_class); XFree(chint.res_name);
XFree( chint.res_class );
XFree( chint.res_name );
}
monitor_dimensions( c->xattr.screen, c->xattr.x, c->xattr.y, &c->monitor );
winlist_append( cache_client, c->window, c );
return c;
@ -587,7 +647,8 @@ client* window_client(Window win)
#define ALLWINDOWS 1
#define DESKTOPWINDOWS 2
unsigned int windows_modmask; KeySym windows_keysym;
unsigned int windows_modmask;
KeySym windows_keysym;
// flags to set if we switch modes on the fly
int run_windows = 0;
Window main_window = None;
@ -598,8 +659,8 @@ void menu_draw(textbox *text, textbox **boxes, int max_lines, int selected, char
{
int i;
textbox_draw( text );
for (i = 0; i < max_lines; i++)
{
for ( i = 0; i < max_lines; i++ ) {
textbox_font( boxes[i], config_menu_font,
i == selected ? config_menu_hlfg: config_menu_fg,
i == selected ? config_menu_hlbg: config_menu_bg );
@ -615,31 +676,42 @@ void menu_draw(textbox *text, textbox **boxes, int max_lines, int selected, char
static int calculate_common_prefix( char **filtered, int max_lines )
{
int length_prefix = 0,j,found = 1;
if ( filtered[0] != NULL ) {
char *p = filtered[0];
do {
found = 1;
for ( j=0; j < max_lines && filtered[j] != NULL; j++ ) {
if ( filtered[j][length_prefix] == '\0' || filtered[j][length_prefix] != *p ) {
if ( found )
found=0;
break;
}
}
if ( found )
length_prefix++;
p++;
} while ( found );
}
return length_prefix;
}
int menu( char **lines, char **input, char *prompt, int selected, Time *time )
{
int line = -1, i, j, chosen = 0, aborted = 0;
workarea mon; monitor_active(&mon);
workarea mon;
monitor_active( &mon );
int num_lines = 0;
for ( ; lines[num_lines]; num_lines++ );
int num_lines = 0; for (; lines[num_lines]; num_lines++);
int max_lines = MIN( config_menu_lines, num_lines );
selected = MAX( MIN( num_lines-1, selected ), 0 );
@ -650,18 +722,16 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
XWindowAttributes attr;
// main window isn't explicitly destroyed in case we switch modes. Reusing it prevents flicker
if (main_window != None && XGetWindowAttributes(display, main_window, &attr))
{
if ( main_window != None && XGetWindowAttributes( display, main_window, &attr ) ) {
box = main_window;
}
else
{
} else {
box = XCreateSimpleWindow( display, root, x, 0, w, 300, 1, color_get( config_menu_bc ), color_get( config_menu_bg ) );
XSelectInput( display, box, ExposureMask );
// make it an unmanaged window
window_set_atom_prop( box, netatoms[_NET_WM_STATE], &netatoms[_NET_WM_STATE_ABOVE], 1 );
//window_set_atom_prop(box, netatoms[_NET_WM_WINDOW_TYPE], &netatoms[_NET_WM_WINDOW_TYPE_DOCK], 1);
XSetWindowAttributes sattr; sattr.override_redirect = True;
XSetWindowAttributes sattr;
sattr.override_redirect = True;
XChangeWindowAttributes( display, box, CWOverrideRedirect, &sattr );
main_window = box;
@ -686,8 +756,7 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
// filtered list display
textbox **boxes = allocate_clear( sizeof( textbox* ) * max_lines );
for (i = 0; i < max_lines; i++)
{
for ( i = 0; i < max_lines; i++ ) {
boxes[i] = textbox_create( box, TB_AUTOHEIGHT, 5, ( i+1 ) * line_height + 5, w-10, 1,
config_menu_font, config_menu_fg, config_menu_bg, lines[i], NULL );
textbox_show( boxes[i] );
@ -699,8 +768,8 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
int filtered_lines = 0;
int jin = 0;
for (i = 0; i < max_lines; i++)
{
for ( i = 0; i < max_lines; i++ ) {
filtered[jin] = lines[i];
line_map[jin] = i;
jin++;
@ -714,90 +783,87 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
XMapRaised( display, box );
take_keyboard( box );
for (;;)
{
for ( ;; ) {
XEvent ev;
XNextEvent( display, &ev );
if (ev.type == Expose)
{
if ( ev.type == Expose ) {
while ( XCheckTypedEvent( display, Expose, &ev ) );
menu_draw( text, boxes, max_lines, selected, filtered );
}
else
if (ev.type == KeyPress)
{
} else if ( ev.type == KeyPress ) {
while ( XCheckTypedEvent( display, KeyPress, &ev ) );
if ( time )
*time = ev.xkey.time;
int rc = textbox_keypress( text, &ev );
if (rc < 0)
{
if ( rc < 0 ) {
chosen = 1;
break;
}
else
if (rc)
{
} else if ( rc ) {
char **tokens = tokenize( text->text );
// input changed
for (i = 0, j = 0; i < num_lines && j < max_lines; i++)
{
for ( i = 0, j = 0; i < num_lines && j < max_lines; i++ ) {
int match = 1;
// Do a tokenized match.
if(tokens) for(int j = 1; match && tokens[j]; j++)
{
if ( tokens ) for ( int j = 1; match && tokens[j]; j++ ) {
match = ( strcasestr( lines[i], tokens[j] ) != NULL );
}
// If each token was matched, add it to list.
if(match)
{
if ( match ) {
line_map[j] = i;
filtered[j++] = lines[i];
}
}
// Cleanup + bookkeeping.
filtered_lines = j;
selected = MAX( 0, MIN( selected, j-1 ) );
for ( ; j < max_lines; j++ )
filtered[j] = NULL;
if ( config_zeltak_mode && filtered_lines == 1 ) {
chosen = 1;
break;
}
tokenize_free( tokens );
}
else
{
} else {
// unhandled key
KeySym key = XkbKeycodeToKeysym( display, ev.xkey.keycode, 0, 0 );
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 )
)
{
) {
aborted = 1;
break;
}
else
// Up or Shift-Tab
if ( key == XK_Up || ( key == XK_Tab && ev.xkey.state & ShiftMask ) )
selected = selected ? MAX( 0, selected-1 ): MAX( 0, filtered_lines-1 );
else
// Down or Tab
if (key == XK_Down || key == XK_Tab)
{
if ( key == XK_Down || key == XK_Tab ) {
if ( filtered_lines == 1 ) {
chosen = 1;
break;
}
int length_prefix = calculate_common_prefix( filtered, max_lines );
if ( length_prefix && strncasecmp( filtered[0], text->text, length_prefix ) ) {
// Do not want to modify original string, so make copy.
// not eff..
@ -805,14 +871,15 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
textbox_text( text, str );
textbox_cursor_end( text );
free( str );
}
else
} else
selected = selected < filtered_lines-1 ? MIN( filtered_lines-1, selected+1 ): 0;
}
}
menu_draw( text, boxes, max_lines, selected, filtered );
}
}
release_keyboard();
if ( chosen && filtered[selected] )
@ -822,6 +889,7 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
*input = strdup( text->text );
textbox_free( text );
for ( i = 0; i < max_lines; i++ )
textbox_free( boxes[i] );
@ -845,9 +913,9 @@ void run_switcher(int fmode)
// this also happens to isolate the Xft font stuff in a child process
// that gets cleaned up every time. that library shows some valgrind
// strangeness...
if (fmode == FORK)
{
if ( fmode == FORK ) {
if ( fork() ) return;
display = XOpenDisplay( 0 );
XSync( display, True );
}
@ -858,7 +926,8 @@ void run_switcher(int fmode)
int i, plen = 0, lines = 0;
unsigned int classfield = 0;
unsigned long desktops = 0, current_desktop = 0;
Window w; client *c;
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...
@ -868,21 +937,23 @@ void run_switcher(int fmode)
current_desktop = 0;
// find window list
Atom type; int nwins; unsigned long *wins = allocate_clear(sizeof(unsigned long) * 100);
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)
{
&& type == XA_WINDOW ) {
// calc widths of fields
for (i = nwins-1; i > -1; i--)
{
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]))
{
&& !client_has_state( c, netatoms[_NET_WM_STATE_SKIP_TASKBAR] ) ) {
classfield = MAX( classfield, strlen( c->class ) );
// In i3 mode, skip the i3bar completely.
if ( config_i3_mode && strstr( c->class, "i3bar" ) != NULL ) continue;
winlist_append( ids, c->window, NULL );
}
}
@ -892,13 +963,12 @@ void run_switcher(int fmode)
plen += sprintf( pattern+plen, "%%-%ds %%s", MAX( 5, classfield ) );
list = allocate_clear(sizeof(char*) * (ids->len+1)); lines = 0;
list = allocate_clear( sizeof( char* ) * ( ids->len+1 ) );
lines = 0;
// build the actual list
winlist_ascend(ids, i, w)
{
if ((c = window_client(w)))
{
winlist_ascend( ids, i, w ) {
if ( ( c = window_client( w ) ) ) {
// final line format
char *line = allocate( strlen( c->title ) + strlen( c->class ) + classfield + 50 );
@ -910,43 +980,41 @@ void run_switcher(int fmode)
char *input = NULL;
Time time;
int n = menu( list, &input, "> ", 1, &time );
if (n >= 0 && list[n])
{
if(config_i3_mode)
{
if ( n >= 0 && list[n] ) {
if ( config_i3_mode ) {
// Hack for i3.
char array[128];
snprintf( array,128,"i3-msg [id=\"%d\"] focus",( int )( ids->array[n] ) );
printf( "Executing: %s\n", array );
exec_cmd( array );
}
else
{
if (isdigit(list[n][0]))
{
} else {
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 );
}
}
else
} else
// act as a launcher
if (input)
{
if ( input ) {
exec_cmd( input );
}
for ( i = 0; i < lines; i++ )
free( list[i] );
free( list );
}
free( wins );
winlist_free( ids );
}
while (run_windows );
} while ( run_windows );
if ( fmode == FORK )
exit( EXIT_SUCCESS );
@ -965,24 +1033,34 @@ void handle_keypress(XEvent *ev)
void parse_key( char *combo, unsigned int *mod, KeySym *key )
{
unsigned int modmask = 0;
if ( strcasestr( combo, "shift" ) ) modmask |= ShiftMask;
if ( strcasestr( combo, "control" ) ) modmask |= ControlMask;
if ( strcasestr( combo, "mod1" ) ) modmask |= Mod1Mask;
if ( strcasestr( combo, "mod2" ) ) modmask |= Mod2Mask;
if ( strcasestr( combo, "mod3" ) ) modmask |= Mod3Mask;
if ( strcasestr( combo, "mod4" ) ) modmask |= Mod4Mask;
if ( strcasestr( combo, "mod5" ) ) modmask |= Mod5Mask;
*mod = modmask ? modmask: AnyModifier;
char i = strlen( combo );
while ( i > 0 && !strchr( "-+", combo[i-1] ) ) i--;
KeySym sym = XStringToKeysym( combo+i );
if (sym == NoSymbol || (!modmask && (strchr(combo, '-') || strchr(combo, '+'))))
{
if ( sym == NoSymbol || ( !modmask && ( strchr( combo, '-' ) || strchr( combo, '+' ) ) ) ) {
fprintf( stderr, "sorry, cannot understand key combination: %s\n", combo );
exit( EXIT_FAILURE );
}
*key = sym;
}
@ -992,19 +1070,16 @@ void grab_key(unsigned int modmask, KeySym key)
KeyCode keycode = XKeysymToKeycode( display, key );
XUngrabKey( display, keycode, AnyModifier, root );
if (modmask != AnyModifier)
{
if ( modmask != AnyModifier ) {
// bind to combinations of mod and lock masks, so caps and numlock don't confuse people
XGrabKey( display, keycode, modmask, root, True, GrabModeAsync, GrabModeAsync );
XGrabKey( display, keycode, modmask|LockMask, root, True, GrabModeAsync, GrabModeAsync );
if (NumlockMask)
{
if ( NumlockMask ) {
XGrabKey( display, keycode, modmask|NumlockMask, root, True, GrabModeAsync, GrabModeAsync );
XGrabKey( display, keycode, modmask|NumlockMask|LockMask, root, True, GrabModeAsync, GrabModeAsync );
}
}
else
{
} else {
// nice simple single key bind
XGrabKey( display, keycode, AnyModifier, root, True, GrabModeAsync, GrabModeAsync );
}
@ -1017,32 +1092,37 @@ int main(int argc, char *argv[])
// catch help request
if ( find_arg( argc, argv, "-help" ) >= 0
|| find_arg( argc, argv, "--help" ) >= 0
|| find_arg(argc, argv, "-h") >= 0)
{
|| find_arg( argc, argv, "-h" ) >= 0 ) {
fprintf( stderr, "See the man page or visit http://github.com/DaveDavenport/simpleswitcher\n" );
fprintf( stderr, "Original code can be found: http://github.com/seanpringle/simpleswitcher\n" );
return EXIT_FAILURE;
}
if(!(display = XOpenDisplay(0)))
{
if ( !( display = XOpenDisplay( 0 ) ) ) {
fprintf( stderr, "cannot open display!\n" );
return EXIT_FAILURE;
}
signal( SIGCHLD, catch_exit );
screen = DefaultScreenOfDisplay( display );
screen_id = DefaultScreen( display );
root = DefaultRootWindow( display );
XSync(display, False); xerror = XSetErrorHandler(oops); XSync(display, False);
XSync( display, False );
xerror = XSetErrorHandler( oops );
XSync( display, False );
// determine numlock mask so we can bind on keys with and without it
XModifierKeymap *modmap = XGetModifierMapping( display );
for ( i = 0; i < 8; i++ )
for ( j = 0; j < ( int )modmap->max_keypermod; j++ )
if ( modmap->modifiermap[i*modmap->max_keypermod+j] == XKeysymToKeycode( display, XK_Num_Lock ) )
NumlockMask = ( 1<<i );
XFreeModifiermap( modmap );
int ac = argc; char **av = argv;
int ac = argc;
char **av = argv;
cache_client = winlist_new();
cache_xattr = winlist_new();
@ -1065,8 +1145,7 @@ int main(int argc, char *argv[])
config_i3_mode = ( find_arg( ac, av, "-i3" ) >= 0 );
// flags to run immediately and exit
if (find_arg(ac, av, "-now") >= 0)
{
if ( find_arg( ac, av, "-now" ) >= 0 ) {
run_switcher( NOFORK );
exit( EXIT_SUCCESS );
}
@ -1081,17 +1160,19 @@ int main(int argc, char *argv[])
grab_key( windows_modmask, windows_keysym );
XEvent ev;
for (;;)
{
for ( ;; ) {
// caches only live for a single event
winlist_empty( cache_xattr );
winlist_empty( cache_client );
// block and wait for something
XNextEvent( display, &ev );
if ( ev.xany.window == None ) continue;
if ( ev.type == KeyPress ) handle_keypress( &ev );
}
return EXIT_SUCCESS;
}

View File

@ -56,9 +56,13 @@ textbox* textbox_create(Window parent, unsigned long flags, short x, short y, sh
tb->flags = flags;
tb->parent = parent;
tb->x = x; tb->y = y; tb->w = MAX(1, w); tb->h = MAX(1, h);
tb->x = x;
tb->y = y;
tb->w = MAX( 1, w );
tb->h = MAX( 1, h );
XColor color; Colormap map = DefaultColormap(display, DefaultScreen(display));
XColor color;
Colormap map = DefaultColormap( display, DefaultScreen( display ) );
unsigned int cp = XAllocNamedColor( display, map, bg, &color, &color ) ? color.pixel: None;
tb->window = XCreateSimpleWindow( display, tb->parent, tb->x, tb->y, tb->w, tb->h, 0, None, cp );
@ -73,8 +77,7 @@ textbox* textbox_create(Window parent, unsigned long flags, short x, short y, sh
textbox_moveresize( tb, tb->x, tb->y, tb->w, tb->h );
// edit mode controls
if (tb->flags & TB_EDITABLE)
{
if ( tb->flags & TB_EDITABLE ) {
tb->xim = XOpenIM( display, NULL, NULL, NULL );
tb->xic = XCreateIC( tb->xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, tb->window, XNFocusWindow, tb->window, NULL );
}
@ -86,6 +89,7 @@ textbox* textbox_create(Window parent, unsigned long flags, short x, short y, sh
void textbox_font( textbox *tb, char *font, char *fg, char *bg )
{
if ( tb->font ) XftFontClose( display, tb->font );
tb->font = XftFontOpenName( display, DefaultScreen( display ), font );
XftColorAllocName( display, DefaultVisual( display, DefaultScreen( display ) ), DefaultColormap( display, DefaultScreen( display ) ), fg, &tb->color_fg );
@ -105,6 +109,7 @@ void textbox_extents(textbox *tb)
void textbox_text( textbox *tb, char *text )
{
if ( tb->text ) free( tb->text );
tb->text = strdup( text );
tb->cursor = MAX( 0,MIN( ( int )strlen( text ), tb->cursor ) );
textbox_extents( tb );
@ -114,6 +119,7 @@ void textbox_text(textbox *tb, char *text)
void textbox_prompt( textbox *tb, char *text )
{
if ( tb->prompt ) free( tb->prompt );
tb->prompt = strdup( text );
textbox_extents( tb );
}
@ -127,9 +133,11 @@ void textbox_moveresize(textbox *tb, int x, int y, int w, int h)
if ( tb->flags & TB_AUTOWIDTH )
w = tb->extents.width;
if (x != tb->x || y != tb->y || w != tb->w || h != tb->h)
{
tb->x = x; tb->y = y; tb->w = MAX(1, w); tb->h = MAX(1, h);
if ( x != tb->x || y != tb->y || w != tb->w || h != tb->h ) {
tb->x = x;
tb->y = y;
tb->w = MAX( 1, w );
tb->h = MAX( 1, h );
XMoveResizeWindow( display, tb->window, tb->x, tb->y, tb->w, tb->h );
}
}
@ -147,14 +155,15 @@ void textbox_hide(textbox *tb)
// will also unmap the window if still displayed
void textbox_free( textbox *tb )
{
if (tb->flags & TB_EDITABLE)
{
if ( tb->flags & TB_EDITABLE ) {
XDestroyIC( tb->xic );
XCloseIM( tb->xim );
}
if ( tb->text ) free( tb->text );
if ( tb->prompt ) free( tb->prompt );
if ( tb->font ) XftFontClose( display, tb->font );
XDestroyWindow( display, tb->window );
@ -186,8 +195,7 @@ void textbox_draw(textbox *tb)
int cursor_offset = 0;
int cursor_width = MAX( 2, line_height/10 );
if (tb->flags & TB_EDITABLE)
{
if ( tb->flags & TB_EDITABLE ) {
int prompt_len = strlen( prompt );
length = text_len + prompt_len;
cursor_offset = MIN( tb->cursor + prompt_len, length );
@ -211,7 +219,9 @@ void textbox_draw(textbox *tb)
line_width = extents.width;
int x = 2, y = tb->font->ascent;
if ( tb->flags & TB_RIGHT ) x = tb->w - line_width;
if ( tb->flags & TB_CENTER ) x = ( tb->w - line_width ) / 2;
// draw the text, including any prompt in edit mode
@ -302,8 +312,7 @@ void textbox_cursor_del(textbox *tb)
// back up and delete one character
void textbox_cursor_bkspc( textbox *tb )
{
if (tb->cursor > 0)
{
if ( tb->cursor > 0 ) {
textbox_cursor_dec( tb );
textbox_cursor_del( tb );
}
@ -315,60 +324,41 @@ void textbox_cursor_bkspc(textbox *tb)
// -1 = handled and return pressed (finished)
int textbox_keypress( textbox *tb, XEvent *ev )
{
KeySym key; Status stat;
char pad[32]; int len;
KeySym key;
Status stat;
char pad[32];
int len;
if ( !( tb->flags & TB_EDITABLE ) ) return 0;
len = XmbLookupString( tb->xic, &ev->xkey, pad, sizeof( pad ), &key, &stat );
pad[len] = 0;
if (key == XK_Left)
{
if ( key == XK_Left ) {
textbox_cursor_dec( tb );
return 1;
}
else
if (key == XK_Right)
{
} else if ( key == XK_Right ) {
textbox_cursor_inc( tb );
return 1;
}
else
if (key == XK_Home)
{
} else if ( key == XK_Home ) {
textbox_cursor_home( tb );
return 1;
}
else
if (key == XK_End)
{
} else if ( key == XK_End ) {
textbox_cursor_end( tb );
return 1;
}
else
if (key == XK_Delete)
{
} else if ( key == XK_Delete ) {
textbox_cursor_del( tb );
return 1;
}
else
if (key == XK_BackSpace)
{
} else if ( key == XK_BackSpace ) {
textbox_cursor_bkspc( tb );
return 1;
}
else
if (key == XK_Return)
{
} else if ( key == XK_Return ) {
return -1;
}
else
if (!iscntrl(*pad))
{
} else if ( !iscntrl( *pad ) ) {
textbox_insert( tb, tb->cursor, pad );
textbox_cursor_inc( tb );
return 1;
}
return 0;
}