merge in r6153-6154 from the 3.4 branch
This commit is contained in:
parent
edf29cfe73
commit
3905872982
7 changed files with 231 additions and 60 deletions
|
@ -159,7 +159,7 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
|
|||
}
|
||||
for (; it; it = next, ++i) {
|
||||
next = g_slist_next(it);
|
||||
menu_free(it->data);
|
||||
menu_unref(it->data);
|
||||
desktop_menus = g_slist_delete_link(desktop_menus, it);
|
||||
menu_entry_remove(menu_find_entry_id(menu, i));
|
||||
}
|
||||
|
|
|
@ -314,7 +314,7 @@ parse_menu_fail:
|
|||
}
|
||||
|
||||
ObMenu* menu_new(const gchar *name, const gchar *title,
|
||||
gboolean allow_shortcut, gpointer data)
|
||||
gboolean allow_shortcut_selection, gpointer data)
|
||||
{
|
||||
ObMenu *self;
|
||||
|
||||
|
@ -322,11 +322,17 @@ ObMenu* menu_new(const gchar *name, const gchar *title,
|
|||
self->name = g_strdup(name);
|
||||
self->data = data;
|
||||
|
||||
self->shortcut = parse_shortcut(title, allow_shortcut, &self->title,
|
||||
&self->shortcut_position);
|
||||
self->shortcut = parse_shortcut(title, allow_shortcut_selection,
|
||||
&self->title, &self->shortcut_position);
|
||||
|
||||
g_hash_table_replace(menu_hash, self->name, self);
|
||||
|
||||
self->more_menu = g_new0(ObMenu, 1);
|
||||
self->more_menu->name = "More...";
|
||||
self->more_menu->title = "More...";
|
||||
self->more_menu->data = data;
|
||||
self->more_menu->shortcut = g_unichar_tolower(g_utf8_get_char("M"));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -355,8 +361,9 @@ static void menu_destroy_hash_value(ObMenu *self)
|
|||
g_free(self);
|
||||
}
|
||||
|
||||
void menu_free(ObMenu *menu)
|
||||
void menu_unref(ObMenu *menu)
|
||||
{
|
||||
if (menu)
|
||||
g_hash_table_remove(menu_hash, menu->name);
|
||||
}
|
||||
|
||||
|
@ -378,7 +385,7 @@ void menu_show(gchar *name, gint x, gint y, gint button, ObClient *client)
|
|||
|
||||
menu_frame_hide_all();
|
||||
|
||||
frame = menu_frame_new(self, client);
|
||||
frame = menu_frame_new(self, 0, client);
|
||||
if (!menu_frame_show_topmenu(frame, x, y, button))
|
||||
menu_frame_free(frame);
|
||||
else if (frame->entries) {
|
||||
|
@ -396,6 +403,7 @@ static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type, gint id)
|
|||
g_assert(menu);
|
||||
|
||||
self = g_new0(ObMenuEntry, 1);
|
||||
self->ref = 1;
|
||||
self->type = type;
|
||||
self->menu = menu;
|
||||
self->id = id;
|
||||
|
@ -412,9 +420,14 @@ static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type, gint id)
|
|||
return self;
|
||||
}
|
||||
|
||||
void menu_entry_free(ObMenuEntry *self)
|
||||
void menu_entry_ref(ObMenuEntry *self)
|
||||
{
|
||||
if (self) {
|
||||
++self->ref;
|
||||
}
|
||||
|
||||
void menu_entry_unref(ObMenuEntry *self)
|
||||
{
|
||||
if (self && --self->ref == 0) {
|
||||
switch (self->type) {
|
||||
case OB_MENU_ENTRY_TYPE_NORMAL:
|
||||
g_free(self->data.normal.label);
|
||||
|
@ -452,15 +465,16 @@ void menu_clear_entries(ObMenu *self)
|
|||
#endif
|
||||
|
||||
while (self->entries) {
|
||||
menu_entry_free(self->entries->data);
|
||||
menu_entry_unref(self->entries->data);
|
||||
self->entries = g_list_delete_link(self->entries, self->entries);
|
||||
}
|
||||
self->more_menu->entries = self->entries; /* keep it in sync */
|
||||
}
|
||||
|
||||
void menu_entry_remove(ObMenuEntry *self)
|
||||
{
|
||||
self->menu->entries = g_list_remove(self->menu->entries, self);
|
||||
menu_entry_free(self);
|
||||
menu_entry_unref(self);
|
||||
}
|
||||
|
||||
ObMenuEntry* menu_add_normal(ObMenu *self, gint id, const gchar *label,
|
||||
|
@ -474,6 +488,18 @@ ObMenuEntry* menu_add_normal(ObMenu *self, gint id, const gchar *label,
|
|||
menu_entry_set_label(e, label, allow_shortcut);
|
||||
|
||||
self->entries = g_list_append(self->entries, e);
|
||||
self->more_menu->entries = self->entries; /* keep it in sync */
|
||||
return e;
|
||||
}
|
||||
|
||||
ObMenuEntry* menu_get_more(ObMenu *self, guint show_from)
|
||||
{
|
||||
ObMenuEntry *e;
|
||||
e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_SUBMENU, -1);
|
||||
/* points to itself */
|
||||
e->data.submenu.name = g_strdup(self->name);
|
||||
e->data.submenu.submenu = self;
|
||||
e->data.submenu.show_from = show_from;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -485,6 +511,7 @@ ObMenuEntry* menu_add_submenu(ObMenu *self, gint id, const gchar *submenu)
|
|||
e->data.submenu.name = g_strdup(submenu);
|
||||
|
||||
self->entries = g_list_append(self->entries, e);
|
||||
self->more_menu->entries = self->entries; /* keep it in sync */
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -497,6 +524,7 @@ ObMenuEntry* menu_add_separator(ObMenu *self, gint id, const gchar *label)
|
|||
menu_entry_set_label(e, label, FALSE);
|
||||
|
||||
self->entries = g_list_append(self->entries, e);
|
||||
self->more_menu->entries = self->entries; /* keep it in sync */
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,6 +82,9 @@ struct _ObMenu
|
|||
|
||||
/* Pipe-menu parent, we get destroyed when it is destroyed */
|
||||
ObMenu *pipe_creator;
|
||||
|
||||
/* The menu used as the destination for the "More..." entry for this menu*/
|
||||
ObMenu *more_menu;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
|
@ -120,6 +123,7 @@ struct _ObNormalMenuEntry {
|
|||
struct _ObSubmenuMenuEntry {
|
||||
gchar *name;
|
||||
ObMenu *submenu;
|
||||
guint show_from;
|
||||
};
|
||||
|
||||
struct _ObSeparatorMenuEntry {
|
||||
|
@ -128,6 +132,8 @@ struct _ObSeparatorMenuEntry {
|
|||
|
||||
struct _ObMenuEntry
|
||||
{
|
||||
guint ref;
|
||||
|
||||
ObMenuEntryType type;
|
||||
ObMenu *menu;
|
||||
|
||||
|
@ -143,10 +149,13 @@ struct _ObMenuEntry
|
|||
void menu_startup(gboolean reconfig);
|
||||
void menu_shutdown(gboolean reconfig);
|
||||
|
||||
void menu_entry_ref(ObMenuEntry *self);
|
||||
void menu_entry_unref(ObMenuEntry *self);
|
||||
|
||||
/*! @param allow_shortcut this should be false when the label is coming from
|
||||
outside data like window or desktop titles */
|
||||
ObMenu* menu_new(const gchar *name, const gchar *title,
|
||||
gboolean allow_shortcut, gpointer data);
|
||||
gboolean allow_shortcut_selection, gpointer data);
|
||||
void menu_free(ObMenu *menu);
|
||||
|
||||
/* Repopulate a pipe-menu by running its command */
|
||||
|
@ -181,4 +190,6 @@ ObMenuEntry* menu_find_entry_id(ObMenu *self, gint id);
|
|||
/* fills in the submenus, for use when a menu is being shown */
|
||||
void menu_find_submenus(ObMenu *self);
|
||||
|
||||
ObMenuEntry* menu_get_more(ObMenu *menu, guint show_from);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#define SEPARATOR_HEIGHT 3
|
||||
#define MAX_MENU_WIDTH 400
|
||||
|
||||
#define ITEM_HEIGHT (ob_rr_theme->menu_font_height + 2*PADDING)
|
||||
|
||||
#define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask |\
|
||||
LeaveWindowMask)
|
||||
#define ENTRY_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
|
||||
|
@ -69,7 +71,7 @@ void menu_frame_shutdown(gboolean reconfig)
|
|||
g_hash_table_destroy(menu_frame_map);
|
||||
}
|
||||
|
||||
ObMenuFrame* menu_frame_new(ObMenu *menu, ObClient *client)
|
||||
ObMenuFrame* menu_frame_new(ObMenu *menu, guint show_from, ObClient *client)
|
||||
{
|
||||
ObMenuFrame *self;
|
||||
XSetWindowAttributes attr;
|
||||
|
@ -80,11 +82,16 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, ObClient *client)
|
|||
self->selected = NULL;
|
||||
self->client = client;
|
||||
self->direction_right = TRUE;
|
||||
self->show_from = show_from;
|
||||
|
||||
attr.event_mask = FRAME_EVENTMASK;
|
||||
self->window = createWindow(RootWindow(ob_display, ob_screen),
|
||||
CWEventMask, &attr);
|
||||
|
||||
XSetWindowBorderWidth(ob_display, self->window, ob_rr_theme->mbwidth);
|
||||
XSetWindowBorder(ob_display, self->window,
|
||||
RrColorPixel(ob_rr_theme->menu_b_color));
|
||||
|
||||
self->a_title = RrAppearanceCopy(ob_rr_theme->a_menu_title);
|
||||
self->a_items = RrAppearanceCopy(ob_rr_theme->a_menu);
|
||||
|
||||
|
@ -122,6 +129,8 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
|
|||
self->entry = entry;
|
||||
self->frame = frame;
|
||||
|
||||
menu_entry_ref(entry);
|
||||
|
||||
attr.event_mask = ENTRY_EVENTMASK;
|
||||
self->window = createWindow(self->frame->window, CWEventMask, &attr);
|
||||
self->text = createWindow(self->window, 0, NULL);
|
||||
|
@ -176,6 +185,8 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
|
|||
static void menu_entry_frame_free(ObMenuEntryFrame *self)
|
||||
{
|
||||
if (self) {
|
||||
menu_entry_unref(self->entry);
|
||||
|
||||
XDestroyWindow(ob_display, self->text);
|
||||
XDestroyWindow(ob_display, self->window);
|
||||
g_hash_table_remove(menu_frame_map, &self->text);
|
||||
|
@ -300,7 +311,7 @@ static void menu_frame_place_submenu(ObMenuFrame *self, gint *x, gint *y)
|
|||
|
||||
*y = self->parent->area.y + self->parent_entry->area.y;
|
||||
if (config_menu_middle)
|
||||
*y -= (self->area.height - (bwidth * 2) - self->item_h) / 2;
|
||||
*y -= (self->area.height - (bwidth * 2) - ITEM_HEIGHT) / 2;
|
||||
else
|
||||
*y += overlap;
|
||||
}
|
||||
|
@ -352,7 +363,7 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
|||
/* enabled */
|
||||
(self == self->frame->selected ?
|
||||
self->a_selected : self->a_normal));
|
||||
th = self->frame->item_h;
|
||||
th = ITEM_HEIGHT;
|
||||
break;
|
||||
case OB_MENU_ENTRY_TYPE_SEPARATOR:
|
||||
if (self->entry->data.separator.label) {
|
||||
|
@ -422,23 +433,23 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
|||
XMoveResizeWindow(ob_display, self->text,
|
||||
self->frame->text_x, PADDING,
|
||||
self->frame->text_w,
|
||||
self->frame->item_h - 2*PADDING);
|
||||
ITEM_HEIGHT - 2*PADDING);
|
||||
text_a->surface.parent = item_a;
|
||||
text_a->surface.parentx = self->frame->text_x;
|
||||
text_a->surface.parenty = PADDING;
|
||||
RrPaint(text_a, self->text, self->frame->text_w,
|
||||
self->frame->item_h - 2*PADDING);
|
||||
ITEM_HEIGHT - 2*PADDING);
|
||||
break;
|
||||
case OB_MENU_ENTRY_TYPE_SUBMENU:
|
||||
XMoveResizeWindow(ob_display, self->text,
|
||||
self->frame->text_x, PADDING,
|
||||
self->frame->text_w - self->frame->item_h,
|
||||
self->frame->item_h - 2*PADDING);
|
||||
self->frame->text_w - ITEM_HEIGHT,
|
||||
ITEM_HEIGHT - 2*PADDING);
|
||||
text_a->surface.parent = item_a;
|
||||
text_a->surface.parentx = self->frame->text_x;
|
||||
text_a->surface.parenty = PADDING;
|
||||
RrPaint(text_a, self->text, self->frame->text_w - self->frame->item_h,
|
||||
self->frame->item_h - 2*PADDING);
|
||||
RrPaint(text_a, self->text, self->frame->text_w - ITEM_HEIGHT,
|
||||
ITEM_HEIGHT - 2*PADDING);
|
||||
break;
|
||||
case OB_MENU_ENTRY_TYPE_SEPARATOR:
|
||||
if (self->entry->data.separator.label != NULL) {
|
||||
|
@ -480,9 +491,9 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
|||
{
|
||||
XMoveResizeWindow(ob_display, self->icon,
|
||||
PADDING, frame->item_margin.top,
|
||||
self->frame->item_h - frame->item_margin.top
|
||||
ITEM_HEIGHT - frame->item_margin.top
|
||||
- frame->item_margin.bottom,
|
||||
self->frame->item_h - frame->item_margin.top
|
||||
ITEM_HEIGHT - frame->item_margin.top
|
||||
- frame->item_margin.bottom);
|
||||
self->a_icon->texture[0].data.rgba.width =
|
||||
self->entry->data.normal.icon_width;
|
||||
|
@ -494,9 +505,9 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
|||
self->a_icon->surface.parentx = PADDING;
|
||||
self->a_icon->surface.parenty = frame->item_margin.top;
|
||||
RrPaint(self->a_icon, self->icon,
|
||||
self->frame->item_h - frame->item_margin.top
|
||||
ITEM_HEIGHT - frame->item_margin.top
|
||||
- frame->item_margin.bottom,
|
||||
self->frame->item_h - frame->item_margin.top
|
||||
ITEM_HEIGHT - frame->item_margin.top
|
||||
- frame->item_margin.bottom);
|
||||
XMapWindow(ob_display, self->icon);
|
||||
} else if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
|
||||
|
@ -506,9 +517,9 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
|||
|
||||
XMoveResizeWindow(ob_display, self->icon,
|
||||
PADDING, frame->item_margin.top,
|
||||
self->frame->item_h - frame->item_margin.top
|
||||
ITEM_HEIGHT - frame->item_margin.top
|
||||
- frame->item_margin.bottom,
|
||||
self->frame->item_h - frame->item_margin.top
|
||||
ITEM_HEIGHT - frame->item_margin.top
|
||||
- frame->item_margin.bottom);
|
||||
self->a_mask->texture[0].data.mask.mask =
|
||||
self->entry->data.normal.mask;
|
||||
|
@ -529,9 +540,9 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
|||
self->a_mask->surface.parentx = PADDING;
|
||||
self->a_mask->surface.parenty = frame->item_margin.top;
|
||||
RrPaint(self->a_mask, self->icon,
|
||||
self->frame->item_h - frame->item_margin.top
|
||||
ITEM_HEIGHT - frame->item_margin.top
|
||||
- frame->item_margin.bottom,
|
||||
self->frame->item_h - frame->item_margin.top
|
||||
ITEM_HEIGHT - frame->item_margin.top
|
||||
- frame->item_margin.bottom);
|
||||
XMapWindow(ob_display, self->icon);
|
||||
} else
|
||||
|
@ -540,21 +551,20 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
|||
if (self->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
|
||||
RrAppearance *bullet_a;
|
||||
XMoveResizeWindow(ob_display, self->bullet,
|
||||
self->frame->text_x + self->frame->text_w
|
||||
- self->frame->item_h + PADDING, PADDING,
|
||||
self->frame->item_h - 2*PADDING,
|
||||
self->frame->item_h - 2*PADDING);
|
||||
self->frame->text_x + self->frame->text_w -
|
||||
ITEM_HEIGHT + PADDING, PADDING,
|
||||
ITEM_HEIGHT - 2*PADDING,
|
||||
ITEM_HEIGHT - 2*PADDING);
|
||||
bullet_a = (self == self->frame->selected ?
|
||||
self->a_bullet_selected :
|
||||
self->a_bullet_normal);
|
||||
bullet_a->surface.parent = item_a;
|
||||
bullet_a->surface.parentx =
|
||||
self->frame->text_x + self->frame->text_w - self->frame->item_h
|
||||
+ PADDING;
|
||||
self->frame->text_x + self->frame->text_w - ITEM_HEIGHT + PADDING;
|
||||
bullet_a->surface.parenty = PADDING;
|
||||
RrPaint(bullet_a, self->bullet,
|
||||
self->frame->item_h - 2*PADDING,
|
||||
self->frame->item_h - 2*PADDING);
|
||||
ITEM_HEIGHT - 2*PADDING,
|
||||
ITEM_HEIGHT - 2*PADDING);
|
||||
XMapWindow(ob_display, self->bullet);
|
||||
} else
|
||||
XUnmapWindow(ob_display, self->bullet);
|
||||
|
@ -562,6 +572,50 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
|||
XFlush(ob_display);
|
||||
}
|
||||
|
||||
/*! this code is taken from the menu_frame_render. if that changes, this won't
|
||||
work.. */
|
||||
static gint menu_entry_frame_get_height(ObMenuEntryFrame *self,
|
||||
gboolean first_entry,
|
||||
gboolean last_entry)
|
||||
{
|
||||
ObMenuEntryType t;
|
||||
gint h = 0;
|
||||
|
||||
h += 2*PADDING;
|
||||
|
||||
if (self)
|
||||
t = self->entry->type;
|
||||
else
|
||||
/* this is the More... entry, it's NORMAL type */
|
||||
t = OB_MENU_ENTRY_TYPE_NORMAL;
|
||||
|
||||
switch (t) {
|
||||
case OB_MENU_ENTRY_TYPE_NORMAL:
|
||||
case OB_MENU_ENTRY_TYPE_SUBMENU:
|
||||
h += ob_rr_theme->menu_font_height;
|
||||
break;
|
||||
case OB_MENU_ENTRY_TYPE_SEPARATOR:
|
||||
if (self->entry->data.separator.label != NULL) {
|
||||
h += ob_rr_theme->menu_title_height +
|
||||
(ob_rr_theme->mbwidth - PADDING) * 2;
|
||||
|
||||
/* if the first entry is a labeled separator, then make its border
|
||||
overlap with the menu's outside border */
|
||||
if (first_entry)
|
||||
h -= ob_rr_theme->mbwidth;
|
||||
/* if the last entry is a labeled separator, then make its border
|
||||
overlap with the menu's outside border */
|
||||
if (last_entry)
|
||||
h -= ob_rr_theme->mbwidth;
|
||||
} else {
|
||||
h += SEPARATOR_HEIGHT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static void menu_frame_render(ObMenuFrame *self)
|
||||
{
|
||||
gint w = 0, h = 0;
|
||||
|
@ -571,10 +625,6 @@ static void menu_frame_render(ObMenuFrame *self)
|
|||
ObMenu *sub;
|
||||
ObMenuEntryFrame *e;
|
||||
|
||||
XSetWindowBorderWidth(ob_display, self->window, ob_rr_theme->mbwidth);
|
||||
XSetWindowBorder(ob_display, self->window,
|
||||
RrColorPixel(ob_rr_theme->menu_b_color));
|
||||
|
||||
/* find text dimensions */
|
||||
|
||||
STRUT_SET(self->item_margin, 0, 0, 0, 0);
|
||||
|
@ -584,10 +634,10 @@ static void menu_frame_render(ObMenuFrame *self)
|
|||
gint l, t, r, b;
|
||||
|
||||
e->a_text_normal->texture[0].data.text.string = "";
|
||||
RrMinSize(e->a_text_normal, &tw, &th);
|
||||
tw = RrMinWidth(e->a_text_normal);
|
||||
tw += 2*PADDING;
|
||||
th += 2*PADDING;
|
||||
self->item_h = th;
|
||||
|
||||
th = ITEM_HEIGHT;
|
||||
|
||||
RrMargins(e->a_normal, &l, &t, &r, &b);
|
||||
STRUT_SET(self->item_margin,
|
||||
|
@ -613,8 +663,7 @@ static void menu_frame_render(ObMenuFrame *self)
|
|||
MAX(self->item_margin.top, t),
|
||||
MAX(self->item_margin.right, r),
|
||||
MAX(self->item_margin.bottom, b));
|
||||
} else
|
||||
self->item_h = 0;
|
||||
}
|
||||
|
||||
/* render the entries */
|
||||
|
||||
|
@ -655,8 +704,9 @@ static void menu_frame_render(ObMenuFrame *self)
|
|||
switch (e->entry->type) {
|
||||
case OB_MENU_ENTRY_TYPE_NORMAL:
|
||||
text_a->texture[0].data.text.string = e->entry->data.normal.label;
|
||||
RrMinSize(text_a, &tw, &th);
|
||||
tw = RrMinWidth(text_a);
|
||||
tw = MIN(tw, MAX_MENU_WIDTH);
|
||||
th = ob_rr_theme->menu_font_height;
|
||||
|
||||
if (e->entry->data.normal.icon_data ||
|
||||
e->entry->data.normal.mask)
|
||||
|
@ -665,20 +715,21 @@ static void menu_frame_render(ObMenuFrame *self)
|
|||
case OB_MENU_ENTRY_TYPE_SUBMENU:
|
||||
sub = e->entry->data.submenu.submenu;
|
||||
text_a->texture[0].data.text.string = sub ? sub->title : "";
|
||||
RrMinSize(text_a, &tw, &th);
|
||||
tw = RrMinWidth(text_a);
|
||||
tw = MIN(tw, MAX_MENU_WIDTH);
|
||||
th = ob_rr_theme->menu_font_height;
|
||||
|
||||
if (e->entry->data.normal.icon_data ||
|
||||
e->entry->data.normal.mask)
|
||||
has_icon = TRUE;
|
||||
|
||||
tw += self->item_h - PADDING;
|
||||
tw += ITEM_HEIGHT - PADDING;
|
||||
break;
|
||||
case OB_MENU_ENTRY_TYPE_SEPARATOR:
|
||||
if (e->entry->data.separator.label != NULL) {
|
||||
e->a_text_title->texture[0].data.text.string =
|
||||
e->entry->data.separator.label;
|
||||
RrMinSize(e->a_text_title, &tw, &th);
|
||||
tw = RrMinWidth(text_a);
|
||||
tw = MIN(tw, MAX_MENU_WIDTH);
|
||||
th = ob_rr_theme->menu_title_height +
|
||||
(ob_rr_theme->mbwidth - PADDING) *2;
|
||||
|
@ -709,8 +760,8 @@ static void menu_frame_render(ObMenuFrame *self)
|
|||
|
||||
if (self->entries) {
|
||||
if (has_icon) {
|
||||
w += self->item_h + PADDING;
|
||||
self->text_x += self->item_h + PADDING;
|
||||
w += ITEM_HEIGHT + PADDING;
|
||||
self->text_x += ITEM_HEIGHT + PADDING;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -737,25 +788,35 @@ static void menu_frame_render(ObMenuFrame *self)
|
|||
static void menu_frame_update(ObMenuFrame *self)
|
||||
{
|
||||
GList *mit, *fit;
|
||||
Rect *a;
|
||||
gint h;
|
||||
|
||||
menu_pipe_execute(self->menu);
|
||||
menu_find_submenus(self->menu);
|
||||
|
||||
self->selected = NULL;
|
||||
|
||||
for (mit = self->menu->entries, fit = self->entries; mit && fit;
|
||||
/* start at show_from */
|
||||
mit = g_list_nth(self->menu->entries, self->show_from);
|
||||
|
||||
/* go through the menu's and frame's entries and connect the frame entries
|
||||
to the menu entries */
|
||||
for (fit = self->entries; mit && fit;
|
||||
mit = g_list_next(mit), fit = g_list_next(fit))
|
||||
{
|
||||
ObMenuEntryFrame *f = fit->data;
|
||||
f->entry = mit->data;
|
||||
}
|
||||
|
||||
/* if there are more menu entries than in the frame, add them */
|
||||
while (mit) {
|
||||
ObMenuEntryFrame *e = menu_entry_frame_new(mit->data, self);
|
||||
self->entries = g_list_append(self->entries, e);
|
||||
mit = g_list_next(mit);
|
||||
}
|
||||
|
||||
/* if there are more frame entries than menu entries then get rid of
|
||||
them */
|
||||
while (fit) {
|
||||
GList *n = g_list_next(fit);
|
||||
menu_entry_frame_free(fit->data);
|
||||
|
@ -764,6 +825,66 @@ static void menu_frame_update(ObMenuFrame *self)
|
|||
}
|
||||
|
||||
menu_frame_render(self);
|
||||
|
||||
/* make the menu fit on the screen. at most we call render twice, at least
|
||||
not like n times or sometime */
|
||||
|
||||
a = screen_physical_area_monitor(self->monitor);
|
||||
h = self->area.height;
|
||||
|
||||
if (h > a->height) {
|
||||
GList *flast, *tmp;
|
||||
gboolean last_entry = TRUE;
|
||||
|
||||
/* take the height of our More... entry into account */
|
||||
h += menu_entry_frame_get_height(NULL, FALSE, TRUE);
|
||||
|
||||
/* start at the end of the entries */
|
||||
flast = g_list_last(self->entries);
|
||||
|
||||
/* pull out all the entries from the frame that don't
|
||||
fit on the screen, leaving at least 1 though */
|
||||
while (h > a->height && g_list_previous(flast) != NULL) {
|
||||
/* update the height, without this entry */
|
||||
h -= menu_entry_frame_get_height(flast->data, FALSE, last_entry);
|
||||
|
||||
/* destroy the entry we're not displaying */
|
||||
tmp = flast;
|
||||
flast = g_list_previous(flast);
|
||||
menu_entry_frame_free(tmp->data);
|
||||
self->entries = g_list_delete_link(self->entries, tmp);
|
||||
|
||||
menu_frame_render(self);
|
||||
|
||||
/* only the first one that we see is the last entry in the menu */
|
||||
last_entry = FALSE;
|
||||
};
|
||||
|
||||
{
|
||||
ObMenuEntry *more_entry;
|
||||
ObMenuEntryFrame *more_frame;
|
||||
/* make the More... menu entry frame which will display in this
|
||||
frame.
|
||||
if self->menu->more_menu is NULL that means that this is already
|
||||
More... menu, so just use ourself.
|
||||
*/
|
||||
more_entry = menu_get_more((self->menu->more_menu ?
|
||||
self->menu->more_menu :
|
||||
self->menu),
|
||||
/* continue where we left off */
|
||||
self->show_from +
|
||||
g_list_length(self->entries));
|
||||
more_frame = menu_entry_frame_new(more_entry, self);
|
||||
/* make it get deleted when the menu frame goes away */
|
||||
menu_entry_unref(more_entry);
|
||||
|
||||
/* add our More... entry to the frame */
|
||||
self->entries = g_list_append(self->entries, more_frame);
|
||||
}
|
||||
|
||||
/* render again */
|
||||
menu_frame_render(self);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean menu_frame_is_visible(ObMenuFrame *self)
|
||||
|
@ -1021,6 +1142,7 @@ void menu_entry_frame_show_submenu(ObMenuEntryFrame *self)
|
|||
if (!self->entry->data.submenu.submenu) return;
|
||||
|
||||
f = menu_frame_new(self->entry->data.submenu.submenu,
|
||||
self->entry->data.submenu.show_from,
|
||||
self->frame->client);
|
||||
/* pass our direction on to our child */
|
||||
f->direction_right = self->frame->direction_right;
|
||||
|
|
|
@ -54,6 +54,9 @@ struct _ObMenuFrame
|
|||
GList *entries;
|
||||
ObMenuEntryFrame *selected;
|
||||
|
||||
/* show entries from the menu starting at this index */
|
||||
guint show_from;
|
||||
|
||||
/* If the submenus are being drawn to the right or the left */
|
||||
gboolean direction_right;
|
||||
|
||||
|
@ -61,10 +64,10 @@ struct _ObMenuFrame
|
|||
Rect area;
|
||||
Strut item_margin;
|
||||
gint inner_w; /* inside the borders */
|
||||
gint title_h; /* height of all title items */
|
||||
gint item_h; /* height of all normal items */
|
||||
gint text_x; /* offset at which the text appears in the items */
|
||||
gint text_w; /* width of the text area in the items */
|
||||
gint text_h; /* height of the items */
|
||||
|
||||
gint monitor; /* monitor on which to show the menu in xinerama */
|
||||
|
||||
|
@ -74,6 +77,9 @@ struct _ObMenuFrame
|
|||
|
||||
struct _ObMenuEntryFrame
|
||||
{
|
||||
/* if this is true then it doesn't have an entry to point to */
|
||||
gboolean more;
|
||||
|
||||
struct _ObMenuEntry *entry;
|
||||
ObMenuFrame *frame;
|
||||
|
||||
|
@ -109,7 +115,9 @@ extern GHashTable *menu_frame_map;
|
|||
void menu_frame_startup(gboolean reconfig);
|
||||
void menu_frame_shutdown(gboolean reconfig);
|
||||
|
||||
ObMenuFrame* menu_frame_new(struct _ObMenu *menu, struct _ObClient *client);
|
||||
ObMenuFrame* menu_frame_new(struct _ObMenu *menu,
|
||||
guint show_from,
|
||||
struct _ObClient *client);
|
||||
void menu_frame_free(ObMenuFrame *self);
|
||||
|
||||
void menu_frame_move(ObMenuFrame *self, gint x, gint y);
|
||||
|
|
|
@ -1204,9 +1204,10 @@ RrTheme* RrThemeNew(const RrInstance *inst, gchar *name,
|
|||
MAX(theme->padding * 2, ut + ub));
|
||||
*/
|
||||
theme->title_height = theme->label_height + theme->paddingy * 2;
|
||||
/* this should match the above title_height given the same font size
|
||||
for both. */
|
||||
theme->menu_title_height = theme->menu_title_font_height +
|
||||
|
||||
RrMargins(theme->a_menu_title, &ul, &ut, &ur, &ub);
|
||||
theme->menu_title_label_height = theme->menu_title_font_height+ut+ub;
|
||||
theme->menu_title_height = theme->menu_title_label_height +
|
||||
theme->paddingy * 2;
|
||||
}
|
||||
theme->button_size = theme->label_height - 2;
|
||||
|
|
|
@ -51,9 +51,10 @@ struct _RrTheme {
|
|||
gint menu_font_height;
|
||||
gint label_height;
|
||||
gint title_height;
|
||||
gint menu_title_height;
|
||||
gint button_size;
|
||||
gint grip_width;
|
||||
gint menu_title_label_height;
|
||||
gint menu_title_height;
|
||||
|
||||
/* style settings - colors */
|
||||
RrColor *menu_b_color;
|
||||
|
|
Loading…
Reference in a new issue