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_idprop.h"
45 #include "BKE_global.h"
47 #include "ED_screen.h"
48 #include "ED_space_api.h"
50 #include "RNA_access.h"
55 #include "wm_window.h"
56 #include "wm_event_system.h"
57 #include "wm_event_types.h"
59 /* ************ event management ************** */
61 void wm_event_add(wmWindow *win, wmEvent *event_to_add)
63 wmEvent *event= MEM_callocN(sizeof(wmEvent), "event");
65 *event= *event_to_add;
66 BLI_addtail(&win->queue, event);
69 wmEvent *wm_event_next(wmWindow *win)
71 wmEvent *event= win->queue.first;
73 if(event) BLI_remlink(&win->queue, event);
77 static void wm_event_free(wmEvent *event)
79 if(event->customdata && event->customdatafree)
80 MEM_freeN(event->customdata);
84 void wm_event_free_all(wmWindow *win)
88 while((event= win->queue.first)) {
89 BLI_remlink(&win->queue, event);
94 /* ********************* notifiers, listeners *************** */
96 /* XXX: in future, which notifiers to send to other windows? */
97 void WM_event_add_notifier(bContext *C, int type, int value, void *data)
99 wmNotifier *note= MEM_callocN(sizeof(wmNotifier), "notifier");
101 BLI_addtail(&C->wm->queue, note);
103 note->window= C->window;
105 /* catch global notifications here */
107 case WM_NOTE_WINDOW_REDRAW:
108 case WM_NOTE_SCREEN_CHANGED:
111 if(C->region) note->swinid= C->region->swinid;
119 static wmNotifier *wm_notifier_next(wmWindowManager *wm)
121 wmNotifier *note= wm->queue.first;
123 if(note) BLI_remlink(&wm->queue, note);
127 /* called in mainloop */
128 void wm_event_do_notifiers(bContext *C)
132 while( (note=wm_notifier_next(C->wm)) ) {
135 for(win= C->wm->windows.first; win; win= win->next) {
140 C->screen= win->screen;
142 if(note->window && note->window!=win)
144 if(win->screen==NULL)
147 /* printf("notifier win %d screen %s\n", win->winid, win->screen->id.name+2); */
148 ED_screen_do_listen(win, note);
150 for(ar=win->screen->regionbase.first; ar; ar= ar->next) {
151 if(note->swinid && note->swinid!=ar->swinid)
155 ED_region_do_listen(ar, note);
159 for(sa= win->screen->areabase.first; sa; sa= sa->next) {
162 for(ar=sa->regionbase.first; ar; ar= ar->next) {
163 if(note->swinid && note->swinid!=ar->swinid)
167 ED_region_do_listen(ar, note);
178 MEM_freeN(note->data);
183 /* quick test to prevent changing window drawable */
184 static int wm_draw_update_test_window(wmWindow *win)
189 if(win->screen->do_refresh)
191 if(win->screen->do_draw)
193 if(win->screen->do_gesture)
196 for(ar=win->screen->regionbase.first; ar; ar= ar->next) {
197 if(ar->swinid && ar->do_draw)
201 for(sa= win->screen->areabase.first; sa; sa= sa->next) {
202 for(ar=sa->regionbase.first; ar; ar= ar->next) {
203 if(ar->swinid && ar->do_draw)
210 void wm_draw_update(bContext *C)
214 for(win= C->wm->windows.first; win; win= win->next) {
215 if(wm_draw_update_test_window(win)) {
220 C->screen= win->screen;
222 /* sets context window+screen */
223 wm_window_make_drawable(C, win);
225 /* notifiers for screen redraw */
226 if(win->screen->do_refresh)
227 ED_screen_refresh(C->wm, win);
229 for(sa= win->screen->areabase.first; sa; sa= sa->next) {
234 for(ar=sa->regionbase.first; ar; ar= ar->next) {
237 if(ar->swinid && ar->do_draw) {
238 ED_region_do_draw(C, ar);
244 /* only internal decoration, like AZone */
246 ED_area_do_draw(C, sa);
251 /* move this here so we can do area 'overlay' drawing */
252 if(win->screen->do_draw)
255 /* regions are menus here */
256 for(ar=win->screen->regionbase.first; ar; ar= ar->next) {
259 if(ar->swinid && ar->do_draw)
260 ED_region_do_draw(C, ar);
265 if(win->screen->do_gesture)
266 wm_gesture_draw(win);
268 wm_window_swap_buffers(win);
276 /* ********************* operators ******************* */
279 static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, IDProperty *properties)
281 int retval= OPERATOR_PASS_THROUGH;
283 if(ot->poll==NULL || ot->poll(C)) {
284 wmOperator *op= MEM_callocN(sizeof(wmOperator), "wmOperator");
287 op->properties= IDP_CopyProperty(properties);
289 /* XXX adding new operator could be function, only happens here now */
291 BLI_strncpy(op->idname, ot->idname, OP_MAX_TYPENAME);
293 op->ptr= MEM_callocN(sizeof(PointerRNA), "wmOperatorPtrRNA");
294 RNA_pointer_create(&RNA_WindowManager, &C->wm->id, ot->srna, op, op->ptr);
297 retval= (*op->type->invoke)(C, op, event);
298 else if(op->type->exec)
299 retval= op->type->exec(C, op);
301 if((retval & OPERATOR_FINISHED) && (ot->flag & OPTYPE_REGISTER)) {
302 wm_operator_register(C->wm, op);
304 else if(!(retval & OPERATOR_RUNNING_MODAL)) {
305 wm_operator_free(op);
312 /* forces event to go to the region window, for header menus */
313 int WM_operator_call_rwin(bContext *C, const char *opstring)
315 wmOperatorType *ot= WM_operatortype_find(opstring);
318 if(ot && C && C->window) {
319 ARegion *ar= C->region;
323 ARegion *ar1= C->area->regionbase.first;
324 for(; ar1; ar1= ar1->next)
325 if(ar1->regiontype==RGN_TYPE_WINDOW)
331 retval= wm_operator_invoke(C, ot, C->window->eventstate, NULL);
333 /* set region back */
342 /* invokes operator in context */
343 int WM_operator_call(bContext *C, const char *opstring)
345 wmOperatorType *ot= WM_operatortype_find(opstring);
348 if(ot && C && C->window) {
349 return wm_operator_invoke(C, ot, C->window->eventstate, NULL);
355 /* ********************* handlers *************** */
358 /* not handler itself, is called by UI to move handlers to other queues, so don't close modal ones */
359 static void wm_event_free_handler(wmEventHandler *handler)
364 /* called on exit or remove area, only here call cancel callback */
365 void WM_event_remove_handlers(bContext *C, ListBase *handlers)
367 wmEventHandler *handler;
369 /* C is zero on freeing database, modal handlers then already were freed */
370 while((handler=handlers->first)) {
371 BLI_remlink(handlers, handler);
374 if(handler->op->type->cancel) {
375 ScrArea *area= C->area;
376 ARegion *region= C->region;
378 C->area= handler->op_area;
379 C->region= handler->op_region;
381 handler->op->type->cancel(C, handler->op);
387 wm_operator_free(handler->op);
389 else if(handler->ui_remove) {
390 ScrArea *area= C->area;
391 ARegion *region= C->region;
393 if(handler->ui_area) C->area= handler->ui_area;
394 if(handler->ui_region) C->region= handler->ui_region;
396 handler->ui_remove(C);
402 wm_event_free_handler(handler);
407 static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *kmi)
410 if(winevent->type!=kmi->type) return 0;
413 if(winevent->val!=kmi->val) return 0;
415 if(winevent->shift!=kmi->shift) return 0;
416 if(winevent->ctrl!=kmi->ctrl) return 0;
417 if(winevent->alt!=kmi->alt) return 0;
418 if(winevent->oskey!=kmi->oskey) return 0;
420 if(winevent->keymodifier!=kmi->keymodifier) return 0;
426 /* Warning: this function removes a modal handler, when finished */
427 static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHandler *handler, wmEvent *event, IDProperty *properties)
429 int retval= OPERATOR_PASS_THROUGH;
431 /* derived, modal or blocking operator */
433 wmOperator *op= handler->op;
434 wmOperatorType *ot= op->type;
437 /* we set context to where modal handler came from */
438 ScrArea *area= C->area;
439 ARegion *region= C->region;
441 C->area= handler->op_area;
442 C->region= handler->op_region;
444 retval= ot->modal(C, op, event);
446 /* putting back screen context */
450 if((retval & OPERATOR_FINISHED) && (ot->flag & OPTYPE_REGISTER)) {
451 wm_operator_register(C->wm, op);
454 else if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
455 wm_operator_free(op);
460 /* remove modal handler, operator itself should have been cancelled and freed */
461 if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
462 BLI_remlink(handlers, handler);
463 wm_event_free_handler(handler);
466 /* prevent silly errors from operator users */
467 retval &= ~OPERATOR_PASS_THROUGH;
472 printf("wm_handler_operator_call error\n");
475 wmOperatorType *ot= WM_operatortype_find(event->keymap_idname);
478 retval= wm_operator_invoke(C, ot, event, properties);
481 if(retval & OPERATOR_PASS_THROUGH)
482 return WM_HANDLER_CONTINUE;
484 return WM_HANDLER_BREAK;
487 static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *event)
489 ScrArea *area= C->area;
490 ARegion *region= C->region;
493 /* we set context to where ui handler came from */
494 if(handler->ui_area) C->area= handler->ui_area;
495 if(handler->ui_region) C->region= handler->ui_region;
497 retval= handler->ui_handle(C, event);
499 /* putting back screen context */
503 if(retval == WM_UI_HANDLER_BREAK)
504 return WM_HANDLER_BREAK;
506 return WM_HANDLER_CONTINUE;
509 static int wm_event_always_pass(wmEvent *event)
511 /* some events we always pass on, to ensure proper communication */
512 return (event->type == TIMER);
515 static int handler_boundbox_test(wmEventHandler *handler, wmEvent *event)
518 if(handler->bblocal) {
519 rcti rect= *handler->bblocal;
520 BLI_translate_rcti(&rect, handler->bbwin->xmin, handler->bbwin->ymin);
521 return BLI_in_rcti(&rect, event->x, event->y);
524 return BLI_in_rcti(handler->bbwin, event->x, event->y);
529 static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
531 wmEventHandler *handler, *nexthandler;
532 int action= WM_HANDLER_CONTINUE;
534 if(handlers==NULL) return action;
536 /* modal handlers can get removed in this loop, we keep the loop this way */
537 for(handler= handlers->first; handler; handler= nexthandler) {
538 nexthandler= handler->next;
540 /* optional boundbox */
541 if(handler_boundbox_test(handler, event)) {
543 /* modal+blocking handler */
544 if(handler->flag & WM_HANDLER_BLOCKING)
545 action= WM_HANDLER_BREAK;
547 if(handler->keymap) {
550 for(kmi= handler->keymap->first; kmi; kmi= kmi->next) {
551 if(wm_eventmatch(event, kmi)) {
552 if((G.f & G_DEBUG) && event->type!=MOUSEMOVE)
553 printf("handle evt %d win %d op %s\n", event->type, C->window->winid, kmi->idname);
555 event->keymap_idname= kmi->idname; /* weak, but allows interactive callback to not use rawkey */
557 action= wm_handler_operator_call(C, handlers, handler, event, kmi->properties);
558 if(action==WM_HANDLER_BREAK) /* not wm_event_always_pass(event) here, it denotes removed handler */
563 else if(handler->ui_handle) {
564 action= wm_handler_ui_call(C, handler, event);
567 /* modal, swallows all */
568 action= wm_handler_operator_call(C, handlers, handler, event, NULL);
571 if(!wm_event_always_pass(event) && action==WM_HANDLER_BREAK)
579 static int wm_event_inside_i(wmEvent *event, rcti *rect)
581 return BLI_in_rcti(rect, event->x, event->y);
584 static int wm_event_prev_inside_i(wmEvent *event, rcti *rect)
586 if(BLI_in_rcti(rect, event->x, event->y))
588 if(event->type==MOUSEMOVE) {
589 if( BLI_in_rcti(rect, event->prevx, event->prevy)) {
597 static ScrArea *area_event_inside(bContext *C, wmEvent *event)
602 for(sa= C->screen->areabase.first; sa; sa= sa->next)
603 if(BLI_in_rcti(&sa->totrct, event->x, event->y))
608 static ARegion *region_event_inside(bContext *C, wmEvent *event)
612 if(C->screen && C->area)
613 for(ar= C->area->regionbase.first; ar; ar= ar->next)
614 if(BLI_in_rcti(&ar->winrct, event->x, event->y))
620 /* called in main loop */
621 /* goes over entire hierarchy: events -> window -> screen -> area -> region */
622 void wm_event_do_handlers(bContext *C)
626 for(win= C->wm->windows.first; win; win= win->next) {
629 if( win->screen==NULL )
630 wm_event_free_all(win);
632 while( (event=wm_event_next(win)) ) {
636 C->screen= win->screen;
637 C->area= area_event_inside(C, event);
638 C->region= region_event_inside(C, event);
640 /* MVC demands to not draw in event handlers... for now we leave it */
641 wm_window_make_drawable(C, win);
643 action= wm_handlers_do(C, event, &win->handlers);
645 if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) {
650 /* XXX to solve, here screen handlers? */
651 if(!wm_event_always_pass(event))
652 ED_screen_set_subwinactive(win); /* state variables in screen */
654 for(sa= win->screen->areabase.first; sa; sa= sa->next) {
655 if(wm_event_always_pass(event) || wm_event_prev_inside_i(event, &sa->totrct)) {
658 action= wm_handlers_do(C, event, &sa->handlers);
660 if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) {
661 for(ar=sa->regionbase.first; ar; ar= ar->next) {
662 if(wm_event_always_pass(event) || wm_event_inside_i(event, &ar->winrct) || wm_event_prev_inside_i(event, &ar->winrct)) {
664 action= wm_handlers_do(C, event, &ar->handlers);
667 if(!wm_event_always_pass(event)) {
668 if(action==WM_HANDLER_BREAK)
676 /* NOTE: do not escape on WM_HANDLER_BREAK, mousemove needs handled for previous area */
679 /* XXX hrmf, this gives reliable previous mouse coord for area change, feels bad?
680 doing it on ghost queue gives errors when mousemoves go over area borders */
682 C->window->eventstate->prevx= event->x;
683 C->window->eventstate->prevy= event->y;
686 wm_event_free(event);
694 /* lets not expose struct outside wm? */
695 void WM_event_set_handler_flag(wmEventHandler *handler, int flag)
700 wmEventHandler *WM_event_add_modal_handler(bContext *C, ListBase *handlers, wmOperator *op)
702 wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "event modal handler");
704 handler->op_area= C->area; /* means frozen screen context for modal handlers! */
705 handler->op_region= C->region;
707 BLI_addhead(handlers, handler);
712 wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, ListBase *keymap)
714 wmEventHandler *handler;
716 /* only allow same keymap once */
717 for(handler= handlers->first; handler; handler= handler->next)
718 if(handler->keymap==keymap)
721 handler= MEM_callocN(sizeof(wmEventHandler), "event keymap handler");
722 BLI_addtail(handlers, handler);
723 handler->keymap= keymap;
728 wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, ListBase *keymap, rcti *bblocal, rcti *bbwin)
730 wmEventHandler *handler= WM_event_add_keymap_handler(handlers, keymap);
731 handler->bblocal= bblocal;
732 handler->bbwin= bbwin;
737 void WM_event_remove_keymap_handler(ListBase *handlers, ListBase *keymap)
739 wmEventHandler *handler;
741 for(handler= handlers->first; handler; handler= handler->next) {
742 if(handler->keymap==keymap) {
743 BLI_remlink(handlers, handler);
744 wm_event_free_handler(handler);
751 wmEventHandler *WM_event_add_ui_handler(bContext *C, ListBase *handlers, wmUIHandlerFunc func, wmUIHandlerRemoveFunc remove)
753 wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "event ui handler");
754 handler->ui_handle= func;
755 handler->ui_remove= remove;
756 handler->ui_area= (C)? C->area: NULL;
757 handler->ui_region= (C)? C->region: NULL;
759 BLI_addhead(handlers, handler);
764 void WM_event_remove_ui_handler(ListBase *handlers)
766 wmEventHandler *handler;
768 for(handler= handlers->first; handler; handler= handler->next) {
769 if(handler->ui_handle) {
770 BLI_remlink(handlers, handler);
771 wm_event_free_handler(handler);
778 void WM_event_add_mousemove(bContext *C)
780 wmEvent event= *(C->window->eventstate);
781 event.type= MOUSEMOVE;
782 event.prevx= event.x;
783 event.prevy= event.y;
784 wm_event_add(C->window, &event);
787 /* ********************* ghost stuff *************** */
789 static int convert_key(GHOST_TKey key)
791 if (key>=GHOST_kKeyA && key<=GHOST_kKeyZ) {
792 return (AKEY + ((int) key - GHOST_kKeyA));
793 } else if (key>=GHOST_kKey0 && key<=GHOST_kKey9) {
794 return (ZEROKEY + ((int) key - GHOST_kKey0));
795 } else if (key>=GHOST_kKeyNumpad0 && key<=GHOST_kKeyNumpad9) {
796 return (PAD0 + ((int) key - GHOST_kKeyNumpad0));
797 } else if (key>=GHOST_kKeyF1 && key<=GHOST_kKeyF12) {
798 return (F1KEY + ((int) key - GHOST_kKeyF1));
801 case GHOST_kKeyBackSpace: return BACKSPACEKEY;
802 case GHOST_kKeyTab: return TABKEY;
803 case GHOST_kKeyLinefeed: return LINEFEEDKEY;
804 case GHOST_kKeyClear: return 0;
805 case GHOST_kKeyEnter: return RETKEY;
807 case GHOST_kKeyEsc: return ESCKEY;
808 case GHOST_kKeySpace: return SPACEKEY;
809 case GHOST_kKeyQuote: return QUOTEKEY;
810 case GHOST_kKeyComma: return COMMAKEY;
811 case GHOST_kKeyMinus: return MINUSKEY;
812 case GHOST_kKeyPeriod: return PERIODKEY;
813 case GHOST_kKeySlash: return SLASHKEY;
815 case GHOST_kKeySemicolon: return SEMICOLONKEY;
816 case GHOST_kKeyEqual: return EQUALKEY;
818 case GHOST_kKeyLeftBracket: return LEFTBRACKETKEY;
819 case GHOST_kKeyRightBracket: return RIGHTBRACKETKEY;
820 case GHOST_kKeyBackslash: return BACKSLASHKEY;
821 case GHOST_kKeyAccentGrave: return ACCENTGRAVEKEY;
823 case GHOST_kKeyLeftShift: return LEFTSHIFTKEY;
824 case GHOST_kKeyRightShift: return RIGHTSHIFTKEY;
825 case GHOST_kKeyLeftControl: return LEFTCTRLKEY;
826 case GHOST_kKeyRightControl: return RIGHTCTRLKEY;
827 case GHOST_kKeyCommand: return COMMANDKEY;
828 case GHOST_kKeyLeftAlt: return LEFTALTKEY;
829 case GHOST_kKeyRightAlt: return RIGHTALTKEY;
831 case GHOST_kKeyCapsLock: return CAPSLOCKKEY;
832 case GHOST_kKeyNumLock: return 0;
833 case GHOST_kKeyScrollLock: return 0;
835 case GHOST_kKeyLeftArrow: return LEFTARROWKEY;
836 case GHOST_kKeyRightArrow: return RIGHTARROWKEY;
837 case GHOST_kKeyUpArrow: return UPARROWKEY;
838 case GHOST_kKeyDownArrow: return DOWNARROWKEY;
840 case GHOST_kKeyPrintScreen: return 0;
841 case GHOST_kKeyPause: return PAUSEKEY;
843 case GHOST_kKeyInsert: return INSERTKEY;
844 case GHOST_kKeyDelete: return DELKEY;
845 case GHOST_kKeyHome: return HOMEKEY;
846 case GHOST_kKeyEnd: return ENDKEY;
847 case GHOST_kKeyUpPage: return PAGEUPKEY;
848 case GHOST_kKeyDownPage: return PAGEDOWNKEY;
850 case GHOST_kKeyNumpadPeriod: return PADPERIOD;
851 case GHOST_kKeyNumpadEnter: return PADENTER;
852 case GHOST_kKeyNumpadPlus: return PADPLUSKEY;
853 case GHOST_kKeyNumpadMinus: return PADMINUS;
854 case GHOST_kKeyNumpadAsterisk: return PADASTERKEY;
855 case GHOST_kKeyNumpadSlash: return PADSLASHKEY;
857 case GHOST_kKeyGrLess: return GRLESSKEY;
860 return UNKNOWNKEY; /* GHOST_kKeyUnknown */
865 /* adds customdata to event */
866 static void update_tablet_data(wmWindow *win, wmEvent *event)
868 const GHOST_TabletData *td= GHOST_GetTabletData(win->ghostwin);
870 /* if there's tablet data from an active tablet device then add it */
871 if ((td != NULL) && td->Active) {
872 struct wmTabletData *wmtab= MEM_mallocN(sizeof(wmTabletData), "customdata tablet");
874 wmtab->Active = td->Active;
875 wmtab->Pressure = td->Pressure;
876 wmtab->Xtilt = td->Xtilt;
877 wmtab->Ytilt = td->Ytilt;
879 event->custom= EVT_DATA_TABLET;
880 event->customdata= wmtab;
881 event->customdatafree= 1;
886 /* windows store own event queues, no bContext here */
887 void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata)
889 wmEvent event, *evt= win->eventstate;
891 /* initialize and copy state (only mouse x y and modifiers) */
896 case GHOST_kEventCursorMove: {
898 GHOST_TEventCursorData *cd= customdata;
901 GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy);
903 event.type= MOUSEMOVE;
905 event.y= evt->y= (win->sizey-1) - cy;
907 update_tablet_data(win, &event);
908 wm_event_add(win, &event);
913 case GHOST_kEventButtonDown:
914 case GHOST_kEventButtonUp: {
915 GHOST_TEventButtonData *bd= customdata;
916 event.val= (type==GHOST_kEventButtonDown);
918 if (bd->button == GHOST_kButtonMaskLeft)
919 event.type= LEFTMOUSE;
920 else if (bd->button == GHOST_kButtonMaskRight)
921 event.type= RIGHTMOUSE;
923 event.type= MIDDLEMOUSE;
926 event.keymodifier= evt->keymodifier= event.type;
928 event.keymodifier= evt->keymodifier= 0;
930 update_tablet_data(win, &event);
931 wm_event_add(win, &event);
936 case GHOST_kEventKeyDown:
937 case GHOST_kEventKeyUp: {
938 GHOST_TEventKeyData *kd= customdata;
939 event.type= convert_key(kd->key);
940 event.ascii= kd->ascii;
941 event.val= (type==GHOST_kEventKeyDown); /* XXX eventmatch uses defines, bad code... */
944 if (event.type==LEFTSHIFTKEY || event.type==RIGHTSHIFTKEY) {
945 event.shift= evt->shift= event.val;
946 } else if (event.type==LEFTCTRLKEY || event.type==RIGHTCTRLKEY) {
947 event.ctrl= evt->ctrl= event.val;
948 } else if (event.type==LEFTALTKEY || event.type==RIGHTALTKEY) {
949 event.alt= evt->alt= event.val;
950 } else if (event.type==COMMANDKEY) {
951 event.oskey= evt->oskey= event.val;
954 wm_event_add(win, &event);
959 case GHOST_kEventWheel: {
960 GHOST_TEventWheelData* wheelData = customdata;
962 if (wheelData->z > 0)
963 event.type= WHEELUPMOUSE;
965 event.type= WHEELDOWNMOUSE;
967 event.val= wheelData->z; /* currently -1 or +1, see ghost for improvements here... */
968 wm_event_add(win, &event);
972 case GHOST_kEventTimer: {
974 event.custom= EVT_DATA_TIMER;
975 event.customdata= customdata;
976 wm_event_add(win, &event);
981 case GHOST_kEventUnknown:
982 case GHOST_kNumEventTypes: