Fix a crash when moving into a menu on top of a separator and nothing is selected
[dana/openbox.git] / openbox / actions / focus.c
1 #include "openbox/actions.h"
2 #include "openbox/event.h"
3 #include "openbox/client.h"
4 #include "openbox/focus.h"
5 #include "openbox/screen.h"
6
7 typedef struct {
8     gboolean here;
9     gboolean stop_int;
10 } Options;
11
12 static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
13 static void     free_func(gpointer options);
14 static gboolean run_func(ObActionsData *data, gpointer options);
15
16 void action_focus_startup(void)
17 {
18     actions_register("Focus",
19                      setup_func,
20                      free_func,
21                      run_func,
22                      NULL, NULL);
23 }
24
25 static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
26 {
27     xmlNodePtr n;
28     Options *o;
29
30     o = g_new0(Options, 1);
31     o->stop_int = TRUE;
32
33     if ((n = parse_find_node("here", node)))
34         o->here = parse_bool(doc, n);
35     if ((n = parse_find_node("stopInteractive", node)))
36         o->stop_int = parse_bool(doc, n);
37     return o;
38 }
39
40 static void free_func(gpointer options)
41 {
42     Options *o = options;
43
44     g_free(o);
45 }
46
47 /* Always return FALSE because its not interactive */
48 static gboolean run_func(ObActionsData *data, gpointer options)
49 {
50     Options *o = options;
51
52     if (data->client) {
53 /*
54         ob_debug("button %d focusable %d context %d %d %d\n",
55                  data->button, client_mouse_focusable(data->client),
56                  data->context,
57                  OB_FRAME_CONTEXT_CLIENT, OB_FRAME_CONTEXT_FRAME);
58 */
59         if (data->button == 0 || client_mouse_focusable(data->client) ||
60             (data->context != OB_FRAME_CONTEXT_CLIENT &&
61              data->context != OB_FRAME_CONTEXT_FRAME))
62         {
63             if (o->stop_int)
64                 actions_interactive_cancel_act();
65
66             actions_client_move(data, TRUE);
67             client_activate(data->client, TRUE, o->here, FALSE, FALSE, TRUE);
68             actions_client_move(data, FALSE);
69         }
70     } else if (data->context == OB_FRAME_CONTEXT_DESKTOP) {
71         if (o->stop_int)
72             actions_interactive_cancel_act();
73
74         /* focus action on the root window. make keybindings work for this
75            openbox instance, but don't focus any specific client */
76         focus_nothing();
77     }
78
79     return FALSE;
80 }