]> icculus.org git repositories - mikachu/openbox.git/blob - openbox/actions.c
make mouse use the new action stuff
[mikachu/openbox.git] / openbox / actions.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    actions.h for the Openbox window manager
4    Copyright (c) 2007        Dana Jansens
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    See the COPYING file for a copy of the GNU General Public License.
17 */
18
19 #include "actions.h"
20 #include "gettext.h"
21
22 static void actions_definition_ref(ObActionsDefinition *def);
23 static void actions_definition_unref(ObActionsDefinition *def);
24
25 struct _ObActionsDefinition {
26     guint ref;
27
28     gchar *name;
29     ObActionsType type;
30
31     ObActionsDataSetupFunc setup;
32     ObActionsDataFreeFunc free;
33     ObActionsRunFunc run;
34 };
35
36 struct _ObActionsAct {
37     guint ref;
38
39     ObActionsDefinition *def;
40     gpointer options;
41 };
42
43 static GSList *registered = NULL;
44
45
46 void actions_startup(gboolean reconfig)
47 {
48     if (reconfig) return;
49
50     
51 }
52
53 void actions_shutdown(gboolean reconfig)
54 {
55     if (reconfig) return;
56
57     /* free all the registered actions */
58     while (registered) {
59         actions_definition_unref(registered->data);
60         registered = g_slist_delete_link(registered, registered);
61     }
62 }
63
64 gboolean actions_register(const gchar *name,
65                           ObActionsType type,
66                           ObActionsDataSetupFunc setup,
67                           ObActionsDataFreeFunc free,
68                           ObActionsRunFunc run)
69 {
70     GSList *it;
71     ObActionsDefinition *def;
72
73     for (it = registered; it; it = g_slist_next(it)) {
74         def = it->data;
75         if (!g_ascii_strcasecmp(name, def->name)) /* already registered */
76             return FALSE;
77     }
78
79     def = g_new(ObActionsDefinition, 1);
80     def->ref = 1;
81     def->name = g_strdup(name);
82     def->type = type;
83     def->setup = setup;
84     def->free = free;
85     def->run = run;
86     return TRUE;
87 }
88
89 static void actions_definition_ref(ObActionsDefinition *def)
90 {
91     ++def->ref;
92 }
93
94 static void actions_definition_unref(ObActionsDefinition *def)
95 {
96     if (def && --def->ref == 0) {
97         g_free(def->name);
98         g_free(def);
99     }
100 }
101
102 ObActionsAct* actions_parse_string(const gchar *name)
103 {
104     GSList *it;
105     ObActionsDefinition *def;
106     ObActionsAct *act = NULL;
107
108     /* find the requested action */
109     for (it = registered; it; it = g_slist_next(it)) {
110         def = it->data;
111         if (!g_ascii_strcasecmp(name, def->name))
112             break;
113         def = NULL;
114     }
115
116     /* if we found the action */
117     if (def) {
118         act = g_new(ObActionsAct, 1);
119         act->ref = 1;
120         act->def = def;
121         actions_definition_ref(act->def);
122         act->options = NULL;
123     } else
124         g_message(_("Invalid action '%s' requested. No such action exists."),
125                   name);
126
127     return act;
128 }
129
130 ObActionsAct* actions_parse(ObParseInst *i,
131                             xmlDocPtr doc,
132                             xmlNodePtr node)
133 {
134     gchar *name;
135     ObActionsAct *act = NULL;
136
137     if (parse_attr_string("name", node, &name)) {
138         if ((act = actions_parse_string(name)))
139             /* there is more stuff to parse here */
140             act->options = act->def->setup(i, doc, node->children);
141
142         g_free(name);
143     }
144
145     return act;
146 }
147
148 void actions_act_ref(ObActionsAct *act)
149 {
150     ++act->ref;
151 }
152
153 void actions_act_unref(ObActionsAct *act)
154 {
155     if (act && --act->ref == 0) {
156         /* free the action specific options */
157         act->def->free(act->options);
158         /* unref the definition */
159         actions_definition_unref(act->def);
160         g_free(act);
161     }
162 }
163
164 static void actions_setup_data(ObActionsData *data,
165                                ObUserAction uact,
166                                Time time,
167                                guint state,
168                                guint button,
169                                gint x,
170                                gint y)
171 {
172     data->any.uact = uact;
173     data->any.time = time;
174     data->any.state = state;
175     data->any.button = button;
176     data->any.x = x;
177     data->any.y = y;
178 }
179
180 void actions_run_acts(GSList *acts,
181                       ObUserAction uact,
182                       Time time,
183                       guint state,
184                       guint button,
185                       gint x,
186                       gint y,
187                       ObFrameContext con,
188                       struct _ObClient *client,
189                       ObActionsInteractiveState interactive)
190 {
191     GSList *it;
192
193     for (it = acts; it; it = g_slist_next(it)) {
194         ObActionsData data;
195         ObActionsAct *act = it->data;
196
197         data.type = act->def->type;
198         actions_setup_data(&data, uact, time, state, button, x, y);
199         switch (data.type) {
200         case OB_ACTION_TYPE_GLOBAL:
201             break;
202         case OB_ACTION_TYPE_CLIENT:
203             data.client.context = con;
204             data.client.c = client;
205             break;
206         case OB_ACTION_TYPE_SELECTOR:
207             data.selector.interactive = interactive;
208             break;
209         default:
210             g_assert_not_reached();
211         }
212
213         /* fire the action's run function with this data */
214         act->def->run(&data, act->options);
215     }
216 }