19e858a9f59640b5d02248ead7dd3c217a851ff3
[blender.git] / source / blender / src / ghostwinlay.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32 #include <stdlib.h>
33 #include <stdio.h>
34
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include "MEM_guardedalloc.h"
40
41 #include "DNA_listBase.h"       
42 #include "DNA_userdef_types.h"  /* U.flag & TWOBUTTONMOUSE */
43
44 #include "BLI_blenlib.h"
45
46 #include "GHOST_C-api.h"
47
48 #include "BKE_utildefines.h"
49 #include "BKE_global.h"
50
51 #include "BIF_gl.h"
52 #include "BIF_graphics.h"
53 #include "BIF_mywindow.h"
54 #include "BIF_screen.h"
55 #include "BIF_usiblender.h"
56 #include "BIF_cursors.h"
57
58 #include "PIL_dynlib.h"
59
60 #include "mydevice.h"
61 #include "blendef.h"
62
63 #include "winlay.h"
64
65 #include <math.h>
66
67
68 #ifdef __APPLE__
69 #include <OpenGL/OpenGL.h>
70 #define __CARBONSOUND__
71 #include <Carbon/Carbon.h>
72
73 /*declarations*/
74 int checkAppleVideoCard(void);
75 void getMacAvailableBounds(short *, short *, short *, short *);
76
77 #endif
78 ///
79
80 struct _Window {
81         GHOST_WindowHandle      ghostwin;
82         
83         /* Handler and private data for handler */
84         WindowHandlerFP         handler;
85         void                            *user_data;
86         
87         /* Window state */
88         int             size[2], position[2];
89         int             active, visible;
90         
91         /* Last known mouse/button/qualifier state */
92         int             lmouse[2];
93         int             lqual;          /* (LR_SHFTKEY, LR_CTRLKEY, LR_ALTKEY, LR_COMMANDKEY) */
94         int             lmbut;          /* (L_MOUSE, M_MOUSE, R_MOUSE) */
95
96         /* xtilt and ytilt represent how much the pen is tilted away from 
97          * vertically upright in either the X or Y direction, with X and Y the
98          * axes of the tablet surface.
99          * In other words, Xtilt and Ytilt are components of a vector created by projecting
100          * the pen's angle in 3D space vertically downwards on to the XY plane
101          * --Matt
102          */
103         float pressure;                 /* tablet pressure - 0.0 (no pressure) to 1.0 (full pressure) */
104                                                         /* mouse clicks and non-contacting stylus buttons generate pressure of 0.0. */
105         float xtilt, ytilt;             /* tablet tilt value - x and y components of 3D angle 
106                                                          * ranging from 0.0 (pen upright) to 1.0 (pen fully leaning over) */
107         short activedevice;             /* Active input device currently in use (DEV_MOUSE, DEV_STYLUS, DEV_ERASER) */
108         
109         
110         /* Tracks the faked mouse button, if non-zero it is
111          * the event number of the last faked button.
112          */
113         int             faked_mbut;
114
115                 /* Last known ndof device state
116          * note that the ghost device manager 
117          * can handle any number of devices, but ghostwinlay can't
118          */
119     float   ndof[7];    /* tx, ty, tz, rx, ry, rz, dt */
120
121         GHOST_TimerTaskHandle   timer;
122         int                                             timer_event;
123 };
124
125 ///
126
127 #ifdef __APPLE__
128
129 /* to avoid killing small end comps, we want to allow
130    blender to start maximised if all the followings are true :
131                 - Renderer is OpenGL capable
132                 - Hardware acceleration
133                 - VRAM > 16 Mo
134                 
135    we will bail out if VRAM is less than 8Mo
136                 */
137                 
138 static int macPrefState = 0;
139                 
140 int checkAppleVideoCard(void) {
141         long theErr;
142         unsigned long display_mask;
143         CGLRendererInfoObj rend;
144         long nrend;
145         int j;
146         long value;
147         long maxvram = 0;   /* we get always more than 1 renderer, check one, at least, has 8 Mo */
148         
149         display_mask = CGDisplayIDToOpenGLDisplayMask (CGMainDisplayID() );     
150         
151         theErr = CGLQueryRendererInfo( display_mask, &rend, &nrend);
152         if (theErr == 0) {
153                 theErr = CGLDescribeRenderer (rend, 0, kCGLRPRendererCount, &nrend);
154                 if (theErr == 0) {
155                         for (j = 0; j < nrend; j++) {
156                                 theErr = CGLDescribeRenderer (rend, j, kCGLRPVideoMemory, &value); 
157                                 if (value > maxvram)
158                                         maxvram = value;
159                                 if ((theErr == 0) && (value >= 20000000)) {
160                                         theErr = CGLDescribeRenderer (rend, j, kCGLRPAccelerated, &value); 
161                                         if ((theErr == 0) && (value != 0)) {
162                                                 theErr = CGLDescribeRenderer (rend, j, kCGLRPCompliant, &value); 
163                                                 if ((theErr == 0) && (value != 0)) {
164                                                         /*fprintf(stderr,"make it big\n");*/
165                                                         CGLDestroyRendererInfo (rend);
166                                                         macPrefState = 8;
167                                                         return 1;
168                                                 }
169                                         }
170                                 }
171                         }
172                 }
173         }
174         if (maxvram < 7500000 ) {       /* put a standard alert and quit*/ 
175                 SInt16 junkHit;
176                 char  inError[] = "* Not enough VRAM    ";
177                 char  inText[] = "* blender needs at least 8Mb    ";
178                 inError[0] = 16;
179                 inText[0] = 28;
180                                 
181                 fprintf(stderr, " vram is %li . not enough, aborting\n", maxvram);
182                 StandardAlert (   kAlertStopAlert, (ConstStr255Param) &inError, (ConstStr255Param)&inText,NULL,&junkHit);
183                 abort();
184         }
185         CGLDestroyRendererInfo (rend);
186         return 0;
187 }
188
189 void getMacAvailableBounds(short *top, short *left, short *bottom, short *right) {
190         Rect outAvailableRect;
191         
192         GetAvailableWindowPositioningBounds ( GetMainDevice(), &outAvailableRect);
193         
194         *top = outAvailableRect.top;  
195     *left = outAvailableRect.left;
196     *bottom = outAvailableRect.bottom; 
197     *right = outAvailableRect.right;
198 }
199
200 #endif
201
202
203 static GHOST_SystemHandle g_system= 0;
204
205         /* Some simple ghost <-> blender conversions */
206         
207 static GHOST_TStandardCursor convert_cursor(int curs) {
208         switch(curs) {
209         default:
210         case CURSOR_STD:                return GHOST_kStandardCursorDefault;
211         case CURSOR_VPAINT:             return GHOST_kStandardCursorRightArrow;
212         case CURSOR_FACESEL:            return GHOST_kStandardCursorRightArrow;
213         case CURSOR_WAIT:               return GHOST_kStandardCursorWait;
214         case CURSOR_EDIT:               return GHOST_kStandardCursorCrosshair;
215         case CURSOR_HELP:               return GHOST_kStandardCursorHelp;
216         case CURSOR_X_MOVE:             return GHOST_kStandardCursorLeftRight;
217         case CURSOR_Y_MOVE:             return GHOST_kStandardCursorUpDown;
218         case CURSOR_PENCIL:             return GHOST_kStandardCursorPencil;
219         }
220 }
221
222 static int convert_mbut(GHOST_TButtonMask but) {
223         if (but == GHOST_kButtonMaskLeft) {
224                 return LEFTMOUSE;
225         } else if (but == GHOST_kButtonMaskRight) {
226                 return RIGHTMOUSE;
227         } else {
228                 return MIDDLEMOUSE;
229         }
230 }
231
232 static int convert_key(GHOST_TKey key) {
233         if (key>=GHOST_kKeyA && key<=GHOST_kKeyZ) {
234                 return (AKEY + ((int) key - GHOST_kKeyA));
235         } else if (key>=GHOST_kKey0 && key<=GHOST_kKey9) {
236                 return (ZEROKEY + ((int) key - GHOST_kKey0));
237         } else if (key>=GHOST_kKeyNumpad0 && key<=GHOST_kKeyNumpad9) {
238                 return (PAD0 + ((int) key - GHOST_kKeyNumpad0));
239         } else if (key>=GHOST_kKeyF1 && key<=GHOST_kKeyF12) {
240                 return (F1KEY + ((int) key - GHOST_kKeyF1));
241         } else {
242                 switch (key) {
243                 case GHOST_kKeyBackSpace:               return BACKSPACEKEY;
244                 case GHOST_kKeyTab:                             return TABKEY;
245                 case GHOST_kKeyLinefeed:                return LINEFEEDKEY;
246                 case GHOST_kKeyClear:                   return 0;
247                 case GHOST_kKeyEnter:                   return RETKEY;
248         
249                 case GHOST_kKeyEsc:                             return ESCKEY;
250                 case GHOST_kKeySpace:                   return SPACEKEY;
251                 case GHOST_kKeyQuote:                   return QUOTEKEY;
252                 case GHOST_kKeyComma:                   return COMMAKEY;
253                 case GHOST_kKeyMinus:                   return MINUSKEY;
254                 case GHOST_kKeyPeriod:                  return PERIODKEY;
255                 case GHOST_kKeySlash:                   return SLASHKEY;
256
257                 case GHOST_kKeySemicolon:               return SEMICOLONKEY;
258                 case GHOST_kKeyEqual:                   return EQUALKEY;
259
260                 case GHOST_kKeyLeftBracket:             return LEFTBRACKETKEY;
261                 case GHOST_kKeyRightBracket:    return RIGHTBRACKETKEY;
262                 case GHOST_kKeyBackslash:               return BACKSLASHKEY;
263                 case GHOST_kKeyAccentGrave:             return ACCENTGRAVEKEY;
264
265                 case GHOST_kKeyLeftShift:               return LEFTSHIFTKEY;
266                 case GHOST_kKeyRightShift:              return RIGHTSHIFTKEY;
267                 case GHOST_kKeyLeftControl:             return LEFTCTRLKEY;
268                 case GHOST_kKeyRightControl:    return RIGHTCTRLKEY;
269                 case GHOST_kKeyCommand:                 return COMMANDKEY;
270                 case GHOST_kKeyLeftAlt:                 return LEFTALTKEY;
271                 case GHOST_kKeyRightAlt:                return RIGHTALTKEY;
272
273                 case GHOST_kKeyCapsLock:                return CAPSLOCKKEY;
274                 case GHOST_kKeyNumLock:                 return 0;
275                 case GHOST_kKeyScrollLock:              return 0;
276
277                 case GHOST_kKeyLeftArrow:               return LEFTARROWKEY;
278                 case GHOST_kKeyRightArrow:              return RIGHTARROWKEY;
279                 case GHOST_kKeyUpArrow:                 return UPARROWKEY;
280                 case GHOST_kKeyDownArrow:               return DOWNARROWKEY;
281
282                 case GHOST_kKeyPrintScreen:             return 0;
283                 case GHOST_kKeyPause:                   return PAUSEKEY;
284
285                 case GHOST_kKeyInsert:                  return INSERTKEY;
286                 case GHOST_kKeyDelete:                  return DELKEY;
287                 case GHOST_kKeyHome:                    return HOMEKEY;
288                 case GHOST_kKeyEnd:                             return ENDKEY;
289                 case GHOST_kKeyUpPage:                  return PAGEUPKEY;
290                 case GHOST_kKeyDownPage:                return PAGEDOWNKEY;
291
292                 case GHOST_kKeyNumpadPeriod:    return PADPERIOD;
293                 case GHOST_kKeyNumpadEnter:             return PADENTER;
294                 case GHOST_kKeyNumpadPlus:              return PADPLUSKEY;
295                 case GHOST_kKeyNumpadMinus:             return PADMINUS;
296                 case GHOST_kKeyNumpadAsterisk:  return PADASTERKEY;
297                 case GHOST_kKeyNumpadSlash:             return PADSLASHKEY;
298
299                 case GHOST_kKeyGrLess:              return GRLESSKEY; 
300                         
301                 case GHOST_kKeyUnknown:                 return UNKNOWNKEY;
302
303                 default:
304                         return 0;
305                 }
306         }
307 }
308
309         /***/
310         
311
312 static Window *window_new(GHOST_WindowHandle ghostwin)
313 {
314         Window *win= MEM_callocN(sizeof(*win), "Window");
315         win->ghostwin= ghostwin;
316         
317         return win;
318 }
319
320 static void window_handle(Window *win, short event, short val)
321 {
322         if (win->handler) {
323                 win->handler(win, win->user_data, event, val, 0);
324         }
325 }
326
327 static void window_handle_ext(Window *win, short event, short val, short extra)
328 {
329         if (win->handler) {
330                 win->handler(win, win->user_data, event, val, extra);
331         }
332 }
333
334 static void window_free(Window *win) 
335 {
336         MEM_freeN(win);
337 }
338
339         /***/
340
341 static Window *active_gl_window= NULL;
342
343 Window *window_open(char *title, int posx, int posy, int sizex, int sizey, int start_maximized)
344 {
345         GHOST_WindowHandle ghostwin;
346         GHOST_TWindowState inital_state;
347         int scr_w, scr_h;
348     int i;
349
350         winlay_get_screensize(&scr_w, &scr_h);
351         posy= (scr_h-posy-sizey);
352         
353         if (start_maximized == G_WINDOWSTATE_FULLSCREEN)
354                 inital_state = start_maximized?GHOST_kWindowStateFullScreen:GHOST_kWindowStateNormal;
355         else
356                 inital_state = start_maximized?GHOST_kWindowStateMaximized:GHOST_kWindowStateNormal;
357 #ifdef __APPLE__
358         inital_state += macPrefState;
359 #endif
360
361         ghostwin= GHOST_CreateWindow(g_system, 
362                                                                 title, 
363                                                                 posx, posy, sizex, sizey, 
364                                                                 inital_state, 
365                                                                 GHOST_kDrawingContextTypeOpenGL,
366                                                                 0 /* no stereo */);
367         
368         if (ghostwin) {
369                 Window *win= window_new(ghostwin);
370                 
371                 if (win) {
372                         GHOST_SetWindowUserData(ghostwin, win);
373                         
374                         win->position[0]= posx;
375                         win->position[1]= posy;
376                         win->size[0]= sizex;
377                         win->size[1]= sizey;
378                         
379                         win->lmouse[0]= win->size[0]/2;
380                         win->lmouse[1]= win->size[1]/2;
381
382             for (i = 0; i < 7; ++i)
383                 win->ndof[i] = 0;
384                 
385                         
386                 } else {
387                         GHOST_DisposeWindow(g_system, ghostwin);
388                 }
389                 
390                 return win;
391         } else {
392                 return NULL;
393         }
394 }
395
396 void window_set_handler(Window *win, WindowHandlerFP handler, void *user_data)
397 {
398         win->handler= handler;
399         win->user_data= user_data;
400 }
401
402 static void window_timer_proc(GHOST_TimerTaskHandle timer, GHOST_TUns64 time)
403 {
404         Window *win= GHOST_GetTimerTaskUserData(timer);
405
406         win->handler(win, win->user_data, win->timer_event, 0, 0);
407 }
408
409 void window_set_timer(Window *win, int delay_ms, int event)
410 {
411         if (win->timer) GHOST_RemoveTimer(g_system, win->timer);
412
413         win->timer_event= event;
414         win->timer= GHOST_InstallTimer(g_system, delay_ms, delay_ms, window_timer_proc, win);
415 }
416
417 void window_destroy(Window *win) {
418         if (active_gl_window==win) {
419                 active_gl_window= NULL;
420         }
421         
422         if (win->timer) {
423                 GHOST_RemoveTimer(g_system, win->timer);
424                 win->timer= NULL;
425         }
426
427         GHOST_DisposeWindow(g_system, win->ghostwin);
428         window_free(win);
429 }
430
431 void window_set_cursor(Window *win, int curs) {
432         if (curs==CURSOR_NONE) {
433                 GHOST_SetCursorVisibility(win->ghostwin, 0);
434         } else {
435                 GHOST_SetCursorVisibility(win->ghostwin, 1);
436                 
437                 /* detect if we use system cursor or Blender cursor */
438                 switch(curs) {
439                         case CURSOR_TEXTEDIT:
440                                 SetBlenderCursor(BC_TEXTEDITCURSOR);
441                                 break;
442                         case CURSOR_VPAINT:
443                                 SetBlenderCursor(BC_PAINTBRUSHCURSOR);
444                                 break;
445                         default:
446                                 GHOST_SetCursorShape(win->ghostwin, convert_cursor(curs));
447                 }
448         }
449 }
450
451 void window_set_custom_cursor(Window *win, unsigned char mask[16][2], 
452                                         unsigned char bitmap[16][2], int hotx, int hoty) {
453         GHOST_SetCustomCursorShape(win->ghostwin, bitmap, mask, hotx, hoty);
454 }
455
456 void window_set_custom_cursor_ex(Window *win, BCursor *cursor, int useBig) {
457         if (useBig) {
458                 GHOST_SetCustomCursorShapeEx(win->ghostwin, 
459                         (GHOST_TUns8 *)cursor->big_bm, (GHOST_TUns8 *)cursor->big_mask, 
460                         cursor->big_sizex,cursor->big_sizey,
461                         cursor->big_hotx,cursor->big_hoty,
462                         cursor->fg_color, cursor->bg_color);
463         } else {
464                 GHOST_SetCustomCursorShapeEx(win->ghostwin, 
465                         (GHOST_TUns8 *)cursor->small_bm, (GHOST_TUns8 *)cursor->small_mask, 
466                         cursor->small_sizex,cursor->small_sizey,
467                         cursor->small_hotx,cursor->small_hoty,
468                         cursor->fg_color, cursor->bg_color);
469         }
470 }
471
472 void window_make_active(Window *win) {
473         if (win != active_gl_window) {
474                 win->lmbut= 0;  /* keeps hanging when mousepressed while other window opened */
475                 active_gl_window= win;
476                 GHOST_ActivateWindowDrawingContext(win->ghostwin);
477         }
478 }
479
480 void window_swap_buffers(Window *win) {
481         GHOST_SwapWindowBuffers(win->ghostwin);
482 }
483
484 static int query_qual(char qual) {
485         GHOST_TModifierKeyMask left, right;
486         int val= 0;
487         
488         if (qual=='s') {
489                 left= GHOST_kModifierKeyLeftShift;
490                 right= GHOST_kModifierKeyRightShift;
491         } else if (qual=='c') {
492                 left= GHOST_kModifierKeyLeftControl;
493                 right= GHOST_kModifierKeyRightControl;
494         } else if (qual=='C') {
495                 left= right= GHOST_kModifierKeyCommand;
496         } else {
497                 left= GHOST_kModifierKeyLeftAlt;
498                 right= GHOST_kModifierKeyRightAlt;
499         }
500
501         GHOST_GetModifierKeyState(g_system, left, &val);
502         if (!val)
503                 GHOST_GetModifierKeyState(g_system, right, &val);
504         
505         return val;
506 }
507
508 static int change_bit(int val, int bit, int to_on) {
509         return to_on?(val|bit):(val&~bit);
510 }
511
512 static void update_tablet_data(Window *win, Window *ghostwin) {
513         const GHOST_TabletData *td= GHOST_GetTabletData(ghostwin);
514         
515         /* if there's tablet data from an active tablet device then use it,
516          * otherwise set all tablet related data to default */
517         if ((td != NULL) && ELEM(td->Active, DEV_STYLUS, DEV_ERASER)) {
518                 win->activedevice = (short)td->Active;
519                 win->pressure = td->Pressure;
520                 win->xtilt = td->Xtilt;
521                 win->ytilt = td->Ytilt;
522         } else {
523                 win->activedevice = DEV_MOUSE;
524                 win->pressure = 0.0;
525                 win->xtilt = win->ytilt = 0.0;
526         }
527 }
528
529
530 static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) 
531 {
532         GHOST_TEventType type= GHOST_GetEventType(evt);
533
534         if (type == GHOST_kEventQuit) {
535                 exit_usiblender();
536         } else {
537                 GHOST_WindowHandle ghostwin= GHOST_GetEventWindow(evt);
538                 GHOST_TEventDataPtr data= GHOST_GetEventData(evt);
539                 Window *win;
540                 
541                 if (!ghostwin) {
542                         // XXX - should be checked, why are we getting an event here, and
543                         //      what is it?
544
545                         return 1;
546                 } else if (!GHOST_ValidWindow(g_system, ghostwin)) {
547                         // XXX - should be checked, why are we getting an event here, and
548                         //      what is it?
549
550                         return 1;
551                 } else {
552                         win= GHOST_GetWindowUserData(ghostwin);
553                 }
554                 
555                 switch (type) {
556
557         case GHOST_kEventNDOFMotion: {
558             // update ndof device data, and dispatch motion event
559             GHOST_TEventNDOFData *sb= data;
560
561             win->ndof[0] = sb->tx;
562             win->ndof[1] = sb->ty;
563             win->ndof[2] = sb->tz;
564             win->ndof[3] = sb->rx;
565             win->ndof[4] = sb->ry;
566             win->ndof[5] = sb->rz;
567             win->ndof[6] = sb->dt;
568
569             // start interaction for larger than teeny-tiny motions
570             if ((fabsf(sb->tx) > 0.03f) ||
571                 (fabsf(sb->ty) > 0.03f) ||
572                 (fabsf(sb->tz) > 0.03f) ||
573                 (fabsf(sb->rx) > 0.03f) ||
574                 (fabsf(sb->ry) > 0.03f) ||
575                 (fabsf(sb->rz) > 0.03f)) {
576                     window_handle(win, NDOFMOTION, sb->dt * 255);
577             }
578           break;
579         }
580
581                 case GHOST_kEventCursorMove: {
582                         if(win->active == 1) {
583                                 GHOST_TEventCursorData *cd= data;
584                                 
585                                 int cx, cy;
586                                 
587                                 GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy);
588                                 win->lmouse[0]= cx;
589                                 win->lmouse[1]= (win->size[1]-1) - cy;
590                                 
591                                 update_tablet_data(win, ghostwin);                      
592                                 window_handle(win, MOUSEX, win->lmouse[0]);
593                                 window_handle(win, MOUSEY, win->lmouse[1]);
594                         }
595                         break;
596                 }
597                 case GHOST_kEventButtonDown:
598                 case GHOST_kEventButtonUp: {
599                         GHOST_TEventButtonData *bd= data;
600                         int val= (type==GHOST_kEventButtonDown);
601                         int bbut= convert_mbut(bd->button);
602                 
603                         if (bbut==LEFTMOUSE) {
604                                 if (val) {
605                                         if (win->lqual & LR_COMMANDKEY) {
606                                                 bbut= win->faked_mbut= RIGHTMOUSE;
607                                         } else if ((win->lqual & LR_ALTKEY) && (U.flag & USER_TWOBUTTONMOUSE)) {
608                                                 /* finally, it actually USES the userpref! :) -intrr */
609                                                 bbut= win->faked_mbut= MIDDLEMOUSE;
610                                         }
611                                 } else {
612                                         if (win->faked_mbut) {
613                                                 bbut= win->faked_mbut;
614                                                 win->faked_mbut= 0;
615                                         }
616                                 }
617                         }
618
619                         if (bbut==LEFTMOUSE) {
620                                 win->lmbut= change_bit(win->lmbut, L_MOUSE, val);
621                         } else if (bbut==MIDDLEMOUSE) {
622                                 win->lmbut= change_bit(win->lmbut, M_MOUSE, val);
623                         } else {
624                                 win->lmbut= change_bit(win->lmbut, R_MOUSE, val);
625                         }
626                         
627                         update_tablet_data(win, ghostwin);
628                         window_handle(win, bbut, val);
629                         
630                         break;
631                 }
632         
633                 case GHOST_kEventKeyDown:
634                 case GHOST_kEventKeyUp: {
635                         GHOST_TEventKeyData *kd= data;
636                         int val= (type==GHOST_kEventKeyDown);
637                         int bkey= convert_key(kd->key);
638
639                         if (bkey) {
640                                 if (bkey==LEFTSHIFTKEY || bkey==RIGHTSHIFTKEY) {
641                                         win->lqual= change_bit(win->lqual, LR_SHIFTKEY, val);
642                                 } else if (bkey==LEFTCTRLKEY || bkey==RIGHTCTRLKEY) {
643                                         win->lqual= change_bit(win->lqual, LR_CTRLKEY, val);
644                                 } else if (bkey==LEFTALTKEY || bkey==RIGHTALTKEY) {
645                                         win->lqual= change_bit(win->lqual, LR_ALTKEY, val);
646                                 } else if (bkey==COMMANDKEY) {
647                                         win->lqual= change_bit(win->lqual, LR_COMMANDKEY, val);
648                                 }
649
650                                 window_handle_ext(win, bkey, val, kd->ascii);
651                         }
652                         
653                         break;
654                 }
655
656                 case GHOST_kEventWheel: {
657                         GHOST_TEventWheelData* wheelData = (GHOST_TEventWheelData*) data;
658                         if (wheelData->z > 0) {
659                                 window_handle(win, WHEELUPMOUSE, 1);
660                         } else {
661                                 window_handle(win, WHEELDOWNMOUSE, 1);
662                         }
663                         break;
664                 }
665
666                 case GHOST_kEventWindowDeactivate:
667                 case GHOST_kEventWindowActivate: {
668                         win->active= (type==GHOST_kEventWindowActivate);
669                         window_handle(win, INPUTCHANGE, win->active);
670                         
671                         if (win->active) {
672                                 if ((win->lqual & LR_SHIFTKEY) && !query_qual('s')) {
673                                         win->lqual= change_bit(win->lqual, LR_SHIFTKEY, 0);
674                                         window_handle(win, LEFTSHIFTKEY, 0);
675                                 }
676                                 if ((win->lqual & LR_CTRLKEY) && !query_qual('c')) {
677                                         win->lqual= change_bit(win->lqual, LR_CTRLKEY, 0);
678                                         window_handle(win, LEFTCTRLKEY, 0);
679                                 }
680                                 if ((win->lqual & LR_ALTKEY) && !query_qual('a')) {
681                                         win->lqual= change_bit(win->lqual, LR_ALTKEY, 0);
682                                         window_handle(win, LEFTALTKEY, 0);
683                                 }
684                                 if ((win->lqual & LR_COMMANDKEY) && !query_qual('C')) {
685                                         win->lqual= change_bit(win->lqual, LR_COMMANDKEY, 0);
686                                         window_handle(win, LR_COMMANDKEY, 0);
687                                 }
688
689                                 /* 
690                                  * XXX quick hack so OSX version works better
691                                  * when the window is clicked on (focused).
692                                  *
693                                  * it used to pass on the old win->lmouse value,
694                                  * which causes a wrong click in Blender.
695                                  * Actually, a 'focus' click should not be passed
696                                  * on to blender... (ton)
697                                  */
698                                 if(1) { /* enables me to add locals */
699                                         int cx, cy, wx, wy;
700                                         GHOST_GetCursorPosition(g_system, &wx, &wy);
701
702                                         GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy);
703                                         win->lmouse[0]= cx;
704                                         win->lmouse[1]= (win->size[1]-1) - cy;
705                                         window_handle(win, MOUSEX, win->lmouse[0]);
706                                         window_handle(win, MOUSEY, win->lmouse[1]);
707                                 }
708                         }
709                         
710                         break;
711                 }
712                 case GHOST_kEventWindowClose: {
713                         window_handle(win, WINCLOSE, 1);
714                         break;
715                 }
716                 case GHOST_kEventWindowUpdate: {
717                         window_handle(win, REDRAW, 1);
718                         break;
719                 }
720                 case GHOST_kEventWindowSize: {
721                         GHOST_RectangleHandle client_rect;
722                         int l, t, r, b, scr_w, scr_h;
723
724                         client_rect= GHOST_GetClientBounds(win->ghostwin);
725                         GHOST_GetRectangle(client_rect, &l, &t, &r, &b);
726                         
727                         GHOST_DisposeRectangle(client_rect);
728                         
729                         winlay_get_screensize(&scr_w, &scr_h);
730                         win->position[0]= l;
731                         win->position[1]= scr_h - b - 1;
732                         win->size[0]= r-l;
733                         win->size[1]= b-t;
734
735                         window_handle(win, RESHAPE, 1);
736                         break;
737                 }
738                 case GHOST_kEventUnknown:
739                 case GHOST_kEventQuit:
740                 case GHOST_kNumEventTypes:
741                         break;
742         }
743         }
744         
745         return 1;
746 }
747
748 void window_get_ndof(Window* win, float* sbval) {
749     int i;
750     for (i = 0; i < 7; ++i) {
751         *sbval++ = win->ndof[i];
752     }
753 }
754
755 char *window_get_title(Window *win) {
756         char *title= GHOST_GetTitle(win->ghostwin);
757         char *mem_title= BLI_strdup(title);
758         free(title);
759
760         return mem_title;
761 }
762
763 void window_set_title(Window *win, char *title) {
764         GHOST_SetTitle(win->ghostwin, title);
765 }
766
767 short window_get_qual(Window *win) 
768 {
769         int qual= 0;
770         
771         if( query_qual('s')) qual |= LR_SHIFTKEY;
772         if( query_qual('a')) qual |= LR_ALTKEY;
773         if( query_qual('c')) qual |= LR_CTRLKEY;
774         return qual;
775 //      return win->lqual;
776 }
777
778 short window_get_mbut(Window *win) {
779         return win->lmbut;
780 }
781
782 void window_get_mouse(Window *win, short *mval) {
783         mval[0]= win->lmouse[0];
784         mval[1]= win->lmouse[1];
785 }
786
787 float window_get_pressure(Window *win) {
788         return win->pressure;
789 }
790
791 void window_get_tilt(Window *win, float *xtilt, float *ytilt) {
792         *xtilt= win->xtilt;
793         *ytilt= win->ytilt;
794 }
795
796 short window_get_activedevice(Window *win) {
797         return win->activedevice;
798 }
799
800 void window_get_position(Window *win, int *posx_r, int *posy_r) {
801         *posx_r= win->position[0];
802         *posy_r= win->position[1];
803 }
804
805 void window_get_size(Window *win, int *width_r, int *height_r) {
806         *width_r= win->size[0];
807         *height_r= win->size[1];
808 }
809
810 void window_set_size(Window *win, int width, int height) {
811         GHOST_SetClientSize(win->ghostwin, width, height);
812 }
813
814 void window_lower(Window *win) {
815         GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderBottom);
816 }
817
818 void window_raise(Window *win) {
819         GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderTop);
820 #ifdef _WIN32
821         markdirty_all(); /* to avoid redraw errors in fullscreen mode (aphex) */
822 #endif
823 }
824
825 #if 0
826 //#ifdef _WIN32 //FULLSCREEN
827 void window_toggle_fullscreen(Window *win, int fullscreen) {
828         /* these two lines make sure front and backbuffer are equal. for swapbuffers */
829         markdirty_all();
830         screen_swapbuffers();
831
832         if(fullscreen)
833                 GHOST_SetWindowState(win->ghostwin, GHOST_kWindowStateFullScreen);
834         else
835                 GHOST_SetWindowState(win->ghostwin, GHOST_kWindowStateMaximized);
836 }
837 #endif
838
839 void window_warp_pointer(Window *win, int x, int y) {
840         int oldx=x, oldy=y;
841         
842         y= win->size[1] - y - 1;
843         GHOST_ClientToScreen(win->ghostwin, x, y, &x, &y);
844         GHOST_SetCursorPosition(g_system, x, y);
845         
846         /* on OSX (for example) the setcursor doesnt create event */
847         win->lmouse[0]= oldx;
848         win->lmouse[1]= oldy;
849 }
850
851 void window_queue_redraw(Window *win) {
852         GHOST_InvalidateWindow(win->ghostwin); // ghost will send back a redraw to blender
853 }
854
855 /***/
856
857 void winlay_process_events(int wait_for_event) {
858         GHOST_ProcessEvents(g_system, wait_for_event);
859         GHOST_DispatchEvents(g_system);
860 }
861
862 void winlay_get_screensize(int *width_r, int *height_r) {
863         unsigned int uiwidth;
864         unsigned int uiheight;
865         
866         if (!g_system) {
867                 GHOST_EventConsumerHandle consumer= GHOST_CreateEventConsumer(event_proc, NULL);
868         
869                 g_system= GHOST_CreateSystem();
870                 GHOST_AddEventConsumer(g_system, consumer);
871         }
872         
873         GHOST_GetMainDisplayDimensions(g_system, &uiwidth, &uiheight);
874         *width_r= uiwidth;
875         *height_r= uiheight;
876 }
877
878 Window *winlay_get_active_window(void) {
879         return active_gl_window;
880 }
881
882 void window_open_ndof(Window* win)
883 {
884     PILdynlib* ndofLib = PIL_dynlib_open("spaceplug.plug");
885     if (ndofLib) {
886
887         GHOST_OpenNDOF(g_system, win->ghostwin, 
888             PIL_dynlib_find_symbol(ndofLib, "ndofInit"),
889             PIL_dynlib_find_symbol(ndofLib, "ndofShutdown"),
890             PIL_dynlib_find_symbol(ndofLib, "ndofOpen"),
891             PIL_dynlib_find_symbol(ndofLib, "ndofEventHandler"));
892     }
893     else {
894         GHOST_OpenNDOF(g_system, win->ghostwin, 0, 0, 0, 0);
895     }
896  }