win32u: Don't report cloned monitors in EnumDisplayMonitors().
[wine.git] / dlls / winemac.drv / event.c
blobd76c6ee8edbd8d189e9562d1a1362dec987245f4
1 /*
2 * MACDRV event driver
4 * Copyright 1993 Alexandre Julliard
5 * 1999 Noel Borthwick
6 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #if 0
24 #pragma makedep unix
25 #endif
27 #include "config.h"
29 #include "macdrv.h"
30 #include "oleidl.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(event);
33 WINE_DECLARE_DEBUG_CHANNEL(imm);
36 /* return the name of an Mac event */
37 static const char *dbgstr_event(int type)
39 static const char * const event_names[] = {
40 "APP_ACTIVATED",
41 "APP_DEACTIVATED",
42 "APP_QUIT_REQUESTED",
43 "DISPLAYS_CHANGED",
44 "HOTKEY_PRESS",
45 "IM_SET_TEXT",
46 "KEY_PRESS",
47 "KEY_RELEASE",
48 "KEYBOARD_CHANGED",
49 "LOST_PASTEBOARD_OWNERSHIP",
50 "MOUSE_BUTTON",
51 "MOUSE_MOVED_RELATIVE",
52 "MOUSE_MOVED_ABSOLUTE",
53 "MOUSE_SCROLL",
54 "QUERY_EVENT",
55 "QUERY_EVENT_NO_PREEMPT_WAIT",
56 "REASSERT_WINDOW_POSITION",
57 "RELEASE_CAPTURE",
58 "SENT_TEXT_INPUT",
59 "STATUS_ITEM_MOUSE_BUTTON",
60 "STATUS_ITEM_MOUSE_MOVE",
61 "WINDOW_BROUGHT_FORWARD",
62 "WINDOW_CLOSE_REQUESTED",
63 "WINDOW_DID_UNMINIMIZE",
64 "WINDOW_DRAG_BEGIN",
65 "WINDOW_DRAG_END",
66 "WINDOW_FRAME_CHANGED",
67 "WINDOW_GOT_FOCUS",
68 "WINDOW_LOST_FOCUS",
69 "WINDOW_MAXIMIZE_REQUESTED",
70 "WINDOW_MINIMIZE_REQUESTED",
71 "WINDOW_RESIZE_ENDED",
72 "WINDOW_RESTORE_REQUESTED",
75 if (0 <= type && type < NUM_EVENT_TYPES) return event_names[type];
76 return wine_dbg_sprintf("Unknown event %d", type);
80 /***********************************************************************
81 * get_event_mask
83 static macdrv_event_mask get_event_mask(DWORD mask)
85 macdrv_event_mask event_mask = 0;
87 if ((mask & QS_ALLINPUT) == QS_ALLINPUT) return -1;
89 if (mask & QS_HOTKEY)
90 event_mask |= event_mask_for_type(HOTKEY_PRESS);
92 if (mask & QS_KEY)
94 event_mask |= event_mask_for_type(KEY_PRESS);
95 event_mask |= event_mask_for_type(KEY_RELEASE);
96 event_mask |= event_mask_for_type(KEYBOARD_CHANGED);
99 if (mask & QS_MOUSEBUTTON)
101 event_mask |= event_mask_for_type(MOUSE_BUTTON);
102 event_mask |= event_mask_for_type(MOUSE_SCROLL);
105 if (mask & QS_MOUSEMOVE)
107 event_mask |= event_mask_for_type(MOUSE_MOVED_RELATIVE);
108 event_mask |= event_mask_for_type(MOUSE_MOVED_ABSOLUTE);
111 if (mask & QS_POSTMESSAGE)
113 event_mask |= event_mask_for_type(APP_ACTIVATED);
114 event_mask |= event_mask_for_type(APP_DEACTIVATED);
115 event_mask |= event_mask_for_type(APP_QUIT_REQUESTED);
116 event_mask |= event_mask_for_type(DISPLAYS_CHANGED);
117 event_mask |= event_mask_for_type(IM_SET_TEXT);
118 event_mask |= event_mask_for_type(LOST_PASTEBOARD_OWNERSHIP);
119 event_mask |= event_mask_for_type(STATUS_ITEM_MOUSE_BUTTON);
120 event_mask |= event_mask_for_type(STATUS_ITEM_MOUSE_MOVE);
121 event_mask |= event_mask_for_type(WINDOW_DID_UNMINIMIZE);
122 event_mask |= event_mask_for_type(WINDOW_FRAME_CHANGED);
123 event_mask |= event_mask_for_type(WINDOW_GOT_FOCUS);
124 event_mask |= event_mask_for_type(WINDOW_LOST_FOCUS);
127 if (mask & QS_SENDMESSAGE)
129 event_mask |= event_mask_for_type(QUERY_EVENT);
130 event_mask |= event_mask_for_type(QUERY_EVENT_NO_PREEMPT_WAIT);
131 event_mask |= event_mask_for_type(REASSERT_WINDOW_POSITION);
132 event_mask |= event_mask_for_type(RELEASE_CAPTURE);
133 event_mask |= event_mask_for_type(SENT_TEXT_INPUT);
134 event_mask |= event_mask_for_type(WINDOW_BROUGHT_FORWARD);
135 event_mask |= event_mask_for_type(WINDOW_CLOSE_REQUESTED);
136 event_mask |= event_mask_for_type(WINDOW_DRAG_BEGIN);
137 event_mask |= event_mask_for_type(WINDOW_DRAG_END);
138 event_mask |= event_mask_for_type(WINDOW_MAXIMIZE_REQUESTED);
139 event_mask |= event_mask_for_type(WINDOW_MINIMIZE_REQUESTED);
140 event_mask |= event_mask_for_type(WINDOW_RESIZE_ENDED);
141 event_mask |= event_mask_for_type(WINDOW_RESTORE_REQUESTED);
144 return event_mask;
148 /***********************************************************************
149 * macdrv_im_set_text
151 static void macdrv_im_set_text(const macdrv_event *event)
153 HWND hwnd = macdrv_get_window_hwnd(event->window);
154 struct ime_set_text_params *params;
155 CFIndex length = 0, size;
157 TRACE_(imm)("win %p/%p himc %p text %s complete %u\n", hwnd, event->window, event->im_set_text.data,
158 debugstr_cf(event->im_set_text.text), event->im_set_text.complete);
160 if (event->im_set_text.text)
161 length = CFStringGetLength(event->im_set_text.text);
163 size = offsetof(struct ime_set_text_params, text[length]);
164 if (!(params = malloc(size))) return;
165 params->hwnd = hwnd;
166 params->data = event->im_set_text.data;
167 params->cursor_pos = event->im_set_text.cursor_pos;
168 params->complete = event->im_set_text.complete;
170 if (length)
171 CFStringGetCharacters(event->im_set_text.text, CFRangeMake(0, length), params->text);
173 macdrv_client_func(client_func_ime_set_text, params, size);
176 /***********************************************************************
177 * macdrv_sent_text_input
179 static void macdrv_sent_text_input(const macdrv_event *event)
181 TRACE_(imm)("handled: %s\n", event->sent_text_input.handled ? "TRUE" : "FALSE");
182 *event->sent_text_input.done = event->sent_text_input.handled ? 1 : -1;
186 /**************************************************************************
187 * drag_operations_to_dropeffects
189 static DWORD drag_operations_to_dropeffects(uint32_t ops)
191 DWORD effects = 0;
192 if (ops & (DRAG_OP_COPY | DRAG_OP_GENERIC))
193 effects |= DROPEFFECT_COPY;
194 if (ops & DRAG_OP_MOVE)
195 effects |= DROPEFFECT_MOVE;
196 if (ops & (DRAG_OP_LINK | DRAG_OP_GENERIC))
197 effects |= DROPEFFECT_LINK;
198 return effects;
202 /**************************************************************************
203 * dropeffect_to_drag_operation
205 static uint32_t dropeffect_to_drag_operation(DWORD effect, uint32_t ops)
207 if (effect & DROPEFFECT_LINK && ops & DRAG_OP_LINK) return DRAG_OP_LINK;
208 if (effect & DROPEFFECT_COPY && ops & DRAG_OP_COPY) return DRAG_OP_COPY;
209 if (effect & DROPEFFECT_MOVE && ops & DRAG_OP_MOVE) return DRAG_OP_MOVE;
210 if (effect & DROPEFFECT_LINK && ops & DRAG_OP_GENERIC) return DRAG_OP_GENERIC;
211 if (effect & DROPEFFECT_COPY && ops & DRAG_OP_GENERIC) return DRAG_OP_GENERIC;
213 return DRAG_OP_NONE;
217 /**************************************************************************
218 * query_drag_drop
220 static BOOL query_drag_drop(macdrv_query *query)
222 HWND hwnd = macdrv_get_window_hwnd(query->window);
223 struct macdrv_win_data *data = get_win_data(hwnd);
224 struct dnd_query_drop_params params;
226 if (!data)
228 WARN("no win_data for win %p/%p\n", hwnd, query->window);
229 return FALSE;
232 params.hwnd = hwnd;
233 params.effect = drag_operations_to_dropeffects(query->drag_drop.op);
234 params.x = query->drag_drop.x + data->whole_rect.left;
235 params.y = query->drag_drop.y + data->whole_rect.top;
236 params.handle = (UINT_PTR)query->drag_drop.pasteboard;
237 release_win_data(data);
238 return macdrv_client_func(client_func_dnd_query_drop, &params, sizeof(params));
241 /**************************************************************************
242 * query_drag_exited
244 static BOOL query_drag_exited(macdrv_query *query)
246 struct dnd_query_exited_params params;
247 params.hwnd = macdrv_get_window_hwnd(query->window);
248 return macdrv_client_func(client_func_dnd_query_exited, &params, sizeof(params));
252 /**************************************************************************
253 * query_drag_operation
255 static BOOL query_drag_operation(macdrv_query *query)
257 struct dnd_query_drag_params params;
258 HWND hwnd = macdrv_get_window_hwnd(query->window);
259 struct macdrv_win_data *data = get_win_data(hwnd);
260 DWORD effect;
262 if (!data)
264 WARN("no win_data for win %p/%p\n", hwnd, query->window);
265 return FALSE;
268 params.hwnd = hwnd;
269 params.effect = drag_operations_to_dropeffects(query->drag_operation.offered_ops);
270 params.x = query->drag_operation.x + data->whole_rect.left;
271 params.y = query->drag_operation.y + data->whole_rect.top;
272 params.handle = (UINT_PTR)query->drag_operation.pasteboard;
273 release_win_data(data);
275 effect = macdrv_client_func(client_func_dnd_query_drag, &params, sizeof(params));
276 if (!effect) return FALSE;
278 query->drag_operation.accepted_op = dropeffect_to_drag_operation(effect,
279 query->drag_operation.offered_ops);
280 return TRUE;
284 /**************************************************************************
285 * query_ime_char_rect
287 BOOL query_ime_char_rect(macdrv_query* query)
289 HWND hwnd = macdrv_get_window_hwnd(query->window);
290 void *himc = query->ime_char_rect.data;
291 CFRange *range = &query->ime_char_rect.range;
292 CGRect *rect = &query->ime_char_rect.rect;
293 struct ime_query_char_rect_result result = {0};
294 struct ime_query_char_rect_params params;
295 BOOL ret;
297 TRACE_(imm)("win %p/%p himc %p range %ld-%ld\n", hwnd, query->window, himc, range->location,
298 range->length);
300 params.hwnd = hwnd;
301 params.data = himc;
302 params.result = &result;
303 params.location = range->location;
304 params.length = range->length;
305 ret = macdrv_client_func(client_func_ime_query_char_rect, &params, sizeof(params));
306 *range = CFRangeMake(result.location, result.length);
307 *rect = cgrect_from_rect(result.rect);
309 TRACE_(imm)(" -> %s range %ld-%ld rect %s\n", ret ? "TRUE" : "FALSE", range->location,
310 range->length, wine_dbgstr_cgrect(*rect));
312 return ret;
316 /***********************************************************************
317 * macdrv_query_event
319 * Handler for QUERY_EVENT and QUERY_EVENT_NO_PREEMPT_WAIT queries.
321 static void macdrv_query_event(HWND hwnd, const macdrv_event *event)
323 BOOL success = FALSE;
324 macdrv_query *query = event->query_event.query;
326 switch (query->type)
328 case QUERY_DRAG_DROP:
329 TRACE("QUERY_DRAG_DROP\n");
330 success = query_drag_drop(query);
331 break;
332 case QUERY_DRAG_EXITED:
333 TRACE("QUERY_DRAG_EXITED\n");
334 success = query_drag_exited(query);
335 break;
336 case QUERY_DRAG_OPERATION:
337 TRACE("QUERY_DRAG_OPERATION\n");
338 success = query_drag_operation(query);
339 break;
340 case QUERY_IME_CHAR_RECT:
341 TRACE("QUERY_IME_CHAR_RECT\n");
342 success = query_ime_char_rect(query);
343 break;
344 case QUERY_PASTEBOARD_DATA:
345 TRACE("QUERY_PASTEBOARD_DATA\n");
346 success = query_pasteboard_data(hwnd, query->pasteboard_data.type);
347 break;
348 case QUERY_RESIZE_SIZE:
349 TRACE("QUERY_RESIZE_SIZE\n");
350 success = query_resize_size(hwnd, query);
351 break;
352 case QUERY_RESIZE_START:
353 TRACE("QUERY_RESIZE_START\n");
354 success = query_resize_start(hwnd);
355 break;
356 case QUERY_MIN_MAX_INFO:
357 TRACE("QUERY_MIN_MAX_INFO\n");
358 success = query_min_max_info(hwnd);
359 break;
360 default:
361 FIXME("unrecognized query type %d\n", query->type);
362 break;
365 TRACE("success %d\n", success);
366 query->status = success;
367 macdrv_set_query_done(query);
371 /***********************************************************************
372 * macdrv_handle_event
374 void macdrv_handle_event(const macdrv_event *event)
376 HWND hwnd = macdrv_get_window_hwnd(event->window);
377 const macdrv_event *prev;
378 struct macdrv_thread_data *thread_data = macdrv_thread_data();
380 TRACE("%s for hwnd/window %p/%p\n", dbgstr_event(event->type), hwnd,
381 event->window);
383 prev = thread_data->current_event;
384 thread_data->current_event = event;
386 switch (event->type)
388 case APP_ACTIVATED:
389 macdrv_app_activated();
390 break;
391 case APP_DEACTIVATED:
392 macdrv_app_deactivated();
393 break;
394 case APP_QUIT_REQUESTED:
395 macdrv_app_quit_requested(event);
396 break;
397 case DISPLAYS_CHANGED:
398 macdrv_displays_changed(event);
399 break;
400 case HOTKEY_PRESS:
401 macdrv_hotkey_press(event);
402 break;
403 case IM_SET_TEXT:
404 macdrv_im_set_text(event);
405 break;
406 case KEY_PRESS:
407 case KEY_RELEASE:
408 macdrv_key_event(hwnd, event);
409 break;
410 case KEYBOARD_CHANGED:
411 macdrv_keyboard_changed(event);
412 break;
413 case LOST_PASTEBOARD_OWNERSHIP:
414 macdrv_lost_pasteboard_ownership(hwnd);
415 break;
416 case MOUSE_BUTTON:
417 macdrv_mouse_button(hwnd, event);
418 break;
419 case MOUSE_MOVED_RELATIVE:
420 case MOUSE_MOVED_ABSOLUTE:
421 macdrv_mouse_moved(hwnd, event);
422 break;
423 case MOUSE_SCROLL:
424 macdrv_mouse_scroll(hwnd, event);
425 break;
426 case QUERY_EVENT:
427 case QUERY_EVENT_NO_PREEMPT_WAIT:
428 macdrv_query_event(hwnd, event);
429 break;
430 case REASSERT_WINDOW_POSITION:
431 macdrv_reassert_window_position(hwnd);
432 break;
433 case RELEASE_CAPTURE:
434 macdrv_release_capture(hwnd, event);
435 break;
436 case SENT_TEXT_INPUT:
437 macdrv_sent_text_input(event);
438 break;
439 case STATUS_ITEM_MOUSE_BUTTON:
440 macdrv_status_item_mouse_button(event);
441 break;
442 case STATUS_ITEM_MOUSE_MOVE:
443 macdrv_status_item_mouse_move(event);
444 break;
445 case WINDOW_BROUGHT_FORWARD:
446 macdrv_window_brought_forward(hwnd);
447 break;
448 case WINDOW_CLOSE_REQUESTED:
449 macdrv_window_close_requested(hwnd);
450 break;
451 case WINDOW_DID_MINIMIZE:
452 macdrv_window_did_minimize(hwnd);
453 break;
454 case WINDOW_DID_UNMINIMIZE:
455 macdrv_window_did_unminimize(hwnd);
456 break;
457 case WINDOW_DRAG_BEGIN:
458 macdrv_window_drag_begin(hwnd, event);
459 break;
460 case WINDOW_DRAG_END:
461 macdrv_window_drag_end(hwnd);
462 break;
463 case WINDOW_FRAME_CHANGED:
464 macdrv_window_frame_changed(hwnd, event);
465 break;
466 case WINDOW_GOT_FOCUS:
467 macdrv_window_got_focus(hwnd, event);
468 break;
469 case WINDOW_LOST_FOCUS:
470 macdrv_window_lost_focus(hwnd, event);
471 break;
472 case WINDOW_MAXIMIZE_REQUESTED:
473 macdrv_window_maximize_requested(hwnd);
474 break;
475 case WINDOW_MINIMIZE_REQUESTED:
476 macdrv_window_minimize_requested(hwnd);
477 break;
478 case WINDOW_RESIZE_ENDED:
479 macdrv_window_resize_ended(hwnd);
480 break;
481 case WINDOW_RESTORE_REQUESTED:
482 macdrv_window_restore_requested(hwnd, event);
483 break;
484 default:
485 TRACE(" ignoring\n");
486 break;
489 thread_data->current_event = prev;
493 /***********************************************************************
494 * process_events
496 static int process_events(macdrv_event_queue queue, macdrv_event_mask mask)
498 macdrv_event *event;
499 int count = 0;
501 while (macdrv_copy_event_from_queue(queue, mask, &event))
503 count++;
504 macdrv_handle_event(event);
505 macdrv_release_event(event);
507 if (count) TRACE("processed %d events\n", count);
508 return count;
512 /***********************************************************************
513 * MsgWaitForMultipleObjectsEx (MACDRV.@)
515 NTSTATUS macdrv_MsgWaitForMultipleObjectsEx(DWORD count, const HANDLE *handles,
516 const LARGE_INTEGER *timeout, DWORD mask, DWORD flags)
518 DWORD ret;
519 struct macdrv_thread_data *data = macdrv_thread_data();
520 macdrv_event_mask event_mask = get_event_mask(mask);
522 TRACE("count %d, handles %p, timeout %p, mask %x, flags %x\n", count,
523 handles, timeout, mask, flags);
525 if (!data)
527 if (!count && timeout && !timeout->QuadPart) return WAIT_TIMEOUT;
528 return pNtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL),
529 !!(flags & MWMO_ALERTABLE), timeout );
532 if (data->current_event && data->current_event->type != QUERY_EVENT &&
533 data->current_event->type != QUERY_EVENT_NO_PREEMPT_WAIT &&
534 data->current_event->type != APP_QUIT_REQUESTED &&
535 data->current_event->type != WINDOW_DRAG_BEGIN)
536 event_mask = 0; /* don't process nested events */
538 if (process_events(data->queue, event_mask)) ret = count - 1;
539 else if (count || !timeout || timeout->QuadPart)
541 ret = pNtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL),
542 !!(flags & MWMO_ALERTABLE), timeout );
543 if (ret == count - 1) process_events(data->queue, event_mask);
545 else ret = WAIT_TIMEOUT;
547 return ret;