From 1e6bf6821a9a14a49771c70455194d63e93b0c1c Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Sat, 21 Mar 2009 20:34:42 +0100 Subject: [PATCH] Titlebar/button: New feature: Titlebar button. (titlebar{ button {} } in the configuration file) --- CMakeLists.txt | 23 ----------------------- src/client.c | 21 +++++++++++++++++++++ src/config.c | 24 ++++++++++++++++++++++- src/config_struct.h | 13 ++++++++++++- src/event.c | 13 +++++++++++-- src/frame.c | 46 ++++++++++++++++++++++++++++++++++----------- src/structs.h | 13 +++++++++++-- src/wmfs.c | 39 +++++++++++++++++++------------------- src/wmfs.h | 3 +++ wmfsrc | 2 ++ 10 files changed, 137 insertions(+), 60 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 920a4ca..f4d4b5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,18 +81,6 @@ else (X11_FOUND) message(FATAL_ERROR "Could not find X11") endif (X11_FOUND) -find_package(PythonInterp) -if(PYTHONINTERP_FOUND) -else(PYTHONINTERP_FOUND) - message(FATAL_ERROR "Could not find Python interpreter") -endif(PYTHONINTERP_FOUND) - -find_package(PythonLibs) -if(PYTHONLIBS_FOUND) -else(PYTHONLIBS_FOUND) - message(FATAL_ERROR "Could not find Python libs") -endif(PYTHONLIBS_FOUND) - # Link Libraries set(LIBRARIES_TO_LINK ${FREETYPE_LIBRARIES} @@ -168,17 +156,6 @@ execute_process( endif() -# Build python lib -add_custom_command( - COMMAND ${PYTHON_EXECUTABLE} - ARGS python/setup.py build - WORKING_DIRECTORY ${SOURCE_DIR} - COMMENT "Building python lib" - TARGET ${SOURCE_DIR} - ) -add_custom_target(python_lib) -add_dependencies(${PROJECT_NAME} python_lib) - # {{{ Check if documentation can be build if(GENERATE_MANPAGES) if(NOT ASCIIDOC_EXECUTABLE OR NOT XMLTO_EXECUTABLE OR NOT GZIP_EXECUTABLE) diff --git a/src/client.c b/src/client.c index 21d69b7..434e855 100644 --- a/src/client.c +++ b/src/client.c @@ -228,6 +228,27 @@ client_focus(Client *c) return c; } +/** Get a client->button[button_num] with a window + * \param w Window + * \param n Pointer who return the button_num + * \return The client +*/ + Client* client_gb_button(Window w, int *n) + { + Client *c; + int i; + + for(c = clients; c; c = c->next) + for(i = 0; i < conf.titlebar.nbutton; ++i) + if(c->button[i] == w) + { + *n = i; + return c; + } + + return NULL; + } + /* }}} */ /** Get a client name diff --git a/src/config.c b/src/config.c index f0f7e43..32298fe 100644 --- a/src/config.c +++ b/src/config.c @@ -158,6 +158,9 @@ conf_root_section(cfg_t *cfg_r) void conf_client_section(cfg_t *cfg_c) { + int i; + cfg_t *cfgtmp2; + /* Client misc */ conf.client.borderheight = (cfg_getint(cfg_c, "border_height")) ? cfg_getint(cfg_c, "border_height") : 1; conf.client.place_at_mouse = cfg_getbool(cfg_c, "place_at_mouse"); @@ -166,23 +169,42 @@ conf_client_section(cfg_t *cfg_c) conf.client.resizecorner_normal = getcolor(alias_to_str(cfg_getstr(cfg_c, "resize_corner_normal"))); conf.client.resizecorner_focus = getcolor(alias_to_str(cfg_getstr(cfg_c, "resize_corner_focus"))); conf.client.mod |= char_to_modkey(cfg_getstr(cfg_c, "modifier"), key_list); + if((conf.client.nmouse = cfg_size(cfg_c, "mouse"))) { conf.client.mouse = emalloc(conf.client.nmouse, sizeof(MouseBinding)); mouse_section(conf.client.mouse, cfg_c, conf.client.nmouse); } - /* Titlebar part */ + /* Titlebar part {{ */ cfgtmp = cfg_getsec(cfg_c, "titlebar"); conf.titlebar.height = cfg_getint(cfgtmp, "height"); conf.titlebar.stipple = cfg_getbool(cfgtmp, "stipple"); conf.titlebar.fg_normal = alias_to_str(cfg_getstr(cfgtmp, "fg_normal")); conf.titlebar.fg_focus = alias_to_str(cfg_getstr(cfgtmp, "fg_focus")); + if((conf.titlebar.nmouse = cfg_size(cfgtmp, "mouse"))) { conf.titlebar.mouse = emalloc(conf.titlebar.nmouse, sizeof(MouseBinding)); mouse_section(conf.titlebar.mouse, cfgtmp, conf.titlebar.nmouse); } + + /* Multi button part */ + if((conf.titlebar.nbutton = cfg_size(cfgtmp, "button"))) + { + conf.titlebar.button = emalloc(conf.titlebar.nbutton, sizeof(Button)); + for(i = 0; i < conf.titlebar.nbutton; ++i) + { + cfgtmp2 = cfg_getnsec(cfgtmp, "button", i); + if((conf.titlebar.button[i].nmouse = cfg_size(cfgtmp2, "mouse"))) + { + conf.titlebar.button[i].mouse = emalloc(conf.titlebar.button[i].nmouse, sizeof(MouseBinding)); + mouse_section(conf.titlebar.button[i].mouse, cfgtmp2, conf.titlebar.button[i].nmouse); + } + } + } + /* }} */ + return; } diff --git a/src/config_struct.h b/src/config_struct.h index d5be9e0..a4cf7d1 100644 --- a/src/config_struct.h +++ b/src/config_struct.h @@ -70,6 +70,14 @@ cfg_opt_t root_opts[] = CFG_END() }; +/* CLIENT {{{ */ + +cfg_opt_t button_opts[] = +{ + CFG_SEC("mouse", mouse_button_opts, CFGF_MULTI), + CFG_END() +}; + cfg_opt_t titlebar_opts[] = { CFG_INT("height", 0, CFGF_NONE), @@ -77,6 +85,7 @@ cfg_opt_t titlebar_opts[] = CFG_STR("fg_normal", "#FFFFFF", CFGF_NONE), CFG_STR("fg_focus", "#FFFFFF", CFGF_NONE), CFG_SEC("mouse", mouse_button_opts, CFGF_MULTI), + CFG_SEC("button", button_opts, CFGF_MULTI), CFG_END() }; @@ -94,6 +103,8 @@ cfg_opt_t client_opts[]= CFG_END() }; +/* }}} */ + /* TAGS {{{ */ cfg_opt_t layout_opts[] = @@ -147,7 +158,7 @@ cfg_opt_t tags_opts[] = cfg_opt_t menu_items_opts[] = { - CFG_STR("name", "iten_wname", CFGF_NONE), + CFG_STR("name", "item_wname", CFGF_NONE), CFG_STR("func", "", CFGF_NONE), CFG_STR("cmd", "", CFGF_NONE), CFG_END() diff --git a/src/event.c b/src/event.c index 90a4094..2e61718 100644 --- a/src/event.c +++ b/src/event.c @@ -39,7 +39,7 @@ void buttonpress(XButtonEvent *ev) { Client *c; - int i, x, y; + int i, n, x, y; screen_get_sel(); @@ -50,6 +50,13 @@ buttonpress(XButtonEvent *ev) if(conf.titlebar.mouse[i].func) conf.titlebar.mouse[i].func(conf.titlebar.mouse[i].cmd); + /* Titlebar buttons */ + if((c = client_gb_button(ev->window, &n))) + for(i = 0; i < conf.titlebar.button[n].nmouse; ++i) + if(ev->button == conf.titlebar.button[n].mouse[i].button) + if(conf.titlebar.button[n].mouse[i].func) + conf.titlebar.button[n].mouse[i].func(conf.titlebar.button[n].mouse[i].cmd); + /* Frame Resize Area */ if((c = client_gb_resize(ev->window))) mouse_resize(c); @@ -293,6 +300,7 @@ void enternotify(XCrossingEvent *ev) { Client *c; + int n; if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) @@ -301,7 +309,8 @@ enternotify(XCrossingEvent *ev) if((c = client_gb_win(ev->window)) || (c = client_gb_frame(ev->window)) - || (c = client_gb_titlebar(ev->window))) + || (c = client_gb_titlebar(ev->window)) + || (c = client_gb_button(ev->window, &n))) client_focus(c); else client_focus(NULL); diff --git a/src/frame.c b/src/frame.c index 869ae47..7f98616 100644 --- a/src/frame.c +++ b/src/frame.c @@ -40,6 +40,7 @@ void frame_create(Client *c) { XSetWindowAttributes at; + int i; at.background_pixel = conf.client.bordernormal; at.background_pixmap = ParentRelative; @@ -78,12 +79,25 @@ frame_create(Client *c) c->colors.fg, True, conf.titlebar.stipple, False); - /* - CWIN(c->button, c->titlebar->win, 2, 2, TBARH - 3, TBARH - 3, 1, - CWOverrideRedirect|CWBackPixmap, c->colors.frame, &at); - XSetWindowBorder(dpy, c->button, getcolor(c->colors.fg)); - */ + /* Buttons */ + if(BUTTONWH) + { + c->button = emalloc(conf.titlebar.nbutton, sizeof(Window)); + for(i = 0; i < conf.titlebar.nbutton; ++i) + { + CWIN(c->button[i], c->titlebar->win, + (BORDH + (BUTTONWH * i) + (4 * i)), + (((TBARH + BORDH) - BUTTONWH) / 2), BUTTONWH, BUTTONWH, + 1, CWEventMask|CWOverrideRedirect|CWBackPixmap, + c->colors.frame, &at); + XSetWindowBorder(dpy, c->button[i], getcolor(c->colors.fg)); + + /* Save the position of the last button to draw the font rectangle (frame_update) */ + if(i == conf.titlebar.nbutton - 1) + c->button_last_x = (BORDH + (BUTTONWH * i) + (4 * i)) + TBARH + 1; + } + } } at.event_mask &= ~(EnterWindowMask | LeaveWindowMask); /* <- Delete useless mask */ @@ -174,6 +188,8 @@ frame_moveresize(Client *c, XRectangle geo) void frame_update(Client *c) { + int i ; + CHECK(c); if(TBARH) @@ -183,13 +199,21 @@ frame_update(Client *c) barwin_refresh_color(c->titlebar); -/* - draw_rectangle(c->titlebar->dr, 0, 0, TBARH + 4, TBARH + BORDH * 2, c->colors.frame); + /* Buttons */ + if(conf.titlebar.nbutton && BUTTONWH) + { + draw_rectangle(c->titlebar->dr, 0, 0, c->button_last_x, + TBARH + BORDH * 2, c->colors.frame); + + for(i = 0; i < conf.titlebar.nbutton; ++i) + { + XSetWindowBackground(dpy, c->button[i], c->colors.frame); + XClearWindow(dpy, c->button[i]); + XSetWindowBorder(dpy, c->button[i], getcolor(c->colors.fg)); + } + } + barwin_refresh(c->titlebar); - XSetWindowBackground(dpy, c->button, c->colors.frame); - XClearWindow(dpy, c->button); - XSetWindowBorder(dpy, c->button, getcolor(c->colors.fg)); -*/ } XSetWindowBackground(dpy, c->frame, c->colors.frame); diff --git a/src/structs.h b/src/structs.h index 224149c..339352e 100644 --- a/src/structs.h +++ b/src/structs.h @@ -137,7 +137,8 @@ struct Client int minax, maxax, minay, maxay; /* Client composant {{{ */ Window win; - Window button; + Window *button; + int button_last_x; BarWindow *titlebar; Window frame, resize; /* Border */ @@ -245,6 +246,13 @@ typedef struct char *command; } Launcher; +/* Button struct */ +typedef struct +{ + MouseBinding *mouse; + int nmouse; +} Button; + /* Alias struct */ typedef struct { @@ -300,6 +308,8 @@ typedef struct Bool stipple; MouseBinding *mouse; int nmouse; + Button *button; + int nbutton; } titlebar; struct { @@ -316,7 +326,6 @@ typedef struct Bool layout_system; /* Switch: False, Menu: True. */ /* Number of... */ int nkeybind; - int nbutton; int nlayout; int nmenu; int nlauncher; diff --git a/src/wmfs.c b/src/wmfs.c index 63c0507..eb88547 100644 --- a/src/wmfs.c +++ b/src/wmfs.c @@ -96,38 +96,37 @@ quit(void) client_unmanage(c); } - if(tags) - free(tags); - free(seltag); + IFREE(tags); + IFREE(seltag); XftFontClose(dpy, font); XFreeCursor(dpy, cursor[CurNormal]); XFreeCursor(dpy, cursor[CurMove]); XFreeCursor(dpy, cursor[CurResize]); infobar_destroy(); - free(sgeo); - free(infobar); - free(keys); - free(func_list); + IFREE(sgeo); + IFREE(infobar); + IFREE(keys); + IFREE(func_list); /* Clean conf alloced thing {{{ */ - if(menulayout.item) - free(menulayout.item); + IFREE(menulayout.item); + if(conf.menu) { for(i = 0; i < LEN(conf.menu); ++i) - free(conf.menu[i].item); - free(conf.menu); + IFREE(conf.menu[i].item); + IFREE(conf.menu); } - if(conf.launcher) - free(conf.launcher); - free(conf.ntag); - if(conf.titlebar.nmouse) - free(conf.titlebar.mouse); - if(conf.client.nmouse) - free(conf.client.mouse); - if(conf.root.nmouse) - free(conf.root.mouse); + + IFREE(conf.launcher); + IFREE(conf.ntag); + IFREE(conf.titlebar.mouse); + for(i = 0; i < conf.titlebar.nbutton; ++i) + IFREE(conf.titlebar.button[i].mouse); + IFREE(conf.titlebar.button); + IFREE(conf.client.mouse); + IFREE(conf.root.mouse); /* }}} */ XSync(dpy, False); diff --git a/src/wmfs.h b/src/wmfs.h index a4dbeb5..f5dd1b3 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -82,7 +82,9 @@ #define FRAMEW(w) ((w) + BORDH * 2) #define FRAMEH(h) ((h) + (BORDH * 2) + TBARH) #define RESHW (5 * BORDH) +#define BUTTONWH (TBARH - 4) #define CHECK(x) if(!(x)) return +#define IFREE(x) if(x) free(x) #define LEN(x) (sizeof(x) / sizeof((x)[0])) #define deb(p) fprintf(stderr, "debug: %d\n", (p)) #define PAD (14) @@ -131,6 +133,7 @@ Client* client_gb_win(Window w); Client* client_gb_frame(Window w); Client* client_gb_titlebar(Window w); Client* client_gb_resize(Window w); +Client* client_gb_button(Window w, int *n); /* }}} */ void client_get_name(Client *c); void client_hide(Client *c); diff --git a/wmfsrc b/wmfsrc index 5c4d0c7..e1b282e 100644 --- a/wmfsrc +++ b/wmfsrc @@ -101,6 +101,8 @@ client mouse { button = "2" func = "tile_switch" } mouse { button = "3" func = "client_raise" } mouse { button = "3" func = "mouse_resize" } + + button { mouse { button = "1" func = "client_kill" } } } }