add the kill/close/cyclewindows actions
[dana/openbox.git] / openbox / actions / cyclewindows.c
1 #include "openbox/actions.h"
2 #include "openbox/event.h"
3 #include "openbox/focus_cycle.h"
4 #include "openbox/openbox.h"
5 #include "gettext.h"
6
7 typedef struct {
8     gboolean linear;
9     gboolean dialog;
10     gboolean dock_windows;
11     gboolean desktop_windows;
12     gboolean all_desktops;
13     gboolean forward;
14     GSList *actions;
15 } Options;
16
17 static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
18 static void     free_func(gpointer options);
19 static gboolean run_func(ObActionsData *data, gpointer options);
20 static gboolean i_input_func(guint initial_state,
21                              XEvent *e,
22                              gpointer options,
23                              gboolean *used);
24 static void     i_cancel_func(gpointer options);
25
26 static void     end_cycle(gboolean cancel, guint state, Options *o);
27
28 void action_cyclewindows_startup()
29 {
30     actions_register("CycleWindows",
31                      setup_func,
32                      free_func,
33                      run_func,
34                      i_input_func,
35                      i_cancel_func);
36 }
37
38 static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
39 {
40     xmlNodePtr n;
41     Options *o;
42
43     o = g_new0(Options, 1);
44     o->dialog = TRUE;
45
46     if ((n = parse_find_node("forward", node)))
47         o->forward = parse_bool(doc, n);
48     if ((n = parse_find_node("linear", node)))
49         o->linear = parse_bool(doc, n);
50     if ((n = parse_find_node("dialog", node)))
51         o->dialog = parse_bool(doc, n);
52     if ((n = parse_find_node("panels", node)))
53         o->dock_windows = parse_bool(doc, n);
54     if ((n = parse_find_node("desktop", node)))
55         o->desktop_windows = parse_bool(doc, n);
56     if ((n = parse_find_node("allDesktops", node)))
57         o->all_desktops = parse_bool(doc, n);
58
59     if ((n = parse_find_node("actions", node))) {
60         xmlNodePtr m;
61
62         m = parse_find_node("action", n->xmlChildrenNode);
63         while (m) {
64             ObActionsAct *action = actions_parse(i, doc, m);
65             if (action) o->actions = g_slist_prepend(o->actions, action);
66             m = parse_find_node("action", m->next);
67         }
68     }
69     return o;
70 }
71
72 static void free_func(gpointer options)
73 {
74     Options *o = options;
75
76     g_free(o);
77 }
78
79 static gboolean run_func(ObActionsData *data, gpointer options)
80 {
81     Options *o = options;
82
83     /* if using focus_delay, stop the timer now so that focus doesn't go moving
84        on us */
85     event_halt_focus_delay();
86     
87     focus_cycle(o->forward,
88                 o->all_desktops,
89                 o->dock_windows,
90                 o->desktop_windows,
91                 o->linear,
92                 TRUE,
93                 o->dialog,
94                 FALSE, FALSE);
95
96     return TRUE;
97 }
98
99 static gboolean i_input_func(guint initial_state,
100                              XEvent *e,
101                              gpointer options,
102                              gboolean *used)
103 {
104     if (e->type == KeyPress) {
105         /* Escape cancels no matter what */
106         if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) {
107             end_cycle(TRUE, e->xkey.state, options);
108             return FALSE;
109         }
110
111         /* There were no modifiers and they pressed enter */
112         else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN) &&
113                  !initial_state)
114         {
115             end_cycle(FALSE, e->xkey.state, options);
116             return FALSE;
117         }
118     }
119     /* They released the modifiers */
120     else if (e->type == KeyRelease && initial_state &&
121              (e->xkey.state & initial_state) == 0)
122     {
123         end_cycle(FALSE, e->xkey.state, options);
124         return FALSE;
125     }
126
127     return TRUE;
128 }
129
130 static void i_cancel_func(gpointer options)
131 {
132     end_cycle(TRUE, 0, options);
133 }
134
135 static void end_cycle(gboolean cancel, guint state, Options *o)
136 {
137     struct _ObClient *ft;
138
139     ft = focus_cycle(o->forward,
140                      o->all_desktops,
141                      o->dock_windows,
142                      o->desktop_windows,
143                      o->linear,
144                      TRUE,
145                      o->dialog,
146                      TRUE, cancel);
147
148     if (ft) {
149         actions_run_acts(o->actions, OB_USER_ACTION_KEYBOARD_KEY,
150                          state, -1, -1, 0, OB_FRAME_CONTEXT_NONE, ft);
151     }
152 }