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