diff --git a/src/client.c b/src/client.c index b1e6f71..ac7dfc5 100644 --- a/src/client.c +++ b/src/client.c @@ -664,7 +664,142 @@ client_map(Client *c) return; } -static void client_set_rules(Client *c); +/** Set the wanted tag or autofree/max of a client + *\param c Client pointer +*/ +static void +client_set_rules(Client *c) +{ + XClassHint xch; + int i, j, k, f; + Atom rf; + ulong n, il; + uchar *data = NULL; + char wwrole[256] = { 0 }; + Bool applied_tag_rule = False; + Bool applied_screen_rule = False; + + memset(&xch, 0, sizeof(xch)); + + if(conf.ignore_next_client_rules) + { + conf.ignore_next_client_rules = False; + return; + } + + /* Get WM_CLASS */ + XGetClassHint(dpy, c->win, &xch); + + /* Get WM_WINDOW_ROLE */ + if(XGetWindowProperty(dpy, c->win, ATOM("WM_WINDOW_ROLE"), 0L, 0x7FFFFFFFL, False, + XA_STRING, &rf, &f, &n, &il, &data) == Success && data) + { + strncpy(wwrole, (char*)data, sizeof(wwrole)); + XFree(data); + } + + /* Following features is *DEPRECATED*, will be removed in some revision. {{{ */ + + /* Auto free */ + if(conf.client.autofree && ((xch.res_name && strstr(conf.client.autofree, xch.res_name)) + || (xch.res_class && strstr(conf.client.autofree, xch.res_class)))) + c->flags |= FreeFlag; + + /* Auto maximize */ + if(conf.client.automax && ((xch.res_name && strstr(conf.client.automax, xch.res_name)) + || (xch.res_class && strstr(conf.client.automax, xch.res_class)))) + { + client_maximize(c); + c->flags |= MaxFlag; + } + + /* Wanted tag */ + for(i = 0; i < screen_count(); ++i) + for(j = 1; j < conf.ntag[i] + 1; ++j) + if(tags[i][j].clients) + for(k = 0; k < tags[i][j].nclients; ++k) + if((xch.res_name && strstr(xch.res_name, tags[i][j].clients[k])) + || (xch.res_class && strstr(xch.res_class, tags[i][j].clients[k]))) + { + c->screen = i; + c->tag = j; + + if(c->tag != (uint)seltag[selscreen]) + tags[c->screen][c->tag].request_update = True; + else + tags[c->screen][c->tag].layout.func(c->screen); + + /* Deprecated but still in use */ + applied_tag_rule = True; + applied_screen_rule = True; + } + + /* }}} */ + + /* Apply Rule if class || instance || role match */ + for(i = 0; i < conf.nrule; ++i) + { + if((xch.res_class && conf.rule[i].class && !strcmp(xch.res_class, conf.rule[i].class)) + || (xch.res_name && conf.rule[i].instance && !strcmp(xch.res_name, conf.rule[i].instance))) + { + if((strlen(wwrole) && conf.rule[i].role && !strcmp(wwrole, conf.rule[i].role)) || (!strlen(wwrole) || !conf.rule[i].role)) + { + if(conf.rule[i].screen != -1) + c->screen = conf.rule[i].screen; + + if(conf.rule[i].tag != -1) + { + c->tag = conf.rule[i].tag; + applied_tag_rule = True; + } + + if(conf.rule[i].free) + c->flags |= FreeFlag; + + if(conf.rule[i].ignoretags) + c->tag = MAXTAG + 1; + + if(conf.rule[i].max) + { + client_maximize(c); + c->flags |= MaxFlag; + } + + if(c->tag != (uint)seltag[selscreen]) + { + tags[c->screen][c->tag].request_update = True; + client_focus(NULL); + } + + if(!conf.rule[i].ignoretags) + tags[c->screen][c->tag].layout.func(c->screen); + + if(conf.rule[i].follow_client) + seltag[c->screen] = c->tag; + } + } + } + + if(!applied_tag_rule && conf.client.default_open_tag > 0 + && conf.client.default_open_tag < (uint)conf.ntag[selscreen]) + { + c->tag = conf.client.default_open_tag; + + client_focus_next(c); + tags[c->screen][c->tag].request_update = True; + } + + if(!applied_screen_rule && conf.client.default_open_screen > -1 + && conf.client.default_open_screen < screen_count()) + { + c->screen = conf.client.default_open_screen; + + client_focus_next(c); + tags[c->screen][c->tag].request_update = True; + } + + return; +} /** Manage a client with a window and his attributes * \param w Cient's futur Window @@ -1036,143 +1171,6 @@ client_swap(Client *c1, Client *c2) return; } -/** Set the wanted tag or autofree/max of a client - *\param c Client pointer -*/ -static void -client_set_rules(Client *c) -{ - XClassHint xch; - int i, j, k, f; - Atom rf; - ulong n, il; - uchar *data = NULL; - char wwrole[256] = { 0 }; - Bool applied_tag_rule = False; - Bool applied_screen_rule = False; - - memset(&xch, 0, sizeof(xch)); - - if(conf.ignore_next_client_rules) - { - conf.ignore_next_client_rules = False; - return; - } - - /* Get WM_CLASS */ - XGetClassHint(dpy, c->win, &xch); - - /* Get WM_WINDOW_ROLE */ - if(XGetWindowProperty(dpy, c->win, ATOM("WM_WINDOW_ROLE"), 0L, 0x7FFFFFFFL, False, - XA_STRING, &rf, &f, &n, &il, &data) == Success && data) - { - strncpy(wwrole, (char*)data, sizeof(wwrole)); - XFree(data); - } - - /* Following features is *DEPRECATED*, will be removed in some revision. {{{ */ - - /* Auto free */ - if(conf.client.autofree && ((xch.res_name && strstr(conf.client.autofree, xch.res_name)) - || (xch.res_class && strstr(conf.client.autofree, xch.res_class)))) - c->flags |= FreeFlag; - - /* Auto maximize */ - if(conf.client.automax && ((xch.res_name && strstr(conf.client.automax, xch.res_name)) - || (xch.res_class && strstr(conf.client.automax, xch.res_class)))) - { - client_maximize(c); - c->flags |= MaxFlag; - } - - /* Wanted tag */ - for(i = 0; i < screen_count(); ++i) - for(j = 1; j < conf.ntag[i] + 1; ++j) - if(tags[i][j].clients) - for(k = 0; k < tags[i][j].nclients; ++k) - if((xch.res_name && strstr(xch.res_name, tags[i][j].clients[k])) - || (xch.res_class && strstr(xch.res_class, tags[i][j].clients[k]))) - { - c->screen = i; - c->tag = j; - - if(c->tag != (uint)seltag[selscreen]) - tags[c->screen][c->tag].request_update = True; - else - tags[c->screen][c->tag].layout.func(c->screen); - - /* Deprecated but still in use */ - applied_tag_rule = True; - applied_screen_rule = True; - } - - /* }}} */ - - /* Apply Rule if class || instance || role match */ - for(i = 0; i < conf.nrule; ++i) - { - if((xch.res_class && conf.rule[i].class && !strcmp(xch.res_class, conf.rule[i].class)) - || (xch.res_name && conf.rule[i].instance && !strcmp(xch.res_name, conf.rule[i].instance))) - { - if((strlen(wwrole) && conf.rule[i].role && !strcmp(wwrole, conf.rule[i].role)) || (!strlen(wwrole) || !conf.rule[i].role)) - { - if(conf.rule[i].screen != -1) - c->screen = conf.rule[i].screen; - - if(conf.rule[i].tag != -1) - { - c->tag = conf.rule[i].tag; - applied_tag_rule = True; - } - - if(conf.rule[i].free) - c->flags |= FreeFlag; - - if(conf.rule[i].ignoretags) - c->tag = MAXTAG + 1; - - if(conf.rule[i].max) - { - client_maximize(c); - c->flags |= MaxFlag; - } - - if(c->tag != (uint)seltag[selscreen]) - { - tags[c->screen][c->tag].request_update = True; - client_focus(NULL); - } - - if(!conf.rule[i].ignoretags) - tags[c->screen][c->tag].layout.func(c->screen); - - if(conf.rule[i].follow_client) - seltag[c->screen] = c->tag; - } - } - } - - if(!applied_tag_rule && conf.client.default_open_tag > 0 - && conf.client.default_open_tag < (uint)conf.ntag[selscreen]) - { - c->tag = conf.client.default_open_tag; - - client_focus_next(c); - tags[c->screen][c->tag].request_update = True; - } - - if(!applied_screen_rule && conf.client.default_open_screen > -1 - && conf.client.default_open_screen < screen_count()) - { - c->screen = conf.client.default_open_screen; - - client_focus_next(c); - tags[c->screen][c->tag].request_update = True; - } - - return; -} - /** Update client attributes (_WMFS_TAG _WMFS_SCREEN) *\param c Client pointer */ @@ -1491,7 +1489,38 @@ uicb_ignore_next_client_rules(uicb_t cmd) return; } -static void uicb_client_select(uicb_t cmd); +/** Select client + *\param cmd uicb_t type clientlist index + */ +static void +uicb_client_select(uicb_t cmd) +{ + int i; + Window w; + int d, x, y; + + + for(i = 0; i < MAXCLIST && clist_index[i].client; ++i) + if(!strcmp(cmd, clist_index[i].key)) + { + if(clist_index[i].client->screen != selscreen) + screen_set_sel(clist_index[i].client->screen); + + if(clist_index[i].client->tag != (uint)seltag[clist_index[i].client->screen]) + tag_set(clist_index[i].client->tag); + + client_focus(clist_index[i].client); + client_raise(clist_index[i].client); + + /* Move pointer on client */ + XQueryPointer(dpy, ROOT, &w, &w, &x, &y, &d, &d, (uint *)&d); + XWarpPointer(dpy, ROOT, ROOT, x, y, d, d, + clist_index[i].client->geo.x + clist_index[i].client->geo.width / 2, + clist_index[i].client->geo.y + clist_index[i].client->geo.height / 2); + } + + return; +} /** Show clientlist menu *\param cmd uicb_t type @@ -1552,39 +1581,6 @@ uicb_clientlist(uicb_t cmd) return; } -/** Select client - *\param cmd uicb_t type clientlist index - */ -static void -uicb_client_select(uicb_t cmd) -{ - int i; - Window w; - int d, x, y; - - - for(i = 0; i < MAXCLIST && clist_index[i].client; ++i) - if(!strcmp(cmd, clist_index[i].key)) - { - if(clist_index[i].client->screen != selscreen) - screen_set_sel(clist_index[i].client->screen); - - if(clist_index[i].client->tag != (uint)seltag[clist_index[i].client->screen]) - tag_set(clist_index[i].client->tag); - - client_focus(clist_index[i].client); - client_raise(clist_index[i].client); - - /* Move pointer on client */ - XQueryPointer(dpy, ROOT, &w, &w, &x, &y, &d, &d, (uint *)&d); - XWarpPointer(dpy, ROOT, ROOT, x, y, d, d, - clist_index[i].client->geo.x + clist_index[i].client->geo.width / 2, - clist_index[i].client->geo.y + clist_index[i].client->geo.height / 2); - } - - return; -} - /** Check clientlist menu fake function * \param cmd uicb_t type unused */ diff --git a/src/color.c b/src/color.c index cd77454..98ef035 100644 --- a/src/color.c +++ b/src/color.c @@ -32,37 +32,6 @@ #include "wmfs.h" -static void color_unpack_rgb(uint, uint*, uint*, uint*); -static void color_rgb_to_hsl(uint, uint, uint, double*, double*, double*); -static void color_hsl_to_rgb(double, double, double, uint*, uint*, uint*); -static double color_clamp(double, double, double); -static uint color_pack_rgb(uint, uint, uint); - -/** Shades a color by the amount. This works by converting a packed RGB - * color to HSL, adding the amount to the lightness, - * and then converting back to RGB. 1.0 is max lightness, 0.0 is min lightness. - * \param shadeVal the amount to shade the lightness by. - * \return the shaded color - */ -uint -color_shade(uint rgb, double shadeVal) -{ - uint r, g, b; - double h, s, l; - - color_unpack_rgb(rgb, &r, &g, &b); - color_rgb_to_hsl(r, g, b, &h, &s, &l); - - l += shadeVal; - - l = color_clamp(l, 0, 1); - - color_hsl_to_rgb(h, s, l, &r, &g, &b); - rgb = color_pack_rgb(r, g, b); - - return rgb; -} - /** Clamp a number x within the range [a, b]. * \param x the number which to clamp * \param a the lowest possible value @@ -227,3 +196,28 @@ color_hsl_to_rgb(double h, double sl, double l, uint *rx, uint *gx, uint *bx) *gx = g * 255.0; *bx = b * 255.0; } + +/** Shades a color by the amount. This works by converting a packed RGB + * color to HSL, adding the amount to the lightness, + * and then converting back to RGB. 1.0 is max lightness, 0.0 is min lightness. + * \param shadeVal the amount to shade the lightness by. + * \return the shaded color + */ +uint +color_shade(uint rgb, double shadeVal) +{ + uint r, g, b; + double h, s, l; + + color_unpack_rgb(rgb, &r, &g, &b); + color_rgb_to_hsl(r, g, b, &h, &s, &l); + + l += shadeVal; + + l = color_clamp(l, 0, 1); + + color_hsl_to_rgb(h, s, l, &r, &g, &b); + rgb = color_pack_rgb(r, g, b); + + return rgb; +} diff --git a/src/draw.c b/src/draw.c index b2a80ad..38d89a9 100644 --- a/src/draw.c +++ b/src/draw.c @@ -33,7 +33,44 @@ #include "wmfs.h" #ifdef HAVE_IMLIB -static void draw_image(Drawable dr, int x, int y, int w, int h, char *name); +/** Draw an image in a drawable + * \param dr Drawable + * \param x X position + * \param y Y position + * \param name Path of the image +*/ +static void draw_image(Drawable dr, int x, int y, int w, int h, char *name) +{ + Imlib_Image image; + + if(!name) + return; + + imlib_set_cache_size(2048 * 1024); + imlib_context_set_display(dpy); + imlib_context_set_visual(DefaultVisual(dpy, DefaultScreen(dpy))); + imlib_context_set_colormap(DefaultColormap(dpy, DefaultScreen(dpy))); + imlib_context_set_drawable(dr); + + image = imlib_load_image(patht(name)); + imlib_context_set_image(image); + + if(w <= 0) + w = imlib_image_get_width(); + + if(h <= 0) + h = imlib_image_get_height(); + + if(image) + { + imlib_render_image_on_drawable_at_size(x, y, w, h); + imlib_free_image(); + } + else + warnx("Can't draw image: '%s'", name); + + return; +} #endif /* HAVE_IMLIB */ void @@ -155,48 +192,6 @@ draw_graph(Drawable dr, int x, int y, uint w, uint h, uint color, char *data) return; } -#ifdef HAVE_IMLIB -/** Draw an image in a drawable - * \param dr Drawable - * \param x X position - * \param y Y position - * \param name Path of the image -*/ -void -draw_image(Drawable dr, int x, int y, int w, int h, char *name) -{ - Imlib_Image image; - - if(!name) - return; - - imlib_set_cache_size(2048 * 1024); - imlib_context_set_display(dpy); - imlib_context_set_visual(DefaultVisual(dpy, DefaultScreen(dpy))); - imlib_context_set_colormap(DefaultColormap(dpy, DefaultScreen(dpy))); - imlib_context_set_drawable(dr); - - image = imlib_load_image(patht(name)); - imlib_context_set_image(image); - - if(w <= 0) - w = imlib_image_get_width(); - - if(h <= 0) - h = imlib_image_get_height(); - - if(image) - { - imlib_render_image_on_drawable_at_size(x, y, w, h); - imlib_free_image(); - } - else - warnx("Can't draw image: '%s'", name); - - return; -} -#endif /* HAVE_IMLIB */ - /** Calculates the text's size relatively to the font * \param text Text string * \return final text width diff --git a/src/event.c b/src/event.c index b38b428..7807c8f 100644 --- a/src/event.c +++ b/src/event.c @@ -439,27 +439,6 @@ focusin(XFocusChangeEvent *ev) return; } -/** Key grabbing function -*/ -void -grabkeys(void) -{ - int i; - KeyCode code; - - XUngrabKey(dpy, AnyKey, AnyModifier, ROOT); - for(i = 0; i < conf.nkeybind; ++i) - if((code = XKeysymToKeycode(dpy, keys[i].keysym))) - { - XGrabKey(dpy, code, keys[i].mod, ROOT, True, GrabModeAsync, GrabModeAsync); - XGrabKey(dpy, code, keys[i].mod | LockMask, ROOT, True, GrabModeAsync, GrabModeAsync); - XGrabKey(dpy, code, keys[i].mod | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync); - XGrabKey(dpy, code, keys[i].mod | LockMask | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync); - } - - return; -} - /** KeyPress handle event * \param ev XKeyPressedEvent pointer */ @@ -646,6 +625,27 @@ unmapnotify(XUnmapEvent *ev) return; } +/** Key grabbing function +*/ +void +grabkeys(void) +{ + int i; + KeyCode code; + + XUngrabKey(dpy, AnyKey, AnyModifier, ROOT); + for(i = 0; i < conf.nkeybind; ++i) + if((code = XKeysymToKeycode(dpy, keys[i].keysym))) + { + XGrabKey(dpy, code, keys[i].mod, ROOT, True, GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, keys[i].mod | LockMask, ROOT, True, GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, keys[i].mod | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, keys[i].mod | LockMask | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync); + } + + return; +} + /** Event handle function: execute every function * handle by event * \param ev Event diff --git a/src/infobar.c b/src/infobar.c index 4156355..660c023 100644 --- a/src/infobar.c +++ b/src/infobar.c @@ -135,23 +135,6 @@ infobar_init(void) return; } -static void infobar_draw_layout(int sc); - -/** Draw the Infobar - *\param sc Screen number -*/ -void -infobar_draw(int sc) -{ - infobar_draw_taglist(sc); - infobar_draw_layout(sc); - infobar_draw_selbar(sc); - barwin_refresh_color(infobar[sc].bar); - statustext_handle(sc, infobar[sc].statustext); - - return; -} - /** Draw the layout button in the InfoBar *\param sc Screen number */ @@ -170,6 +153,21 @@ infobar_draw_layout(int sc) return; } +/** Draw the Infobar + *\param sc Screen number +*/ +void +infobar_draw(int sc) +{ + infobar_draw_taglist(sc); + infobar_draw_layout(sc); + infobar_draw_selbar(sc); + barwin_refresh_color(infobar[sc].bar); + statustext_handle(sc, infobar[sc].statustext); + + return; +} + /** Draw Selbar (selected client title bar in infobar *\param sc Screen Number */ diff --git a/src/launcher.c b/src/launcher.c index 2df2160..33bb1ca 100644 --- a/src/launcher.c +++ b/src/launcher.c @@ -32,8 +32,151 @@ #include "wmfs.h" -static char *complete_on_command(char*, size_t); -static char *complete_on_files(char*, size_t); +/* + * Just search command in PATH. + * Return the characters to complete the command. + */ +static char * +complete_on_command(char *start, size_t hits) +{ + char *path; + char *dirname; + char *ret = NULL; + DIR *dir; + struct dirent *content; + + char **namelist = NULL; + int n = 0, i; + + if (!getenv("PATH") || !start || hits <= 0) + return NULL; + + path = xstrdup(getenv("PATH")); + dirname = strtok(path, ":"); + + /* recursively open PATH */ + while (dirname != NULL) + { + if ((dir = opendir(dirname))) + { + while ((content = readdir(dir))) + { + if(strncmp(content->d_name, ".", 1)) + { + if (!strncmp(content->d_name, start, strlen(start))) + { + namelist = xrealloc(namelist, ++n, sizeof(*namelist)); + namelist[n-1] = xstrdup(content->d_name); + } + } + } + closedir(dir); + } + dirname = strtok(NULL, ":"); + } + + free(path); + + if(n > 0) + { + qsort(namelist, n, sizeof(char *), qsort_string_compare); + ret = xstrdup(namelist[((hits > 0) ? hits - 1 : 0) % n] + strlen(start)); + + for(i = 0; i < n; i++) + free(namelist[i]); + + free(namelist); + } + + return ret; +} + +/* + * Complete a filename or directory name. + * works like complete_on_command. + */ +static char * +complete_on_files(char *start, size_t hits) +{ + char *ret = NULL; + char *p = NULL; + char *dirname = NULL; + char *path = NULL; + char *filepath = NULL; + DIR *dir = NULL; + struct dirent *content = NULL; + struct stat st; + size_t count = 0; + + if (!start || hits <= 0 || !(p = strrchr(start, ' '))) + return NULL; + + /* + * Search the directory to open and set + * the beginning of file to complete on pointer 'p'. + */ + if (*(++p) == '\0' || !strrchr(p, '/')) + path = xstrdup("."); + else + { + /* remplace ~ by $HOME in dirname */ + if (!strncmp(p, "~/", 2) && getenv("HOME")) + xasprintf(&dirname, "%s%s", getenv("HOME"), p+1); + else + dirname = xstrdup(p); + + /* Set p to filename to be complete + * and path the directory containing the file + * /foooooo/baaaaaar/somethinglikethis + * <---- path - ---><------- p ------> + */ + p = strrchr(dirname, '/'); + if (p != dirname) + { + *(p++) = '\0'; + path = xstrdup(dirname); + } + else + { + path = xstrdup("/"); + p++; + } + } + + if ((dir = opendir(path))) + { + while ((content = readdir(dir))) + { + if (!strcmp(content->d_name, ".") || !strcmp(content->d_name, "..")) + continue; + if (!strncmp(content->d_name, p, strlen(p)) && ++count == hits) + { + /* If it's a directory append '/' to the completion */ + xasprintf(&filepath, "%s/%s", path, content->d_name); + + if (filepath && stat(filepath, &st) != -1) + { + if (S_ISDIR(st.st_mode)) + xasprintf(&ret, "%s/", content->d_name + strlen(p)); + else + ret = xstrdup(content->d_name + strlen(p)); + } + else + warn("%s", filepath); + + free(filepath); + + break; + } + } + closedir(dir); + } + + free(dirname); + free(path); + + return ret; +} static void launcher_execute(Launcher *launcher) @@ -237,149 +380,3 @@ uicb_launcher(uicb_t cmd) return; } - -/* - * Just search command in PATH. - * Return the characters to complete the command. - */ -static char * -complete_on_command(char *start, size_t hits) -{ - char *path; - char *dirname; - char *ret = NULL; - DIR *dir; - struct dirent *content; - - char **namelist = NULL; - int n = 0, i; - - if (!getenv("PATH") || !start || hits <= 0) - return NULL; - - path = xstrdup(getenv("PATH")); - dirname = strtok(path, ":"); - - /* recursively open PATH */ - while (dirname != NULL) - { - if ((dir = opendir(dirname))) - { - while ((content = readdir(dir))) - { - if(strncmp(content->d_name, ".", 1)) - { - if (!strncmp(content->d_name, start, strlen(start))) - { - namelist = xrealloc(namelist, ++n, sizeof(*namelist)); - namelist[n-1] = xstrdup(content->d_name); - } - } - } - closedir(dir); - } - dirname = strtok(NULL, ":"); - } - - free(path); - - if(n > 0) - { - qsort(namelist, n, sizeof(char *), qsort_string_compare); - ret = xstrdup(namelist[((hits > 0) ? hits - 1 : 0) % n] + strlen(start)); - - for(i = 0; i < n; i++) - free(namelist[i]); - - free(namelist); - } - - return ret; -} - -/* - * Complete a filename or directory name. - * works like complete_on_command. - */ -static char * -complete_on_files(char *start, size_t hits) -{ - char *ret = NULL; - char *p = NULL; - char *dirname = NULL; - char *path = NULL; - char *filepath = NULL; - DIR *dir = NULL; - struct dirent *content = NULL; - struct stat st; - size_t count = 0; - - if (!start || hits <= 0 || !(p = strrchr(start, ' '))) - return NULL; - - /* - * Search the directory to open and set - * the beginning of file to complete on pointer 'p'. - */ - if (*(++p) == '\0' || !strrchr(p, '/')) - path = xstrdup("."); - else - { - /* remplace ~ by $HOME in dirname */ - if (!strncmp(p, "~/", 2) && getenv("HOME")) - xasprintf(&dirname, "%s%s", getenv("HOME"), p+1); - else - dirname = xstrdup(p); - - /* Set p to filename to be complete - * and path the directory containing the file - * /foooooo/baaaaaar/somethinglikethis - * <---- path - ---><------- p ------> - */ - p = strrchr(dirname, '/'); - if (p != dirname) - { - *(p++) = '\0'; - path = xstrdup(dirname); - } - else - { - path = xstrdup("/"); - p++; - } - } - - if ((dir = opendir(path))) - { - while ((content = readdir(dir))) - { - if (!strcmp(content->d_name, ".") || !strcmp(content->d_name, "..")) - continue; - if (!strncmp(content->d_name, p, strlen(p)) && ++count == hits) - { - /* If it's a directory append '/' to the completion */ - xasprintf(&filepath, "%s/%s", path, content->d_name); - - if (filepath && stat(filepath, &st) != -1) - { - if (S_ISDIR(st.st_mode)) - xasprintf(&ret, "%s/", content->d_name + strlen(p)); - else - ret = xstrdup(content->d_name + strlen(p)); - } - else - warn("%s", filepath); - - free(filepath); - - break; - } - } - closedir(dir); - } - - free(dirname); - free(path); - - return ret; -} diff --git a/src/layout.c b/src/layout.c index 5cea3c2..73e2dcb 100644 --- a/src/layout.c +++ b/src/layout.c @@ -143,26 +143,6 @@ uicb_layout_prev(uicb_t cmd) return; } -/** Max layout function -*/ -void -maxlayout(int screen) -{ - Client *c; - int i; - - for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) - { - c->flags &= ~TileFlag; - c->flags |= LMaxFlag; - client_maximize(c); - } - - ewmh_update_current_tag_prop(); - - return; -} - /** Sort all the client that can be * tiled * \param c Client pointer @@ -184,6 +164,26 @@ tiled_client(int screen, Client *c) return c; } +/** Max layout function +*/ +void +maxlayout(int screen) +{ + Client *c; + int i; + + for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) + { + c->flags &= ~TileFlag; + c->flags |= LMaxFlag; + client_maximize(c); + } + + ewmh_update_current_tag_prop(); + + return; +} + /** Set the mwfact * \param cmd Mwfact (string) */ diff --git a/src/menu.c b/src/menu.c index 1301353..478359e 100644 --- a/src/menu.c +++ b/src/menu.c @@ -32,100 +32,113 @@ #include "wmfs.h" -static Bool menu_activate_item(Menu *menu, int i); -static Bool menu_get_checkstring_needed(MenuItem *mi, int nitem); -static Bool menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[]); -static Bool menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[]); -static int menu_get_longer_string(MenuItem *mi, int nitem); -static void menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[], int chcklen); -static void menu_focus_item(Menu *menu, int item, BarWindow *winitem[]); - -void -menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n) +static int +menu_get_longer_string(MenuItem *mi, int nitem) { - /* Item */ - menu->nitem = nitem; - menu->item = xcalloc(nitem, sizeof(*menu->item)); - menu->name = name; + int i, w, l = 0; - /* Colors */ - menu->colors.focus.bg = bg_f; - menu->colors.focus.fg = fg_f; - menu->colors.normal.bg = bg_n; - menu->colors.normal.fg = fg_n; + for(i = 0; i < nitem; ++i) + if((w = textw(mi[i].name)) > l) + l = w; + + return l; +} + +static Bool +menu_get_checkstring_needed(MenuItem *mi, int nitem) +{ + (void)mi; + (void)nitem; + return True; +} + +static void +menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[], int chcklen) +{ + int x; + int width = menu_get_longer_string(menu->item, menu->nitem) + chcklen + PAD / 3; + + switch(menu->align) + { + case MA_Left: + x = chcklen + PAD / 2; + break; + case MA_Right: + x = width - textw(menu->item[item].name) + PAD * 3 / 2; + break; + default: + case MA_Center: + x = (width - (chcklen + PAD / 3)) / 2 - textw(menu->item[item].name) / 2 + chcklen + PAD / 3; + break; + } + barwin_draw_image_ofset_text(winitem[item], x, FHINFOBAR, menu->item[item].name, chcklen + PAD / 2, 0); + + if(menu->item[item].check) + if(menu->item[item].check(menu->item[item].cmd)) + barwin_draw_image_ofset_text(winitem[item], PAD / 3, FHINFOBAR, conf.selected_layout_symbol, PAD / 3, 0); + + if(menu->item[item].submenu) + barwin_draw_text(winitem[item], width + PAD * 2, FHINFOBAR, ">"); return; } -void -menu_new_item(MenuItem *mi, char *name, void *func, char *cmd) +static Bool +menu_activate_item(Menu *menu, int i) { - mi->name = name; - mi->func = func; - mi->cmd = cmd; - - return; -} - -void -menu_draw(Menu menu, int x, int y) -{ - int i, width, height, out; - XEvent ev; - BarWindow *item[menu.nitem]; - BarWindow *frame; - + int j, x, y; int chcklen = 0; - if(menu_get_checkstring_needed(menu.item, menu.nitem)) + if(menu_get_checkstring_needed(menu->item, menu->nitem)) chcklen = textw(conf.selected_layout_symbol) + PAD / 3; - width = menu_get_longer_string(menu.item, menu.nitem) + chcklen + textw(">") + PAD * 3; - height = menu.nitem * (INFOBARH - SHADH); - - /* Frame barwin */ - screen_get_sel(); - - if((out = x + width - MAXW) > 0) - x -= out; - if((out = y + height - MAXH) > 0) - y -= out; - - frame = barwin_create(ROOT, x, y, width + SHADH, height + SHADH * 3, - menu.colors.normal.bg, menu.colors.normal.fg, False, False, True); - - barwin_map(frame); - barwin_map_subwin(frame); - barwin_refresh_color(frame); - - for(i = 0; i < menu.nitem; ++i) + if(menu->item[i].submenu) { - item[i] = barwin_create(frame->win, - SHADH, - (i * (INFOBARH - SHADH) + SHADH), - width - SHADH, - INFOBARH, - menu.colors.normal.bg, - menu.colors.normal.fg, - True, False, False); + for(j = 0; j < conf.nmenu; ++j) + if(!strcmp(menu->item[i].submenu, conf.menu[j].name)) + { + y = menu->y + ((i - 1) * INFOBARH + PAD) - SHADH * 2; + x = menu->x + menu_get_longer_string(menu->item, menu->nitem) + chcklen + textw(">") + PAD * 3; - barwin_map(item[i]); - barwin_refresh_color(item[i]); - menu_draw_item_name(&menu, i, item, chcklen); - barwin_refresh(item[i]); + menu_draw(conf.menu[j], x, y); + + return True; + } + } + else if(menu->item[i].func) + { + menu->item[i].func(menu->item[i].cmd); + + return True; } - /* Select the first item */ - menu_focus_item(&menu, 0, item); + return False; +} - XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime); +static void +menu_focus_item(Menu *menu, int item, BarWindow *winitem[]) +{ + int i; - while(!menu_manage_event(&ev, &menu, item)); + int chcklen = 0; + if(menu_get_checkstring_needed(menu->item, menu->nitem)) + chcklen = textw(conf.selected_layout_symbol) + PAD / 3; - XUngrabKeyboard(dpy, CurrentTime); + menu->focus_item = item; - for(i = 0; i < menu.nitem; ++i) - barwin_delete(item[i]); - barwin_delete(frame); + if(menu->focus_item > menu->nitem - 1) + menu->focus_item = 0; + else if(menu->focus_item < 0) + menu->focus_item = menu->nitem - 1; + + for(i = 0; i < menu->nitem; ++i) + { + winitem[i]->fg = ((i == menu->focus_item) ? menu->colors.focus.fg : menu->colors.normal.fg); + winitem[i]->bg = ((i == menu->focus_item) ? menu->colors.focus.bg : menu->colors.normal.bg); + + barwin_refresh_color(winitem[i]); + menu_draw_item_name(menu, i, winitem, chcklen); + barwin_refresh(winitem[i]); + } return; } @@ -216,109 +229,6 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[]) return quit; } -static Bool -menu_activate_item(Menu *menu, int i) -{ - int j, x, y; - int chcklen = 0; - if(menu_get_checkstring_needed(menu->item, menu->nitem)) - chcklen = textw(conf.selected_layout_symbol) + PAD / 3; - - if(menu->item[i].submenu) - { - for(j = 0; j < conf.nmenu; ++j) - if(!strcmp(menu->item[i].submenu, conf.menu[j].name)) - { - y = menu->y + ((i - 1) * INFOBARH + PAD) - SHADH * 2; - x = menu->x + menu_get_longer_string(menu->item, menu->nitem) + chcklen + textw(">") + PAD * 3; - - menu_draw(conf.menu[j], x, y); - - return True; - } - } - else if(menu->item[i].func) - { - menu->item[i].func(menu->item[i].cmd); - - return True; - } - - return False; -} - -static void -menu_focus_item(Menu *menu, int item, BarWindow *winitem[]) -{ - int i; - - int chcklen = 0; - if(menu_get_checkstring_needed(menu->item, menu->nitem)) - chcklen = textw(conf.selected_layout_symbol) + PAD / 3; - - menu->focus_item = item; - - if(menu->focus_item > menu->nitem - 1) - menu->focus_item = 0; - else if(menu->focus_item < 0) - menu->focus_item = menu->nitem - 1; - - for(i = 0; i < menu->nitem; ++i) - { - winitem[i]->fg = ((i == menu->focus_item) ? menu->colors.focus.fg : menu->colors.normal.fg); - winitem[i]->bg = ((i == menu->focus_item) ? menu->colors.focus.bg : menu->colors.normal.bg); - - barwin_refresh_color(winitem[i]); - menu_draw_item_name(menu, i, winitem, chcklen); - barwin_refresh(winitem[i]); - } - - return; -} - -static void -menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[], int chcklen) -{ - int x; - int width = menu_get_longer_string(menu->item, menu->nitem) + chcklen + PAD / 3; - - switch(menu->align) - { - case MA_Left: - x = chcklen + PAD / 2; - break; - case MA_Right: - x = width - textw(menu->item[item].name) + PAD * 3 / 2; - break; - default: - case MA_Center: - x = (width - (chcklen + PAD / 3)) / 2 - textw(menu->item[item].name) / 2 + chcklen + PAD / 3; - break; - } - barwin_draw_image_ofset_text(winitem[item], x, FHINFOBAR, menu->item[item].name, chcklen + PAD / 2, 0); - - if(menu->item[item].check) - if(menu->item[item].check(menu->item[item].cmd)) - barwin_draw_image_ofset_text(winitem[item], PAD / 3, FHINFOBAR, conf.selected_layout_symbol, PAD / 3, 0); - - if(menu->item[item].submenu) - barwin_draw_text(winitem[item], width + PAD * 2, FHINFOBAR, ">"); - - return; -} - -static int -menu_get_longer_string(MenuItem *mi, int nitem) -{ - int i, w, l = 0; - - for(i = 0; i < nitem; ++i) - if((w = textw(mi[i].name)) > l) - l = w; - - return l; -} - void uicb_menu(uicb_t cmd) { @@ -358,10 +268,92 @@ menu_clear(Menu *menu) return; } -static Bool -menu_get_checkstring_needed(MenuItem *mi, int nitem) +void +menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n) { - (void)mi; - (void)nitem; - return True; + /* Item */ + menu->nitem = nitem; + menu->item = xcalloc(nitem, sizeof(*menu->item)); + menu->name = name; + + /* Colors */ + menu->colors.focus.bg = bg_f; + menu->colors.focus.fg = fg_f; + menu->colors.normal.bg = bg_n; + menu->colors.normal.fg = fg_n; + + return; +} + +void +menu_new_item(MenuItem *mi, char *name, void *func, char *cmd) +{ + mi->name = name; + mi->func = func; + mi->cmd = cmd; + + return; +} + +void +menu_draw(Menu menu, int x, int y) +{ + int i, width, height, out; + XEvent ev; + BarWindow *item[menu.nitem]; + BarWindow *frame; + + int chcklen = 0; + if(menu_get_checkstring_needed(menu.item, menu.nitem)) + chcklen = textw(conf.selected_layout_symbol) + PAD / 3; + + width = menu_get_longer_string(menu.item, menu.nitem) + chcklen + textw(">") + PAD * 3; + height = menu.nitem * (INFOBARH - SHADH); + + /* Frame barwin */ + screen_get_sel(); + + if((out = x + width - MAXW) > 0) + x -= out; + if((out = y + height - MAXH) > 0) + y -= out; + + frame = barwin_create(ROOT, x, y, width + SHADH, height + SHADH * 3, + menu.colors.normal.bg, menu.colors.normal.fg, False, False, True); + + barwin_map(frame); + barwin_map_subwin(frame); + barwin_refresh_color(frame); + + for(i = 0; i < menu.nitem; ++i) + { + item[i] = barwin_create(frame->win, + SHADH, + (i * (INFOBARH - SHADH) + SHADH), + width - SHADH, + INFOBARH, + menu.colors.normal.bg, + menu.colors.normal.fg, + True, False, False); + + barwin_map(item[i]); + barwin_refresh_color(item[i]); + menu_draw_item_name(&menu, i, item, chcklen); + barwin_refresh(item[i]); + } + + /* Select the first item */ + menu_focus_item(&menu, 0, item); + + XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime); + + while(!menu_manage_event(&ev, &menu, item)); + + XUngrabKeyboard(dpy, CurrentTime); + + for(i = 0; i < menu.nitem; ++i) + barwin_delete(item[i]); + barwin_delete(frame); + + return; } diff --git a/src/tag.c b/src/tag.c index 473ff4a..dfd1f36 100644 --- a/src/tag.c +++ b/src/tag.c @@ -303,8 +303,57 @@ uicb_tag_last(uicb_t cmd) return; } -static void tag_swap(int s, int t1, int t2); -static void remove_old_last_tag(int selscreen); +/** + *\param selscreen int +*/ +static void +remove_old_last_tag(int selscreen) +{ + int i; + for(i = 0; i <= conf.ntag[selscreen]; i++) + { + if(tags[selscreen][i].stay_last) + { + tags[selscreen][i].stay_last = False; + break; + } + } + + return; +} + +/** Swap 2 tags + *\param s Screen + *\param t1 Tag 1 + *\param t2 Tag 2 +*/ +static void +tag_swap(int s, int t1, int t2) +{ + Client *c; + Tag t; + + if(t1 > conf.ntag[s] || t1 < 1 + || t2 > conf.ntag[s] || t2 < 1 || t1 == t2) + return; + + t = tags[s][t1]; + tags[s][t1] = tags[s][t2]; + tags[s][t2] = t; + + for(c = clients; c; c = c->next) + { + if(c->screen == s && c->tag == (uint)t1) + c->tag = t2; + else if(c->screen == s && c->tag == (uint)t2) + c->tag = t1; + } + + infobar_update_taglist(s); + tag_set(t2); + + return; +} /** Keep that tag the last one *\param cmd uicb_t type unused @@ -469,39 +518,6 @@ uicb_tag_toggle_additional(uicb_t cmd) return; } -/** Swap 2 tags - *\param s Screen - *\param t1 Tag 1 - *\param t2 Tag 2 -*/ -static void -tag_swap(int s, int t1, int t2) -{ - Client *c; - Tag t; - - if(t1 > conf.ntag[s] || t1 < 1 - || t2 > conf.ntag[s] || t2 < 1 || t1 == t2) - return; - - t = tags[s][t1]; - tags[s][t1] = tags[s][t2]; - tags[s][t2] = t; - - for(c = clients; c; c = c->next) - { - if(c->screen == s && c->tag == (uint)t1) - c->tag = t2; - else if(c->screen == s && c->tag == (uint)t2) - c->tag = t1; - } - - infobar_update_taglist(s); - tag_set(t2); - - return; -} - /** Swap current tag with a specified tag *\param cmd uicb_t type */ @@ -718,22 +734,3 @@ uicb_tag_rename(uicb_t cmd) return; } - -/** - *\param selscreen int -*/ -static void -remove_old_last_tag(int selscreen) -{ - int i; - for(i = 0; i <= conf.ntag[selscreen]; i++) - { - if(tags[selscreen][i].stay_last) - { - tags[selscreen][i].stay_last = False; - break; - } - } - - return; -} diff --git a/src/wmfs.c b/src/wmfs.c index 3821890..f73fb38 100644 --- a/src/wmfs.c +++ b/src/wmfs.c @@ -35,8 +35,6 @@ static volatile Bool exiting = False, sig_chld = False; static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; -static void signal_handle(int); - int errorhandler(Display *d, XErrorEvent *event) {