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