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