ce035cbf87ed11ca49c67c269c741ae430353f36
1 /* Copyright (c) 2008 Sadrul Habib Chowdhury (sadrul@users.sf.net)
2 * 2009 Rui Guo (firemeteor.guo@gmail.com)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3, or (at your option)
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program (see the file COPYING); if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
19 ****************************************************************
27 /*Binding structure & functions*/
29 struct binding
*bindings
= NULL
;
32 register_binding (struct binding
*new_binding
)
34 if (!new_binding
->registered
)
36 new_binding
->b_next
= bindings
;
37 bindings
= new_binding
;
38 new_binding
->registered
= 1;
43 extern struct binding lua_binding
;
46 void LoadBindings(void)
49 register_binding(&lua_binding
);
54 FinalizeBindings (void)
56 struct binding
*binding
=bindings
;
61 binding
= binding
->b_next
;
66 ScriptSource(int argc
, const char **argv
)
70 const char *bd_select
= 0, *script
;
71 struct binding
*binding
= bindings
;
73 /* Parse the commandline options
74 * script source [-async|-a] [-binding|-b <binding>] script
76 while (*argv
&& **argv
== '-')
78 /* check for (-a | -async) */
79 const char *arg
= *argv
;
80 if ((arg
[1] == 'a' && !arg
[2])
81 || strcmp(arg
, "-async") == 0)
83 /* check for (-b | -binding) */
84 else if ((arg
[1] == 'b' && !arg
[2])
85 || strcmp(arg
, "-binding") == 0)
96 if (!bd_select
|| strcmp(bd_select
, binding
->name
) == 0)
98 /*dynamically initialize the binding*/
105 /*and source the script*/
106 ret
= binding
->bd_Source(script
, async
);
110 binding
= binding
->b_next
;
113 LMsg(0, "Could not source specified script %s", script
);
117 ScriptCall(int argc
, const char **argv
)
120 struct binding
*binding
= bindings
;
121 const char *bd_select
= 0, *func
;
122 /* Parse the commandline options
123 * script call [-binding|-b <binding>] function
125 while (*argv
&& **argv
== '-')
127 const char *arg
= *argv
;
128 /* check for (-b | -binding) */
129 if ((arg
[1] == 'b' && !arg
[2])
130 || strcmp(arg
, "-binding") == 0)
142 if (!bd_select
|| strcmp(bd_select
, binding
->name
) == 0)
144 ret
= binding
->bd_call(func
, argv
);
148 binding
= binding
->b_next
;
152 LMsg(0, "Failed to run specified script coummand '%s'", func
);
157 ScriptCmd(int argc
, const char **argv
)
159 const char * sub
= *argv
;
161 if (!strcmp(sub
, "call"))
162 ScriptCall(argc
, argv
);
163 else if (!strcmp(sub
, "source"))
164 ScriptSource(argc
, argv
);
167 /* Event notification handling */
169 struct gevents globalevents
;
171 /* To add a new event, introduce a field for that event to the object in
172 * question, and don't forget to put an descriptor here. NOTE: keep the
173 * name field sorted in alphabet order, the searching relies on it.
175 * the params string specifies the expected parameters. The length of the
176 * string equals to the number of parameters. Each char specifies the type of
177 * the parameter, with its meaning similar to those in printf().
180 * S: string array (char **)
186 struct sev_description
{
191 /* NOTE: Manually sorted in Alphabet order! */
194 {"display_onidle", "d", offsetof(struct display
, d_sev
.onidle
)},
196 {"global_cmdexecuted", "sS", offsetof(struct gevents
, cmdexecuted
)},
197 {"global_detached", "di", offsetof(struct gevents
, detached
)},
198 /* The command "detach" triggers both 'cmdexecuted' and 'detached' events.
199 However, we need the 'detached' event to trigger callbacks from remote detaches.
201 /* fore window changed to window w on display d. */
202 {"global_forechanged", "dw", offsetof(struct gevents
, forechanged
)},
203 {"global_onattach", "d", offsetof(struct gevents
, onattach
)},
204 {"global_processcaption", "c", offsetof(struct gevents
, processcaption
)},
207 {"window_can_resize", "", offsetof(struct win
, w_sev
.canresize
)},
208 {"window_onfocus", "dw", offsetof(struct win
, w_sev
.onfocus
)},
209 /* last view of window w disappeared on display d. */
210 {"window_onhide", "dw", offsetof(struct win
, w_sev
.onhide
)},
211 /* window w lost its focus on display d. */
212 {"window_onleave", "dw", offsetof(struct win
, w_sev
.onleave
)},
213 {"window_onresize", "w", offsetof(struct win
, w_sev
.onresize
)},
214 /* window w first showed up on display d. When there are regions, it can
215 * still be shown while losing focus. */
216 {"window_onshow", "dw", offsetof(struct win
, w_sev
.onshow
)},
219 /* Get the event queue with the given name in the obj. If the obj is NULL,
220 * global events are searched. If no event is found, a NULL is returned.
222 struct script_event
*
223 object_get_event(char *obj
, const char *name
)
227 obj
= (char *)&globalevents
;
230 n
= hi
= sizeof(event_table
) / sizeof(struct sev_description
);
234 half
= (lo
+ hi
) >> 1;
235 cmp
= strcmp(name
, event_table
[half
].name
);
242 if (lo
>= n
|| strcmp(name
, event_table
[lo
].name
))
247 struct script_event
*res
;
248 res
= (struct script_event
*) (obj
+ event_table
[lo
].offset
);
249 /*Setup the parameter record.*/
250 res
->params
= event_table
[lo
].params
;
255 /* Put a listener in a proper position in the chain
256 * according to the privlege.
257 * Not insert duplicate entry. return zero if successful.*/
259 register_listener(struct script_event
*ev
, struct listener
*l
)
261 unsigned int priv
= l
->priv
;
262 struct listener
*p
, *iter
= &ev
->listeners
;
264 while(iter
->chain
&& priv
>= iter
->chain
->priv
)
279 unregister_listener(struct listener
*l
)
281 struct listener
*p
= l
->prev
;
285 l
->chain
= l
->prev
= 0;
290 /* Trigger event with given parameters.*/
292 trigger_sevent(struct script_event
*ev
, VA_DOTS
)
295 struct listener
*chain
;
298 /*invalid or un-registered event structure*/
299 if (!ev
|| !ev
->params
)
302 /*process the chain in order, stop if any of the handler returns true.*/
303 chain
= ev
->listeners
.chain
;
308 res
= chain
->bd
->bd_dispatch(chain
->handler
, params
, va
);
312 chain
= chain
->chain
;
318 #define ALL_SCRIPTS(fn, params, stop) do { \
319 struct binding *iter; \
320 for (iter = bindings; iter; iter = iter->b_next) \
322 if (iter->fns && iter->fns->fn && (ret = (iter->fns->fn params)) && stop) \
327 /* Broker functions */
330 struct broker
*b_hash
[255];
332 #define DELETED ((struct broker*)1)
333 #define BHASH(o) (((int)(o) >> sizeof(struct broker *)) & 255)
334 struct broker
**broker_from_obj(void *obj
)
336 struct broker
**bucket
= b_hash
+ BHASH(obj
);
337 while (*bucket
&& (*bucket
)->obj
!= obj
)
339 bucket
= &(*bucket
)->b_next
;
345 get_obj_broker(void *obj
)
347 struct broker
**bucket
= broker_from_obj(obj
);
351 /* Not found, allocate a new one */
354 struct broker
*tmp
= (struct broker
*)malloc(sizeof(struct broker
));
369 void * get_broker_obj(struct broker
*broker
)
374 if (--broker
->ref
== 0)
376 struct broker
**b
= broker_from_obj(broker
->obj
);
382 void broker_inv_obj(void *obj
)
384 struct broker
**b
= broker_from_obj(obj
);