1
0
Fork 0
mirror of https://github.com/davatorium/rofi.git synced 2025-04-21 17:52:51 -04:00

port fixes from goomwwm switcher

This commit is contained in:
seanpringle 2012-07-18 22:14:13 +10:00
parent 08464e902f
commit 66e3cabefc
2 changed files with 115 additions and 90 deletions

View file

@ -74,6 +74,20 @@ Set the background text color (X11 named color or hex #rrggbb) for the menu (def
simpleswitcher -fg "#222222"
.RE
.TP
.B -bc
Set the border color (X11 named color or hex #rrggbb) for the menu (default: #000000).
.P
.RS
simpleswitcher -bc black
.RE
.TP
.B -bw
Set the border width in pixels (default: 1).
.P
.RS
simpleswitcher -bw 1
.RE
.TP
.B -fg
Set the foreground text color (X11 named color or hex #rrggbb) for the menu (default: #cccccc).
.P

View file

@ -95,12 +95,6 @@ char* find_arg_str(int argc, char *argv[], char *key, char* def)
int i = find_arg(argc, argv, key);
return (i > 0 && i < argc-1) ? argv[i+1]: def;
}
int find_arg_opts(int argc, char *argv[], char *key, char **list, int count)
{
char *s = find_arg_str(argc, argv, key, NULL);
int i; for (i = 0; i < count; i++) if (s && !strcasecmp(s, list[i])) return i;
return -1;
}
int find_arg_int(int argc, char *argv[], char *key, int def)
{
int i = find_arg(argc, argv, key);
@ -108,7 +102,7 @@ int find_arg_int(int argc, char *argv[], char *key, int def)
}
unsigned int NumlockMask = 0;
Display *display;
Display *display; Screen *screen; Window root; int screen_id;
static int (*xerror)(Display *, XErrorEvent *);
@ -263,12 +257,27 @@ typedef struct {
workarea monitor;
} client;
#define MENUXFTFONT "mono-14"
#define MENUWIDTH 50
#define MENULINES 25
#define MENUFG "#222222"
#define MENUBG "#f2f1f0"
#define MENUBGALT "#e9e8e7"
#define MENUHLFG "#ffffff"
#define MENUHLBG "#005577"
#define MENURETURN 1
#define MENUMODUP 2
#define MENUBC "black"
char *config_menu_font, *config_menu_fg, *config_menu_bg, *config_menu_hlfg, *config_menu_hlbg, *config_menu_bgalt, *config_menu_bc;
unsigned int config_menu_width, config_menu_lines, config_focus_mode, config_raise_mode, config_window_placement, config_menu_bw;
// allocate a pixel value for an X named color
unsigned int color_get(Display *d, const char *name)
unsigned int color_get(const char *name)
{
XColor color;
Colormap map = DefaultColormap(d, DefaultScreen(d));
return XAllocNamedColor(d, map, name, &color, &color) ? color.pixel: None;
Colormap map = DefaultColormap(display, screen_id);
return XAllocNamedColor(display, map, name, &color, &color) ? color.pixel: None;
}
// find mouse pointer location
@ -284,6 +293,22 @@ int pointer_get(Window root, int *x, int *y)
return 0;
}
int take_keyboard(Window w)
{
int 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()
{
XUngrabKeyboard(display, CurrentTime);
}
// XGetWindowAttributes with caching
XWindowAttributes* window_get_attributes(Window w)
{
@ -403,7 +428,7 @@ void monitor_dimensions(Screen *screen, int x, int y, workarea *mon)
}
// determine which monitor holds the active window, or failing that the mouse pointer
void monitor_active(Screen *screen, workarea *mon)
void monitor_active(workarea *mon)
{
Window root = RootWindow(display, XScreenNumberOfScreen(screen));
@ -482,17 +507,6 @@ client* window_client(Window win)
return c;
}
#define MENUXFTFONT "mono-14"
#define MENUWIDTH 50
#define MENULINES 25
#define MENUFG "#cccccc"
#define MENUBG "#222222"
#define MENUHLFG "#ffffff"
#define MENUHLBG "#005577"
char *config_menu_font, *config_menu_fg, *config_menu_bg, *config_menu_hlfg, *config_menu_hlbg;
unsigned int config_menu_width, config_menu_lines, config_focus_mode, config_raise_mode, config_window_placement;
// built-in filterable popup menu list
struct localmenu {
Window window;
@ -501,7 +515,7 @@ struct localmenu {
XftFont *font;
XftColor *color;
XftDraw *draw;
XftColor fg, bg, hlfg, hlbg;
XftColor fg, bg, hlfg, hlbg, bgalt;
unsigned long xbg;
char **lines, **filtered;
int done, max_lines, num_lines, input_size, line_height;
@ -517,16 +531,18 @@ void menu_draw(struct localmenu *my)
int i, n;
// draw text input bar
char bar[100]; int len = snprintf(bar, 100, ">.%s", my->input), cursor = MAX(2, my->line_height/10);
XGlyphInfo extents; XftTextExtentsUtf8(display, my->font, (unsigned char*)bar, len, &extents);
bar[1] = ' '; // XftTextExtentsUtf8 trims trailing space. replace the leading period we used to ensure cursor offset
XftDrawRect(my->draw, &my->bg, 0, 0, my->width, my->height);
XftDrawStringUtf8(my->draw, &my->fg, my->font, my->horz_pad, my->vert_pad+my->line_height-my->font->descent, (unsigned char*)my->input, strlen(my->input));
XftDrawStringUtf8(my->draw, &my->fg, my->font, my->horz_pad, my->vert_pad+my->line_height-my->font->descent, (unsigned char*)bar, len);
XftDrawRect(my->draw, &my->fg, extents.width + my->horz_pad + cursor, my->vert_pad+2, cursor, my->line_height-4);
// filter lines by current input text
memset(my->filtered, 0, sizeof(char*) * (my->num_lines+1));
for (i = 0, n = 0; my->lines[i]; i++)
{
if (!my->offset || strcasestr(my->lines[i], my->input))
my->filtered[n++] = my->lines[i];
}
// vertical bounds of highlight bar
my->current = MAX(0, MIN(my->current, n-1));
for (i = 0; my->filtered[i]; i++)
@ -535,12 +551,17 @@ void menu_draw(struct localmenu *my)
// vertical position of *top* of current line
int y = my->vert_pad+(my->line_height*(i+1));
// http://en.wikipedia.org/wiki/Typeface#Font_metrics
int font_baseline = y + my->line_height - my->font->descent -1;
int font_baseline = y + my->line_height - my->font->descent -2;
// are we highlighting this line?
if (i == my->current)
{
fg = my->hlfg;
XftDrawRect(my->draw, &my->hlbg, my->horz_pad, y, my->width-(my->horz_pad*2), my->line_height);
} else
if (!(i%2))
{
// shade alternate lines for better readability
XftDrawRect(my->draw, &my->bgalt, my->horz_pad, y, my->width-(my->horz_pad*2), my->line_height);
}
XftDrawStringUtf8(my->draw, &fg, my->font, my->horz_pad, font_baseline, (unsigned char*)my->filtered[i], strlen(my->filtered[i]));
}
@ -548,6 +569,17 @@ void menu_draw(struct localmenu *my)
XCopyArea(display, my->canvas, my->window, my->gc, 0, 0, my->width, my->height, 0, 0);
}
// select currently highlighted line and exit
void menu_select_current(struct localmenu *my)
{
if (my->filtered[my->current])
my->selected = my->filtered[my->current];
else
if (my->manual)
strcpy(my->manual, my->input);
my->done = 1;
}
// handle popup menu text input for filtering
void menu_key(struct localmenu *my, XEvent *ev)
{
@ -561,27 +593,17 @@ void menu_key(struct localmenu *my, XEvent *ev)
if (key == XK_Escape)
my->done = 1;
else
if (key == XK_BackSpace)
{
if (my->offset > 0)
my->input[--(my->offset)] = 0;
}
if (key == XK_BackSpace && my->offset > 0)
my->input[--(my->offset)] = 0;
else
if (key == XK_Up)
if (key == XK_Up || key == XK_KP_Up || key == XK_KP_Subtract)
my->current = (my->current == 0 ? my->max_lines-1: my->current-1);
else
if (key == XK_Down || key == XK_Tab)
if (key == XK_Down || key == XK_Tab || key == XK_KP_Add)
my->current = (my->current == my->max_lines-1 ? 0: my->current+1);
else
if (key == XK_Return)
{
if (my->filtered[my->current])
my->selected = my->filtered[my->current];
else
if (my->manual)
strcpy(my->manual, my->input);
my->done = 1;
}
if (key == XK_Return || key == XK_KP_Enter)
menu_select_current(my);
else
if (!iscntrl(*pad) && my->offset < my->input_size-1)
{
@ -591,36 +613,21 @@ void menu_key(struct localmenu *my, XEvent *ev)
menu_draw(my);
}
// take over keyboard for popup menu
int menu_grab(struct localmenu *my)
{
int i;
for (i = 0; i < 1000; i++)
{
if (XGrabKeyboard(display, my->window, True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess)
return 1;
usleep(1000);
}
return 0;
}
// menu
int menu(Window root, char **lines, char *manual)
int menu(char **lines, char *manual, int firstsel)
{
int i, l, scr;
int i, l;
struct localmenu _my, *my = &_my;
XWindowAttributes *attr = window_get_attributes(root);
workarea mon; monitor_active(attr->screen, &mon);
scr = XScreenNumberOfScreen(attr->screen);
workarea mon; monitor_active(&mon);
// this never fails, afaics. we get some sort of font, no matter what
my->font = XftFontOpenName(display, scr, config_menu_font);
XftColorAllocName(display, DefaultVisual(display, scr), DefaultColormap(display, scr), config_menu_fg, &my->fg);
XftColorAllocName(display, DefaultVisual(display, scr), DefaultColormap(display, scr), config_menu_bg, &my->bg);
XftColorAllocName(display, DefaultVisual(display, scr), DefaultColormap(display, scr), config_menu_hlfg, &my->hlfg);
XftColorAllocName(display, DefaultVisual(display, scr), DefaultColormap(display, scr), config_menu_hlbg, &my->hlbg);
my->line_height = my->font->ascent + my->font->descent +2; // +2 pixel extra line spacing
my->font = XftFontOpenName(display, screen_id, config_menu_font);
XftColorAllocName(display, DefaultVisual(display, screen_id), DefaultColormap(display, screen_id), config_menu_fg, &my->fg);
XftColorAllocName(display, DefaultVisual(display, screen_id), DefaultColormap(display, screen_id), config_menu_bg, &my->bg);
XftColorAllocName(display, DefaultVisual(display, screen_id), DefaultColormap(display, screen_id), config_menu_bgalt, &my->bgalt);
XftColorAllocName(display, DefaultVisual(display, screen_id), DefaultColormap(display, screen_id), config_menu_hlfg, &my->hlfg);
XftColorAllocName(display, DefaultVisual(display, screen_id), DefaultColormap(display, screen_id), config_menu_hlbg, &my->hlbg);
my->line_height = my->font->ascent + my->font->descent +4; // +2 pixel extra line spacing
for (l = 0, i = 0; lines[i]; i++) l = MAX(l, strlen(lines[i]));
@ -630,21 +637,22 @@ int menu(Window root, char **lines, char *manual)
my->input_size = MAX(l, 100);
my->filtered = allocate_clear(sizeof(char*) * (my->num_lines+1));
my->input = allocate_clear((my->input_size+1)*3); // utf8 in copied line
my->current = 0; // index of currently highlighted line
my->current = firstsel; // index of currently highlighted line
my->offset = 0; // length of text in input buffer
my->done = 0; // bailout flag
my->horz_pad = 5; // horizontal padding
my->vert_pad = 5; // vertical padding
my->width = (mon.w/100)*config_menu_width;
my->width = config_menu_width < 101 ? (mon.w/100)*config_menu_width: config_menu_width;
my->height = ((my->line_height) * (my->max_lines+1)) + (my->vert_pad*2);
my->xbg = color_get(display, config_menu_bg);
my->xbg = color_get(config_menu_bg);
my->selected = NULL;
my->manual = manual;
int x = mon.x + ((mon.w - my->width)/2);
int y = mon.y + (mon.h/2) - (my->height/2);
int b = 1;
my->window = XCreateSimpleWindow(display, root, x, y, my->width, my->height, 0, my->xbg, my->xbg);
my->window = XCreateSimpleWindow(display, root, x-b, y-b, my->width, my->height, b, color_get(config_menu_bc), my->xbg);
// make it an unmanaged window
window_set_atom_prop(my->window, netatoms[_NET_WM_STATE], &netatoms[_NET_WM_STATE_ABOVE], 1);
window_set_atom_prop(my->window, netatoms[_NET_WM_WINDOW_TYPE], &netatoms[_NET_WM_WINDOW_TYPE_DOCK], 1);
@ -652,8 +660,8 @@ int menu(Window root, char **lines, char *manual)
// drawing environment
my->gc = XCreateGC(display, my->window, 0, 0);
my->canvas = XCreatePixmap(display, root, my->width, my->height, DefaultDepth(display, scr));
my->draw = XftDrawCreate(display, my->canvas, DefaultVisual(display, scr), DefaultColormap(display, scr));
my->canvas = XCreatePixmap(display, root, my->width, my->height, DefaultDepth(display, screen_id));
my->draw = XftDrawCreate(display, my->canvas, DefaultVisual(display, screen_id), DefaultColormap(display, screen_id));
// input keymap->charmap handling
my->xim = XOpenIM(display, NULL, NULL, NULL);
@ -661,7 +669,7 @@ int menu(Window root, char **lines, char *manual)
menu_draw(my);
XMapRaised(display, my->window);
if (!menu_grab(my))
if (!take_keyboard(my->window))
{
fprintf(stderr, "cannot grab keyboard!\n");
return my->max_lines;
@ -682,7 +690,8 @@ int menu(Window root, char **lines, char *manual)
XftDrawDestroy(my->draw);
XFreeGC(display, my->gc);
XftFontClose(display, my->font);
XUngrabKeyboard(display, CurrentTime);
XDestroyWindow(display, my->window);
release_keyboard();
free(my->input);
if (my->selected)
@ -698,7 +707,7 @@ int menu(Window root, char **lines, char *manual)
#define FORK 1
#define NOFORK 2
void run_switcher(Window root, int mode, int fmode)
void run_switcher(int mode, int fmode)
{
// TODO: this whole function is messy. build a nicer solution
char pattern[50], **list = NULL;
@ -771,7 +780,7 @@ void run_switcher(Window root, int mode, int fmode)
// strangeness...
display = XOpenDisplay(0);
XSync(display, True);
int n = menu(root, list, NULL);
int n = menu(list, NULL, 1);
if (n >= 0 && list[n])
{
if (mode == ALLWINDOWS)
@ -802,10 +811,10 @@ void handle_keypress(XEvent *ev)
KeySym key = XkbKeycodeToKeysym(display, ev->xkey.keycode, 0, 0);
if ((all_windows_modmask == AnyModifier || ev->xkey.state & all_windows_modmask) && key == all_windows_keysym)
run_switcher(ev->xany.window, ALLWINDOWS, FORK);
run_switcher(ALLWINDOWS, FORK);
if ((desktop_windows_modmask == AnyModifier || ev->xkey.state & desktop_windows_modmask) && key == desktop_windows_keysym)
run_switcher(ev->xany.window, DESKTOPWINDOWS, FORK);
run_switcher(DESKTOPWINDOWS, FORK);
}
// convert a Mod+key arg to mod mask and keysym
@ -834,7 +843,7 @@ void parse_key(char *combo, unsigned int *mod, KeySym *key)
}
// bind a key combination on a root window, compensating for Lock* states
void grab_key(Window root, unsigned int modmask, KeySym key)
void grab_key(unsigned int modmask, KeySym key)
{
KeyCode keycode = XKeysymToKeycode(display, key);
XUngrabKey(display, keycode, AnyModifier, root);
@ -859,7 +868,7 @@ void grab_key(Window root, unsigned int modmask, KeySym key)
int main(int argc, char *argv[])
{
int i, j, scr;
int i, j;
// catch help request
if (find_arg(argc, argv, "-help") >= 0
@ -875,6 +884,9 @@ int main(int argc, char *argv[])
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);
// determine numlock mask so we can bind on keys with and without it
@ -897,18 +909,21 @@ int main(int argc, char *argv[])
config_menu_font = find_arg_str(ac, av, "-font", MENUXFTFONT);
config_menu_fg = find_arg_str(ac, av, "-fg", MENUFG);
config_menu_bg = find_arg_str(ac, av, "-bg", MENUBG);
config_menu_bgalt = find_arg_str(ac, av, "-bgalt", MENUBGALT);
config_menu_hlfg = find_arg_str(ac, av, "-hlfg", MENUHLFG);
config_menu_hlbg = find_arg_str(ac, av, "-hlbg", MENUHLBG);
config_menu_bc = find_arg_str(ac, av, "-bc", MENUBC);
config_menu_bw = find_arg_int(ac, av, "-bw", 1);
// flags to run immediately and exit
if (find_arg(ac, av, "-now") >= 0)
{
run_switcher(RootWindow(display, DefaultScreen(display)), ALLWINDOWS, NOFORK);
run_switcher(ALLWINDOWS, NOFORK);
exit(EXIT_SUCCESS);
}
if (find_arg(ac, av, "-dnow") >= 0)
{
run_switcher(RootWindow(display, DefaultScreen(display)), DESKTOPWINDOWS, NOFORK);
run_switcher(DESKTOPWINDOWS, NOFORK);
exit(EXIT_SUCCESS);
}
// in background mode from here on
@ -920,12 +935,8 @@ int main(int argc, char *argv[])
parse_key(find_arg_str(ac, av, "-dkey", "F11"), &desktop_windows_modmask, &desktop_windows_keysym);
// bind key combos
for (scr = 0; scr < ScreenCount(display); scr++)
{
Window root = RootWindow(display, scr);
grab_key(root, all_windows_modmask, all_windows_keysym);
grab_key(root, desktop_windows_modmask, desktop_windows_keysym);
}
grab_key(all_windows_modmask, all_windows_keysym);
grab_key(desktop_windows_modmask, desktop_windows_keysym);
XEvent ev;
for (;;)