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