4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2007 Blender Foundation.
21 * All rights reserved.
24 * Contributor(s): Blender Foundation
26 * ***** END GPL LICENSE BLOCK *****
32 #include "DNA_listBase.h"
33 #include "DNA_screen_types.h"
34 #include "DNA_windowmanager_types.h"
35 #include "DNA_userdef_types.h" /* U.flag & TWOBUTTONMOUSE */
37 #include "MEM_guardedalloc.h"
39 #include "GHOST_C-api.h"
41 #include "BLI_blenlib.h"
43 #include "BKE_blender.h"
44 #include "BKE_context.h"
45 #include "BKE_idprop.h"
46 #include "BKE_global.h"
48 #include "ED_screen.h"
49 #include "ED_space_api.h"
51 #include "RNA_access.h"
56 #include "wm_window.h"
57 #include "wm_event_system.h"
58 #include "wm_event_types.h"
60 /* ************ event management ************** */
62 void wm_event_add(wmWindow *win, wmEvent *event_to_add)
64 wmEvent *event= MEM_callocN(sizeof(wmEvent), "event");
66 *event= *event_to_add;
67 BLI_addtail(&win->queue, event);
70 wmEvent *wm_event_next(wmWindow *win)
72 wmEvent *event= win->queue.first;
74 if(event) BLI_remlink(&win->queue, event);
78 static void wm_event_free(wmEvent *event)
80 if(event->customdata && event->customdatafree)
81 MEM_freeN(event->customdata);
85 void wm_event_free_all(wmWindow *win)
89 while((event= win->queue.first)) {
90 BLI_remlink(&win->queue, event);
95 /* ********************* notifiers, listeners *************** */
97 /* XXX: in future, which notifiers to send to other windows? */
98 void WM_event_add_notifier(bContext *C, int type, int value, void *data)
100 wmNotifier *note= MEM_callocN(sizeof(wmNotifier), "notifier");
102 BLI_addtail(&CTX_wm_manager(C)->queue, note);
104 note->window= CTX_wm_window(C);
106 note->swinid= CTX_wm_region(C)->swinid;
112 static wmNotifier *wm_notifier_next(wmWindowManager *wm)
114 wmNotifier *note= wm->queue.first;
116 if(note) BLI_remlink(&wm->queue, note);
120 /* called in mainloop */
121 void wm_event_do_notifiers(bContext *C)
123 wmWindowManager *wm= CTX_wm_manager(C);
126 while( (note=wm_notifier_next(wm)) ) {
129 for(win= wm->windows.first; win; win= win->next) {
133 /* XXX context in notifiers? */
134 CTX_wm_window_set(C, win);
136 /* printf("notifier win %d screen %s\n", win->winid, win->screen->id.name+2); */
137 ED_screen_do_listen(win, note);
139 for(ar=win->screen->regionbase.first; ar; ar= ar->next) {
140 ED_region_do_listen(ar, note);
143 for(sa= win->screen->areabase.first; sa; sa= sa->next) {
144 for(ar=sa->regionbase.first; ar; ar= ar->next) {
145 ED_region_do_listen(ar, note);
149 CTX_wm_window_set(C, NULL);
156 /* mark regions to redraw if overlapped with rect */
157 static void wm_flush_regions(bScreen *screen, rcti *dirty)
162 for(ar= screen->regionbase.first; ar; ar= ar->next)
163 if(BLI_isect_rcti(dirty, &ar->winrct, NULL))
166 for(sa= screen->areabase.first; sa; sa= sa->next)
167 for(ar= sa->regionbase.first; ar; ar= ar->next)
168 if(BLI_isect_rcti(dirty, &ar->winrct, NULL))
172 /* all the overlay management, menus, actionzones, region tabs, etc */
173 static void wm_flush_draw_update(bContext *C)
176 bScreen *screen= CTX_wm_screen(C);
178 /* flush redraws of screen regions (menus) down */
179 for(ar= screen->regionbase.last; ar; ar= ar->prev) {
180 if(ar->swinid && ar->do_draw) {
181 wm_flush_regions(screen, &ar->winrct);
185 /* sets redraws for Azones, future region tabs, etc */
186 ED_area_overdraw_flush(C);
189 /* quick test to prevent changing window drawable */
190 static int wm_draw_update_test_window(wmWindow *win)
195 if(win->screen->do_refresh)
197 if(win->screen->do_draw)
199 if(win->screen->do_gesture)
202 for(ar= win->screen->regionbase.first; ar; ar= ar->next)
203 if(ar->swinid && ar->do_draw)
206 for(sa= win->screen->areabase.first; sa; sa= sa->next)
207 for(ar=sa->regionbase.first; ar; ar= ar->next)
208 if(ar->swinid && ar->do_draw)
214 void wm_draw_update(bContext *C)
216 wmWindowManager *wm= CTX_wm_manager(C);
219 for(win= wm->windows.first; win; win= win->next) {
220 if(wm_draw_update_test_window(win)) {
224 CTX_wm_window_set(C, win);
226 /* sets context window+screen */
227 wm_window_make_drawable(C, win);
229 /* notifiers for screen redraw */
230 if(win->screen->do_refresh)
231 ED_screen_refresh(wm, win);
233 /* flush draw updates for multiple layers */
234 wm_flush_draw_update(C);
236 for(sa= win->screen->areabase.first; sa; sa= sa->next) {
238 CTX_wm_area_set(C, sa);
240 for(ar=sa->regionbase.first; ar; ar= ar->next) {
241 CTX_wm_region_set(C, ar);
243 if(ar->swinid && ar->do_draw)
244 ED_region_do_draw(C, ar);
246 CTX_wm_region_set(C, NULL);
249 CTX_wm_area_set(C, NULL);
252 /* move this here so we can do area 'overlay' drawing */
253 if(win->screen->do_draw)
258 /* regions are menus here */
259 for(ar=win->screen->regionbase.first; ar; ar= ar->next) {
260 CTX_wm_region_set(C, ar);
262 if(ar->swinid && ar->do_draw)
263 ED_region_do_draw(C, ar);
265 CTX_wm_region_set(C, NULL);
268 if(win->screen->do_gesture)
269 wm_gesture_draw(win);
271 wm_window_swap_buffers(win);
273 CTX_wm_window_set(C, NULL);
278 /* ********************* operators ******************* */
281 static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, IDProperty *properties)
283 wmWindowManager *wm= CTX_wm_manager(C);
284 int retval= OPERATOR_PASS_THROUGH;
286 if(ot->poll==NULL || ot->poll(C)) {
287 wmOperator *op= MEM_callocN(sizeof(wmOperator), "wmOperator");
290 op->properties= IDP_CopyProperty(properties);
292 /* XXX adding new operator could be function, only happens here now */
294 BLI_strncpy(op->idname, ot->idname, OP_MAX_TYPENAME);
296 op->ptr= MEM_callocN(sizeof(PointerRNA), "wmOperatorPtrRNA");
297 RNA_pointer_create(&RNA_WindowManager, &wm->id, ot->srna, &op->properties, op->ptr);
300 retval= (*op->type->invoke)(C, op, event);
301 else if(op->type->exec)
302 retval= op->type->exec(C, op);
304 if((retval & OPERATOR_FINISHED) && (ot->flag & OPTYPE_REGISTER)) {
305 wm_operator_register(wm, op);
307 else if(!(retval & OPERATOR_RUNNING_MODAL)) {
308 wm_operator_free(op);
315 /* invokes operator in context */
316 int WM_operator_call(bContext *C, const char *opstring, int context, IDProperty *properties)
318 wmOperatorType *ot= WM_operatortype_find(opstring);
319 wmWindow *window= CTX_wm_window(C);
323 if(ot && C && window) {
324 if(context == WM_OP_REGION_WIN) {
325 /* forces event to go to the region window, for header menus */
326 ARegion *ar= CTX_wm_region(C);
327 ScrArea *area= CTX_wm_area(C);
330 ARegion *ar1= area->regionbase.first;
331 for(; ar1; ar1= ar1->next)
332 if(ar1->regiontype==RGN_TYPE_WINDOW)
335 CTX_wm_region_set(C, ar1);
338 retval= wm_operator_invoke(C, ot, window->eventstate, properties);
340 /* set region back */
341 CTX_wm_region_set(C, ar);
345 else if(context == WM_OP_AREA) {
346 /* remove region from context */
347 ARegion *ar= CTX_wm_region(C);
349 CTX_wm_region_set(C, NULL);
350 retval= wm_operator_invoke(C, ot, window->eventstate, properties);
351 CTX_wm_region_set(C, ar);
355 else if(context == WM_OP_SCREEN) {
356 /* remove region + area from context */
357 ARegion *ar= CTX_wm_region(C);
358 ScrArea *area= CTX_wm_area(C);
360 CTX_wm_region_set(C, NULL);
361 CTX_wm_area_set(C, NULL);
362 retval= wm_operator_invoke(C, ot, window->eventstate, properties);
363 CTX_wm_region_set(C, ar);
364 CTX_wm_area_set(C, area);
369 return wm_operator_invoke(C, ot, window->eventstate, properties);
375 /* ********************* handlers *************** */
378 /* not handler itself, is called by UI to move handlers to other queues, so don't close modal ones */
379 static void wm_event_free_handler(wmEventHandler *handler)
384 /* called on exit or remove area, only here call cancel callback */
385 void WM_event_remove_handlers(bContext *C, ListBase *handlers)
387 wmEventHandler *handler;
389 /* C is zero on freeing database, modal handlers then already were freed */
390 while((handler=handlers->first)) {
391 BLI_remlink(handlers, handler);
394 if(handler->op->type->cancel) {
395 ScrArea *area= CTX_wm_area(C);
396 ARegion *region= CTX_wm_region(C);
398 CTX_wm_area_set(C, handler->op_area);
399 CTX_wm_region_set(C, handler->op_region);
401 handler->op->type->cancel(C, handler->op);
403 CTX_wm_area_set(C, area);
404 CTX_wm_region_set(C, region);
407 wm_operator_free(handler->op);
409 else if(handler->ui_remove) {
410 ScrArea *area= CTX_wm_area(C);
411 ARegion *region= CTX_wm_region(C);
413 if(handler->ui_area) CTX_wm_area_set(C, handler->ui_area);
414 if(handler->ui_region) CTX_wm_region_set(C, handler->ui_region);
416 handler->ui_remove(C, handler->ui_userdata);
418 CTX_wm_area_set(C, area);
419 CTX_wm_region_set(C, region);
422 wm_event_free_handler(handler);
427 static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *kmi)
429 int kmitype= kmi->type;
431 /* first do default mappings */
432 if(kmitype==SELECTMOUSE) {
433 if(U.flag & USER_LMOUSESELECT)
439 /* the matching rules */
440 if(winevent->type!=kmitype) return 0;
443 if(winevent->val!=kmi->val) return 0;
444 if(kmi->shift!=KM_ANY)
445 if(winevent->shift!=kmi->shift) return 0;
446 if(kmi->ctrl!=KM_ANY)
447 if(winevent->ctrl!=kmi->ctrl) return 0;
449 if(winevent->alt!=kmi->alt) return 0;
450 if(kmi->oskey!=KM_ANY)
451 if(winevent->oskey!=kmi->oskey) return 0;
453 if(winevent->keymodifier!=kmi->keymodifier) return 0;
459 static int wm_event_always_pass(wmEvent *event)
461 /* some events we always pass on, to ensure proper communication */
462 return (event->type == TIMER);
465 /* Warning: this function removes a modal handler, when finished */
466 static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHandler *handler, wmEvent *event, IDProperty *properties)
468 int retval= OPERATOR_PASS_THROUGH;
470 /* derived, modal or blocking operator */
472 wmOperator *op= handler->op;
473 wmOperatorType *ot= op->type;
476 /* we set context to where modal handler came from */
477 ScrArea *area= CTX_wm_area(C);
478 ARegion *region= CTX_wm_region(C);
480 CTX_wm_area_set(C, handler->op_area);
481 CTX_wm_region_set(C, handler->op_region);
483 retval= ot->modal(C, op, event);
485 /* putting back screen context */
486 if((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) {
487 CTX_wm_area_set(C, area);
488 CTX_wm_region_set(C, region);
491 /* this special cases is for areas and regions that get removed */
492 CTX_wm_area_set(C, NULL);
493 CTX_wm_region_set(C, NULL);
496 if((retval & OPERATOR_FINISHED) && (ot->flag & OPTYPE_REGISTER)) {
497 wm_operator_register(CTX_wm_manager(C), op);
500 else if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
501 wm_operator_free(op);
505 /* remove modal handler, operator itself should have been cancelled and freed */
506 if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
507 BLI_remlink(handlers, handler);
508 wm_event_free_handler(handler);
511 /* prevent silly errors from operator users */
512 retval &= ~OPERATOR_PASS_THROUGH;
517 printf("wm_handler_operator_call error\n");
520 wmOperatorType *ot= WM_operatortype_find(event->keymap_idname);
523 retval= wm_operator_invoke(C, ot, event, properties);
526 if(retval & OPERATOR_PASS_THROUGH)
527 return WM_HANDLER_CONTINUE;
529 return WM_HANDLER_BREAK;
532 static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *event)
534 ScrArea *area= CTX_wm_area(C);
535 ARegion *region= CTX_wm_region(C);
538 /* we set context to where ui handler came from */
539 if(handler->ui_area) CTX_wm_area_set(C, handler->ui_area);
540 if(handler->ui_region) CTX_wm_region_set(C, handler->ui_region);
542 retval= handler->ui_handle(C, event, handler->ui_userdata);
544 /* putting back screen context */
545 CTX_wm_area_set(C, area);
546 CTX_wm_region_set(C, region);
548 if(retval == WM_UI_HANDLER_BREAK)
549 return WM_HANDLER_BREAK;
551 return WM_HANDLER_CONTINUE;
554 static int handler_boundbox_test(wmEventHandler *handler, wmEvent *event)
557 if(handler->bblocal) {
558 rcti rect= *handler->bblocal;
559 BLI_translate_rcti(&rect, handler->bbwin->xmin, handler->bbwin->ymin);
560 return BLI_in_rcti(&rect, event->x, event->y);
563 return BLI_in_rcti(handler->bbwin, event->x, event->y);
568 static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
570 wmEventHandler *handler, *nexthandler;
571 int action= WM_HANDLER_CONTINUE;
573 if(handlers==NULL) return action;
575 /* modal handlers can get removed in this loop, we keep the loop this way */
576 for(handler= handlers->first; handler; handler= nexthandler) {
577 nexthandler= handler->next;
579 /* optional boundbox */
580 if(handler_boundbox_test(handler, event)) {
582 /* modal+blocking handler */
583 if(handler->flag & WM_HANDLER_BLOCKING)
584 action= WM_HANDLER_BREAK;
586 if(handler->keymap) {
589 for(kmi= handler->keymap->first; kmi; kmi= kmi->next) {
590 if(wm_eventmatch(event, kmi)) {
591 if((G.f & G_DEBUG) && event->type!=MOUSEMOVE)
592 printf("handle evt %d win %d op %s\n", event->type, CTX_wm_screen(C)->subwinactive, kmi->idname);
594 event->keymap_idname= kmi->idname; /* weak, but allows interactive callback to not use rawkey */
596 action= wm_handler_operator_call(C, handlers, handler, event, kmi->properties);
597 if(action==WM_HANDLER_BREAK) /* not wm_event_always_pass(event) here, it denotes removed handler */
602 else if(handler->ui_handle) {
603 action= wm_handler_ui_call(C, handler, event);
606 /* modal, swallows all */
607 action= wm_handler_operator_call(C, handlers, handler, event, NULL);
610 if(!wm_event_always_pass(event) && action==WM_HANDLER_BREAK)
618 static int wm_event_inside_i(wmEvent *event, rcti *rect)
620 return BLI_in_rcti(rect, event->x, event->y);
623 static int wm_event_prev_inside_i(wmEvent *event, rcti *rect)
625 if(BLI_in_rcti(rect, event->x, event->y))
627 if(event->type==MOUSEMOVE) {
628 if( BLI_in_rcti(rect, event->prevx, event->prevy)) {
636 static ScrArea *area_event_inside(bContext *C, wmEvent *event)
638 bScreen *screen= CTX_wm_screen(C);
642 for(sa= screen->areabase.first; sa; sa= sa->next)
643 if(BLI_in_rcti(&sa->totrct, event->x, event->y))
648 static ARegion *region_event_inside(bContext *C, wmEvent *event)
650 bScreen *screen= CTX_wm_screen(C);
651 ScrArea *area= CTX_wm_area(C);
655 for(ar= area->regionbase.first; ar; ar= ar->next)
656 if(BLI_in_rcti(&ar->winrct, event->x, event->y))
662 /* called in main loop */
663 /* goes over entire hierarchy: events -> window -> screen -> area -> region */
664 void wm_event_do_handlers(bContext *C)
668 for(win= CTX_wm_manager(C)->windows.first; win; win= win->next) {
671 if( win->screen==NULL )
672 wm_event_free_all(win);
674 while( (event=wm_event_next(win)) ) {
677 CTX_wm_window_set(C, win);
678 CTX_wm_area_set(C, area_event_inside(C, event));
679 CTX_wm_region_set(C, region_event_inside(C, event));
681 /* MVC demands to not draw in event handlers... but we need to leave it for ogl selecting etc */
682 wm_window_make_drawable(C, win);
684 action= wm_handlers_do(C, event, &win->handlers);
686 if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) {
691 /* XXX to solve, here screen handlers? */
692 if(!wm_event_always_pass(event))
693 ED_screen_set_subwinactive(win, event); /* state variables in screen */
695 for(sa= win->screen->areabase.first; sa; sa= sa->next) {
696 if(wm_event_always_pass(event) || wm_event_prev_inside_i(event, &sa->totrct)) {
698 CTX_wm_area_set(C, sa);
699 action= wm_handlers_do(C, event, &sa->handlers);
701 if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) {
702 for(ar=sa->regionbase.first; ar; ar= ar->next) {
703 if(wm_event_always_pass(event) || wm_event_inside_i(event, &ar->winrct) || wm_event_prev_inside_i(event, &ar->winrct)) {
704 CTX_wm_region_set(C, ar);
705 action= wm_handlers_do(C, event, &ar->handlers);
706 CTX_wm_region_set(C, NULL);
708 if(!wm_event_always_pass(event)) {
709 if(action==WM_HANDLER_BREAK)
716 CTX_wm_area_set(C, NULL);
717 /* NOTE: do not escape on WM_HANDLER_BREAK, mousemove needs handled for previous area */
720 /* XXX hrmf, this gives reliable previous mouse coord for area change, feels bad?
721 doing it on ghost queue gives errors when mousemoves go over area borders */
723 CTX_wm_window(C)->eventstate->prevx= event->x;
724 CTX_wm_window(C)->eventstate->prevy= event->y;
727 wm_event_free(event);
729 CTX_wm_window_set(C, NULL);
734 /* lets not expose struct outside wm? */
735 void WM_event_set_handler_flag(wmEventHandler *handler, int flag)
740 wmEventHandler *WM_event_add_modal_handler(bContext *C, ListBase *handlers, wmOperator *op)
742 wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "event modal handler");
744 handler->op_area= CTX_wm_area(C); /* means frozen screen context for modal handlers! */
745 handler->op_region= CTX_wm_region(C);
747 BLI_addhead(handlers, handler);
752 wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, ListBase *keymap)
754 wmEventHandler *handler;
756 /* only allow same keymap once */
757 for(handler= handlers->first; handler; handler= handler->next)
758 if(handler->keymap==keymap)
761 handler= MEM_callocN(sizeof(wmEventHandler), "event keymap handler");
762 BLI_addtail(handlers, handler);
763 handler->keymap= keymap;
768 wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, ListBase *keymap, rcti *bblocal, rcti *bbwin)
770 wmEventHandler *handler= WM_event_add_keymap_handler(handlers, keymap);
771 handler->bblocal= bblocal;
772 handler->bbwin= bbwin;
777 void WM_event_remove_keymap_handler(ListBase *handlers, ListBase *keymap)
779 wmEventHandler *handler;
781 for(handler= handlers->first; handler; handler= handler->next) {
782 if(handler->keymap==keymap) {
783 BLI_remlink(handlers, handler);
784 wm_event_free_handler(handler);
791 wmEventHandler *WM_event_add_ui_handler(bContext *C, ListBase *handlers, wmUIHandlerFunc func, wmUIHandlerRemoveFunc remove, void *userdata)
793 wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "event ui handler");
794 handler->ui_handle= func;
795 handler->ui_remove= remove;
796 handler->ui_userdata= userdata;
797 handler->ui_area= (C)? CTX_wm_area(C): NULL;
798 handler->ui_region= (C)? CTX_wm_region(C): NULL;
800 BLI_addhead(handlers, handler);
805 void WM_event_remove_ui_handler(ListBase *handlers, wmUIHandlerFunc func, wmUIHandlerRemoveFunc remove, void *userdata)
807 wmEventHandler *handler;
809 for(handler= handlers->first; handler; handler= handler->next) {
810 if(handler->ui_handle == func && handler->ui_remove == remove && handler->ui_userdata == userdata) {
811 BLI_remlink(handlers, handler);
812 wm_event_free_handler(handler);
819 void WM_event_add_mousemove(bContext *C)
821 wmWindow *window= CTX_wm_window(C);
822 wmEvent event= *(window->eventstate);
823 event.type= MOUSEMOVE;
824 event.prevx= event.x;
825 event.prevy= event.y;
826 wm_event_add(window, &event);
829 /* ********************* ghost stuff *************** */
831 static int convert_key(GHOST_TKey key)
833 if (key>=GHOST_kKeyA && key<=GHOST_kKeyZ) {
834 return (AKEY + ((int) key - GHOST_kKeyA));
835 } else if (key>=GHOST_kKey0 && key<=GHOST_kKey9) {
836 return (ZEROKEY + ((int) key - GHOST_kKey0));
837 } else if (key>=GHOST_kKeyNumpad0 && key<=GHOST_kKeyNumpad9) {
838 return (PAD0 + ((int) key - GHOST_kKeyNumpad0));
839 } else if (key>=GHOST_kKeyF1 && key<=GHOST_kKeyF12) {
840 return (F1KEY + ((int) key - GHOST_kKeyF1));
843 case GHOST_kKeyBackSpace: return BACKSPACEKEY;
844 case GHOST_kKeyTab: return TABKEY;
845 case GHOST_kKeyLinefeed: return LINEFEEDKEY;
846 case GHOST_kKeyClear: return 0;
847 case GHOST_kKeyEnter: return RETKEY;
849 case GHOST_kKeyEsc: return ESCKEY;
850 case GHOST_kKeySpace: return SPACEKEY;
851 case GHOST_kKeyQuote: return QUOTEKEY;
852 case GHOST_kKeyComma: return COMMAKEY;
853 case GHOST_kKeyMinus: return MINUSKEY;
854 case GHOST_kKeyPeriod: return PERIODKEY;
855 case GHOST_kKeySlash: return SLASHKEY;
857 case GHOST_kKeySemicolon: return SEMICOLONKEY;
858 case GHOST_kKeyEqual: return EQUALKEY;
860 case GHOST_kKeyLeftBracket: return LEFTBRACKETKEY;
861 case GHOST_kKeyRightBracket: return RIGHTBRACKETKEY;
862 case GHOST_kKeyBackslash: return BACKSLASHKEY;
863 case GHOST_kKeyAccentGrave: return ACCENTGRAVEKEY;
865 case GHOST_kKeyLeftShift: return LEFTSHIFTKEY;
866 case GHOST_kKeyRightShift: return RIGHTSHIFTKEY;
867 case GHOST_kKeyLeftControl: return LEFTCTRLKEY;
868 case GHOST_kKeyRightControl: return RIGHTCTRLKEY;
869 case GHOST_kKeyCommand: return COMMANDKEY;
870 case GHOST_kKeyLeftAlt: return LEFTALTKEY;
871 case GHOST_kKeyRightAlt: return RIGHTALTKEY;
873 case GHOST_kKeyCapsLock: return CAPSLOCKKEY;
874 case GHOST_kKeyNumLock: return 0;
875 case GHOST_kKeyScrollLock: return 0;
877 case GHOST_kKeyLeftArrow: return LEFTARROWKEY;
878 case GHOST_kKeyRightArrow: return RIGHTARROWKEY;
879 case GHOST_kKeyUpArrow: return UPARROWKEY;
880 case GHOST_kKeyDownArrow: return DOWNARROWKEY;
882 case GHOST_kKeyPrintScreen: return 0;
883 case GHOST_kKeyPause: return PAUSEKEY;
885 case GHOST_kKeyInsert: return INSERTKEY;
886 case GHOST_kKeyDelete: return DELKEY;
887 case GHOST_kKeyHome: return HOMEKEY;
888 case GHOST_kKeyEnd: return ENDKEY;
889 case GHOST_kKeyUpPage: return PAGEUPKEY;
890 case GHOST_kKeyDownPage: return PAGEDOWNKEY;
892 case GHOST_kKeyNumpadPeriod: return PADPERIOD;
893 case GHOST_kKeyNumpadEnter: return PADENTER;
894 case GHOST_kKeyNumpadPlus: return PADPLUSKEY;
895 case GHOST_kKeyNumpadMinus: return PADMINUS;
896 case GHOST_kKeyNumpadAsterisk: return PADASTERKEY;
897 case GHOST_kKeyNumpadSlash: return PADSLASHKEY;
899 case GHOST_kKeyGrLess: return GRLESSKEY;
902 return UNKNOWNKEY; /* GHOST_kKeyUnknown */
907 /* adds customdata to event */
908 static void update_tablet_data(wmWindow *win, wmEvent *event)
910 const GHOST_TabletData *td= GHOST_GetTabletData(win->ghostwin);
912 /* if there's tablet data from an active tablet device then add it */
913 if ((td != NULL) && td->Active) {
914 struct wmTabletData *wmtab= MEM_mallocN(sizeof(wmTabletData), "customdata tablet");
916 wmtab->Active = td->Active;
917 wmtab->Pressure = td->Pressure;
918 wmtab->Xtilt = td->Xtilt;
919 wmtab->Ytilt = td->Ytilt;
921 event->custom= EVT_DATA_TABLET;
922 event->customdata= wmtab;
923 event->customdatafree= 1;
928 /* windows store own event queues, no bContext here */
929 void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata)
931 wmEvent event, *evt= win->eventstate;
933 /* initialize and copy state (only mouse x y and modifiers) */
938 case GHOST_kEventCursorMove: {
940 GHOST_TEventCursorData *cd= customdata;
943 GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy);
945 event.type= MOUSEMOVE;
947 event.y= evt->y= (win->sizey-1) - cy;
949 update_tablet_data(win, &event);
950 wm_event_add(win, &event);
955 case GHOST_kEventButtonDown:
956 case GHOST_kEventButtonUp: {
957 GHOST_TEventButtonData *bd= customdata;
958 event.val= (type==GHOST_kEventButtonDown);
960 if (bd->button == GHOST_kButtonMaskLeft)
961 event.type= LEFTMOUSE;
962 else if (bd->button == GHOST_kButtonMaskRight)
963 event.type= RIGHTMOUSE;
965 event.type= MIDDLEMOUSE;
968 event.keymodifier= evt->keymodifier= event.type;
970 event.keymodifier= evt->keymodifier= 0;
972 update_tablet_data(win, &event);
973 wm_event_add(win, &event);
978 case GHOST_kEventKeyDown:
979 case GHOST_kEventKeyUp: {
980 GHOST_TEventKeyData *kd= customdata;
981 event.type= convert_key(kd->key);
982 event.ascii= kd->ascii;
983 event.val= (type==GHOST_kEventKeyDown); /* XXX eventmatch uses defines, bad code... */
986 if (event.type==LEFTSHIFTKEY || event.type==RIGHTSHIFTKEY) {
987 event.shift= evt->shift= event.val;
988 } else if (event.type==LEFTCTRLKEY || event.type==RIGHTCTRLKEY) {
989 event.ctrl= evt->ctrl= event.val;
990 } else if (event.type==LEFTALTKEY || event.type==RIGHTALTKEY) {
991 event.alt= evt->alt= event.val;
992 } else if (event.type==COMMANDKEY) {
993 event.oskey= evt->oskey= event.val;
996 wm_event_add(win, &event);
1001 case GHOST_kEventWheel: {
1002 GHOST_TEventWheelData* wheelData = customdata;
1004 if (wheelData->z > 0)
1005 event.type= WHEELUPMOUSE;
1007 event.type= WHEELDOWNMOUSE;
1009 event.val= wheelData->z; /* currently -1 or +1, see ghost for improvements here... */
1010 wm_event_add(win, &event);
1014 case GHOST_kEventTimer: {
1016 event.custom= EVT_DATA_TIMER;
1017 event.customdata= customdata;
1018 wm_event_add(win, &event);
1023 case GHOST_kEventUnknown:
1024 case GHOST_kNumEventTypes: