Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/windowmanager/intern/wm_event_system.c')
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c980
1 files changed, 980 insertions, 0 deletions
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
new file mode 100644
index 00000000000..88c29ddae29
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -0,0 +1,980 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "DNA_listBase.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_userdef_types.h" /* U.flag & TWOBUTTONMOUSE */
+
+#include "MEM_guardedalloc.h"
+
+#include "GHOST_C-api.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_blender.h"
+#include "BKE_global.h"
+
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm.h"
+#include "wm_window.h"
+#include "wm_event_system.h"
+#include "wm_event_types.h"
+
+/* ************ event management ************** */
+
+void wm_event_add(wmWindow *win, wmEvent *event_to_add)
+{
+ wmEvent *event= MEM_callocN(sizeof(wmEvent), "event");
+
+ *event= *event_to_add;
+ BLI_addtail(&win->queue, event);
+}
+
+wmEvent *wm_event_next(wmWindow *win)
+{
+ wmEvent *event= win->queue.first;
+
+ if(event) BLI_remlink(&win->queue, event);
+ return event;
+}
+
+static void wm_event_free(wmEvent *event)
+{
+ if(event->customdata && event->customdatafree)
+ MEM_freeN(event->customdata);
+ MEM_freeN(event);
+}
+
+void wm_event_free_all(wmWindow *win)
+{
+ wmEvent *event;
+
+ while((event= win->queue.first)) {
+ BLI_remlink(&win->queue, event);
+ wm_event_free(event);
+ }
+}
+
+/* ********************* notifiers, listeners *************** */
+
+/* XXX: in future, which notifiers to send to other windows? */
+void WM_event_add_notifier(bContext *C, int type, int value, void *data)
+{
+ wmNotifier *note= MEM_callocN(sizeof(wmNotifier), "notifier");
+
+ BLI_addtail(&C->wm->queue, note);
+
+ note->window= C->window;
+
+ /* catch global notifications here */
+ switch (type) {
+ case WM_NOTE_WINDOW_REDRAW:
+ case WM_NOTE_SCREEN_CHANGED:
+ break;
+ default:
+ if(C->region) note->swinid= C->region->swinid;
+ }
+
+ note->type= type;
+ note->value= value;
+ note->data= data;
+}
+
+static wmNotifier *wm_notifier_next(wmWindowManager *wm)
+{
+ wmNotifier *note= wm->queue.first;
+
+ if(note) BLI_remlink(&wm->queue, note);
+ return note;
+}
+
+/* called in mainloop */
+void wm_event_do_notifiers(bContext *C)
+{
+ wmNotifier *note;
+
+ while( (note=wm_notifier_next(C->wm)) ) {
+ wmWindow *win;
+
+ for(win= C->wm->windows.first; win; win= win->next) {
+ ScrArea *sa;
+ ARegion *ar;
+
+ C->window= win;
+ C->screen= win->screen;
+
+ if(note->window && note->window!=win)
+ continue;
+ if(win->screen==NULL)
+ continue;
+
+ /* printf("notifier win %d screen %s\n", win->winid, win->screen->id.name+2); */
+ ED_screen_do_listen(win, note);
+
+ for(ar=win->screen->regionbase.first; ar; ar= ar->next) {
+ if(note->swinid && note->swinid!=ar->swinid)
+ continue;
+
+ C->region= ar;
+ ED_region_do_listen(ar, note);
+ C->region= NULL;
+ }
+
+ for(sa= win->screen->areabase.first; sa; sa= sa->next) {
+ C->area= sa;
+
+ for(ar=sa->regionbase.first; ar; ar= ar->next) {
+ if(note->swinid && note->swinid!=ar->swinid)
+ continue;
+
+ C->region= ar;
+ ED_region_do_listen(ar, note);
+ C->region= NULL;
+ }
+
+ C->area= NULL;
+ }
+
+ C->window= NULL;
+ C->screen= NULL;
+ }
+ if(note->data)
+ MEM_freeN(note->data);
+ MEM_freeN(note);
+ }
+}
+
+/* quick test to prevent changing window drawable */
+static int wm_draw_update_test_window(wmWindow *win)
+{
+ ScrArea *sa;
+ ARegion *ar;
+
+ if(win->screen->do_refresh)
+ return 1;
+ if(win->screen->do_draw)
+ return 1;
+ if(win->screen->do_gesture)
+ return 1;
+
+ for(ar=win->screen->regionbase.first; ar; ar= ar->next) {
+ if(ar->swinid && ar->do_draw)
+ return 1;
+ }
+
+ for(sa= win->screen->areabase.first; sa; sa= sa->next) {
+ for(ar=sa->regionbase.first; ar; ar= ar->next) {
+ if(ar->swinid && ar->do_draw)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void wm_draw_update(bContext *C)
+{
+ wmWindow *win;
+
+ for(win= C->wm->windows.first; win; win= win->next) {
+ if(wm_draw_update_test_window(win)) {
+ ScrArea *sa;
+ ARegion *ar;
+
+ C->window= win;
+ C->screen= win->screen;
+
+ /* sets context window+screen */
+ wm_window_make_drawable(C, win);
+
+ /* notifiers for screen redraw */
+ if(win->screen->do_refresh)
+ ED_screen_refresh(C->wm, win);
+
+ for(sa= win->screen->areabase.first; sa; sa= sa->next) {
+ int area_do_draw= 0;
+
+ C->area= sa;
+
+ for(ar=sa->regionbase.first; ar; ar= ar->next) {
+ C->region= ar;
+
+ if(ar->swinid && ar->do_draw) {
+ ED_region_do_draw(C, ar);
+ area_do_draw= 1;
+ }
+
+ C->region= NULL;
+ }
+ /* only internal decoration, like AZone */
+ if(area_do_draw)
+ ED_area_do_draw(C, sa);
+
+ C->area = NULL;
+ }
+
+ /* move this here so we can do area 'overlay' drawing */
+ if(win->screen->do_draw)
+ ED_screen_draw(win);
+
+ /* regions are menus here */
+ for(ar=win->screen->regionbase.first; ar; ar= ar->next) {
+ C->region= ar;
+
+ if(ar->swinid && ar->do_draw)
+ ED_region_do_draw(C, ar);
+
+ C->region= NULL;
+ }
+
+ if(win->screen->do_gesture)
+ wm_gesture_draw(win);
+
+ wm_window_swap_buffers(win);
+
+ C->window= NULL;
+ C->screen= NULL;
+ }
+ }
+}
+
+/* ********************* operators ******************* */
+
+
+int WM_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event)
+{
+ int retval= OPERATOR_PASS_THROUGH;
+
+ if(ot->poll==NULL || ot->poll(C)) {
+ wmOperator *op= MEM_callocN(sizeof(wmOperator), "wmOperator");
+
+ /* XXX adding new operator could be function, only happens here now */
+ op->type= ot;
+ BLI_strncpy(op->idname, ot->idname, OP_MAX_TYPENAME);
+
+ op->ptr= MEM_callocN(sizeof(PointerRNA), "wmOperatorPtrRNA");
+ RNA_pointer_create(&RNA_WindowManager, &C->wm->id, ot->srna, op, op->ptr);
+
+ if(op->type->invoke)
+ retval= (*op->type->invoke)(C, op, event);
+ else if(op->type->exec)
+ retval= op->type->exec(C, op);
+
+ if((retval & OPERATOR_FINISHED) && (ot->flag & OPTYPE_REGISTER)) {
+ wm_operator_register(C->wm, op);
+ }
+ else if(!(retval & OPERATOR_RUNNING_MODAL)) {
+ wm_operator_free(op);
+ }
+ }
+
+ return retval;
+}
+
+/* forces event to go to the region window, for header menus */
+int WM_operator_call_rwin(bContext *C, const char *opstring)
+{
+ wmOperatorType *ot= WM_operatortype_find(opstring);
+
+ /* dummie test */
+ if(ot && C && C->window) {
+ ARegion *ar= C->region;
+ int retval;
+
+ if(C->area) {
+ ARegion *ar1= C->area->regionbase.first;
+ for(; ar1; ar1= ar1->next)
+ if(ar1->regiontype==RGN_TYPE_WINDOW)
+ break;
+ if(ar1)
+ C->region= ar1;
+ }
+
+ retval= WM_operator_invoke(C, ot, C->window->eventstate);
+
+ /* set region back */
+ C->region= ar;
+
+ return retval;
+ }
+
+ return 0;
+}
+
+/* invokes operator in context */
+int WM_operator_call(bContext *C, const char *opstring)
+{
+ wmOperatorType *ot= WM_operatortype_find(opstring);
+
+ /* dummie test */
+ if(ot && C && C->window) {
+ return WM_operator_invoke(C, ot, C->window->eventstate);
+ }
+
+ return 0;
+}
+
+/* ********************* handlers *************** */
+
+
+/* not handler itself, is called by UI to move handlers to other queues, so don't close modal ones */
+static void wm_event_free_handler(wmEventHandler *handler)
+{
+
+}
+
+/* called on exit or remove area, only here call cancel callback */
+void WM_event_remove_handlers(bContext *C, ListBase *handlers)
+{
+ wmEventHandler *handler;
+
+ /* C is zero on freeing database, modal handlers then already were freed */
+ while((handler=handlers->first)) {
+ BLI_remlink(handlers, handler);
+
+ if(handler->op) {
+ if(handler->op->type->cancel) {
+ ScrArea *area= C->area;
+ ARegion *region= C->region;
+
+ C->area= handler->op_area;
+ C->region= handler->op_region;
+
+ handler->op->type->cancel(C, handler->op);
+
+ C->area= area;
+ C->region= region;
+ }
+
+ wm_operator_free(handler->op);
+ }
+ else if(handler->ui_remove) {
+ ScrArea *area= C->area;
+ ARegion *region= C->region;
+
+ if(handler->ui_area) C->area= handler->ui_area;
+ if(handler->ui_region) C->region= handler->ui_region;
+
+ handler->ui_remove(C);
+
+ C->area= area;
+ C->region= region;
+ }
+
+ wm_event_free_handler(handler);
+ MEM_freeN(handler);
+ }
+}
+
+static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *kmi)
+{
+
+ if(winevent->type!=kmi->type) return 0;
+
+ if(kmi->val!=KM_ANY)
+ if(winevent->val!=kmi->val) return 0;
+
+ if(winevent->shift!=kmi->shift) return 0;
+ if(winevent->ctrl!=kmi->ctrl) return 0;
+ if(winevent->alt!=kmi->alt) return 0;
+ if(winevent->oskey!=kmi->oskey) return 0;
+ if(kmi->keymodifier)
+ if(winevent->keymodifier!=kmi->keymodifier) return 0;
+
+
+ return 1;
+}
+
+/* Warning: this function removes a modal handler, when finished */
+static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHandler *handler, wmEvent *event)
+{
+ int retval= OPERATOR_PASS_THROUGH;
+
+ /* derived, modal or blocking operator */
+ if(handler->op) {
+ wmOperator *op= handler->op;
+ wmOperatorType *ot= op->type;
+
+ if(ot->modal) {
+ /* we set context to where modal handler came from */
+ ScrArea *area= C->area;
+ ARegion *region= C->region;
+
+ C->area= handler->op_area;
+ C->region= handler->op_region;
+
+ retval= ot->modal(C, op, event);
+
+ /* putting back screen context */
+ C->area= area;
+ C->region= region;
+
+ if((retval & OPERATOR_FINISHED) && (ot->flag & OPTYPE_REGISTER)) {
+ wm_operator_register(C->wm, op);
+ handler->op= NULL;
+ }
+ else if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
+ wm_operator_free(op);
+ handler->op= NULL;
+ }
+
+
+ /* remove modal handler, operator itself should have been cancelled and freed */
+ if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
+ BLI_remlink(handlers, handler);
+ wm_event_free_handler(handler);
+ MEM_freeN(handler);
+
+ /* prevent silly errors from operator users */
+ retval &= ~OPERATOR_PASS_THROUGH;
+ }
+
+ }
+ else
+ printf("wm_handler_operator_call error\n");
+ }
+ else {
+ wmOperatorType *ot= WM_operatortype_find(event->keymap_idname);
+
+ if(ot)
+ retval= WM_operator_invoke(C, ot, event);
+ }
+
+ if(retval & OPERATOR_PASS_THROUGH)
+ return WM_HANDLER_CONTINUE;
+
+ return WM_HANDLER_BREAK;
+}
+
+static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *event)
+{
+ ScrArea *area= C->area;
+ ARegion *region= C->region;
+ int retval;
+
+ /* we set context to where ui handler came from */
+ if(handler->ui_area) C->area= handler->ui_area;
+ if(handler->ui_region) C->region= handler->ui_region;
+
+ retval= handler->ui_handle(C, event);
+
+ /* putting back screen context */
+ C->area= area;
+ C->region= region;
+
+ if(retval == WM_UI_HANDLER_BREAK)
+ return WM_HANDLER_BREAK;
+
+ return WM_HANDLER_CONTINUE;
+}
+
+static int wm_event_always_pass(wmEvent *event)
+{
+ /* some events we always pass on, to ensure proper communication */
+ return (event->type == TIMER);
+}
+
+static int handler_boundbox_test(wmEventHandler *handler, wmEvent *event)
+{
+ if(handler->bbwin) {
+ if(handler->bblocal) {
+ rcti rect= *handler->bblocal;
+ BLI_translate_rcti(&rect, handler->bbwin->xmin, handler->bbwin->ymin);
+ return BLI_in_rcti(&rect, event->x, event->y);
+ }
+ else
+ return BLI_in_rcti(handler->bbwin, event->x, event->y);
+ }
+ return 1;
+}
+
+static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
+{
+ wmEventHandler *handler, *nexthandler;
+ int action= WM_HANDLER_CONTINUE;
+
+ if(handlers==NULL) return action;
+
+ /* modal handlers can get removed in this loop, we keep the loop this way */
+ for(handler= handlers->first; handler; handler= nexthandler) {
+ nexthandler= handler->next;
+
+ /* optional boundbox */
+ if(handler_boundbox_test(handler, event)) {
+
+ /* modal+blocking handler */
+ if(handler->flag & WM_HANDLER_BLOCKING)
+ action= WM_HANDLER_BREAK;
+
+ if(handler->keymap) {
+ wmKeymapItem *kmi;
+
+ for(kmi= handler->keymap->first; kmi; kmi= kmi->next) {
+ if(wm_eventmatch(event, kmi)) {
+ /* if(event->type!=MOUSEMOVE)
+ printf("handle evt %d win %d op %s\n", event->type, C->window->winid, kmi->idname); */
+
+ event->keymap_idname= kmi->idname; /* weak, but allows interactive callback to not use rawkey */
+
+ action= wm_handler_operator_call(C, handlers, handler, event);
+ if(action==WM_HANDLER_BREAK) /* not wm_event_always_pass(event) here, it denotes removed handler */
+ break;
+ }
+ }
+ }
+ else if(handler->ui_handle) {
+ action= wm_handler_ui_call(C, handler, event);
+ }
+ else {
+ /* modal, swallows all */
+ action= wm_handler_operator_call(C, handlers, handler, event);
+ }
+
+ if(!wm_event_always_pass(event) && action==WM_HANDLER_BREAK)
+ break;
+ }
+
+ }
+ return action;
+}
+
+static int wm_event_inside_i(wmEvent *event, rcti *rect)
+{
+ return BLI_in_rcti(rect, event->x, event->y);
+}
+
+static int wm_event_prev_inside_i(wmEvent *event, rcti *rect)
+{
+ if(BLI_in_rcti(rect, event->x, event->y))
+ return 1;
+ if(event->type==MOUSEMOVE) {
+ if( BLI_in_rcti(rect, event->prevx, event->prevy)) {
+ return 1;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+static ScrArea *area_event_inside(bContext *C, wmEvent *event)
+{
+ ScrArea *sa;
+
+ if(C->screen)
+ for(sa= C->screen->areabase.first; sa; sa= sa->next)
+ if(BLI_in_rcti(&sa->totrct, event->x, event->y))
+ return sa;
+ return NULL;
+}
+
+static ARegion *region_event_inside(bContext *C, wmEvent *event)
+{
+ ARegion *ar;
+
+ if(C->screen && C->area)
+ for(ar= C->area->regionbase.first; ar; ar= ar->next)
+ if(BLI_in_rcti(&ar->winrct, event->x, event->y))
+ return ar;
+ return NULL;
+}
+
+
+/* called in main loop */
+/* goes over entire hierarchy: events -> window -> screen -> area -> region */
+void wm_event_do_handlers(bContext *C)
+{
+ wmWindow *win;
+
+ for(win= C->wm->windows.first; win; win= win->next) {
+ wmEvent *event;
+
+ if( win->screen==NULL )
+ wm_event_free_all(win);
+
+ while( (event=wm_event_next(win)) ) {
+ int action;
+
+ C->window= win;
+ C->screen= win->screen;
+ C->area= area_event_inside(C, event);
+ C->region= region_event_inside(C, event);
+
+ /* MVC demands to not draw in event handlers... for now we leave it */
+ wm_window_make_drawable(C, win);
+
+ action= wm_handlers_do(C, event, &win->handlers);
+
+ if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) {
+ ScrArea *sa;
+ ARegion *ar;
+ int doit= 0;
+
+ for(sa= win->screen->areabase.first; sa; sa= sa->next) {
+ if(wm_event_always_pass(event) || wm_event_prev_inside_i(event, &sa->totrct)) {
+ doit= 1;
+ C->area= sa;
+ action= wm_handlers_do(C, event, &sa->handlers);
+
+ if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) {
+ for(ar=sa->regionbase.first; ar; ar= ar->next) {
+ if(wm_event_always_pass(event) || wm_event_inside_i(event, &ar->winrct) || wm_event_prev_inside_i(event, &ar->winrct)) {
+ C->region= ar;
+ action= wm_handlers_do(C, event, &ar->handlers);
+ C->region= NULL;
+
+ if(!wm_event_always_pass(event)) {
+ if(action==WM_HANDLER_BREAK)
+ break;
+ }
+ }
+ }
+ }
+
+ C->area= NULL;
+ /* NOTE: do not escape on WM_HANDLER_BREAK, mousemove needs handled for previous area */
+ }
+ }
+ /* XXX hrmf, this gives reliable previous mouse coord for area change, feels bad?
+ doing it on ghost queue gives errors when mousemoves go over area borders */
+ if(doit) {
+ C->window->eventstate->prevx= event->x;
+ C->window->eventstate->prevy= event->y;
+ }
+ }
+ wm_event_free(event);
+
+ C->window= NULL;
+ C->screen= NULL;
+ }
+ }
+}
+
+/* lets not expose struct outside wm? */
+void WM_event_set_handler_flag(wmEventHandler *handler, int flag)
+{
+ handler->flag= flag;
+}
+
+wmEventHandler *WM_event_add_modal_handler(bContext *C, ListBase *handlers, wmOperator *op)
+{
+ wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "event modal handler");
+ handler->op= op;
+ handler->op_area= C->area; /* means frozen screen context for modal handlers! */
+ handler->op_region= C->region;
+
+ BLI_addhead(handlers, handler);
+
+ return handler;
+}
+
+wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, ListBase *keymap)
+{
+ wmEventHandler *handler;
+
+ /* only allow same keymap once */
+ for(handler= handlers->first; handler; handler= handler->next)
+ if(handler->keymap==keymap)
+ return handler;
+
+ handler= MEM_callocN(sizeof(wmEventHandler), "event keymap handler");
+ BLI_addtail(handlers, handler);
+ handler->keymap= keymap;
+
+ return handler;
+}
+
+wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, ListBase *keymap, rcti *bblocal, rcti *bbwin)
+{
+ wmEventHandler *handler= WM_event_add_keymap_handler(handlers, keymap);
+ handler->bblocal= bblocal;
+ handler->bbwin= bbwin;
+
+ return handler;
+}
+
+void WM_event_remove_keymap_handler(ListBase *handlers, ListBase *keymap)
+{
+ wmEventHandler *handler;
+
+ for(handler= handlers->first; handler; handler= handler->next) {
+ if(handler->keymap==keymap) {
+ BLI_remlink(handlers, handler);
+ wm_event_free_handler(handler);
+ MEM_freeN(handler);
+ break;
+ }
+ }
+}
+
+wmEventHandler *WM_event_add_ui_handler(bContext *C, ListBase *handlers, wmUIHandlerFunc func, wmUIHandlerRemoveFunc remove)
+{
+ wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "event ui handler");
+ handler->ui_handle= func;
+ handler->ui_remove= remove;
+ handler->ui_area= (C)? C->area: NULL;
+ handler->ui_region= (C)? C->region: NULL;
+
+ BLI_addhead(handlers, handler);
+
+ return handler;
+}
+
+void WM_event_remove_ui_handler(ListBase *handlers)
+{
+ wmEventHandler *handler;
+
+ for(handler= handlers->first; handler; handler= handler->next) {
+ if(handler->ui_handle) {
+ BLI_remlink(handlers, handler);
+ wm_event_free_handler(handler);
+ MEM_freeN(handler);
+ break;
+ }
+ }
+}
+
+void WM_event_add_mousemove(bContext *C)
+{
+ wmEvent event= *(C->window->eventstate);
+ event.type= MOUSEMOVE;
+ event.prevx= event.x;
+ event.prevy= event.y;
+ wm_event_add(C->window, &event);
+}
+
+/* ********************* ghost stuff *************** */
+
+static int convert_key(GHOST_TKey key)
+{
+ if (key>=GHOST_kKeyA && key<=GHOST_kKeyZ) {
+ return (AKEY + ((int) key - GHOST_kKeyA));
+ } else if (key>=GHOST_kKey0 && key<=GHOST_kKey9) {
+ return (ZEROKEY + ((int) key - GHOST_kKey0));
+ } else if (key>=GHOST_kKeyNumpad0 && key<=GHOST_kKeyNumpad9) {
+ return (PAD0 + ((int) key - GHOST_kKeyNumpad0));
+ } else if (key>=GHOST_kKeyF1 && key<=GHOST_kKeyF12) {
+ return (F1KEY + ((int) key - GHOST_kKeyF1));
+ } else {
+ switch (key) {
+ case GHOST_kKeyBackSpace: return BACKSPACEKEY;
+ case GHOST_kKeyTab: return TABKEY;
+ case GHOST_kKeyLinefeed: return LINEFEEDKEY;
+ case GHOST_kKeyClear: return 0;
+ case GHOST_kKeyEnter: return RETKEY;
+
+ case GHOST_kKeyEsc: return ESCKEY;
+ case GHOST_kKeySpace: return SPACEKEY;
+ case GHOST_kKeyQuote: return QUOTEKEY;
+ case GHOST_kKeyComma: return COMMAKEY;
+ case GHOST_kKeyMinus: return MINUSKEY;
+ case GHOST_kKeyPeriod: return PERIODKEY;
+ case GHOST_kKeySlash: return SLASHKEY;
+
+ case GHOST_kKeySemicolon: return SEMICOLONKEY;
+ case GHOST_kKeyEqual: return EQUALKEY;
+
+ case GHOST_kKeyLeftBracket: return LEFTBRACKETKEY;
+ case GHOST_kKeyRightBracket: return RIGHTBRACKETKEY;
+ case GHOST_kKeyBackslash: return BACKSLASHKEY;
+ case GHOST_kKeyAccentGrave: return ACCENTGRAVEKEY;
+
+ case GHOST_kKeyLeftShift: return LEFTSHIFTKEY;
+ case GHOST_kKeyRightShift: return RIGHTSHIFTKEY;
+ case GHOST_kKeyLeftControl: return LEFTCTRLKEY;
+ case GHOST_kKeyRightControl: return RIGHTCTRLKEY;
+ case GHOST_kKeyCommand: return COMMANDKEY;
+ case GHOST_kKeyLeftAlt: return LEFTALTKEY;
+ case GHOST_kKeyRightAlt: return RIGHTALTKEY;
+
+ case GHOST_kKeyCapsLock: return CAPSLOCKKEY;
+ case GHOST_kKeyNumLock: return 0;
+ case GHOST_kKeyScrollLock: return 0;
+
+ case GHOST_kKeyLeftArrow: return LEFTARROWKEY;
+ case GHOST_kKeyRightArrow: return RIGHTARROWKEY;
+ case GHOST_kKeyUpArrow: return UPARROWKEY;
+ case GHOST_kKeyDownArrow: return DOWNARROWKEY;
+
+ case GHOST_kKeyPrintScreen: return 0;
+ case GHOST_kKeyPause: return PAUSEKEY;
+
+ case GHOST_kKeyInsert: return INSERTKEY;
+ case GHOST_kKeyDelete: return DELKEY;
+ case GHOST_kKeyHome: return HOMEKEY;
+ case GHOST_kKeyEnd: return ENDKEY;
+ case GHOST_kKeyUpPage: return PAGEUPKEY;
+ case GHOST_kKeyDownPage: return PAGEDOWNKEY;
+
+ case GHOST_kKeyNumpadPeriod: return PADPERIOD;
+ case GHOST_kKeyNumpadEnter: return PADENTER;
+ case GHOST_kKeyNumpadPlus: return PADPLUSKEY;
+ case GHOST_kKeyNumpadMinus: return PADMINUS;
+ case GHOST_kKeyNumpadAsterisk: return PADASTERKEY;
+ case GHOST_kKeyNumpadSlash: return PADSLASHKEY;
+
+ case GHOST_kKeyGrLess: return GRLESSKEY;
+
+ default:
+ return UNKNOWNKEY; /* GHOST_kKeyUnknown */
+ }
+ }
+}
+
+/* adds customdata to event */
+static void update_tablet_data(wmWindow *win, wmEvent *event)
+{
+ const GHOST_TabletData *td= GHOST_GetTabletData(win->ghostwin);
+
+ /* if there's tablet data from an active tablet device then add it */
+ if ((td != NULL) && td->Active) {
+ struct wmTabletData *wmtab= MEM_mallocN(sizeof(wmTabletData), "customdata tablet");
+
+ wmtab->Active = td->Active;
+ wmtab->Pressure = td->Pressure;
+ wmtab->Xtilt = td->Xtilt;
+ wmtab->Ytilt = td->Ytilt;
+
+ event->custom= EVT_DATA_TABLET;
+ event->customdata= wmtab;
+ event->customdatafree= 1;
+ }
+}
+
+
+/* windows store own event queues, no bContext here */
+void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata)
+{
+ wmEvent event, *evt= win->eventstate;
+
+ /* initialize and copy state (only mouse x y and modifiers) */
+ event= *evt;
+
+ switch (type) {
+ /* mouse move */
+ case GHOST_kEventCursorMove: {
+ if(win->active) {
+ GHOST_TEventCursorData *cd= customdata;
+ int cx, cy;
+
+ GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy);
+
+ event.type= MOUSEMOVE;
+ event.x= evt->x= cx;
+ event.y= evt->y= (win->sizey-1) - cy;
+
+ ED_screen_set_subwinactive(win); /* state variables in screen */
+
+ update_tablet_data(win, &event);
+ wm_event_add(win, &event);
+ }
+ break;
+ }
+ /* mouse button */
+ case GHOST_kEventButtonDown:
+ case GHOST_kEventButtonUp: {
+ GHOST_TEventButtonData *bd= customdata;
+ event.val= (type==GHOST_kEventButtonDown);
+
+ if (bd->button == GHOST_kButtonMaskLeft)
+ event.type= LEFTMOUSE;
+ else if (bd->button == GHOST_kButtonMaskRight)
+ event.type= RIGHTMOUSE;
+ else
+ event.type= MIDDLEMOUSE;
+
+ if(event.val)
+ event.keymodifier= evt->keymodifier= event.type;
+ else
+ event.keymodifier= evt->keymodifier= 0;
+
+ update_tablet_data(win, &event);
+ wm_event_add(win, &event);
+
+ break;
+ }
+ /* keyboard */
+ case GHOST_kEventKeyDown:
+ case GHOST_kEventKeyUp: {
+ GHOST_TEventKeyData *kd= customdata;
+ event.type= convert_key(kd->key);
+ event.ascii= kd->ascii;
+ event.val= (type==GHOST_kEventKeyDown); /* XXX eventmatch uses defines, bad code... */
+
+ /* modifiers */
+ if (event.type==LEFTSHIFTKEY || event.type==RIGHTSHIFTKEY) {
+ event.shift= evt->shift= event.val;
+ } else if (event.type==LEFTCTRLKEY || event.type==RIGHTCTRLKEY) {
+ event.ctrl= evt->ctrl= event.val;
+ } else if (event.type==LEFTALTKEY || event.type==RIGHTALTKEY) {
+ event.alt= evt->alt= event.val;
+ } else if (event.type==COMMANDKEY) {
+ event.oskey= evt->oskey= event.val;
+ }
+
+ wm_event_add(win, &event);
+
+ break;
+ }
+
+ case GHOST_kEventWheel: {
+ GHOST_TEventWheelData* wheelData = customdata;
+
+ if (wheelData->z > 0)
+ event.type= WHEELUPMOUSE;
+ else
+ event.type= WHEELDOWNMOUSE;
+
+ event.val= wheelData->z; /* currently -1 or +1, see ghost for improvements here... */
+ wm_event_add(win, &event);
+
+ break;
+ }
+ case GHOST_kEventTimer: {
+ event.type= TIMER;
+ event.custom= EVT_DATA_TIMER;
+ event.customdata= customdata;
+ wm_event_add(win, &event);
+
+ break;
+ }
+
+ case GHOST_kEventUnknown:
+ case GHOST_kNumEventTypes:
+ break;
+ }
+}
+