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