1 #include "openbox/actions.h"
2 #include "openbox/menu.h"
3 #include "openbox/place.h"
4 #include "openbox/geom.h"
5 #include "openbox/screen.h"
11 ObPlaceMonitor monitor_type;
13 gboolean use_position;
16 static gpointer setup_func(xmlNodePtr node);
17 static void free_func(gpointer options);
18 static gboolean run_func(ObActionsData *data, gpointer options);
20 void action_showmenu_startup(void)
22 actions_register("ShowMenu", setup_func, free_func, run_func);
25 static gpointer setup_func(xmlNodePtr node)
29 gboolean x_pos_given = FALSE;
31 o = g_slice_new0(Options);
34 if ((n = obt_xml_find_node(node, "menu")))
35 o->name = obt_xml_node_string(n);
37 if ((n = obt_xml_find_node(node, "position"))) {
38 if ((c = obt_xml_find_node(n->children, "x"))) {
39 if (!obt_xml_node_contains(c, "default")) {
40 config_parse_gravity_coord(c, &o->x);
45 if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
46 if (!obt_xml_node_contains(c, "default")) {
47 config_parse_gravity_coord(c, &o->y);
48 o->use_position = TRUE;
52 /* unlike client placement, x/y is needed to specify a monitor,
53 * either it's under the mouse or it's in an exact actual position */
54 if (o->use_position && (c = obt_xml_find_node(n->children, "monitor"))) {
55 if (!obt_xml_node_contains(c, "default")) {
56 gchar *s = obt_xml_node_string(c);
57 if (!g_ascii_strcasecmp(s, "mouse"))
58 o->monitor_type = OB_PLACE_MONITOR_MOUSE;
59 else if (!g_ascii_strcasecmp(s, "active"))
60 o->monitor_type = OB_PLACE_MONITOR_ACTIVE;
61 else if (!g_ascii_strcasecmp(s, "primary"))
62 o->monitor_type = OB_PLACE_MONITOR_PRIMARY;
63 else if (!g_ascii_strcasecmp(s, "all"))
64 o->monitor_type = OB_PLACE_MONITOR_ALL;
66 o->monitor = obt_xml_node_int(c) - 1;
74 static void free_func(gpointer options)
78 g_slice_free(Options, o);
81 static void calc_position(Options *o, gint *x, gint *y)
87 else switch (o->monitor_type) {
88 case OB_PLACE_MONITOR_ANY:
89 case OB_PLACE_MONITOR_PRIMARY:
90 monitor = screen_monitor_primary(FALSE);
92 case OB_PLACE_MONITOR_MOUSE:
93 monitor = screen_monitor_pointer();
95 case OB_PLACE_MONITOR_ACTIVE:
96 monitor = screen_monitor_active();
98 case OB_PLACE_MONITOR_ALL:
99 monitor = screen_num_monitors;
102 g_assert_not_reached();
104 area = screen_physical_area_monitor(monitor);
107 *x = area->width / 2; /* - client->area.width / 2; */
111 *x = (*x * area->width) / o->x.denom;
113 *x = area->width /* - frame_size.width */ - *x;
117 *y = area->height / 2; /* - client->area.height / 2; */
121 *y = (*y * area->height) / o->y.denom;
123 *y = area->height /* - frame_size.height */ - *y;
130 /* Always return FALSE because its not interactive */
131 static gboolean run_func(ObActionsData *data, gpointer options)
133 Options *o = options;
136 if (o->use_position) {
137 calc_position(o, &x, &y);
143 /* you cannot call ShowMenu from inside a menu */
144 if (data->uact != OB_USER_ACTION_MENU_SELECTION && o->name)
145 menu_show(o->name, x, y, data->button != 0, data->client);