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"
6 #include "openbox/config.h"
11 GravityPoint position;
12 ObPlaceMonitor monitor_type;
14 gboolean use_position;
17 static gpointer setup_func(xmlNodePtr node);
18 static void free_func(gpointer options);
19 static gboolean run_func(ObActionsData *data, gpointer options);
21 void action_showmenu_startup(void)
23 actions_register("ShowMenu", setup_func, free_func, run_func);
26 static gpointer setup_func(xmlNodePtr node)
30 gboolean x_pos_given = FALSE;
32 o = g_slice_new0(Options);
35 if ((n = obt_xml_find_node(node, "menu")))
36 o->name = obt_xml_node_string(n);
38 if ((n = obt_xml_find_node(node, "position"))) {
39 if ((c = obt_xml_find_node(n->children, "x"))) {
40 if (!obt_xml_node_contains(c, "default")) {
41 config_parse_gravity_coord(c, &o->position.x);
46 if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
47 if (!obt_xml_node_contains(c, "default")) {
48 config_parse_gravity_coord(c, &o->position.y);
49 o->use_position = TRUE;
53 /* unlike client placement, x/y is needed to specify a monitor,
54 * either it's under the mouse or it's in an exact actual position */
55 if (o->use_position && (c = obt_xml_find_node(n->children, "monitor"))) {
56 if (!obt_xml_node_contains(c, "default")) {
57 gchar *s = obt_xml_node_string(c);
58 if (!g_ascii_strcasecmp(s, "mouse"))
59 o->monitor_type = OB_PLACE_MONITOR_MOUSE;
60 else if (!g_ascii_strcasecmp(s, "active"))
61 o->monitor_type = OB_PLACE_MONITOR_ACTIVE;
62 else if (!g_ascii_strcasecmp(s, "primary"))
63 o->monitor_type = OB_PLACE_MONITOR_PRIMARY;
64 else if (!g_ascii_strcasecmp(s, "all"))
65 o->monitor_type = OB_PLACE_MONITOR_ALL;
67 o->monitor = obt_xml_node_int(c) - 1;
75 static void free_func(gpointer options)
79 g_slice_free(Options, o);
82 /* Always return FALSE because its not interactive */
83 static gboolean run_func(ObActionsData *data, gpointer options)
86 GravityPoint position = { { 0, }, };
89 if (o->use_position) {
92 else switch (o->monitor_type) {
93 case OB_PLACE_MONITOR_ANY:
94 case OB_PLACE_MONITOR_PRIMARY:
95 monitor = screen_monitor_primary(FALSE);
97 case OB_PLACE_MONITOR_MOUSE:
98 monitor = screen_monitor_pointer();
100 case OB_PLACE_MONITOR_ACTIVE:
101 monitor = screen_monitor_active();
103 case OB_PLACE_MONITOR_ALL:
104 monitor = screen_num_monitors;
107 g_assert_not_reached();
110 position = o->position;
113 monitor = screen_num_monitors;
114 allmon = screen_physical_area_monitor(monitor);
115 position.x.pos = data->x - allmon->x;
116 position.y.pos = data->y - allmon->y;
119 /* you cannot call ShowMenu from inside a menu */
120 if (data->uact != OB_USER_ACTION_MENU_SELECTION && o->name)
121 menu_show(o->name, &position, monitor,
122 data->button != 0, o->use_position, data->client);