make client-list-menu work too
more menu cleanups
This commit is contained in:
parent
ffba11aeb0
commit
f7eb47dba4
12 changed files with 190 additions and 145 deletions
|
@ -27,11 +27,11 @@ bin_PROGRAMS = \
|
||||||
|
|
||||||
plugin_LTLIBRARIES = \
|
plugin_LTLIBRARIES = \
|
||||||
plugins/placement/placement.la \
|
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/timed_menu.la \
|
||||||
# plugins/menu/fifo_menu.la \
|
# plugins/menu/fifo_menu.la \
|
||||||
# plugins/menu/include_menu.la \
|
# plugins/menu/include_menu.la \
|
||||||
# plugins/menu/client_list_menu.la
|
|
||||||
|
|
||||||
if OBCONF
|
if OBCONF
|
||||||
bin_PROGRAMS += \
|
bin_PROGRAMS += \
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
</menu>
|
</menu>
|
||||||
|
|
||||||
<menu id="client-menu" plugin="client_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="root-menu" label="Openbox 3">
|
||||||
<menu id="apps-menu" />
|
<menu id="apps-menu" />
|
||||||
|
@ -35,6 +36,8 @@
|
||||||
<separator />
|
<separator />
|
||||||
<menu id="client-menu" plugin="client_menu" />
|
<menu id="client-menu" plugin="client_menu" />
|
||||||
<separator />
|
<separator />
|
||||||
|
<menu id="client-list-menu" plugin="client_list_menu" />
|
||||||
|
<separator />
|
||||||
<item label="Restart">
|
<item label="Restart">
|
||||||
<action name="restart" />
|
<action name="restart" />
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -693,7 +693,7 @@ ObAction *action_from_string(char *name)
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node)
|
ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
|
||||||
{
|
{
|
||||||
char *actname;
|
char *actname;
|
||||||
ObAction *act = NULL;
|
ObAction *act = NULL;
|
||||||
|
@ -705,8 +705,13 @@ ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node)
|
||||||
if ((n = parse_find_node("execute", node->xmlChildrenNode)))
|
if ((n = parse_find_node("execute", node->xmlChildrenNode)))
|
||||||
act->data.execute.path = parse_string(doc, n);
|
act->data.execute.path = parse_string(doc, n);
|
||||||
} else if (act->func == action_showmenu) {
|
} 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);
|
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) {
|
} else if (act->func == action_desktop) {
|
||||||
if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
|
if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
|
||||||
act->data.desktop.desk = parse_int(doc, n);
|
act->data.desktop.desk = parse_int(doc, n);
|
||||||
|
|
|
@ -137,7 +137,7 @@ ObAction *action_new(void (*func)(union ActionData *data));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ObAction *action_from_string(char *name);
|
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);
|
void action_free(ObAction *a);
|
||||||
|
|
||||||
/* Execute */
|
/* Execute */
|
||||||
|
|
|
@ -92,7 +92,7 @@ static void parse_key(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
||||||
if (keylist) {
|
if (keylist) {
|
||||||
nact = parse_find_node("action", node);
|
nact = parse_find_node("action", node);
|
||||||
while (nact) {
|
while (nact) {
|
||||||
if ((action = action_parse(doc, nact))) {
|
if ((action = action_parse(i, doc, nact))) {
|
||||||
/* validate that its okay for a key binding */
|
/* validate that its okay for a key binding */
|
||||||
if (action->func == action_moveresize &&
|
if (action->func == action_moveresize &&
|
||||||
action->data.moveresize.corner !=
|
action->data.moveresize.corner !=
|
||||||
|
@ -165,7 +165,7 @@ static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
||||||
goto next_nbut;
|
goto next_nbut;
|
||||||
nact = parse_find_node("action", nbut->xmlChildrenNode);
|
nact = parse_find_node("action", nbut->xmlChildrenNode);
|
||||||
while (nact) {
|
while (nact) {
|
||||||
if ((action = action_parse(doc, nact))) {
|
if ((action = action_parse(i, doc, nact))) {
|
||||||
/* validate that its okay for a mouse binding*/
|
/* validate that its okay for a mouse binding*/
|
||||||
if (mact == OB_MOUSE_ACTION_MOTION) {
|
if (mact == OB_MOUSE_ACTION_MOTION) {
|
||||||
if (action->func != action_moveresize ||
|
if (action->func != action_moveresize ||
|
||||||
|
|
|
@ -1170,13 +1170,14 @@ static void event_handle_menu(XEvent *ev)
|
||||||
|
|
||||||
switch (ev->type) {
|
switch (ev->type) {
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
if (!(f = menu_frame_under(ev->xmotion.x_root,
|
if (!(f = menu_frame_under(ev->xbutton.x_root,
|
||||||
ev->xmotion.y_root)))
|
ev->xbutton.y_root)))
|
||||||
menu_frame_hide_all();
|
menu_frame_hide_all();
|
||||||
else {
|
else {
|
||||||
if ((e = menu_entry_frame_under(ev->xmotion.x_root,
|
if ((e = menu_entry_frame_under(ev->xbutton.x_root,
|
||||||
ev->xmotion.y_root)))
|
ev->xbutton.y_root)))
|
||||||
menu_entry_frame_execute(e);
|
menu_entry_frame_execute(e,
|
||||||
|
!(ev->xbutton.state & ControlMask));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MotionNotify:
|
case MotionNotify:
|
||||||
|
|
|
@ -47,7 +47,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(i, doc, node));
|
||||||
menu_add_normal(state->menus->data, 0, label, acts);
|
menu_add_normal(state->menus->data, 0, label, acts);
|
||||||
g_free(label);
|
g_free(label);
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,21 @@ static void parse_menu_separator(ObParseInst *i,
|
||||||
menu_add_separator(state->menus->data, 0);
|
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,
|
static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
|
@ -75,13 +90,7 @@ static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
||||||
|
|
||||||
if (!g_hash_table_lookup(menu_hash, name)) {
|
if (!g_hash_table_lookup(menu_hash, name)) {
|
||||||
if (parse_attr_string("plugin", node, &plugin)) {
|
if (parse_attr_string("plugin", node, &plugin)) {
|
||||||
if (!plugin_open(plugin, i))
|
menu_open_plugin(i, name, plugin);
|
||||||
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;
|
|
||||||
} else {
|
} else {
|
||||||
if (!parse_attr_string("label", node, &title))
|
if (!parse_attr_string("label", node, &title))
|
||||||
goto parse_menu_fail;
|
goto parse_menu_fail;
|
||||||
|
@ -107,6 +116,10 @@ parse_menu_fail:
|
||||||
void menu_destroy_hash_value(ObMenu *self)
|
void menu_destroy_hash_value(ObMenu *self)
|
||||||
{
|
{
|
||||||
/* XXX make sure its not visible */
|
/* XXX make sure its not visible */
|
||||||
|
|
||||||
|
if (self->destroy_func)
|
||||||
|
self->destroy_func(self, self->data);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -315,6 +328,22 @@ void menu_set_update_func(gchar *name, ObMenuUpdateFunc func)
|
||||||
self->update_func = func;
|
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* menu_find_entry_id(ObMenu *self, gint id)
|
||||||
{
|
{
|
||||||
ObMenuEntry *ret = NULL;
|
ObMenuEntry *ret = NULL;
|
||||||
|
|
|
@ -3,13 +3,15 @@
|
||||||
|
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "render/render.h"
|
|
||||||
#include "geom.h"
|
#include "geom.h"
|
||||||
|
#include "render/render.h"
|
||||||
|
#include "parser/parse.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
struct _ObClient;
|
struct _ObClient;
|
||||||
struct _ObMenuFrame;
|
struct _ObMenuFrame;
|
||||||
|
struct _ObMenuEntryFrame;
|
||||||
|
|
||||||
typedef struct _ObMenu ObMenu;
|
typedef struct _ObMenu ObMenu;
|
||||||
typedef struct _ObMenuEntry ObMenuEntry;
|
typedef struct _ObMenuEntry ObMenuEntry;
|
||||||
|
@ -18,6 +20,9 @@ typedef struct _ObSubmenuMenuEntry ObSubmenuMenuEntry;
|
||||||
typedef struct _ObSeparatorMenuEntry ObSeparatorMenuEntry;
|
typedef struct _ObSeparatorMenuEntry ObSeparatorMenuEntry;
|
||||||
|
|
||||||
typedef void (*ObMenuUpdateFunc)(struct _ObMenuFrame *frame, gpointer data);
|
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;
|
extern GList *menu_visible;
|
||||||
|
|
||||||
|
@ -35,6 +40,8 @@ struct _ObMenu
|
||||||
gpointer data;
|
gpointer data;
|
||||||
|
|
||||||
ObMenuUpdateFunc update_func;
|
ObMenuUpdateFunc update_func;
|
||||||
|
ObMenuExecuteFunc execute_func;
|
||||||
|
ObMenuDestroyFunc destroy_func;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -84,7 +91,11 @@ 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_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_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);
|
void menu_show(gchar *name, gint x, gint y, struct _ObClient *client);
|
||||||
|
|
||||||
|
|
|
@ -344,8 +344,10 @@ static void menu_frame_render(ObMenuFrame *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!w) w = 10;
|
if (!w) w = 10;
|
||||||
if (!allitems_h) allitems_h = 3;
|
if (!allitems_h) {
|
||||||
if (!h) h = 3;
|
allitems_h = 3;
|
||||||
|
h += 3;
|
||||||
|
}
|
||||||
|
|
||||||
XResizeWindow(ob_display, self->window, w, h);
|
XResizeWindow(ob_display, self->window, w, h);
|
||||||
XResizeWindow(ob_display, self->items, w, allitems_h);
|
XResizeWindow(ob_display, self->items, w, allitems_h);
|
||||||
|
@ -546,14 +548,17 @@ void menu_entry_frame_show_submenu(ObMenuEntryFrame *self)
|
||||||
menu_frame_show(f, self->frame);
|
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) {
|
if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) {
|
||||||
GSList *it;
|
|
||||||
|
|
||||||
/* release grabs before executing the shit */
|
/* release grabs before executing the shit */
|
||||||
menu_frame_hide_all();
|
menu_frame_hide_all();
|
||||||
|
|
||||||
|
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;
|
for (it = self->entry->data.normal.actions; it;
|
||||||
it = g_slist_next(it))
|
it = g_slist_next(it))
|
||||||
{
|
{
|
||||||
|
@ -562,4 +567,5 @@ void menu_entry_frame_execute(ObMenuEntryFrame *self)
|
||||||
act->func(&act->data);
|
act->func(&act->data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,6 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y);
|
||||||
|
|
||||||
void menu_entry_frame_show_submenu(ObMenuEntryFrame *self);
|
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
|
#endif
|
||||||
|
|
|
@ -1,142 +1,123 @@
|
||||||
#include "kernel/openbox.h"
|
#include "kernel/openbox.h"
|
||||||
#include "kernel/menu.h"
|
#include "kernel/menu.h"
|
||||||
|
#include "kernel/menuframe.h"
|
||||||
#include "kernel/action.h"
|
#include "kernel/action.h"
|
||||||
#include "kernel/screen.h"
|
#include "kernel/screen.h"
|
||||||
#include "kernel/client.h"
|
#include "kernel/client.h"
|
||||||
#include "kernel/focus.h"
|
#include "kernel/focus.h"
|
||||||
|
#include "gettext.h"
|
||||||
|
|
||||||
#include "render/theme.h"
|
#include "render/theme.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
static char *PLUGIN_NAME = "client_list_menu";
|
#define MENU_NAME "client-list-menu"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GSList *submenus;
|
/* how many desktop menus we've made */
|
||||||
} Client_List_Menu_Data;
|
guint desktops;
|
||||||
|
} MenuData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
guint desktop;
|
guint desktop;
|
||||||
} Client_List_Desktop_Menu_Data;
|
} DesktopData;
|
||||||
|
|
||||||
#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);
|
|
||||||
|
|
||||||
void plugin_setup_config() { }
|
void plugin_setup_config() { }
|
||||||
void plugin_shutdown() { }
|
|
||||||
void plugin_destroy (ObMenu *m) { }
|
|
||||||
|
|
||||||
void *plugin_create()
|
static void desk_menu_update(ObMenuFrame *frame, gpointer data)
|
||||||
{
|
{
|
||||||
ObMenu *menu = menu_new_full("Desktops", "client-list-menu", NULL,
|
ObMenu *menu = frame->menu;
|
||||||
NULL, self_update, NULL,
|
DesktopData *d = data;
|
||||||
NULL, NULL, self_destroy);
|
GList *it;
|
||||||
|
|
||||||
menu->plugin = PLUGIN_NAME;
|
menu_clear_entries(menu->name);
|
||||||
menu->plugin_data = g_new(Client_List_Menu_Data, 1);
|
|
||||||
CLIENT_LIST_MENU_DATA(menu)->submenus = NULL;
|
|
||||||
|
|
||||||
return (void *)menu;
|
for (it = focus_order[d->desktop]; it; it = g_list_next(it)) {
|
||||||
|
ObClient *c = it->data;
|
||||||
|
if (client_normal(c)) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
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_menu_destroy(ObMenu *menu, gpointer data)
|
||||||
|
{
|
||||||
|
DesktopData *d = data;
|
||||||
|
|
||||||
|
g_free(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void self_update(ObMenuFrame *frame, gpointer data)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
MenuData *d = data;
|
||||||
|
|
||||||
|
menu_clear_entries(MENU_NAME);
|
||||||
|
|
||||||
|
for (i = 0; i < screen_num_desktops; ++i) {
|
||||||
|
gchar *name = g_strdup_printf("%s-%u", MENU_NAME, i);
|
||||||
|
DesktopData *data = g_new(DesktopData, 1);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
menu_add_submenu(MENU_NAME, 0, name);
|
||||||
|
|
||||||
|
g_free(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
void plugin_startup()
|
||||||
{
|
{
|
||||||
plugin_create("client_list_menu");
|
MenuData *data;
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void plugin_shutdown()
|
||||||
static void desk_update(ObMenu *self)
|
|
||||||
{
|
{
|
||||||
GList *it;
|
menu_free(MENU_NAME);
|
||||||
guint desk;
|
|
||||||
|
|
||||||
menu_clear(self);
|
|
||||||
|
|
||||||
desk = CLIENT_LIST_DESKTOP_MENU_DATA(self)->desktop;
|
|
||||||
|
|
||||||
for (it = focus_order[desk]; it; it = g_list_next(it)) {
|
|
||||||
ObClient *c = (ObClient *)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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
menu_render(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void desk_selected(ObMenuEntry *entry,
|
|
||||||
unsigned int button, unsigned int x, unsigned int y)
|
|
||||||
{
|
|
||||||
entry->action->data.activate.here = (button == 2);
|
|
||||||
entry->parent->client = entry->action->data.activate.c;
|
|
||||||
menu_entry_fire(entry, button, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void desk_destroy(ObMenu *self)
|
|
||||||
{
|
|
||||||
g_free(self->plugin_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void self_update(ObMenu *self)
|
|
||||||
{
|
|
||||||
guint i, n;
|
|
||||||
ObMenu *deskmenu;
|
|
||||||
gchar *s;
|
|
||||||
GList *eit, *enext;
|
|
||||||
GSList *sit, *snext;
|
|
||||||
|
|
||||||
n = g_slist_length(CLIENT_LIST_MENU_DATA(self)->submenus);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
menu_add_entry(self, menu_entry_new_submenu(screen_desktop_names[i],
|
|
||||||
deskmenu));
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
menu_render(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void self_destroy(ObMenu *self)
|
|
||||||
{
|
|
||||||
g_free(self->plugin_data);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,15 @@ static void layer_update(ObMenuFrame *frame, gpointer data)
|
||||||
if (e->type == OB_MENU_ENTRY_TYPE_NORMAL)
|
if (e->type == OB_MENU_ENTRY_TYPE_NORMAL)
|
||||||
e->data.normal.enabled = !!frame->client;
|
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)
|
static void send_to_update(ObMenuFrame *frame, gpointer data)
|
||||||
|
|
Loading…
Reference in a new issue