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