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 @@
+
+
+
+
+
+
+
+
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);