diff --git a/docs/rc.xml.all b/docs/rc.xml.all index 399f11ed..2fb31403 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -215,6 +215,14 @@ + + + + client-menu + + + + diff --git a/include/ssd.h b/include/ssd.h index 8ec56295..e61ad676 100644 --- a/include/ssd.h +++ b/include/ssd.h @@ -14,6 +14,7 @@ enum ssd_part_type { LAB_SSD_BUTTON_CLOSE, LAB_SSD_BUTTON_MAXIMIZE, LAB_SSD_BUTTON_ICONIFY, + LAB_SSD_BUTTON_WINDOW_MENU, LAB_SSD_PART_TITLEBAR, LAB_SSD_PART_TITLE, LAB_SSD_PART_CORNER_TOP_LEFT, diff --git a/include/theme.h b/include/theme.h index 2f97c10b..38aae4c0 100644 --- a/include/theme.h +++ b/include/theme.h @@ -35,9 +35,11 @@ struct theme { enum lab_justification window_label_text_justify; /* button colors */ + float window_active_button_menu_unpressed_image_color[4]; float window_active_button_iconify_unpressed_image_color[4]; float window_active_button_max_unpressed_image_color[4]; float window_active_button_close_unpressed_image_color[4]; + float window_inactive_button_menu_unpressed_image_color[4]; float window_inactive_button_iconify_unpressed_image_color[4]; float window_inactive_button_max_unpressed_image_color[4]; float window_inactive_button_close_unpressed_image_color[4]; @@ -55,10 +57,12 @@ struct theme { struct wlr_texture *xbm_close_active_unpressed; struct wlr_texture *xbm_maximize_active_unpressed; struct wlr_texture *xbm_iconify_active_unpressed; + struct wlr_texture *xbm_menu_active_unpressed; struct wlr_texture *xbm_close_inactive_unpressed; struct wlr_texture *xbm_maximize_inactive_unpressed; struct wlr_texture *xbm_iconify_inactive_unpressed; + struct wlr_texture *xbm_menu_inactive_unpressed; struct wlr_texture *corner_top_left_active_normal; struct wlr_texture *corner_top_right_active_normal; diff --git a/src/action.c b/src/action.c index ad3e8dab..dfb6ed59 100644 --- a/src/action.c +++ b/src/action.c @@ -5,6 +5,7 @@ #include "common/zfree.h" #include "labwc.h" #include "menu/menu.h" +#include "ssd.h" #include "action.h" enum action_type { @@ -102,6 +103,15 @@ show_menu(struct server *server, struct view *view, const char *menu_name) } else if (!strcasecmp(menu_name, "client-menu") && view) { menu = server->windowmenu; server->rootmenu->visible = false; + enum ssd_part_type type = ssd_at(view, server->seat.cursor->x, + server->seat.cursor->y); + if (type == LAB_SSD_BUTTON_WINDOW_MENU) { + force_menu_top_left = true; + } else if (ssd_part_contains(LAB_SSD_PART_TITLEBAR, type)) { + force_menu_top_left = false; + } else { + force_menu_top_left = true; + } } else { return; } diff --git a/src/config/mousebind.c b/src/config/mousebind.c index 37962c3e..9d44f735 100644 --- a/src/config/mousebind.c +++ b/src/config/mousebind.c @@ -66,6 +66,8 @@ context_from_str(const char *str) return LAB_SSD_BUTTON_MAXIMIZE; } else if (!strcasecmp(str, "Iconify")) { return LAB_SSD_BUTTON_ICONIFY; + } else if (!strcasecmp(str, "WindowMenu")) { + return LAB_SSD_BUTTON_WINDOW_MENU; } else if (!strcasecmp(str, "Titlebar")) { return LAB_SSD_PART_TITLEBAR; } else if (!strcasecmp(str, "Title")) { diff --git a/src/config/rcxml.c b/src/config/rcxml.c index a541970f..5496dc98 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -560,6 +560,7 @@ static struct { { "Close", "Left", "Click", "Close", NULL }, { "Iconify", "Left", "Click", "Iconify", NULL}, { "Maximize", "Left", "Click", "ToggleMaximize", NULL}, + { "WindowMenu", "Left", "Click", "ShowMenu", "client-menu"}, { "Root", "Left", "Press", "ShowMenu", "root-menu"}, { "Root", "Right", "Press", "ShowMenu", "root-menu"}, { "Root", "Middle", "Press", "ShowMenu", "root-menu"}, diff --git a/src/output.c b/src/output.c index 6295c180..b5640f24 100644 --- a/src/output.c +++ b/src/output.c @@ -549,7 +549,8 @@ isbutton(enum ssd_part_type type) { return type == LAB_SSD_BUTTON_CLOSE || type == LAB_SSD_BUTTON_MAXIMIZE || - type == LAB_SSD_BUTTON_ICONIFY; + type == LAB_SSD_BUTTON_ICONIFY || + type == LAB_SSD_BUTTON_WINDOW_MENU; } static void @@ -602,6 +603,9 @@ render_deco(struct view *view, struct output *output, box = ssd_visible_box(view, LAB_SSD_BUTTON_ICONIFY); render_icon(output, output_damage, &box, theme->xbm_iconify_active_unpressed); + box = ssd_visible_box(view, LAB_SSD_BUTTON_WINDOW_MENU); + render_icon(output, output_damage, &box, + theme->xbm_menu_active_unpressed); } else { box = ssd_visible_box(view, LAB_SSD_BUTTON_CLOSE); render_icon(output, output_damage, &box, @@ -612,6 +616,9 @@ render_deco(struct view *view, struct output *output, box = ssd_visible_box(view, LAB_SSD_BUTTON_ICONIFY); render_icon(output, output_damage, &box, theme->xbm_iconify_inactive_unpressed); + box = ssd_visible_box(view, LAB_SSD_BUTTON_WINDOW_MENU); + render_icon(output, output_damage, &box, + theme->xbm_menu_inactive_unpressed); } } diff --git a/src/ssd.c b/src/ssd.c index 533e81cc..f4f36083 100644 --- a/src/ssd.c +++ b/src/ssd.c @@ -40,7 +40,7 @@ ssd_max_extents(struct view *view) return box; } -#define NR_BUTTONS (3) +#define NR_BUTTONS (4) /** * ssd_box - the 'full' decoration geometry which includes both visible @@ -79,6 +79,12 @@ ssd_box(struct view *view, enum ssd_part_type type) box.width = button_width; box.height = button_height; break; + case LAB_SSD_BUTTON_WINDOW_MENU: + box.x = view->x; + box.y = view->y - button_height; + box.width = button_width; + box.height = button_height; + break; case LAB_SSD_PART_TITLEBAR: box.x = view->x; box.y = view->y - theme->title_height; @@ -86,7 +92,7 @@ ssd_box(struct view *view, enum ssd_part_type type) box.height = theme->title_height; break; case LAB_SSD_PART_TITLE: - box.x = view->x + title_x_padding; + box.x = view->x + button_width + title_x_padding; box.y = view->y - theme->title_height; box.width = view->w - title_x_padding * 2 - NR_BUTTONS * button_width; box.height = theme->title_height; @@ -195,6 +201,9 @@ ssd_visible_box(struct view *view, enum ssd_part_type type) case LAB_SSD_BUTTON_ICONIFY: box = ssd_box(view, type); break; + case LAB_SSD_BUTTON_WINDOW_MENU: + box = ssd_box(view, type); + break; case LAB_SSD_PART_TITLEBAR: box = ssd_box(view, type); box.x += theme->title_height; diff --git a/src/theme.c b/src/theme.c index 79e8c535..ec07f9b0 100644 --- a/src/theme.c +++ b/src/theme.c @@ -104,12 +104,16 @@ theme_builtin(struct theme *theme) parse_hexstr("#000000", theme->window_inactive_label_text_color); theme->window_label_text_justify = parse_justification("Left"); + parse_hexstr("#000000", + theme->window_active_button_menu_unpressed_image_color); parse_hexstr("#000000", theme->window_active_button_iconify_unpressed_image_color); parse_hexstr("#000000", theme->window_active_button_max_unpressed_image_color); parse_hexstr("#000000", theme->window_active_button_close_unpressed_image_color); + parse_hexstr("#000000", + theme->window_inactive_button_menu_unpressed_image_color); parse_hexstr("#000000", theme->window_inactive_button_iconify_unpressed_image_color); parse_hexstr("#000000", @@ -192,6 +196,8 @@ entry(struct theme *theme, const char *key, const char *value) /* universal button */ if (match(key, "window.active.button.unpressed.image.color")) { + parse_hexstr(value, + theme->window_active_button_menu_unpressed_image_color); parse_hexstr(value, theme->window_active_button_iconify_unpressed_image_color); parse_hexstr(value, @@ -200,6 +206,8 @@ entry(struct theme *theme, const char *key, const char *value) theme->window_active_button_close_unpressed_image_color); } if (match(key, "window.inactive.button.unpressed.image.color")) { + parse_hexstr(value, + theme->window_inactive_button_menu_unpressed_image_color); parse_hexstr(value, theme->window_inactive_button_iconify_unpressed_image_color); parse_hexstr(value, diff --git a/src/xbm/xbm.c b/src/xbm/xbm.c index 63f0ee1c..35a97cfa 100644 --- a/src/xbm/xbm.c +++ b/src/xbm/xbm.c @@ -17,10 +17,11 @@ #include "xbm/xbm.h" /* built-in 6x6 buttons */ -char close_button_normal[] = { 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 }; +char menu_button_normal[] = { 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00 }; char iconify_button_normal[] = { 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f }; char max_button_normal[] = { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f }; char max_button_toggled[] = { 0x3e, 0x22, 0x2f, 0x29, 0x39, 0x0f }; +char close_button_normal[] = { 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 }; static struct wlr_texture * texture_from_pixmap(struct wlr_renderer *renderer, struct pixmap *pixmap) @@ -87,6 +88,9 @@ out: void xbm_load(struct theme *theme, struct wlr_renderer *r) { + parse_set_color(theme->window_active_button_menu_unpressed_image_color); + load_button(r, "menu.xbm", &theme->xbm_menu_active_unpressed, + menu_button_normal); parse_set_color(theme->window_active_button_iconify_unpressed_image_color); load_button(r, "iconify.xbm", &theme->xbm_iconify_active_unpressed, iconify_button_normal); @@ -97,6 +101,9 @@ xbm_load(struct theme *theme, struct wlr_renderer *r) load_button(r, "close.xbm", &theme->xbm_close_active_unpressed, close_button_normal); + parse_set_color(theme->window_inactive_button_menu_unpressed_image_color); + load_button(r, "menu.xbm", &theme->xbm_menu_inactive_unpressed, + menu_button_normal); parse_set_color(theme->window_inactive_button_iconify_unpressed_image_color); load_button(r, "iconify.xbm", &theme->xbm_iconify_inactive_unpressed, iconify_button_normal);