1 /*
2  * This file is part of libdom.
3  * Licensed under the MIT License,
4  *                http://www.opensource.org/licenses/mit-license.php
5  * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
6  */
7 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "events/mouse_event.h"
12 #include "core/document.h"
13 
14 #include "utils/utils.h"
15 
16 static void _virtual_dom_mouse_event_destroy(struct dom_event *evt);
17 
18 static struct dom_event_private_vtable _event_vtable = {
19 	_virtual_dom_mouse_event_destroy
20 };
21 
22 /* Constructor */
_dom_mouse_event_create(struct dom_mouse_event ** evt)23 dom_exception _dom_mouse_event_create(struct dom_mouse_event **evt)
24 {
25 	*evt = malloc(sizeof(dom_mouse_event));
26 	if (*evt == NULL)
27 		return DOM_NO_MEM_ERR;
28 
29 	((struct dom_event *) *evt)->vtable = &_event_vtable;
30 
31 	return _dom_mouse_event_initialise(*evt);
32 }
33 
34 /* Destructor */
_dom_mouse_event_destroy(struct dom_mouse_event * evt)35 void _dom_mouse_event_destroy(struct dom_mouse_event *evt)
36 {
37 	_dom_mouse_event_finalise((dom_ui_event *) evt);
38 
39 	free(evt);
40 }
41 
42 /* Initialise function */
_dom_mouse_event_initialise(struct dom_mouse_event * evt)43 dom_exception _dom_mouse_event_initialise(struct dom_mouse_event *evt)
44 {
45 	evt->modifier_state = 0;
46 
47 	return _dom_ui_event_initialise((dom_ui_event *) evt);
48 }
49 
50 /* The virtual destroy function */
_virtual_dom_mouse_event_destroy(struct dom_event * evt)51 void _virtual_dom_mouse_event_destroy(struct dom_event *evt)
52 {
53 	_dom_mouse_event_destroy((dom_mouse_event *) evt);
54 }
55 
56 /*----------------------------------------------------------------------*/
57 /* The public API */
58 
59 /**
60  * Get screenX
61  *
62  * \param evt  The Event object
63  * \param x    The returned screenX
64  * \return DOM_NO_ERR.
65  */
_dom_mouse_event_get_screen_x(dom_mouse_event * evt,int32_t * x)66 dom_exception _dom_mouse_event_get_screen_x(dom_mouse_event *evt,
67 		int32_t *x)
68 {
69 	*x = evt->sx;
70 
71 	return DOM_NO_ERR;
72 }
73 
74 /**
75  * Get screenY
76  *
77  * \param evt  The Event object
78  * \param y    The returned screenY
79  * \return DOM_NO_ERR.
80  */
_dom_mouse_event_get_screen_y(dom_mouse_event * evt,int32_t * y)81 dom_exception _dom_mouse_event_get_screen_y(dom_mouse_event *evt,
82 		int32_t *y)
83 {
84 	*y = evt->sy;
85 
86 	return DOM_NO_ERR;
87 }
88 
89 /**
90  * Get clientX
91  *
92  * \param evt  The Event object
93  * \param x    The returned clientX
94  * \return DOM_NO_ERR.
95  */
_dom_mouse_event_get_client_x(dom_mouse_event * evt,int32_t * x)96 dom_exception _dom_mouse_event_get_client_x(dom_mouse_event *evt,
97 		int32_t *x)
98 {
99 	*x = evt->cx;
100 
101 	return DOM_NO_ERR;
102 }
103 
104 /**
105  * Get clientY
106  *
107  * \param evt  The Event object
108  * \param y    The returned clientY
109  * \return DOM_NO_ERR.
110  */
_dom_mouse_event_get_client_y(dom_mouse_event * evt,int32_t * y)111 dom_exception _dom_mouse_event_get_client_y(dom_mouse_event *evt,
112 		int32_t *y)
113 {
114 	*y = evt->cy;
115 
116 	return DOM_NO_ERR;
117 }
118 
119 /**
120  * Get the ctrl key state
121  *
122  * \param evt  The Event object
123  * \param key  Whether the Control key is pressed down
124  * \return DOM_NO_ERR.
125  */
_dom_mouse_event_get_ctrl_key(dom_mouse_event * evt,bool * key)126 dom_exception _dom_mouse_event_get_ctrl_key(dom_mouse_event *evt,
127 		bool *key)
128 {
129 	*key = ((evt->modifier_state & DOM_MOD_CTRL) != 0);
130 
131 	return DOM_NO_ERR;
132 }
133 
134 /**
135  * Get the shift key state
136  *
137  * \param evt  The Event object
138  * \param key  Whether the Shift key is pressed down
139  * \return DOM_NO_ERR.
140  */
_dom_mouse_event_get_shift_key(dom_mouse_event * evt,bool * key)141 dom_exception _dom_mouse_event_get_shift_key(dom_mouse_event *evt,
142 		bool *key)
143 {
144 	*key = ((evt->modifier_state & DOM_MOD_SHIFT) != 0);
145 
146 	return DOM_NO_ERR;
147 }
148 
149 /**
150  * Get the alt key state
151  *
152  * \param evt  The Event object
153  * \param key  Whether the Alt key is pressed down
154  * \return DOM_NO_ERR.
155  */
_dom_mouse_event_get_alt_key(dom_mouse_event * evt,bool * key)156 dom_exception _dom_mouse_event_get_alt_key(dom_mouse_event *evt,
157 		bool *key)
158 {
159 	*key = ((evt->modifier_state & DOM_MOD_ALT) != 0);
160 
161 	return DOM_NO_ERR;
162 }
163 
164 /**
165  * Get the meta key state
166  *
167  * \param evt  The Event object
168  * \param key  Whether the Meta key is pressed down
169  * \return DOM_NO_ERR.
170  */
_dom_mouse_event_get_meta_key(dom_mouse_event * evt,bool * key)171 dom_exception _dom_mouse_event_get_meta_key(dom_mouse_event *evt,
172 		bool *key)
173 {
174 	*key = ((evt->modifier_state & DOM_MOD_META) != 0);
175 
176 	return DOM_NO_ERR;
177 }
178 
179 /**
180  * Get the button which get pressed
181  *
182  * \param evt     The Event object
183  * \param button  The pressed mouse button
184  * \return DOM_NO_ERR.
185  */
_dom_mouse_event_get_button(dom_mouse_event * evt,unsigned short * button)186 dom_exception _dom_mouse_event_get_button(dom_mouse_event *evt,
187 		unsigned short *button)
188 {
189 	*button = evt->button;
190 
191 	return DOM_NO_ERR;
192 }
193 
194 /**
195  * Get the related target
196  *
197  * \param evt  The Event object
198  * \param et   The related EventTarget
199  * \return DOM_NO_ERR.
200  */
_dom_mouse_event_get_related_target(dom_mouse_event * evt,dom_event_target ** et)201 dom_exception _dom_mouse_event_get_related_target(dom_mouse_event *evt,
202 		dom_event_target **et)
203 {
204 	*et = evt->related_target;
205 
206 	return DOM_NO_ERR;
207 }
208 
209 /**
210  * Query the state of a modifier using a key identifier
211  *
212  * \param evt    The event object
213  * \param ml     The modifier identifier, such as "Alt", "Control", "Meta",
214  *               "AltGraph", "CapsLock", "NumLock", "Scroll", "Shift".
215  * \param state  Whether the modifier key is pressed
216  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
217  *
218  * @note: If an application wishes to distinguish between right and left
219  * modifiers, this information could be deduced using keyboard events and
220  * KeyboardEvent.keyLocation.
221  */
_dom_mouse_event_get_modifier_state(dom_mouse_event * evt,dom_string * m,bool * state)222 dom_exception _dom_mouse_event_get_modifier_state(dom_mouse_event *evt,
223 		dom_string *m, bool *state)
224 {
225 	const char *data;
226 	size_t len;
227 
228 	if (m == NULL) {
229 		*state = false;
230 		return DOM_NO_ERR;
231 	}
232 
233 	data = dom_string_data(m);
234 	len = dom_string_byte_length(m);
235 
236 	if (len == SLEN("AltGraph") && strncmp(data, "AltGraph", len) == 0) {
237 		*state = ((evt->modifier_state & DOM_MOD_ALT_GRAPH) != 0);
238 	} else if (len == SLEN("Alt") && strncmp(data, "Alt", len) == 0) {
239 		*state = ((evt->modifier_state & DOM_MOD_ALT) != 0);
240 	} else if (len == SLEN("CapsLock") &&
241 			strncmp(data, "CapsLock", len) == 0) {
242 		*state = ((evt->modifier_state & DOM_MOD_CAPS_LOCK) != 0);
243 	} else if (len == SLEN("Control") &&
244 			strncmp(data, "Control", len) == 0) {
245 		*state = ((evt->modifier_state & DOM_MOD_CTRL) != 0);
246 	} else if (len == SLEN("Meta") && strncmp(data, "Meta", len) == 0) {
247 		*state = ((evt->modifier_state & DOM_MOD_META) != 0);
248 	} else if (len == SLEN("NumLock") &&
249 			strncmp(data, "NumLock", len) == 0) {
250 		*state = ((evt->modifier_state & DOM_MOD_NUM_LOCK) != 0);
251 	} else if (len == SLEN("Scroll") &&
252 			strncmp(data, "Scroll", len) == 0) {
253 		*state = ((evt->modifier_state & DOM_MOD_SCROLL) != 0);
254 	} else if (len == SLEN("Shift") && strncmp(data, "Shift", len) == 0) {
255 		*state = ((evt->modifier_state & DOM_MOD_SHIFT) != 0);
256 	}
257 
258 	return DOM_NO_ERR;
259 }
260 
261 /**
262  * Initialise this mouse event
263  *
264  * \param evt         The Event object
265  * \param type        The event's type
266  * \param bubble      Whether this is a bubbling event
267  * \param cancelable  Whether this is a cancelable event
268  * \param view        The AbstractView associated with this event
269  * \param detail      The detail information of this mouse event
270  * \param screen_x    The x position of the mouse pointer in screen
271  * \param screen_y    The y position of the mouse pointer in screen
272  * \param client_x    The x position of the mouse pointer in client window
273  * \param client_y    The y position of the mouse pointer in client window
274  * \param alt         The state of Alt key, true for pressed, false otherwise
275  * \param shift       The state of Shift key, true for pressed, false otherwise
276  * \param mata        The state of Meta key, true for pressed, false otherwise
277  * \param button      The mouse button pressed
278  * \param et          The related target of this event, may be NULL
279  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
280  */
_dom_mouse_event_init(dom_mouse_event * evt,dom_string * type,bool bubble,bool cancelable,struct dom_abstract_view * view,int32_t detail,int32_t screen_x,int32_t screen_y,int32_t client_x,int32_t client_y,bool ctrl,bool alt,bool shift,bool meta,unsigned short button,dom_event_target * et)281 dom_exception _dom_mouse_event_init(dom_mouse_event *evt,
282 		dom_string *type, bool bubble, bool cancelable,
283 		struct dom_abstract_view *view, int32_t detail, int32_t screen_x,
284 		int32_t screen_y, int32_t client_x, int32_t client_y, bool ctrl,
285 		bool alt, bool shift, bool meta, unsigned short button,
286 		dom_event_target *et)
287 {
288 	evt->sx = screen_x;
289 	evt->sy = screen_y;
290 	evt->cx = client_x;
291 	evt->cy = client_y;
292 
293 	evt->modifier_state = 0;
294 	if (ctrl == true) {
295 		evt->modifier_state = evt->modifier_state | DOM_MOD_CTRL;
296 	}
297 	if (alt == true) {
298 		evt->modifier_state = evt->modifier_state | DOM_MOD_ALT;
299 	}
300 	if (shift == true) {
301 		evt->modifier_state = evt->modifier_state | DOM_MOD_SHIFT;
302 	}
303 	if (meta == true) {
304 		evt->modifier_state = evt->modifier_state | DOM_MOD_META;
305 	}
306 
307 	evt->button = button;
308 	evt->related_target = et;
309 
310 	return _dom_ui_event_init(&evt->base, type, bubble, cancelable, view,
311 			detail);
312 }
313 
314 /**
315  * Initialise the event with namespace
316  *
317  * \param evt         The Event object
318  * \param namespace   The namespace of this event
319  * \param type        The event's type
320  * \param bubble      Whether this is a bubbling event
321  * \param cancelable  Whether this is a cancelable event
322  * \param view        The AbstractView associated with this event
323  * \param detail      The detail information of this mouse event
324  * \param screen_x    The x position of the mouse pointer in screen
325  * \param screen_y    The y position of the mouse pointer in screen
326  * \param client_x    The x position of the mouse pointer in client window
327  * \param client_y    The y position of the mouse pointer in client window
328  * \param alt         The state of Alt key, true for pressed, false otherwise
329  * \param shift       The state of Shift key, true for pressed, false otherwise
330  * \param mata        The state of Meta key, true for pressed, false otherwise
331  * \param button      The mouse button pressed
332  * \param et          The related target of this event, may be NULL
333  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
334  */
_dom_mouse_event_init_ns(dom_mouse_event * evt,dom_string * namespace,dom_string * type,bool bubble,bool cancelable,struct dom_abstract_view * view,int32_t detail,int32_t screen_x,int32_t screen_y,int32_t client_x,int32_t client_y,bool ctrl,bool alt,bool shift,bool meta,unsigned short button,dom_event_target * et)335 dom_exception _dom_mouse_event_init_ns(dom_mouse_event *evt,
336 		dom_string *namespace, dom_string *type,
337 		bool bubble, bool cancelable, struct dom_abstract_view *view,
338 		int32_t detail, int32_t screen_x, int32_t screen_y, int32_t client_x,
339 		int32_t client_y, bool ctrl, bool alt, bool shift, bool meta,
340 		unsigned short button, dom_event_target *et)
341 {
342 	evt->sx = screen_x;
343 	evt->sy = screen_y;
344 	evt->cx = client_x;
345 	evt->cy = client_y;
346 
347 	evt->modifier_state = 0;
348 	if (ctrl == true) {
349 		evt->modifier_state = evt->modifier_state | DOM_MOD_CTRL;
350 	}
351 	if (alt == true) {
352 		evt->modifier_state = evt->modifier_state | DOM_MOD_ALT;
353 	}
354 	if (shift == true) {
355 		evt->modifier_state = evt->modifier_state | DOM_MOD_SHIFT;
356 	}
357 	if (meta == true) {
358 		evt->modifier_state = evt->modifier_state | DOM_MOD_META;
359 	}
360 
361 	evt->button = button;
362 	evt->related_target = et;
363 
364 	return _dom_ui_event_init_ns(&evt->base, namespace, type, bubble,
365 			cancelable, view, detail);
366 }
367 
368