a99435272ad27d82b2687b1aaa69d09b47978c83
[mikachu/openbox.git] / openbox / actions / if.c
1 #include "openbox/actions.h"
2 #include "openbox/misc.h"
3 #include "openbox/client.h"
4 #include "openbox/frame.h"
5 #include "openbox/screen.h"
6 #include "openbox/focus.h"
7 #include <glib.h>
8
9 typedef struct {
10     gboolean shaded_on;
11     gboolean shaded_off;
12     gboolean maxvert_on;
13     gboolean maxvert_off;
14     gboolean maxhorz_on;
15     gboolean maxhorz_off;
16     gboolean maxfull_on;
17     gboolean maxfull_off;
18     gboolean iconic_on;
19     gboolean iconic_off;
20     gboolean focused;
21     gboolean unfocused;
22     gboolean urgent_on;
23     gboolean urgent_off;
24     gboolean decor_off;
25     gboolean decor_on;
26     gboolean omnipresent_on;
27     gboolean omnipresent_off;
28     gboolean desktop_current;
29     gboolean desktop_other;
30     guint    desktop_number;
31     guint    screendesktop_number;
32     GPatternSpec *matchtitle;
33     GSList *thenacts;
34     GSList *elseacts;
35 } Options;
36
37 static gpointer setup_func(xmlNodePtr node);
38 static void     free_func(gpointer options);
39 static gboolean run_func(ObActionsData *data, gpointer options);
40
41 void action_if_startup(void)
42 {
43     actions_register("If", setup_func, free_func, run_func);
44 }
45
46 static gpointer setup_func(xmlNodePtr node)
47 {
48     xmlNodePtr n;
49     Options *o;
50
51     o = g_slice_new0(Options);
52
53     if ((n = obt_xml_find_node(node, "shaded"))) {
54         if (obt_xml_node_bool(n))
55             o->shaded_on = TRUE;
56         else
57             o->shaded_off = TRUE;
58     }
59     if ((n = obt_xml_find_node(node, "maximized"))) {
60         if (obt_xml_node_bool(n))
61             o->maxfull_on = TRUE;
62         else
63             o->maxfull_off = TRUE;
64     }
65     if ((n = obt_xml_find_node(node, "maximizedhorizontal"))) {
66         if (obt_xml_node_bool(n))
67             o->maxhorz_on = TRUE;
68         else
69             o->maxhorz_off = TRUE;
70     }
71     if ((n = obt_xml_find_node(node, "maximizedvertical"))) {
72         if (obt_xml_node_bool(n))
73             o->maxvert_on = TRUE;
74         else
75             o->maxvert_off = TRUE;
76     }
77     if ((n = obt_xml_find_node(node, "iconified"))) {
78         if (obt_xml_node_bool(n))
79             o->iconic_on = TRUE;
80         else
81             o->iconic_off = TRUE;
82     }
83     if ((n = obt_xml_find_node(node, "focused"))) {
84         if (obt_xml_node_bool(n))
85             o->focused = TRUE;
86         else
87             o->unfocused = TRUE;
88     }
89     if ((n = obt_xml_find_node(node, "urgent"))) {
90         if (obt_xml_node_bool(n))
91             o->urgent_on = TRUE;
92         else
93             o->urgent_off = TRUE;
94     }
95     if ((n = obt_xml_find_node(node, "undecorated"))) {
96         if (obt_xml_node_bool(n))
97             o->decor_off = TRUE;
98         else
99             o->decor_on = TRUE;
100     }
101     if ((n = obt_xml_find_node(node, "desktop"))) {
102         gchar *s;
103         if ((s = obt_xml_node_string(n))) {
104             if (!g_ascii_strcasecmp(s, "current"))
105                 o->desktop_current = TRUE;
106             if (!g_ascii_strcasecmp(s, "other"))
107                 o->desktop_other = TRUE;
108             else
109                 o->desktop_number = atoi(s);
110             g_free(s);
111         }
112     }
113     if ((n = obt_xml_find_node(node, "omnipresent"))) {
114         if (obt_xml_node_bool(n))
115             o->omnipresent_on = TRUE;
116         else
117             o->omnipresent_off = TRUE;
118     if ((n = obt_xml_find_node(node, "activedesktop"))) {
119         o->screendesktop_number = obt_xml_node_int(n);
120     }
121     if ((n = obt_xml_find_node(node, "title"))) {
122         gchar *s;
123         if ((s = obt_xml_node_string(n))) {
124             o->matchtitle = g_pattern_spec_new(s);
125             g_free(s);
126         }
127     }
128
129     if ((n = obt_xml_find_node(node, "then"))) {
130         xmlNodePtr m;
131
132         m = obt_xml_find_node(n->children, "action");
133         while (m) {
134             ObActionsAct *action = actions_parse(m);
135             if (action) o->thenacts = g_slist_append(o->thenacts, action);
136             m = obt_xml_find_node(m->next, "action");
137         }
138     }
139     if ((n = obt_xml_find_node(node, "else"))) {
140         xmlNodePtr m;
141
142         m = obt_xml_find_node(n->children, "action");
143         while (m) {
144             ObActionsAct *action = actions_parse(m);
145             if (action) o->elseacts = g_slist_append(o->elseacts, action);
146             m = obt_xml_find_node(m->next, "action");
147         }
148     }
149
150     return o;
151 }
152
153 static void free_func(gpointer options)
154 {
155     Options *o = options;
156
157     while (o->thenacts) {
158         actions_act_unref(o->thenacts->data);
159         o->thenacts = g_slist_delete_link(o->thenacts, o->thenacts);
160     }
161     while (o->elseacts) {
162         actions_act_unref(o->elseacts->data);
163         o->elseacts = g_slist_delete_link(o->elseacts, o->elseacts);
164     }
165     if (o->matchtitle)
166         g_pattern_spec_free(o->matchtitle);
167
168     g_slice_free(Options, o);
169 }
170
171 /* Always return FALSE because its not interactive */
172 static gboolean run_func(ObActionsData *data, gpointer options)
173 {
174     Options *o = options;
175     GSList *acts;
176     ObClient *c = data->client;
177
178     if (c &&
179         (!o->shaded_on   ||  c->shaded) &&
180         (!o->shaded_off  || !c->shaded) &&
181         (!o->iconic_on   ||  c->iconic) &&
182         (!o->iconic_off  || !c->iconic) &&
183         (!o->maxhorz_on  ||  c->max_horz) &&
184         (!o->maxhorz_off || !c->max_horz) &&
185         (!o->maxvert_on  ||  c->max_vert) &&
186         (!o->maxvert_off || !c->max_vert) &&
187         (!o->maxfull_on  ||  (c->max_vert && c->max_horz)) &&
188         (!o->maxfull_off || !(c->max_vert && c->max_horz)) &&
189         (!o->focused     ||  (c == focus_client)) &&
190         (!o->unfocused   || !(c == focus_client)) &&
191         (!o->urgent_on   ||  (c->urgent || c->demands_attention)) &&
192         (!o->urgent_off  || !(c->urgent || c->demands_attention)) &&
193         (!o->decor_off   ||  (c->undecorated || !(c->decorations & OB_FRAME_DECOR_TITLEBAR))) &&
194         (!o->decor_on    ||  (!c->undecorated && (c->decorations & OB_FRAME_DECOR_TITLEBAR))) &&
195         (!o->omnipresent_on  || (c->desktop == DESKTOP_ALL)) &&
196         (!o->omnipresent_off || (c->desktop != DESKTOP_ALL)) &&
197         (!o->desktop_current || ((c->desktop == screen_desktop) ||
198                                  (c->desktop == DESKTOP_ALL))) &&
199         (!o->desktop_other   || ((c->desktop != screen_desktop) &&
200                                  (c->desktop != DESKTOP_ALL))) &&
201         (!o->desktop_number  || ((c->desktop == o->desktop_number - 1) ||
202                                  (c->desktop == DESKTOP_ALL))) &&
203         (!o->screendesktop_number || screen_desktop == o->screendesktop_number - 1) &&
204         (!o->matchtitle ||
205          (g_pattern_match_string(o->matchtitle, c->original_title))))
206     {
207         acts = o->thenacts;
208     }
209     else
210         acts = o->elseacts;
211
212     actions_run_acts(acts, data->uact, data->state,
213                      data->x, data->y, data->button,
214                      data->context, data->client);
215
216     return FALSE;
217 }