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) {
|
for (; it; it = next, ++i) {
|
||||||
next = g_slist_next(it);
|
next = g_slist_next(it);
|
||||||
menu_free(it->data);
|
menu_unref(it->data);
|
||||||
desktop_menus = g_slist_delete_link(desktop_menus, it);
|
desktop_menus = g_slist_delete_link(desktop_menus, it);
|
||||||
menu_entry_remove(menu_find_entry_id(menu, i));
|
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,
|
ObMenu* menu_new(const gchar *name, const gchar *title,
|
||||||
gboolean allow_shortcut, gpointer data)
|
gboolean allow_shortcut_selection, gpointer data)
|
||||||
{
|
{
|
||||||
ObMenu *self;
|
ObMenu *self;
|
||||||
|
|
||||||
|
@ -322,11 +322,17 @@ ObMenu* menu_new(const gchar *name, const gchar *title,
|
||||||
self->name = g_strdup(name);
|
self->name = g_strdup(name);
|
||||||
self->data = data;
|
self->data = data;
|
||||||
|
|
||||||
self->shortcut = parse_shortcut(title, allow_shortcut, &self->title,
|
self->shortcut = parse_shortcut(title, allow_shortcut_selection,
|
||||||
&self->shortcut_position);
|
&self->title, &self->shortcut_position);
|
||||||
|
|
||||||
g_hash_table_replace(menu_hash, self->name, self);
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,9 +361,10 @@ static void menu_destroy_hash_value(ObMenu *self)
|
||||||
g_free(self);
|
g_free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_free(ObMenu *menu)
|
void menu_unref(ObMenu *menu)
|
||||||
{
|
{
|
||||||
g_hash_table_remove(menu_hash, menu->name);
|
if (menu)
|
||||||
|
g_hash_table_remove(menu_hash, menu->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_show(gchar *name, gint x, gint y, gint button, ObClient *client)
|
void menu_show(gchar *name, gint x, gint y, gint button, ObClient *client)
|
||||||
|
@ -378,7 +385,7 @@ void menu_show(gchar *name, gint x, gint y, gint button, ObClient *client)
|
||||||
|
|
||||||
menu_frame_hide_all();
|
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))
|
if (!menu_frame_show_topmenu(frame, x, y, button))
|
||||||
menu_frame_free(frame);
|
menu_frame_free(frame);
|
||||||
else if (frame->entries) {
|
else if (frame->entries) {
|
||||||
|
@ -396,6 +403,7 @@ static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type, gint id)
|
||||||
g_assert(menu);
|
g_assert(menu);
|
||||||
|
|
||||||
self = g_new0(ObMenuEntry, 1);
|
self = g_new0(ObMenuEntry, 1);
|
||||||
|
self->ref = 1;
|
||||||
self->type = type;
|
self->type = type;
|
||||||
self->menu = menu;
|
self->menu = menu;
|
||||||
self->id = id;
|
self->id = id;
|
||||||
|
@ -412,9 +420,14 @@ static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type, gint id)
|
||||||
return self;
|
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) {
|
switch (self->type) {
|
||||||
case OB_MENU_ENTRY_TYPE_NORMAL:
|
case OB_MENU_ENTRY_TYPE_NORMAL:
|
||||||
g_free(self->data.normal.label);
|
g_free(self->data.normal.label);
|
||||||
|
@ -452,15 +465,16 @@ void menu_clear_entries(ObMenu *self)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (self->entries) {
|
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->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)
|
void menu_entry_remove(ObMenuEntry *self)
|
||||||
{
|
{
|
||||||
self->menu->entries = g_list_remove(self->menu->entries, 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,
|
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);
|
menu_entry_set_label(e, label, allow_shortcut);
|
||||||
|
|
||||||
self->entries = g_list_append(self->entries, e);
|
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;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,6 +511,7 @@ ObMenuEntry* menu_add_submenu(ObMenu *self, gint id, const gchar *submenu)
|
||||||
e->data.submenu.name = g_strdup(submenu);
|
e->data.submenu.name = g_strdup(submenu);
|
||||||
|
|
||||||
self->entries = g_list_append(self->entries, e);
|
self->entries = g_list_append(self->entries, e);
|
||||||
|
self->more_menu->entries = self->entries; /* keep it in sync */
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,6 +524,7 @@ ObMenuEntry* menu_add_separator(ObMenu *self, gint id, const gchar *label)
|
||||||
menu_entry_set_label(e, label, FALSE);
|
menu_entry_set_label(e, label, FALSE);
|
||||||
|
|
||||||
self->entries = g_list_append(self->entries, e);
|
self->entries = g_list_append(self->entries, e);
|
||||||
|
self->more_menu->entries = self->entries; /* keep it in sync */
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,9 @@ struct _ObMenu
|
||||||
|
|
||||||
/* Pipe-menu parent, we get destroyed when it is destroyed */
|
/* Pipe-menu parent, we get destroyed when it is destroyed */
|
||||||
ObMenu *pipe_creator;
|
ObMenu *pipe_creator;
|
||||||
|
|
||||||
|
/* The menu used as the destination for the "More..." entry for this menu*/
|
||||||
|
ObMenu *more_menu;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -120,6 +123,7 @@ struct _ObNormalMenuEntry {
|
||||||
struct _ObSubmenuMenuEntry {
|
struct _ObSubmenuMenuEntry {
|
||||||
gchar *name;
|
gchar *name;
|
||||||
ObMenu *submenu;
|
ObMenu *submenu;
|
||||||
|
guint show_from;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ObSeparatorMenuEntry {
|
struct _ObSeparatorMenuEntry {
|
||||||
|
@ -128,6 +132,8 @@ struct _ObSeparatorMenuEntry {
|
||||||
|
|
||||||
struct _ObMenuEntry
|
struct _ObMenuEntry
|
||||||
{
|
{
|
||||||
|
guint ref;
|
||||||
|
|
||||||
ObMenuEntryType type;
|
ObMenuEntryType type;
|
||||||
ObMenu *menu;
|
ObMenu *menu;
|
||||||
|
|
||||||
|
@ -143,10 +149,13 @@ struct _ObMenuEntry
|
||||||
void menu_startup(gboolean reconfig);
|
void menu_startup(gboolean reconfig);
|
||||||
void menu_shutdown(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
|
/*! @param allow_shortcut this should be false when the label is coming from
|
||||||
outside data like window or desktop titles */
|
outside data like window or desktop titles */
|
||||||
ObMenu* menu_new(const gchar *name, const gchar *title,
|
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);
|
void menu_free(ObMenu *menu);
|
||||||
|
|
||||||
/* Repopulate a pipe-menu by running its command */
|
/* 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 */
|
/* fills in the submenus, for use when a menu is being shown */
|
||||||
void menu_find_submenus(ObMenu *self);
|
void menu_find_submenus(ObMenu *self);
|
||||||
|
|
||||||
|
ObMenuEntry* menu_get_more(ObMenu *menu, guint show_from);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#define SEPARATOR_HEIGHT 3
|
#define SEPARATOR_HEIGHT 3
|
||||||
#define MAX_MENU_WIDTH 400
|
#define MAX_MENU_WIDTH 400
|
||||||
|
|
||||||
|
#define ITEM_HEIGHT (ob_rr_theme->menu_font_height + 2*PADDING)
|
||||||
|
|
||||||
#define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask |\
|
#define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask |\
|
||||||
LeaveWindowMask)
|
LeaveWindowMask)
|
||||||
#define ENTRY_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
|
#define ENTRY_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
|
||||||
|
@ -69,7 +71,7 @@ void menu_frame_shutdown(gboolean reconfig)
|
||||||
g_hash_table_destroy(menu_frame_map);
|
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;
|
ObMenuFrame *self;
|
||||||
XSetWindowAttributes attr;
|
XSetWindowAttributes attr;
|
||||||
|
@ -80,11 +82,16 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, ObClient *client)
|
||||||
self->selected = NULL;
|
self->selected = NULL;
|
||||||
self->client = client;
|
self->client = client;
|
||||||
self->direction_right = TRUE;
|
self->direction_right = TRUE;
|
||||||
|
self->show_from = show_from;
|
||||||
|
|
||||||
attr.event_mask = FRAME_EVENTMASK;
|
attr.event_mask = FRAME_EVENTMASK;
|
||||||
self->window = createWindow(RootWindow(ob_display, ob_screen),
|
self->window = createWindow(RootWindow(ob_display, ob_screen),
|
||||||
CWEventMask, &attr);
|
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_title = RrAppearanceCopy(ob_rr_theme->a_menu_title);
|
||||||
self->a_items = RrAppearanceCopy(ob_rr_theme->a_menu);
|
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->entry = entry;
|
||||||
self->frame = frame;
|
self->frame = frame;
|
||||||
|
|
||||||
|
menu_entry_ref(entry);
|
||||||
|
|
||||||
attr.event_mask = ENTRY_EVENTMASK;
|
attr.event_mask = ENTRY_EVENTMASK;
|
||||||
self->window = createWindow(self->frame->window, CWEventMask, &attr);
|
self->window = createWindow(self->frame->window, CWEventMask, &attr);
|
||||||
self->text = createWindow(self->window, 0, NULL);
|
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)
|
static void menu_entry_frame_free(ObMenuEntryFrame *self)
|
||||||
{
|
{
|
||||||
if (self) {
|
if (self) {
|
||||||
|
menu_entry_unref(self->entry);
|
||||||
|
|
||||||
XDestroyWindow(ob_display, self->text);
|
XDestroyWindow(ob_display, self->text);
|
||||||
XDestroyWindow(ob_display, self->window);
|
XDestroyWindow(ob_display, self->window);
|
||||||
g_hash_table_remove(menu_frame_map, &self->text);
|
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;
|
*y = self->parent->area.y + self->parent_entry->area.y;
|
||||||
if (config_menu_middle)
|
if (config_menu_middle)
|
||||||
*y -= (self->area.height - (bwidth * 2) - self->item_h) / 2;
|
*y -= (self->area.height - (bwidth * 2) - ITEM_HEIGHT) / 2;
|
||||||
else
|
else
|
||||||
*y += overlap;
|
*y += overlap;
|
||||||
}
|
}
|
||||||
|
@ -352,7 +363,7 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
||||||
/* enabled */
|
/* enabled */
|
||||||
(self == self->frame->selected ?
|
(self == self->frame->selected ?
|
||||||
self->a_selected : self->a_normal));
|
self->a_selected : self->a_normal));
|
||||||
th = self->frame->item_h;
|
th = ITEM_HEIGHT;
|
||||||
break;
|
break;
|
||||||
case OB_MENU_ENTRY_TYPE_SEPARATOR:
|
case OB_MENU_ENTRY_TYPE_SEPARATOR:
|
||||||
if (self->entry->data.separator.label) {
|
if (self->entry->data.separator.label) {
|
||||||
|
@ -422,23 +433,23 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
||||||
XMoveResizeWindow(ob_display, self->text,
|
XMoveResizeWindow(ob_display, self->text,
|
||||||
self->frame->text_x, PADDING,
|
self->frame->text_x, PADDING,
|
||||||
self->frame->text_w,
|
self->frame->text_w,
|
||||||
self->frame->item_h - 2*PADDING);
|
ITEM_HEIGHT - 2*PADDING);
|
||||||
text_a->surface.parent = item_a;
|
text_a->surface.parent = item_a;
|
||||||
text_a->surface.parentx = self->frame->text_x;
|
text_a->surface.parentx = self->frame->text_x;
|
||||||
text_a->surface.parenty = PADDING;
|
text_a->surface.parenty = PADDING;
|
||||||
RrPaint(text_a, self->text, self->frame->text_w,
|
RrPaint(text_a, self->text, self->frame->text_w,
|
||||||
self->frame->item_h - 2*PADDING);
|
ITEM_HEIGHT - 2*PADDING);
|
||||||
break;
|
break;
|
||||||
case OB_MENU_ENTRY_TYPE_SUBMENU:
|
case OB_MENU_ENTRY_TYPE_SUBMENU:
|
||||||
XMoveResizeWindow(ob_display, self->text,
|
XMoveResizeWindow(ob_display, self->text,
|
||||||
self->frame->text_x, PADDING,
|
self->frame->text_x, PADDING,
|
||||||
self->frame->text_w - self->frame->item_h,
|
self->frame->text_w - ITEM_HEIGHT,
|
||||||
self->frame->item_h - 2*PADDING);
|
ITEM_HEIGHT - 2*PADDING);
|
||||||
text_a->surface.parent = item_a;
|
text_a->surface.parent = item_a;
|
||||||
text_a->surface.parentx = self->frame->text_x;
|
text_a->surface.parentx = self->frame->text_x;
|
||||||
text_a->surface.parenty = PADDING;
|
text_a->surface.parenty = PADDING;
|
||||||
RrPaint(text_a, self->text, self->frame->text_w - self->frame->item_h,
|
RrPaint(text_a, self->text, self->frame->text_w - ITEM_HEIGHT,
|
||||||
self->frame->item_h - 2*PADDING);
|
ITEM_HEIGHT - 2*PADDING);
|
||||||
break;
|
break;
|
||||||
case OB_MENU_ENTRY_TYPE_SEPARATOR:
|
case OB_MENU_ENTRY_TYPE_SEPARATOR:
|
||||||
if (self->entry->data.separator.label != NULL) {
|
if (self->entry->data.separator.label != NULL) {
|
||||||
|
@ -480,9 +491,9 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
||||||
{
|
{
|
||||||
XMoveResizeWindow(ob_display, self->icon,
|
XMoveResizeWindow(ob_display, self->icon,
|
||||||
PADDING, frame->item_margin.top,
|
PADDING, frame->item_margin.top,
|
||||||
self->frame->item_h - frame->item_margin.top
|
ITEM_HEIGHT - frame->item_margin.top
|
||||||
- frame->item_margin.bottom,
|
- frame->item_margin.bottom,
|
||||||
self->frame->item_h - frame->item_margin.top
|
ITEM_HEIGHT - frame->item_margin.top
|
||||||
- frame->item_margin.bottom);
|
- frame->item_margin.bottom);
|
||||||
self->a_icon->texture[0].data.rgba.width =
|
self->a_icon->texture[0].data.rgba.width =
|
||||||
self->entry->data.normal.icon_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.parentx = PADDING;
|
||||||
self->a_icon->surface.parenty = frame->item_margin.top;
|
self->a_icon->surface.parenty = frame->item_margin.top;
|
||||||
RrPaint(self->a_icon, self->icon,
|
RrPaint(self->a_icon, self->icon,
|
||||||
self->frame->item_h - frame->item_margin.top
|
ITEM_HEIGHT - frame->item_margin.top
|
||||||
- frame->item_margin.bottom,
|
- frame->item_margin.bottom,
|
||||||
self->frame->item_h - frame->item_margin.top
|
ITEM_HEIGHT - frame->item_margin.top
|
||||||
- frame->item_margin.bottom);
|
- frame->item_margin.bottom);
|
||||||
XMapWindow(ob_display, self->icon);
|
XMapWindow(ob_display, self->icon);
|
||||||
} else if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
|
} 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,
|
XMoveResizeWindow(ob_display, self->icon,
|
||||||
PADDING, frame->item_margin.top,
|
PADDING, frame->item_margin.top,
|
||||||
self->frame->item_h - frame->item_margin.top
|
ITEM_HEIGHT - frame->item_margin.top
|
||||||
- frame->item_margin.bottom,
|
- frame->item_margin.bottom,
|
||||||
self->frame->item_h - frame->item_margin.top
|
ITEM_HEIGHT - frame->item_margin.top
|
||||||
- frame->item_margin.bottom);
|
- frame->item_margin.bottom);
|
||||||
self->a_mask->texture[0].data.mask.mask =
|
self->a_mask->texture[0].data.mask.mask =
|
||||||
self->entry->data.normal.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.parentx = PADDING;
|
||||||
self->a_mask->surface.parenty = frame->item_margin.top;
|
self->a_mask->surface.parenty = frame->item_margin.top;
|
||||||
RrPaint(self->a_mask, self->icon,
|
RrPaint(self->a_mask, self->icon,
|
||||||
self->frame->item_h - frame->item_margin.top
|
ITEM_HEIGHT - frame->item_margin.top
|
||||||
- frame->item_margin.bottom,
|
- frame->item_margin.bottom,
|
||||||
self->frame->item_h - frame->item_margin.top
|
ITEM_HEIGHT - frame->item_margin.top
|
||||||
- frame->item_margin.bottom);
|
- frame->item_margin.bottom);
|
||||||
XMapWindow(ob_display, self->icon);
|
XMapWindow(ob_display, self->icon);
|
||||||
} else
|
} else
|
||||||
|
@ -540,21 +551,20 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
||||||
if (self->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
|
if (self->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
|
||||||
RrAppearance *bullet_a;
|
RrAppearance *bullet_a;
|
||||||
XMoveResizeWindow(ob_display, self->bullet,
|
XMoveResizeWindow(ob_display, self->bullet,
|
||||||
self->frame->text_x + self->frame->text_w
|
self->frame->text_x + self->frame->text_w -
|
||||||
- self->frame->item_h + PADDING, PADDING,
|
ITEM_HEIGHT + PADDING, PADDING,
|
||||||
self->frame->item_h - 2*PADDING,
|
ITEM_HEIGHT - 2*PADDING,
|
||||||
self->frame->item_h - 2*PADDING);
|
ITEM_HEIGHT - 2*PADDING);
|
||||||
bullet_a = (self == self->frame->selected ?
|
bullet_a = (self == self->frame->selected ?
|
||||||
self->a_bullet_selected :
|
self->a_bullet_selected :
|
||||||
self->a_bullet_normal);
|
self->a_bullet_normal);
|
||||||
bullet_a->surface.parent = item_a;
|
bullet_a->surface.parent = item_a;
|
||||||
bullet_a->surface.parentx =
|
bullet_a->surface.parentx =
|
||||||
self->frame->text_x + self->frame->text_w - self->frame->item_h
|
self->frame->text_x + self->frame->text_w - ITEM_HEIGHT + PADDING;
|
||||||
+ PADDING;
|
|
||||||
bullet_a->surface.parenty = PADDING;
|
bullet_a->surface.parenty = PADDING;
|
||||||
RrPaint(bullet_a, self->bullet,
|
RrPaint(bullet_a, self->bullet,
|
||||||
self->frame->item_h - 2*PADDING,
|
ITEM_HEIGHT - 2*PADDING,
|
||||||
self->frame->item_h - 2*PADDING);
|
ITEM_HEIGHT - 2*PADDING);
|
||||||
XMapWindow(ob_display, self->bullet);
|
XMapWindow(ob_display, self->bullet);
|
||||||
} else
|
} else
|
||||||
XUnmapWindow(ob_display, self->bullet);
|
XUnmapWindow(ob_display, self->bullet);
|
||||||
|
@ -562,6 +572,50 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
||||||
XFlush(ob_display);
|
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)
|
static void menu_frame_render(ObMenuFrame *self)
|
||||||
{
|
{
|
||||||
gint w = 0, h = 0;
|
gint w = 0, h = 0;
|
||||||
|
@ -571,10 +625,6 @@ static void menu_frame_render(ObMenuFrame *self)
|
||||||
ObMenu *sub;
|
ObMenu *sub;
|
||||||
ObMenuEntryFrame *e;
|
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 */
|
/* find text dimensions */
|
||||||
|
|
||||||
STRUT_SET(self->item_margin, 0, 0, 0, 0);
|
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;
|
gint l, t, r, b;
|
||||||
|
|
||||||
e->a_text_normal->texture[0].data.text.string = "";
|
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;
|
tw += 2*PADDING;
|
||||||
th += 2*PADDING;
|
|
||||||
self->item_h = th;
|
th = ITEM_HEIGHT;
|
||||||
|
|
||||||
RrMargins(e->a_normal, &l, &t, &r, &b);
|
RrMargins(e->a_normal, &l, &t, &r, &b);
|
||||||
STRUT_SET(self->item_margin,
|
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.top, t),
|
||||||
MAX(self->item_margin.right, r),
|
MAX(self->item_margin.right, r),
|
||||||
MAX(self->item_margin.bottom, b));
|
MAX(self->item_margin.bottom, b));
|
||||||
} else
|
}
|
||||||
self->item_h = 0;
|
|
||||||
|
|
||||||
/* render the entries */
|
/* render the entries */
|
||||||
|
|
||||||
|
@ -655,8 +704,9 @@ static void menu_frame_render(ObMenuFrame *self)
|
||||||
switch (e->entry->type) {
|
switch (e->entry->type) {
|
||||||
case OB_MENU_ENTRY_TYPE_NORMAL:
|
case OB_MENU_ENTRY_TYPE_NORMAL:
|
||||||
text_a->texture[0].data.text.string = e->entry->data.normal.label;
|
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);
|
tw = MIN(tw, MAX_MENU_WIDTH);
|
||||||
|
th = ob_rr_theme->menu_font_height;
|
||||||
|
|
||||||
if (e->entry->data.normal.icon_data ||
|
if (e->entry->data.normal.icon_data ||
|
||||||
e->entry->data.normal.mask)
|
e->entry->data.normal.mask)
|
||||||
|
@ -665,20 +715,21 @@ static void menu_frame_render(ObMenuFrame *self)
|
||||||
case OB_MENU_ENTRY_TYPE_SUBMENU:
|
case OB_MENU_ENTRY_TYPE_SUBMENU:
|
||||||
sub = e->entry->data.submenu.submenu;
|
sub = e->entry->data.submenu.submenu;
|
||||||
text_a->texture[0].data.text.string = sub ? sub->title : "";
|
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);
|
tw = MIN(tw, MAX_MENU_WIDTH);
|
||||||
|
th = ob_rr_theme->menu_font_height;
|
||||||
|
|
||||||
if (e->entry->data.normal.icon_data ||
|
if (e->entry->data.normal.icon_data ||
|
||||||
e->entry->data.normal.mask)
|
e->entry->data.normal.mask)
|
||||||
has_icon = TRUE;
|
has_icon = TRUE;
|
||||||
|
|
||||||
tw += self->item_h - PADDING;
|
tw += ITEM_HEIGHT - PADDING;
|
||||||
break;
|
break;
|
||||||
case OB_MENU_ENTRY_TYPE_SEPARATOR:
|
case OB_MENU_ENTRY_TYPE_SEPARATOR:
|
||||||
if (e->entry->data.separator.label != NULL) {
|
if (e->entry->data.separator.label != NULL) {
|
||||||
e->a_text_title->texture[0].data.text.string =
|
e->a_text_title->texture[0].data.text.string =
|
||||||
e->entry->data.separator.label;
|
e->entry->data.separator.label;
|
||||||
RrMinSize(e->a_text_title, &tw, &th);
|
tw = RrMinWidth(text_a);
|
||||||
tw = MIN(tw, MAX_MENU_WIDTH);
|
tw = MIN(tw, MAX_MENU_WIDTH);
|
||||||
th = ob_rr_theme->menu_title_height +
|
th = ob_rr_theme->menu_title_height +
|
||||||
(ob_rr_theme->mbwidth - PADDING) *2;
|
(ob_rr_theme->mbwidth - PADDING) *2;
|
||||||
|
@ -709,8 +760,8 @@ static void menu_frame_render(ObMenuFrame *self)
|
||||||
|
|
||||||
if (self->entries) {
|
if (self->entries) {
|
||||||
if (has_icon) {
|
if (has_icon) {
|
||||||
w += self->item_h + PADDING;
|
w += ITEM_HEIGHT + PADDING;
|
||||||
self->text_x += self->item_h + 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)
|
static void menu_frame_update(ObMenuFrame *self)
|
||||||
{
|
{
|
||||||
GList *mit, *fit;
|
GList *mit, *fit;
|
||||||
|
Rect *a;
|
||||||
|
gint h;
|
||||||
|
|
||||||
menu_pipe_execute(self->menu);
|
menu_pipe_execute(self->menu);
|
||||||
menu_find_submenus(self->menu);
|
menu_find_submenus(self->menu);
|
||||||
|
|
||||||
self->selected = NULL;
|
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))
|
mit = g_list_next(mit), fit = g_list_next(fit))
|
||||||
{
|
{
|
||||||
ObMenuEntryFrame *f = fit->data;
|
ObMenuEntryFrame *f = fit->data;
|
||||||
f->entry = mit->data;
|
f->entry = mit->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if there are more menu entries than in the frame, add them */
|
||||||
while (mit) {
|
while (mit) {
|
||||||
ObMenuEntryFrame *e = menu_entry_frame_new(mit->data, self);
|
ObMenuEntryFrame *e = menu_entry_frame_new(mit->data, self);
|
||||||
self->entries = g_list_append(self->entries, e);
|
self->entries = g_list_append(self->entries, e);
|
||||||
mit = g_list_next(mit);
|
mit = g_list_next(mit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if there are more frame entries than menu entries then get rid of
|
||||||
|
them */
|
||||||
while (fit) {
|
while (fit) {
|
||||||
GList *n = g_list_next(fit);
|
GList *n = g_list_next(fit);
|
||||||
menu_entry_frame_free(fit->data);
|
menu_entry_frame_free(fit->data);
|
||||||
|
@ -764,6 +825,66 @@ static void menu_frame_update(ObMenuFrame *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_frame_render(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)
|
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;
|
if (!self->entry->data.submenu.submenu) return;
|
||||||
|
|
||||||
f = menu_frame_new(self->entry->data.submenu.submenu,
|
f = menu_frame_new(self->entry->data.submenu.submenu,
|
||||||
|
self->entry->data.submenu.show_from,
|
||||||
self->frame->client);
|
self->frame->client);
|
||||||
/* pass our direction on to our child */
|
/* pass our direction on to our child */
|
||||||
f->direction_right = self->frame->direction_right;
|
f->direction_right = self->frame->direction_right;
|
||||||
|
|
|
@ -54,6 +54,9 @@ struct _ObMenuFrame
|
||||||
GList *entries;
|
GList *entries;
|
||||||
ObMenuEntryFrame *selected;
|
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 */
|
/* If the submenus are being drawn to the right or the left */
|
||||||
gboolean direction_right;
|
gboolean direction_right;
|
||||||
|
|
||||||
|
@ -61,10 +64,10 @@ struct _ObMenuFrame
|
||||||
Rect area;
|
Rect area;
|
||||||
Strut item_margin;
|
Strut item_margin;
|
||||||
gint inner_w; /* inside the borders */
|
gint inner_w; /* inside the borders */
|
||||||
gint title_h; /* height of all title items */
|
|
||||||
gint item_h; /* height of all normal items */
|
gint item_h; /* height of all normal items */
|
||||||
gint text_x; /* offset at which the text appears in the 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_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 */
|
gint monitor; /* monitor on which to show the menu in xinerama */
|
||||||
|
|
||||||
|
@ -74,6 +77,9 @@ struct _ObMenuFrame
|
||||||
|
|
||||||
struct _ObMenuEntryFrame
|
struct _ObMenuEntryFrame
|
||||||
{
|
{
|
||||||
|
/* if this is true then it doesn't have an entry to point to */
|
||||||
|
gboolean more;
|
||||||
|
|
||||||
struct _ObMenuEntry *entry;
|
struct _ObMenuEntry *entry;
|
||||||
ObMenuFrame *frame;
|
ObMenuFrame *frame;
|
||||||
|
|
||||||
|
@ -109,7 +115,9 @@ extern GHashTable *menu_frame_map;
|
||||||
void menu_frame_startup(gboolean reconfig);
|
void menu_frame_startup(gboolean reconfig);
|
||||||
void menu_frame_shutdown(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_free(ObMenuFrame *self);
|
||||||
|
|
||||||
void menu_frame_move(ObMenuFrame *self, gint x, gint y);
|
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));
|
MAX(theme->padding * 2, ut + ub));
|
||||||
*/
|
*/
|
||||||
theme->title_height = theme->label_height + theme->paddingy * 2;
|
theme->title_height = theme->label_height + theme->paddingy * 2;
|
||||||
/* this should match the above title_height given the same font size
|
|
||||||
for both. */
|
RrMargins(theme->a_menu_title, &ul, &ut, &ur, &ub);
|
||||||
theme->menu_title_height = theme->menu_title_font_height +
|
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->paddingy * 2;
|
||||||
}
|
}
|
||||||
theme->button_size = theme->label_height - 2;
|
theme->button_size = theme->label_height - 2;
|
||||||
|
|
|
@ -51,9 +51,10 @@ struct _RrTheme {
|
||||||
gint menu_font_height;
|
gint menu_font_height;
|
||||||
gint label_height;
|
gint label_height;
|
||||||
gint title_height;
|
gint title_height;
|
||||||
gint menu_title_height;
|
|
||||||
gint button_size;
|
gint button_size;
|
||||||
gint grip_width;
|
gint grip_width;
|
||||||
|
gint menu_title_label_height;
|
||||||
|
gint menu_title_height;
|
||||||
|
|
||||||
/* style settings - colors */
|
/* style settings - colors */
|
||||||
RrColor *menu_b_color;
|
RrColor *menu_b_color;
|
||||||
|
|
Loading…
Reference in a new issue