change the menu plugin interface, no need for the create/destroy functions any more.
redo the client-menu plugin to work with the new menu api
This commit is contained in:
parent
9290376bbb
commit
615cbd9607
13 changed files with 260 additions and 239 deletions
|
@ -26,10 +26,10 @@ bin_PROGRAMS = \
|
||||||
tools/kdetrayproxy/kdetrayproxy
|
tools/kdetrayproxy/kdetrayproxy
|
||||||
|
|
||||||
plugin_LTLIBRARIES = \
|
plugin_LTLIBRARIES = \
|
||||||
plugins/placement/placement.la
|
plugins/placement/placement.la \
|
||||||
|
plugins/menu/client_menu.la
|
||||||
# plugins/menu/timed_menu.la \
|
# plugins/menu/timed_menu.la \
|
||||||
# plugins/menu/fifo_menu.la \
|
# plugins/menu/fifo_menu.la \
|
||||||
# plugins/menu/client_menu.la \
|
|
||||||
# plugins/menu/include_menu.la \
|
# plugins/menu/include_menu.la \
|
||||||
# plugins/menu/client_list_menu.la
|
# plugins/menu/client_list_menu.la
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
</menu>
|
</menu>
|
||||||
|
|
||||||
<menu id="root-menu" label="Openbox 3">
|
<menu id="root-menu" label="Openbox 3">
|
||||||
<menu id="apps-menu">
|
<menu id="apps-menu" />
|
||||||
<menu id="games-menu">
|
<menu id="games-menu" />
|
||||||
<separator />
|
<separator />
|
||||||
<item label="Restart">
|
<item label="Restart">
|
||||||
<action name="restart" />
|
<action name="restart" />
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "openbox.h"
|
#include "openbox.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "menu.h"
|
#include "menuframe.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "mouse.h"
|
#include "mouse.h"
|
||||||
#include "render/render.h"
|
#include "render/render.h"
|
||||||
|
@ -406,7 +406,9 @@ void client_unmanage(ObClient *self)
|
||||||
if (moveresize_client == self)
|
if (moveresize_client == self)
|
||||||
moveresize_end(TRUE);
|
moveresize_end(TRUE);
|
||||||
|
|
||||||
/* XXX close any windows that are attached to this window */
|
/* menus can be associated with a client, so close any that are since
|
||||||
|
we are disappearing now */
|
||||||
|
menu_frame_hide_all_client(self);
|
||||||
|
|
||||||
if (focus_client == self) {
|
if (focus_client == self) {
|
||||||
XEvent e;
|
XEvent e;
|
||||||
|
|
|
@ -1183,8 +1183,8 @@ static void event_handle_menu(XEvent *ev)
|
||||||
if ((f = menu_frame_under(ev->xmotion.x_root,
|
if ((f = menu_frame_under(ev->xmotion.x_root,
|
||||||
ev->xmotion.y_root))) {
|
ev->xmotion.y_root))) {
|
||||||
menu_frame_move_on_screen(f);
|
menu_frame_move_on_screen(f);
|
||||||
if (e = menu_entry_frame_under(ev->xmotion.x_root,
|
if ((e = menu_entry_frame_under(ev->xmotion.x_root,
|
||||||
ev->xmotion.y_root))
|
ev->xmotion.y_root)))
|
||||||
menu_frame_select(f, e);
|
menu_frame_select(f, e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -48,7 +48,7 @@ static void parse_menu_item(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
||||||
for (node = node->xmlChildrenNode; node; node = node->next)
|
for (node = node->xmlChildrenNode; node; node = node->next)
|
||||||
if (!xmlStrcasecmp(node->name, (const xmlChar*) "action"))
|
if (!xmlStrcasecmp(node->name, (const xmlChar*) "action"))
|
||||||
acts = g_slist_append(acts, action_parse(doc, node));
|
acts = g_slist_append(acts, action_parse(doc, node));
|
||||||
menu_add_normal(state->menus->data, label, acts);
|
menu_add_normal(state->menus->data, 0, label, acts);
|
||||||
g_free(label);
|
g_free(label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ static void parse_menu_separator(ObParseInst *i,
|
||||||
ObMenuParseState *state = data;
|
ObMenuParseState *state = data;
|
||||||
|
|
||||||
if (state->menus)
|
if (state->menus)
|
||||||
menu_add_separator(state->menus->data);
|
menu_add_separator(state->menus->data, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
||||||
|
@ -85,7 +85,7 @@ static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->menus)
|
if (state->menus)
|
||||||
menu_add_submenu(state->menus->data, name);
|
menu_add_submenu(state->menus->data, 0, name);
|
||||||
|
|
||||||
parse_menu_fail:
|
parse_menu_fail:
|
||||||
g_free(name);
|
g_free(name);
|
||||||
|
@ -95,6 +95,7 @@ parse_menu_fail:
|
||||||
|
|
||||||
void menu_destroy_hash_value(ObMenu *self)
|
void menu_destroy_hash_value(ObMenu *self)
|
||||||
{
|
{
|
||||||
|
/* XXX make sure its not visible */
|
||||||
menu_clear_entries_internal(self);
|
menu_clear_entries_internal(self);
|
||||||
g_free(self->name);
|
g_free(self->name);
|
||||||
g_free(self->title);
|
g_free(self->title);
|
||||||
|
@ -110,6 +111,7 @@ void menu_shutdown()
|
||||||
{
|
{
|
||||||
menu_frame_hide_all();
|
menu_frame_hide_all();
|
||||||
g_hash_table_destroy(menu_hash);
|
g_hash_table_destroy(menu_hash);
|
||||||
|
menu_hash = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_parse()
|
void menu_parse()
|
||||||
|
@ -170,6 +172,14 @@ gboolean menu_new(gchar *name, gchar *title, gpointer data)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void menu_free(gchar *name)
|
||||||
|
{
|
||||||
|
ObMenu *self;
|
||||||
|
|
||||||
|
if (!(self = menu_from_name(name))) return;
|
||||||
|
g_hash_table_remove(menu_hash, self->name);
|
||||||
|
}
|
||||||
|
|
||||||
void menu_show(gchar *name, gint x, gint y, ObClient *client)
|
void menu_show(gchar *name, gint x, gint y, ObClient *client)
|
||||||
{
|
{
|
||||||
ObMenu *self;
|
ObMenu *self;
|
||||||
|
@ -177,14 +187,12 @@ void menu_show(gchar *name, gint x, gint y, ObClient *client)
|
||||||
|
|
||||||
if (!(self = menu_from_name(name))) return;
|
if (!(self = menu_from_name(name))) return;
|
||||||
|
|
||||||
/* XXX update entries */
|
|
||||||
|
|
||||||
frame = menu_frame_new(self, client);
|
frame = menu_frame_new(self, client);
|
||||||
menu_frame_move(frame, x, y);
|
menu_frame_move(frame, x, y);
|
||||||
menu_frame_show(frame, NULL);
|
menu_frame_show(frame, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type)
|
static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type, gint id)
|
||||||
{
|
{
|
||||||
ObMenuEntry *self;
|
ObMenuEntry *self;
|
||||||
|
|
||||||
|
@ -193,6 +201,7 @@ static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type)
|
||||||
self = g_new0(ObMenuEntry, 1);
|
self = g_new0(ObMenuEntry, 1);
|
||||||
self->type = type;
|
self->type = type;
|
||||||
self->menu = menu;
|
self->menu = menu;
|
||||||
|
self->id = id;
|
||||||
self->enabled = TRUE;
|
self->enabled = TRUE;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -238,21 +247,21 @@ static void menu_clear_entries_internal(ObMenu *self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_add_normal(gchar *name, gchar *label, GSList *actions)
|
void menu_add_normal(gchar *name, gint id, gchar *label, GSList *actions)
|
||||||
{
|
{
|
||||||
ObMenu *self;
|
ObMenu *self;
|
||||||
ObMenuEntry *e;
|
ObMenuEntry *e;
|
||||||
|
|
||||||
if (!(self = menu_from_name(name))) return;
|
if (!(self = menu_from_name(name))) return;
|
||||||
|
|
||||||
e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_NORMAL);
|
e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_NORMAL, id);
|
||||||
e->data.normal.label = g_strdup(label);
|
e->data.normal.label = g_strdup(label);
|
||||||
e->data.normal.actions = actions;
|
e->data.normal.actions = actions;
|
||||||
|
|
||||||
self->entries = g_list_append(self->entries, e);
|
self->entries = g_list_append(self->entries, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_add_submenu(gchar *name, gchar *submenu)
|
void menu_add_submenu(gchar *name, gint id, gchar *submenu)
|
||||||
{
|
{
|
||||||
ObMenu *self, *sub;
|
ObMenu *self, *sub;
|
||||||
ObMenuEntry *e;
|
ObMenuEntry *e;
|
||||||
|
@ -260,20 +269,44 @@ void menu_add_submenu(gchar *name, gchar *submenu)
|
||||||
if (!(self = menu_from_name(name))) return;
|
if (!(self = menu_from_name(name))) return;
|
||||||
if (!(sub = menu_from_name(submenu))) return;
|
if (!(sub = menu_from_name(submenu))) return;
|
||||||
|
|
||||||
e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_SUBMENU);
|
e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_SUBMENU, id);
|
||||||
e->data.submenu.submenu = sub;
|
e->data.submenu.submenu = sub;
|
||||||
|
|
||||||
self->entries = g_list_append(self->entries, e);
|
self->entries = g_list_append(self->entries, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_add_separator(gchar *name)
|
void menu_add_separator(gchar *name, gint id)
|
||||||
{
|
{
|
||||||
ObMenu *self;
|
ObMenu *self;
|
||||||
ObMenuEntry *e;
|
ObMenuEntry *e;
|
||||||
|
|
||||||
if (!(self = menu_from_name(name))) return;
|
if (!(self = menu_from_name(name))) return;
|
||||||
|
|
||||||
e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_SEPARATOR);
|
e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_SEPARATOR, id);
|
||||||
|
|
||||||
self->entries = g_list_append(self->entries, e);
|
self->entries = g_list_append(self->entries, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void menu_set_update_func(gchar *name, ObMenuUpdateFunc func)
|
||||||
|
{
|
||||||
|
ObMenu *self;
|
||||||
|
|
||||||
|
if (!(self = menu_from_name(name))) return;
|
||||||
|
self->update_func = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObMenuEntry* menu_find_entry_id(ObMenu *self, gint id)
|
||||||
|
{
|
||||||
|
ObMenuEntry *ret = NULL;
|
||||||
|
GList *it;
|
||||||
|
|
||||||
|
for (it = self->entries; it; it = g_list_next(it)) {
|
||||||
|
ObMenuEntry *e = it->data;
|
||||||
|
|
||||||
|
if (e->id == id) {
|
||||||
|
ret = e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -17,10 +17,10 @@ typedef struct _ObNormalMenuEntry ObNormalMenuEntry;
|
||||||
typedef struct _ObSubmenuMenuEntry ObSubmenuMenuEntry;
|
typedef struct _ObSubmenuMenuEntry ObSubmenuMenuEntry;
|
||||||
typedef struct _ObSeparatorMenuEntry ObSeparatorMenuEntry;
|
typedef struct _ObSeparatorMenuEntry ObSeparatorMenuEntry;
|
||||||
|
|
||||||
|
typedef void (*ObMenuUpdateFunc)(struct _ObMenuFrame *frame, gpointer data);
|
||||||
|
|
||||||
extern GList *menu_visible;
|
extern GList *menu_visible;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct _ObMenu
|
struct _ObMenu
|
||||||
{
|
{
|
||||||
/* Name of the menu. Used in the showmenu action. */
|
/* Name of the menu. Used in the showmenu action. */
|
||||||
|
@ -33,6 +33,8 @@ struct _ObMenu
|
||||||
|
|
||||||
/* plugin data */
|
/* plugin data */
|
||||||
gpointer data;
|
gpointer data;
|
||||||
|
|
||||||
|
ObMenuUpdateFunc update_func;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -62,6 +64,8 @@ struct _ObMenuEntry
|
||||||
ObMenuEntryType type;
|
ObMenuEntryType type;
|
||||||
ObMenu *menu;
|
ObMenu *menu;
|
||||||
|
|
||||||
|
gint id;
|
||||||
|
|
||||||
/* state */
|
/* state */
|
||||||
gboolean enabled;
|
gboolean enabled;
|
||||||
|
|
||||||
|
@ -78,13 +82,18 @@ void menu_shutdown();
|
||||||
void menu_parse();
|
void menu_parse();
|
||||||
|
|
||||||
gboolean menu_new(gchar *name, gchar *title, gpointer data);
|
gboolean menu_new(gchar *name, gchar *title, gpointer data);
|
||||||
|
void menu_free(gchar *name);
|
||||||
|
|
||||||
|
void menu_set_update_func(gchar *name, ObMenuUpdateFunc func);
|
||||||
|
|
||||||
void menu_show(gchar *name, gint x, gint y, struct _ObClient *client);
|
void menu_show(gchar *name, gint x, gint y, struct _ObClient *client);
|
||||||
|
|
||||||
/* functions for building menus */
|
/* functions for building menus */
|
||||||
void menu_clear_entries(gchar *name);
|
void menu_clear_entries(gchar *name);
|
||||||
void menu_add_normal(gchar *name, gchar *label, GSList *actions);
|
void menu_add_normal(gchar *name, gint id, gchar *label, GSList *actions);
|
||||||
void menu_add_submenu(gchar *name, gchar *submenu);
|
void menu_add_submenu(gchar *name, gint id, gchar *submenu);
|
||||||
void menu_add_separator(gchar *name);
|
void menu_add_separator(gchar *name, gint id);
|
||||||
|
|
||||||
|
ObMenuEntry* menu_find_entry_id(ObMenu *self, gint id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,6 +37,7 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, ObClient *client)
|
||||||
self->type = Window_Menu;
|
self->type = Window_Menu;
|
||||||
self->menu = menu;
|
self->menu = menu;
|
||||||
self->selected = NULL;
|
self->selected = NULL;
|
||||||
|
self->show_title = TRUE;
|
||||||
self->client = client;
|
self->client = client;
|
||||||
|
|
||||||
attr.event_mask = FRAME_EVENTMASK;
|
attr.event_mask = FRAME_EVENTMASK;
|
||||||
|
@ -51,12 +52,16 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, ObClient *client)
|
||||||
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);
|
||||||
|
|
||||||
|
stacking_add(MENU_AS_WINDOW(self));
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_frame_free(ObMenuFrame *self)
|
void menu_frame_free(ObMenuFrame *self)
|
||||||
{
|
{
|
||||||
if (self) {
|
if (self) {
|
||||||
|
stacking_remove(MENU_AS_WINDOW(self));
|
||||||
|
|
||||||
XDestroyWindow(ob_display, self->items);
|
XDestroyWindow(ob_display, self->items);
|
||||||
XDestroyWindow(ob_display, self->title);
|
XDestroyWindow(ob_display, self->title);
|
||||||
XDestroyWindow(ob_display, self->window);
|
XDestroyWindow(ob_display, self->window);
|
||||||
|
@ -263,7 +268,7 @@ static void menu_frame_render(ObMenuFrame *self)
|
||||||
XSetWindowBorder(ob_display, self->window,
|
XSetWindowBorder(ob_display, self->window,
|
||||||
RrColorPixel(ob_rr_theme->b_color));
|
RrColorPixel(ob_rr_theme->b_color));
|
||||||
|
|
||||||
if (!self->parent && self->menu->title) {
|
if (!self->parent && self->show_title) {
|
||||||
XMoveWindow(ob_display, self->title,
|
XMoveWindow(ob_display, self->title,
|
||||||
-ob_rr_theme->bwidth, h - ob_rr_theme->bwidth);
|
-ob_rr_theme->bwidth, h - ob_rr_theme->bwidth);
|
||||||
|
|
||||||
|
@ -344,7 +349,7 @@ static void menu_frame_render(ObMenuFrame *self)
|
||||||
|
|
||||||
self->inner_w = w;
|
self->inner_w = w;
|
||||||
|
|
||||||
if (!self->parent && self->title) {
|
if (!self->parent && self->show_title) {
|
||||||
XResizeWindow(ob_display, self->title,
|
XResizeWindow(ob_display, self->title,
|
||||||
w, self->title_h - ob_rr_theme->bwidth);
|
w, self->title_h - ob_rr_theme->bwidth);
|
||||||
RrPaint(self->a_title, self->title,
|
RrPaint(self->a_title, self->title,
|
||||||
|
@ -411,6 +416,8 @@ void menu_frame_show(ObMenuFrame *self, ObMenuFrame *parent)
|
||||||
if (!g_list_find(menu_frame_visible, self)) {
|
if (!g_list_find(menu_frame_visible, self)) {
|
||||||
menu_frame_visible = g_list_prepend(menu_frame_visible, self);
|
menu_frame_visible = g_list_prepend(menu_frame_visible, self);
|
||||||
|
|
||||||
|
if (self->menu->update_func)
|
||||||
|
self->menu->update_func(self, self->menu->data);
|
||||||
menu_frame_update(self);
|
menu_frame_update(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,10 +450,22 @@ void menu_frame_hide(ObMenuFrame *self)
|
||||||
|
|
||||||
void menu_frame_hide_all()
|
void menu_frame_hide_all()
|
||||||
{
|
{
|
||||||
while (menu_frame_visible)
|
GList *it = g_list_last(menu_frame_visible);
|
||||||
menu_frame_hide(menu_frame_visible->data);
|
if (it)
|
||||||
|
menu_frame_hide(it->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void menu_frame_hide_all_client(ObClient *client)
|
||||||
|
{
|
||||||
|
GList *it = g_list_last(menu_frame_visible);
|
||||||
|
if (it) {
|
||||||
|
ObMenuFrame *f = it->data;
|
||||||
|
if (f->client == client)
|
||||||
|
menu_frame_hide(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ObMenuFrame* menu_frame_under(gint x, gint y)
|
ObMenuFrame* menu_frame_under(gint x, gint y)
|
||||||
{
|
{
|
||||||
ObMenuFrame *ret = NULL;
|
ObMenuFrame *ret = NULL;
|
||||||
|
@ -488,6 +507,7 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y)
|
||||||
void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry)
|
void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry)
|
||||||
{
|
{
|
||||||
ObMenuEntryFrame *old = self->selected;
|
ObMenuEntryFrame *old = self->selected;
|
||||||
|
ObMenuFrame *oldchild = self->child;
|
||||||
|
|
||||||
if (old == entry) return;
|
if (old == entry) return;
|
||||||
|
|
||||||
|
@ -496,11 +516,11 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry)
|
||||||
else
|
else
|
||||||
self->selected = NULL;
|
self->selected = NULL;
|
||||||
|
|
||||||
if (old) {
|
if (old)
|
||||||
menu_entry_frame_render(old);
|
menu_entry_frame_render(old);
|
||||||
if (old->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)
|
if (oldchild)
|
||||||
menu_frame_hide(self->child);
|
menu_frame_hide(oldchild);
|
||||||
}
|
|
||||||
if (self->selected) {
|
if (self->selected) {
|
||||||
menu_entry_frame_render(self->selected);
|
menu_entry_frame_render(self->selected);
|
||||||
|
|
||||||
|
@ -519,7 +539,7 @@ void menu_entry_frame_show_submenu(ObMenuEntryFrame *self)
|
||||||
self->frame->area.x + self->frame->area.width
|
self->frame->area.x + self->frame->area.width
|
||||||
- ob_rr_theme->menu_overlap,
|
- ob_rr_theme->menu_overlap,
|
||||||
self->frame->area.y + self->frame->title_h +
|
self->frame->area.y + self->frame->title_h +
|
||||||
self->area.y);
|
self->area.y + ob_rr_theme->menu_overlap);
|
||||||
menu_frame_show(f, self->frame);
|
menu_frame_show(f, self->frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,6 +548,9 @@ void menu_entry_frame_execute(ObMenuEntryFrame *self)
|
||||||
if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) {
|
if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) {
|
||||||
GSList *it;
|
GSList *it;
|
||||||
|
|
||||||
|
/* release grabs before executing the shit */
|
||||||
|
menu_frame_hide_all();
|
||||||
|
|
||||||
for (it = self->entry->data.normal.actions; it;
|
for (it = self->entry->data.normal.actions; it;
|
||||||
it = g_slist_next(it))
|
it = g_slist_next(it))
|
||||||
{
|
{
|
||||||
|
@ -535,6 +558,5 @@ void menu_entry_frame_execute(ObMenuEntryFrame *self)
|
||||||
act->data.any.c = self->frame->client;
|
act->data.any.c = self->frame->client;
|
||||||
act->func(&act->data);
|
act->func(&act->data);
|
||||||
}
|
}
|
||||||
menu_frame_hide_all();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,12 @@ struct _ObMenuFrame
|
||||||
ObMenuFrame *parent;
|
ObMenuFrame *parent;
|
||||||
ObMenuFrame *child;
|
ObMenuFrame *child;
|
||||||
|
|
||||||
|
GList *entries;
|
||||||
|
ObMenuEntryFrame *selected;
|
||||||
|
|
||||||
|
/* If a titlebar is displayed for the menu or not (for top-level menus) */
|
||||||
|
gboolean show_title;
|
||||||
|
|
||||||
/* On-screen area (including borders!) */
|
/* On-screen area (including borders!) */
|
||||||
Rect area;
|
Rect area;
|
||||||
gint inner_w; /* inside the borders */
|
gint inner_w; /* inside the borders */
|
||||||
|
@ -39,9 +45,6 @@ struct _ObMenuFrame
|
||||||
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 */
|
||||||
|
|
||||||
GList *entries;
|
|
||||||
ObMenuEntryFrame *selected;
|
|
||||||
|
|
||||||
Window title;
|
Window title;
|
||||||
Window items;
|
Window items;
|
||||||
|
|
||||||
|
@ -82,6 +85,7 @@ void menu_frame_show(ObMenuFrame *self, ObMenuFrame *parent);
|
||||||
void menu_frame_hide(ObMenuFrame *self);
|
void menu_frame_hide(ObMenuFrame *self);
|
||||||
|
|
||||||
void menu_frame_hide_all();
|
void menu_frame_hide_all();
|
||||||
|
void menu_frame_hide_all_client(struct _ObClient *client);
|
||||||
|
|
||||||
void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry);
|
void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry);
|
||||||
|
|
||||||
|
|
|
@ -266,8 +266,8 @@ int main(int argc, char **argv)
|
||||||
dock_remove_all();
|
dock_remove_all();
|
||||||
client_unmanage_all();
|
client_unmanage_all();
|
||||||
|
|
||||||
menu_shutdown(); /* destroy menus before unloading plugins */
|
|
||||||
plugin_shutdown(); /* calls all the plugins' shutdown functions */
|
plugin_shutdown(); /* calls all the plugins' shutdown functions */
|
||||||
|
menu_shutdown();
|
||||||
mouse_shutdown();
|
mouse_shutdown();
|
||||||
keyboard_shutdown();
|
keyboard_shutdown();
|
||||||
dock_shutdown();
|
dock_shutdown();
|
||||||
|
|
|
@ -11,8 +11,6 @@ typedef struct {
|
||||||
PluginSetupConfig config;
|
PluginSetupConfig config;
|
||||||
PluginStartup startup;
|
PluginStartup startup;
|
||||||
PluginShutdown shutdown;
|
PluginShutdown shutdown;
|
||||||
PluginCreate create;
|
|
||||||
PluginDestroy destroy;
|
|
||||||
} Plugin;
|
} Plugin;
|
||||||
|
|
||||||
static gpointer load_sym(GModule *module, char *name, char *symbol,
|
static gpointer load_sym(GModule *module, char *name, char *symbol,
|
||||||
|
@ -58,9 +56,6 @@ static Plugin *plugin_new(char *name)
|
||||||
FALSE);
|
FALSE);
|
||||||
p->shutdown = (PluginShutdown)load_sym(p->module, name, "plugin_shutdown",
|
p->shutdown = (PluginShutdown)load_sym(p->module, name, "plugin_shutdown",
|
||||||
FALSE);
|
FALSE);
|
||||||
p->create = (PluginCreate)load_sym(p->module, name, "plugin_create", TRUE);
|
|
||||||
p->destroy = (PluginDestroy)load_sym(p->module, name, "plugin_destroy",
|
|
||||||
TRUE);
|
|
||||||
|
|
||||||
if (p->config == NULL || p->startup == NULL || p->shutdown == NULL) {
|
if (p->config == NULL || p->startup == NULL || p->shutdown == NULL) {
|
||||||
g_module_close(p->module);
|
g_module_close(p->module);
|
||||||
|
@ -174,41 +169,3 @@ void plugin_loadall(ObParseInst *i)
|
||||||
g_io_channel_unref(io);
|
g_io_channel_unref(io);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *plugin_create(char *name, void *data)
|
|
||||||
{
|
|
||||||
Plugin *p = (Plugin *)g_datalist_get_data(&plugins, name);
|
|
||||||
|
|
||||||
if (p == NULL) {
|
|
||||||
g_warning("Unable to find plugin for create: %s", name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p->create == NULL || p->destroy == NULL) {
|
|
||||||
g_critical("Unsupported create/destroy: %s", name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return p->create(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void plugin_destroy(char *name, void *data)
|
|
||||||
{
|
|
||||||
Plugin *p = (Plugin *)g_datalist_get_data(&plugins, name);
|
|
||||||
|
|
||||||
if (p == NULL) {
|
|
||||||
g_critical("Unable to find plugin for destroy: %s", name);
|
|
||||||
/* really shouldn't happen, but attempt to free something anyway? */
|
|
||||||
g_free(data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p->destroy == NULL || p->create == NULL) {
|
|
||||||
g_critical("Unsupported create/destroy: %s", name);
|
|
||||||
/* really, really shouldn't happen, but attempt to free anyway? */
|
|
||||||
g_free(data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
p->destroy(data);
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,9 +15,4 @@ gboolean plugin_open(char *name, struct _ObParseInst *i);
|
||||||
gboolean plugin_open_reopen(char *name, struct _ObParseInst *i);
|
gboolean plugin_open_reopen(char *name, struct _ObParseInst *i);
|
||||||
void plugin_close(char *name);
|
void plugin_close(char *name);
|
||||||
|
|
||||||
/* call plugin's generic constructor */
|
|
||||||
void *plugin_create(char *name, void *data);
|
|
||||||
/* free memory allocated by plugin_create() */
|
|
||||||
void plugin_destroy(char *name, void *object);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,10 +12,4 @@ typedef void (*PluginStartup)(void);
|
||||||
/* plugin_shutdown() */
|
/* plugin_shutdown() */
|
||||||
typedef void (*PluginShutdown)(void);
|
typedef void (*PluginShutdown)(void);
|
||||||
|
|
||||||
/* plugin_create() - for menu plugins only */
|
|
||||||
typedef void *(*PluginCreate)(/* TODO */);
|
|
||||||
|
|
||||||
/* plugin_destroy() - for menu plugins only */
|
|
||||||
typedef void (*PluginDestroy)(void *);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,170 +1,175 @@
|
||||||
#include "kernel/debug.h"
|
#include "kernel/debug.h"
|
||||||
#include "kernel/menu.h"
|
#include "kernel/menu.h"
|
||||||
|
#include "kernel/menuframe.h"
|
||||||
#include "kernel/screen.h"
|
#include "kernel/screen.h"
|
||||||
#include "kernel/client.h"
|
#include "kernel/client.h"
|
||||||
#include "kernel/openbox.h"
|
#include "kernel/openbox.h"
|
||||||
#include "kernel/frame.h"
|
#include "kernel/frame.h"
|
||||||
|
#include "gettext.h"
|
||||||
#include "render/theme.h"
|
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
static char *PLUGIN_NAME = "client_menu";
|
#define CLIENT_MENU_NAME "client-menu"
|
||||||
|
#define SEND_TO_MENU_NAME "client-send-to-menu"
|
||||||
|
#define LAYER_MENU_NAME "client-layer-menu"
|
||||||
|
|
||||||
static ObMenu *send_to_menu;
|
enum {
|
||||||
static ObMenu *layer_menu;
|
LAYER_TOP,
|
||||||
|
LAYER_NORMAL,
|
||||||
|
LAYER_BOTTOM
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
enum {
|
||||||
gint foo;
|
CLIENT_SEND_TO,
|
||||||
} Client_Menu_Data;
|
CLIENT_LAYER,
|
||||||
|
CLIENT_ICONIFY,
|
||||||
#define CLIENT_MENU(m) ((ObMenu *)m)
|
CLIENT_MAXIMIZE,
|
||||||
#define CLIENT_MENU_DATA(m) ((Client_Menu_Data *)((ObMenu *)m)->plugin_data)
|
CLIENT_RAISE,
|
||||||
|
CLIENT_LOWER,
|
||||||
void client_menu_clean_up(ObMenu *m) {
|
CLIENT_SHADE,
|
||||||
}
|
CLIENT_DECORATE,
|
||||||
|
CLIENT_MOVE,
|
||||||
void client_send_to_update(ObMenu *self)
|
CLIENT_RESIZE,
|
||||||
{
|
CLIENT_CLOSE
|
||||||
guint i = 0;
|
};
|
||||||
GList *it = self->entries;
|
|
||||||
|
|
||||||
/* check if we have to update. lame */
|
|
||||||
while (it != NULL) {
|
|
||||||
if (i == screen_desktop) {
|
|
||||||
if (((ObMenuEntry *)it->data)->enabled)
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
if (!((ObMenuEntry *)it->data)->enabled)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i >= screen_num_desktops)
|
|
||||||
break;
|
|
||||||
if (strcmp(screen_desktop_names[i],
|
|
||||||
((ObMenuEntry *)it->data)->label) != 0)
|
|
||||||
break;
|
|
||||||
++i;
|
|
||||||
it = it->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it != NULL || i != screen_num_desktops) {
|
|
||||||
menu_clear(self);
|
|
||||||
ob_debug("update\n");
|
|
||||||
for (i = 0; i < screen_num_desktops; ++i) {
|
|
||||||
ObMenuEntry *e;
|
|
||||||
ObAction *a = action_from_string("sendtodesktop");
|
|
||||||
a->data.sendto.desk = i;
|
|
||||||
a->data.sendto.follow = FALSE;
|
|
||||||
e = menu_entry_new(screen_desktop_names[i], a);
|
|
||||||
if (i == screen_desktop)
|
|
||||||
e->enabled = FALSE;
|
|
||||||
menu_add_entry(self, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
menu_render(self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void client_menu_show(ObMenu *self, int x, int y, ObClient *client)
|
|
||||||
{
|
|
||||||
guint i;
|
|
||||||
gint newy, newx;
|
|
||||||
Rect *a = NULL;
|
|
||||||
|
|
||||||
g_assert(!self->invalid);
|
|
||||||
g_assert(client);
|
|
||||||
|
|
||||||
for (i = 0; i < screen_num_monitors; ++i) {
|
|
||||||
a = screen_physical_area_monitor(i);
|
|
||||||
if (RECT_CONTAINS(*a, x, y))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
g_assert(a != NULL);
|
|
||||||
self->xin_area = i;
|
|
||||||
|
|
||||||
newx = MAX(x, client->area.x);
|
|
||||||
newy = MAX(y, client->area.y);
|
|
||||||
POINT_SET(self->location,
|
|
||||||
MIN(newx, client->area.x + client->area.width - self->size.width),
|
|
||||||
MIN(newy, client->area.y + client->area.height -
|
|
||||||
self->size.height));
|
|
||||||
|
|
||||||
XMoveWindow(ob_display, self->frame, self->location.x, self->location.y);
|
|
||||||
|
|
||||||
if (!self->shown) {
|
|
||||||
XMapWindow(ob_display, self->frame);
|
|
||||||
stacking_raise(MENU_AS_WINDOW(self));
|
|
||||||
self->shown = TRUE;
|
|
||||||
} else if (self->shown && self->open_submenu) {
|
|
||||||
menu_hide(self->open_submenu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void plugin_setup_config() { }
|
void plugin_setup_config() { }
|
||||||
|
|
||||||
void plugin_shutdown() { }
|
static void client_update(ObMenuFrame *frame, gpointer data)
|
||||||
|
|
||||||
void plugin_destroy (ObMenu *m)
|
|
||||||
{
|
{
|
||||||
|
ObMenu *menu = frame->menu;
|
||||||
|
ObMenuEntry *e;
|
||||||
|
|
||||||
|
frame->show_title = FALSE;
|
||||||
|
|
||||||
|
if (!frame->client) {
|
||||||
|
GList *it;
|
||||||
|
|
||||||
|
for (it = menu->entries; it; it = g_list_next(it)) {
|
||||||
|
ObMenuEntry *e = it->data;
|
||||||
|
e->enabled = FALSE;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_ICONIFY);
|
||||||
|
e->enabled = frame->client->functions & OB_CLIENT_FUNC_ICONIFY;
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_MAXIMIZE);
|
||||||
|
e->enabled = frame->client->functions & OB_CLIENT_FUNC_MAXIMIZE;
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_SHADE);
|
||||||
|
e->enabled = frame->client->functions & OB_CLIENT_FUNC_SHADE;
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_MOVE);
|
||||||
|
e->enabled = frame->client->functions & OB_CLIENT_FUNC_MOVE;
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_RESIZE);
|
||||||
|
e->enabled = frame->client->functions & OB_CLIENT_FUNC_RESIZE;
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_CLOSE);
|
||||||
|
e->enabled = frame->client->functions & OB_CLIENT_FUNC_CLOSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *plugin_create() /* TODO: need config */
|
static void send_to_update(ObMenuFrame *frame, gpointer data)
|
||||||
{
|
{
|
||||||
ObMenu *m = menu_new_full(NULL, "client-menu", NULL,
|
ObMenu *menu = frame->menu;
|
||||||
client_menu_show, NULL, NULL, NULL, NULL, NULL);
|
guint i;
|
||||||
m->plugin = PLUGIN_NAME;
|
GSList *acts;
|
||||||
menu_add_entry(m, menu_entry_new_submenu("Send To Workspace",
|
ObAction *act;
|
||||||
send_to_menu));
|
|
||||||
send_to_menu->parent = m;
|
|
||||||
|
|
||||||
menu_add_entry(m, menu_entry_new("Iconify",
|
menu_clear_entries(SEND_TO_MENU_NAME);
|
||||||
action_from_string("iconify")));
|
|
||||||
menu_add_entry(m, menu_entry_new("Raise",
|
|
||||||
action_from_string("raise")));
|
|
||||||
menu_add_entry(m, menu_entry_new("Lower",
|
|
||||||
action_from_string("lower")));
|
|
||||||
menu_add_entry(m, menu_entry_new("Close",
|
|
||||||
action_from_string("close")));
|
|
||||||
menu_add_entry(m, menu_entry_new("Shade",
|
|
||||||
action_from_string("toggleshade")));
|
|
||||||
menu_add_entry(m, menu_entry_new("Omnipresent",
|
|
||||||
action_from_string("toggleomnipresent")));
|
|
||||||
menu_add_entry(m, menu_entry_new("Decorations",
|
|
||||||
action_from_string("toggledecorations")));
|
|
||||||
menu_add_entry(m, menu_entry_new_submenu("Layers",
|
|
||||||
layer_menu));
|
|
||||||
layer_menu->parent = m;
|
|
||||||
|
|
||||||
/* send to desktop
|
if (!frame->client)
|
||||||
iconify
|
return;
|
||||||
raise
|
|
||||||
lower
|
for (i = 0; i <= screen_num_desktops; ++i) {
|
||||||
close
|
gchar *name;
|
||||||
kill
|
guint desk;
|
||||||
shade
|
|
||||||
omnipresent
|
if (i >= screen_num_desktops) {
|
||||||
decorations
|
desk = DESKTOP_ALL;
|
||||||
*/
|
name = _("All desktops");
|
||||||
return (void *)m;
|
} else {
|
||||||
|
desk = i;
|
||||||
|
name = screen_desktop_names[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
act = action_from_string("SendToDesktop");
|
||||||
|
act->data.sendto.desk = desk;
|
||||||
|
act->data.sendto.follow = FALSE;
|
||||||
|
acts = g_slist_prepend(NULL, act);
|
||||||
|
menu_add_normal(SEND_TO_MENU_NAME, desk, name, acts);
|
||||||
|
|
||||||
|
if (frame->client->desktop == desk) {
|
||||||
|
ObMenuEntry *e = menu_find_entry_id(menu, desk);
|
||||||
|
g_assert(e);
|
||||||
|
e->enabled = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_startup()
|
void plugin_startup()
|
||||||
{
|
{
|
||||||
ObMenu *t;
|
GSList *acts;
|
||||||
/* create a Send To Workspace ObMenu */
|
|
||||||
send_to_menu = menu_new_full(NULL, "send-to-workspace",
|
|
||||||
NULL, NULL, client_send_to_update,
|
|
||||||
NULL, NULL, NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
layer_menu = menu_new(NULL, "layer", NULL);
|
menu_new(LAYER_MENU_NAME, _("Layer"), NULL);
|
||||||
menu_add_entry(layer_menu, menu_entry_new("Top Layer",
|
|
||||||
action_from_string("sendtotoplayer")));
|
|
||||||
menu_add_entry(layer_menu, menu_entry_new("Normal Layer",
|
|
||||||
action_from_string("sendtonormallayer")));
|
|
||||||
menu_add_entry(layer_menu, menu_entry_new("Bottom Layer",
|
|
||||||
action_from_string("sendtobottomlayer")));
|
|
||||||
|
|
||||||
t = (ObMenu *)plugin_create("client_menu");
|
acts = g_slist_prepend(NULL, action_from_string("SendToTopLayer"));
|
||||||
|
menu_add_normal(LAYER_MENU_NAME, LAYER_TOP, _("Always on top"), acts);
|
||||||
|
|
||||||
|
acts = g_slist_prepend(NULL, action_from_string("SendToNormalLayer"));
|
||||||
|
menu_add_normal(LAYER_MENU_NAME, LAYER_NORMAL, _("Normal"), acts);
|
||||||
|
|
||||||
|
acts = g_slist_prepend(NULL, action_from_string("SendToBottomLayer"));
|
||||||
|
menu_add_normal(LAYER_MENU_NAME, LAYER_BOTTOM, _("Always on bottom"),acts);
|
||||||
|
|
||||||
|
|
||||||
|
menu_new(SEND_TO_MENU_NAME, _("Send to desktop"), NULL);
|
||||||
|
menu_set_update_func(SEND_TO_MENU_NAME, send_to_update);
|
||||||
|
|
||||||
|
menu_new(CLIENT_MENU_NAME, _("Client menu"), NULL);
|
||||||
|
menu_set_update_func(CLIENT_MENU_NAME, client_update);
|
||||||
|
|
||||||
|
menu_add_submenu(CLIENT_MENU_NAME, CLIENT_SEND_TO, SEND_TO_MENU_NAME);
|
||||||
|
|
||||||
|
menu_add_submenu(CLIENT_MENU_NAME, CLIENT_LAYER, LAYER_MENU_NAME);
|
||||||
|
|
||||||
|
acts = g_slist_prepend(NULL, action_from_string("Iconify"));
|
||||||
|
menu_add_normal(CLIENT_MENU_NAME, CLIENT_ICONIFY, _("Iconify"), acts);
|
||||||
|
|
||||||
|
acts = g_slist_prepend(NULL, action_from_string("Maximize"));
|
||||||
|
menu_add_normal(CLIENT_MENU_NAME, CLIENT_MAXIMIZE, _("Maximize"), acts);
|
||||||
|
|
||||||
|
acts = g_slist_prepend(NULL, action_from_string("Raise"));
|
||||||
|
menu_add_normal(CLIENT_MENU_NAME, CLIENT_RAISE, _("Raise to top"), acts);
|
||||||
|
|
||||||
|
acts = g_slist_prepend(NULL, action_from_string("Lower"));
|
||||||
|
menu_add_normal(CLIENT_MENU_NAME, CLIENT_LOWER, _("Lower to bottom"),acts);
|
||||||
|
|
||||||
|
acts = g_slist_prepend(NULL, action_from_string("ToggleShade"));
|
||||||
|
menu_add_normal(CLIENT_MENU_NAME, CLIENT_SHADE, _("(Un)Shade"), acts);
|
||||||
|
|
||||||
|
acts = g_slist_prepend(NULL, action_from_string("ToggleDecorations"));
|
||||||
|
menu_add_normal(CLIENT_MENU_NAME, CLIENT_DECORATE, _("Decorate"), acts);
|
||||||
|
|
||||||
|
menu_add_separator(CLIENT_MENU_NAME, -1);
|
||||||
|
|
||||||
|
acts = g_slist_prepend(NULL, action_from_string("KeyboardMove"));
|
||||||
|
menu_add_normal(CLIENT_MENU_NAME, CLIENT_MOVE, _("Move"), acts);
|
||||||
|
|
||||||
|
acts = g_slist_prepend(NULL, action_from_string("KeyboardResize"));
|
||||||
|
menu_add_normal(CLIENT_MENU_NAME, CLIENT_RESIZE, _("Resize"), acts);
|
||||||
|
|
||||||
|
menu_add_separator(CLIENT_MENU_NAME, -1);
|
||||||
|
|
||||||
|
acts = g_slist_prepend(NULL, action_from_string("Close"));
|
||||||
|
menu_add_normal(CLIENT_MENU_NAME, CLIENT_CLOSE, _("Close"), acts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void plugin_shutdown()
|
||||||
|
{
|
||||||
|
menu_free(LAYER_MENU_NAME);
|
||||||
|
menu_free(SEND_TO_MENU_NAME);
|
||||||
|
menu_free(CLIENT_MENU_NAME);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue