plugin_LTLIBRARIES = \
plugins/placement/placement.la \
- plugins/menu/client_menu.la
+ plugins/menu/client_menu.la \
+ plugins/menu/client_list_menu.la
# plugins/menu/timed_menu.la \
# plugins/menu/fifo_menu.la \
# plugins/menu/include_menu.la \
-# plugins/menu/client_list_menu.la
if OBCONF
bin_PROGRAMS += \
</menu>
<menu id="client-menu" plugin="client_menu" />
+<menu id="client-list-menu" plugin="client_list_menu" />
<menu id="root-menu" label="Openbox 3">
<menu id="apps-menu" />
<separator />
<menu id="client-menu" plugin="client_menu" />
<separator />
+ <menu id="client-list-menu" plugin="client_list_menu" />
+ <separator />
<item label="Restart">
<action name="restart" />
</item>
return a;
}
-ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node)
+ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
{
char *actname;
ObAction *act = NULL;
if ((n = parse_find_node("execute", node->xmlChildrenNode)))
act->data.execute.path = parse_string(doc, n);
} else if (act->func == action_showmenu) {
- if ((n = parse_find_node("menu", node->xmlChildrenNode)))
+ if ((n = parse_find_node("menu", node->xmlChildrenNode))) {
+ gchar *plugin;
+
act->data.showmenu.name = parse_string(doc, n);
+ if (parse_attr_string("plugin", n, &plugin))
+ menu_open_plugin(i, act->data.showmenu.name, plugin);
+ }
} else if (act->func == action_desktop) {
if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
act->data.desktop.desk = parse_int(doc, n);
*/
ObAction *action_from_string(char *name);
-ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node);
+ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
void action_free(ObAction *a);
/* Execute */
if (keylist) {
nact = parse_find_node("action", node);
while (nact) {
- if ((action = action_parse(doc, nact))) {
+ if ((action = action_parse(i, doc, nact))) {
/* validate that its okay for a key binding */
if (action->func == action_moveresize &&
action->data.moveresize.corner !=
goto next_nbut;
nact = parse_find_node("action", nbut->xmlChildrenNode);
while (nact) {
- if ((action = action_parse(doc, nact))) {
+ if ((action = action_parse(i, doc, nact))) {
/* validate that its okay for a mouse binding*/
if (mact == OB_MOUSE_ACTION_MOTION) {
if (action->func != action_moveresize ||
switch (ev->type) {
case ButtonRelease:
- if (!(f = menu_frame_under(ev->xmotion.x_root,
- ev->xmotion.y_root)))
+ if (!(f = menu_frame_under(ev->xbutton.x_root,
+ ev->xbutton.y_root)))
menu_frame_hide_all();
else {
- if ((e = menu_entry_frame_under(ev->xmotion.x_root,
- ev->xmotion.y_root)))
- menu_entry_frame_execute(e);
+ if ((e = menu_entry_frame_under(ev->xbutton.x_root,
+ ev->xbutton.y_root)))
+ menu_entry_frame_execute(e,
+ !(ev->xbutton.state & ControlMask));
}
break;
case MotionNotify:
for (node = node->xmlChildrenNode; node; node = node->next)
if (!xmlStrcasecmp(node->name, (const xmlChar*) "action"))
- acts = g_slist_append(acts, action_parse(doc, node));
+ acts = g_slist_append(acts, action_parse(i, doc, node));
menu_add_normal(state->menus->data, 0, label, acts);
g_free(label);
}
menu_add_separator(state->menus->data, 0);
}
+gboolean menu_open_plugin(ObParseInst *i, gchar *name, gchar *plugin)
+{
+ gboolean ret = FALSE;
+
+ if (plugin_open(plugin, i)) {
+ plugin_start(plugin);
+ if (g_hash_table_lookup(menu_hash, name))
+ ret = TRUE;
+ else
+ g_warning("Specified plugin '%s' did not provide the "
+ "menu '%s'", plugin, name);
+ }
+ return ret;
+}
+
static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
gpointer data)
{
if (!g_hash_table_lookup(menu_hash, name)) {
if (parse_attr_string("plugin", node, &plugin)) {
- if (!plugin_open(plugin, i))
- goto parse_menu_fail;
- plugin_start(plugin);
- if (!g_hash_table_lookup(menu_hash, name))
- g_warning("Specified plugin '%s' did not provide the "
- "menu '%s'", plugin, name);
- goto parse_menu_fail;
+ menu_open_plugin(i, name, plugin);
} else {
if (!parse_attr_string("label", node, &title))
goto parse_menu_fail;
void menu_destroy_hash_value(ObMenu *self)
{
/* XXX make sure its not visible */
+
+ if (self->destroy_func)
+ self->destroy_func(self, self->data);
+
menu_clear_entries_internal(self);
g_free(self->name);
g_free(self->title);
self->update_func = func;
}
+void menu_set_execute_func(gchar *name, ObMenuExecuteFunc func)
+{
+ ObMenu *self;
+
+ if (!(self = menu_from_name(name))) return;
+ self->execute_func = func;
+}
+
+void menu_set_destroy_func(gchar *name, ObMenuDestroyFunc func)
+{
+ ObMenu *self;
+
+ if (!(self = menu_from_name(name))) return;
+ self->destroy_func = func;
+}
+
ObMenuEntry* menu_find_entry_id(ObMenu *self, gint id)
{
ObMenuEntry *ret = NULL;
#include "action.h"
#include "window.h"
-#include "render/render.h"
#include "geom.h"
+#include "render/render.h"
+#include "parser/parse.h"
#include <glib.h>
struct _ObClient;
struct _ObMenuFrame;
+struct _ObMenuEntryFrame;
typedef struct _ObMenu ObMenu;
typedef struct _ObMenuEntry ObMenuEntry;
typedef struct _ObSeparatorMenuEntry ObSeparatorMenuEntry;
typedef void (*ObMenuUpdateFunc)(struct _ObMenuFrame *frame, gpointer data);
+typedef void (*ObMenuExecuteFunc)(struct _ObMenuEntryFrame *frame,
+ gpointer data);
+typedef void (*ObMenuDestroyFunc)(struct _ObMenu *menu, gpointer data);
extern GList *menu_visible;
gpointer data;
ObMenuUpdateFunc update_func;
+ ObMenuExecuteFunc execute_func;
+ ObMenuDestroyFunc destroy_func;
};
typedef enum
gboolean menu_new(gchar *name, gchar *title, gpointer data);
void menu_free(gchar *name);
+gboolean menu_open_plugin(ObParseInst *i, gchar *name, gchar *plugin);
+
void menu_set_update_func(gchar *name, ObMenuUpdateFunc func);
+void menu_set_execute_func(gchar *name, ObMenuExecuteFunc func);
+void menu_set_destroy_func(gchar *name, ObMenuDestroyFunc func);
void menu_show(gchar *name, gint x, gint y, struct _ObClient *client);
}
if (!w) w = 10;
- if (!allitems_h) allitems_h = 3;
- if (!h) h = 3;
+ if (!allitems_h) {
+ allitems_h = 3;
+ h += 3;
+ }
XResizeWindow(ob_display, self->window, w, h);
XResizeWindow(ob_display, self->items, w, allitems_h);
menu_frame_show(f, self->frame);
}
-void menu_entry_frame_execute(ObMenuEntryFrame *self)
+void menu_entry_frame_execute(ObMenuEntryFrame *self, gboolean hide)
{
if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) {
- GSList *it;
-
/* release grabs before executing the shit */
menu_frame_hide_all();
- for (it = self->entry->data.normal.actions; it;
- it = g_slist_next(it))
- {
- ObAction *act = it->data;
- act->data.any.c = self->frame->client;
- act->func(&act->data);
+ if (self->frame->menu->execute_func)
+ self->frame->menu->execute_func(self, self->frame->menu->data);
+ else {
+ GSList *it;
+
+ for (it = self->entry->data.normal.actions; it;
+ it = g_slist_next(it))
+ {
+ ObAction *act = it->data;
+ act->data.any.c = self->frame->client;
+ act->func(&act->data);
+ }
}
}
}
void menu_entry_frame_show_submenu(ObMenuEntryFrame *self);
-void menu_entry_frame_execute(ObMenuEntryFrame *self);
+void menu_entry_frame_execute(ObMenuEntryFrame *self, gboolean hide);
#endif
#include "kernel/openbox.h"
#include "kernel/menu.h"
+#include "kernel/menuframe.h"
#include "kernel/action.h"
#include "kernel/screen.h"
#include "kernel/client.h"
#include "kernel/focus.h"
+#include "gettext.h"
#include "render/theme.h"
#include <glib.h>
-static char *PLUGIN_NAME = "client_list_menu";
+#define MENU_NAME "client-list-menu"
typedef struct {
- GSList *submenus;
-} Client_List_Menu_Data;
+ /* how many desktop menus we've made */
+ guint desktops;
+} MenuData;
typedef struct {
guint desktop;
-} Client_List_Desktop_Menu_Data;
-
-#define CLIENT_LIST_MENU(m) ((ObMenu *)m)
-#define CLIENT_LIST_MENU_DATA(m) ((Client_List_Menu_Data *)((ObMenu *)m)->plugin_data)
-
-#define CLIENT_LIST_DESKTOP_MENU(m) ((ObMenu *)m)
-#define CLIENT_LIST_DESKTOP_MENU_DATA(m) ((Client_List_Desktop_Menu_Data *)((ObMenu *)m)->plugin_data)
-
-static void self_update(ObMenu *self);
-static void self_destroy(ObMenu *self);
+} DesktopData;
void plugin_setup_config() { }
-void plugin_shutdown() { }
-void plugin_destroy (ObMenu *m) { }
-void *plugin_create()
-{
- ObMenu *menu = menu_new_full("Desktops", "client-list-menu", NULL,
- NULL, self_update, NULL,
- NULL, NULL, self_destroy);
-
- menu->plugin = PLUGIN_NAME;
- menu->plugin_data = g_new(Client_List_Menu_Data, 1);
- CLIENT_LIST_MENU_DATA(menu)->submenus = NULL;
-
- return (void *)menu;
-}
-
-void plugin_startup()
-{
- plugin_create("client_list_menu");
-}
-
-
-static void desk_update(ObMenu *self)
+static void desk_menu_update(ObMenuFrame *frame, gpointer data)
{
+ ObMenu *menu = frame->menu;
+ DesktopData *d = data;
GList *it;
- guint desk;
-
- menu_clear(self);
- desk = CLIENT_LIST_DESKTOP_MENU_DATA(self)->desktop;
+ menu_clear_entries(menu->name);
- for (it = focus_order[desk]; it; it = g_list_next(it)) {
- ObClient *c = (ObClient *)it->data;
+ for (it = focus_order[d->desktop]; it; it = g_list_next(it)) {
+ ObClient *c = it->data;
if (client_normal(c)) {
- ObAction* a = action_from_string("activate");
- a->data.activate.c = c;
- menu_add_entry(self, menu_entry_new((c->iconic ?
- c->icon_title :
- c->title), a));
+ GSList *acts;
+ ObAction* act;
+
+ act = action_from_string("activate");
+ act->data.activate.c = c;
+ acts = g_slist_prepend(NULL, act);
+ menu_add_normal(menu->name, 0,
+ (c->iconic ? c->icon_title : c->title), acts);
}
}
-
- menu_render(self);
+
}
-static void desk_selected(ObMenuEntry *entry,
- unsigned int button, unsigned int x, unsigned int y)
+/* executes it without changing the client in the actions, since we set that
+ when we make the actions! */
+static void desk_menu_execute(ObMenuEntryFrame *self, gpointer data)
{
- entry->action->data.activate.here = (button == 2);
- entry->parent->client = entry->action->data.activate.c;
- menu_entry_fire(entry, button, x, y);
+ GSList *it;
+
+ for (it = self->entry->data.normal.actions; it; it = g_slist_next(it))
+ {
+ ObAction *act = it->data;
+ act->func(&act->data);
+ }
}
-static void desk_destroy(ObMenu *self)
+static void desk_menu_destroy(ObMenu *menu, gpointer data)
{
- g_free(self->plugin_data);
+ DesktopData *d = data;
+
+ g_free(d);
}
-static void self_update(ObMenu *self)
+static void self_update(ObMenuFrame *frame, gpointer data)
{
- guint i, n;
- ObMenu *deskmenu;
- gchar *s;
- GList *eit, *enext;
- GSList *sit, *snext;
-
- n = g_slist_length(CLIENT_LIST_MENU_DATA(self)->submenus);
+ guint i;
+ MenuData *d = data;
+
+ menu_clear_entries(MENU_NAME);
for (i = 0; i < screen_num_desktops; ++i) {
- if (i >= n) {
- s = g_strdup_printf("client-list-menu-desktop-%d", i);
- deskmenu = menu_new_full(screen_desktop_names[i], s, self,
- NULL,
- desk_update, desk_selected, NULL, NULL,
- desk_destroy);
- g_free(s);
-
- deskmenu->plugin = PLUGIN_NAME;
- deskmenu->plugin_data = g_new(Client_List_Desktop_Menu_Data, 1);
- CLIENT_LIST_DESKTOP_MENU_DATA(deskmenu)->desktop = i;
-
- CLIENT_LIST_MENU_DATA(self)->submenus =
- g_slist_append(CLIENT_LIST_MENU_DATA(self)->submenus,
- deskmenu);
- }
+ gchar *name = g_strdup_printf("%s-%u", MENU_NAME, i);
+ DesktopData *data = g_new(DesktopData, 1);
- menu_add_entry(self, menu_entry_new_submenu(screen_desktop_names[i],
- deskmenu));
- }
+ data->desktop = i;
+ menu_new(name, screen_desktop_names[i], data);
+ menu_set_update_func(name, desk_menu_update);
+ menu_set_execute_func(name, desk_menu_execute);
+ menu_set_destroy_func(name, desk_menu_destroy);
- for (eit = g_list_nth(self->entries, i); eit; eit = enext) {
- enext = g_list_next(eit);
- menu_entry_free(eit->data);
- self->entries = g_list_delete_link(self->entries, eit);
+ menu_add_submenu(MENU_NAME, 0, name);
+
+ g_free(name);
}
- for (sit = g_slist_nth(CLIENT_LIST_MENU_DATA(self)->submenus, i);
- sit; sit = snext) {
- snext = g_slist_next(sit);
- menu_free(sit->data);
- CLIENT_LIST_MENU_DATA(self)->submenus =
- g_slist_delete_link(CLIENT_LIST_MENU_DATA(self)->submenus, sit);
+ d->desktops = MAX(d->desktops, screen_num_desktops);
+}
+
+static void self_destroy(ObMenu *menu, gpointer data)
+{
+ MenuData *d = data;
+ guint i;
+
+ for (i = 0; i < d->desktops; ++i) {
+ gchar *name = g_strdup_printf("%s-%u", MENU_NAME, i);
+ menu_free(name);
+ g_free(name);
}
+ g_free(d);
+}
+
+void plugin_startup()
+{
+ MenuData *data;
- menu_render(self);
+ data = g_new(MenuData, 1);
+ data->desktops = 0;
+ menu_new(MENU_NAME, _("Desktops"), data);
+ menu_set_update_func(MENU_NAME, self_update);
+ menu_set_destroy_func(MENU_NAME, self_destroy);
}
-static void self_destroy(ObMenu *self)
+void plugin_shutdown()
{
- g_free(self->plugin_data);
+ menu_free(MENU_NAME);
}
if (e->type == OB_MENU_ENTRY_TYPE_NORMAL)
e->data.normal.enabled = !!frame->client;
}
+
+ e = menu_find_entry_id(menu, LAYER_TOP);
+ e->data.normal.enabled = !frame->client->above;
+
+ e = menu_find_entry_id(menu, LAYER_NORMAL);
+ e->data.normal.enabled = !(frame->client->above || frame->client->below);
+
+ e = menu_find_entry_id(menu, LAYER_BOTTOM);
+ e->data.normal.enabled = !frame->client->below;
}
static void send_to_update(ObMenuFrame *frame, gpointer data)