merge in r6153-6154 from the 3.4 branch
authorDana Jansens <danakj@orodu.net>
Mon, 7 May 2007 22:07:13 +0000 (22:07 +0000)
committerDana Jansens <danakj@orodu.net>
Mon, 7 May 2007 22:07:13 +0000 (22:07 +0000)
openbox/client_list_menu.c
openbox/menu.c
openbox/menu.h
openbox/menuframe.c
openbox/menuframe.h
render/theme.c
render/theme.h

index 12c1681..036c240 100644 (file)
@@ -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));
     }
index 741e27c..3760188 100644 (file)
@@ -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,9 +361,10 @@ static void menu_destroy_hash_value(ObMenu *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)
@@ -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;
 }
 
index 64cbbd6..f66e423 100644 (file)
@@ -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
index f87c3c0..b04fda5 100644 (file)
@@ -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;
index 15bae66..0ce9615 100644 (file)
@@ -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);
index 28a682b..a60fc7b 100644 (file)
@@ -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;
index 3359d04..8f66a38 100644 (file)
@@ -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;