Two in one:
[blender.git] / source / blender / src / ghostwinlay.c
index 0345f77cf2860c744cc77d5bf6461f6e41a28493..d63574e79f9fc002c3659285bfceebac05301e73 100644 (file)
 #include <config.h>
 #endif
 
-#ifdef WIN32
-#include "BLI_winstuff.h"
-#endif
-
 #include "MEM_guardedalloc.h"
 
+#include "DNA_listBase.h"      
+#include "DNA_userdef_types.h" /* U.flag & TWOBUTTONMOUSE */
+
 #include "BLI_blenlib.h"
 
 #include "GHOST_C-api.h"
 #include "BIF_mywindow.h"
 #include "BIF_screen.h"
 #include "BIF_usiblender.h"
+#include "BIF_cursors.h"
 
 #include "mydevice.h"
 #include "blendef.h"
 
 #include "winlay.h"
 
+#ifdef __APPLE__
+#include <OpenGL/OpenGL.h>
+#define __CARBONSOUND__
+#include <Carbon/Carbon.h>
+
+/*declarations*/
+int checkAppleVideoCard(void);
+void getMacAvailableBounds(short *, short *, short *, short *);
+
+#endif
+///
+
+struct _Window {
+       GHOST_WindowHandle      ghostwin;
+       
+               /* Handler and private data for handler */
+       WindowHandlerFP         handler;
+       void                            *user_data;
+       
+               /* Window state */
+       int             size[2], position[2];
+       int             active, visible;
+       
+               /* Last known mouse/button/qualifier state */
+       int             lmouse[2];
+       int             lqual;          /* (LR_SHFTKEY, LR_CTRLKEY, LR_ALTKEY, LR_COMMANDKEY) */
+       int             lmbut;          /* (L_MOUSE, M_MOUSE, R_MOUSE) */
+
+               /* Tracks the faked mouse button, if non-zero it is
+                * the event number of the last faked button.
+                */
+       int             faked_mbut;
+
+       GHOST_TimerTaskHandle   timer;
+       int                                             timer_event;
+};
+
+///
+
+#ifdef __APPLE__
+
+/* to avoid killing small end comps, we want to allow
+   blender to start maximised if all the followings are true :
+               - Renderer is OpenGL capable
+               - Hardware acceleration
+               - VRAM > 16 Mo
+               
+   we will bail out if VRAM is less than 8Mo
+               */
+               
+static int macPrefState = 0;
+               
+int checkAppleVideoCard(void) {
+       long theErr;
+       unsigned long display_mask;
+       CGLRendererInfoObj rend;
+       long nrend;
+       int j;
+       long value;
+       long maxvram = 0;   /* we get always more than 1 renderer, check one, at least, has 8 Mo */
+       
+       display_mask = CGDisplayIDToOpenGLDisplayMask (CGMainDisplayID() );     
+       
+       theErr = CGLQueryRendererInfo( display_mask, &rend, &nrend);
+       if (theErr == 0) {
+               theErr = CGLDescribeRenderer (rend, 0, kCGLRPRendererCount, &nrend);
+               if (theErr == 0) {
+                       for (j = 0; j < nrend; j++) {
+                               theErr = CGLDescribeRenderer (rend, j, kCGLRPVideoMemory, &value); 
+                               if (value > maxvram)
+                                       maxvram = value;
+                               if ((theErr == 0) && (value >= 20000000)) {
+                                       theErr = CGLDescribeRenderer (rend, j, kCGLRPAccelerated, &value); 
+                                       if ((theErr == 0) && (value != 0)) {
+                                               theErr = CGLDescribeRenderer (rend, j, kCGLRPCompliant, &value); 
+                                               if ((theErr == 0) && (value != 0)) {
+                                                       /*fprintf(stderr,"make it big\n");*/
+                                                       CGLDestroyRendererInfo (rend);
+                                                       macPrefState = 8;
+                                                       return 1;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       if (maxvram < 7500000 ) {       /* put a standard alert and quit*/ 
+               SInt16 junkHit;
+               char  inError[] = "* Not enough VRAM    ";
+               char  inText[] = "* blender needs at least 8Mb    ";
+               inError[0] = 16;
+               inText[0] = 28;
+                               
+               fprintf(stderr, " vram is %li . not enough, aborting\n", maxvram);
+               StandardAlert (   kAlertStopAlert, (ConstStr255Param) &inError, (ConstStr255Param)&inText,NULL,&junkHit);
+               abort();
+       }
+       CGLDestroyRendererInfo (rend);
+       return 0;
+}
+
+void getMacAvailableBounds(short *top, short *left, short *bottom, short *right) {
+       Rect outAvailableRect;
+       
+       GetAvailableWindowPositioningBounds ( GetMainDevice(), &outAvailableRect);
+       
+       *top = outAvailableRect.top;  
+    *left = outAvailableRect.left;
+    *bottom = outAvailableRect.bottom; 
+    *right = outAvailableRect.right;
+}
+
+#endif
+
+
 static GHOST_SystemHandle g_system= 0;
 
        /* Some simple ghost <-> blender conversions */
@@ -68,13 +183,14 @@ static GHOST_TStandardCursor convert_cursor(int curs) {
        switch(curs) {
        default:
        case CURSOR_STD:                return GHOST_kStandardCursorDefault;
-       case CURSOR_VPAINT:             return GHOST_kStandardCursorLeftArrow;
-       case CURSOR_FACESEL:    return GHOST_kStandardCursorRightArrow;
+       case CURSOR_VPAINT:             return GHOST_kStandardCursorRightArrow;
+       case CURSOR_FACESEL:            return GHOST_kStandardCursorRightArrow;
        case CURSOR_WAIT:               return GHOST_kStandardCursorWait;
        case CURSOR_EDIT:               return GHOST_kStandardCursorCrosshair;
        case CURSOR_HELP:               return GHOST_kStandardCursorHelp;
        case CURSOR_X_MOVE:             return GHOST_kStandardCursorLeftRight;
        case CURSOR_Y_MOVE:             return GHOST_kStandardCursorUpDown;
+       case CURSOR_PENCIL:             return GHOST_kStandardCursorPencil;
        }
 }
 
@@ -125,6 +241,7 @@ static int convert_key(GHOST_TKey key) {
                case GHOST_kKeyRightShift:              return RIGHTSHIFTKEY;
                case GHOST_kKeyLeftControl:             return LEFTCTRLKEY;
                case GHOST_kKeyRightControl:    return RIGHTCTRLKEY;
+               case GHOST_kKeyCommand:                 return COMMANDKEY;
                case GHOST_kKeyLeftAlt:                 return LEFTALTKEY;
                case GHOST_kKeyRightAlt:                return RIGHTALTKEY;
 
@@ -153,6 +270,9 @@ static int convert_key(GHOST_TKey key) {
                case GHOST_kKeyNumpadMinus:             return PADMINUS;
                case GHOST_kKeyNumpadAsterisk:  return PADASTERKEY;
                case GHOST_kKeyNumpadSlash:             return PADSLASHKEY;
+
+               case GHOST_kKeyGrLess:              return GRLESSKEY; 
+                       
                case GHOST_kKeyUnknown:                 return UNKNOWNKEY;
 
                default:
@@ -163,31 +283,6 @@ static int convert_key(GHOST_TKey key) {
 
        /***/
        
-struct _Window {
-       GHOST_WindowHandle      ghostwin;
-       
-               /* Handler and private data for handler */
-       WindowHandlerFP         handler;
-       void                            *user_data;
-       
-               /* Window state */
-       int             size[2], position[2];
-       int             active, visible;
-       
-               /* Last known mouse/button/qualifier state */
-       int             lmouse[2];
-       int             lqual;          /* (LR_SHFTKEY, LR_CTRLKEY, LR_ALTKEY) */
-       int             lmbut;          /* (L_MOUSE, M_MOUSE, R_MOUSE) */
-       int             commandqual;
-
-               /* Tracks the faked mouse button, if non-zero it is
-                * the event number of the last faked button.
-                */
-       int             faked_mbut;
-
-       GHOST_TimerTaskHandle   timer;
-       int                                             timer_event;
-};
 
 static Window *window_new(GHOST_WindowHandle ghostwin)
 {
@@ -235,12 +330,13 @@ Window *window_open(char *title, int posx, int posy, int sizex, int sizey, int s
                GHOST_kWindowStateFullScreen:GHOST_kWindowStateNormal;
 #else
 #ifdef _WIN32  // FULLSCREEN
-       if (start_maximized == G_WINDOWSTATE_FULLSCREEN)
-               inital_state= GHOST_kWindowStateFullScreen;
-       else
+//     if (start_maximized == G_WINDOWSTATE_FULLSCREEN)
+//             inital_state= GHOST_kWindowStateFullScreen;
+//     else
                inital_state= start_maximized?GHOST_kWindowStateMaximized:GHOST_kWindowStateNormal;
-#else
+#else                  // APPLE
        inital_state= start_maximized?GHOST_kWindowStateMaximized:GHOST_kWindowStateNormal;
+       inital_state += macPrefState;
 #endif
 #endif
 
@@ -264,6 +360,8 @@ Window *window_open(char *title, int posx, int posy, int sizex, int sizey, int s
                        
                        win->lmouse[0]= win->size[0]/2;
                        win->lmouse[1]= win->size[1]/2;
+                       
+                       
                } else {
                        GHOST_DisposeWindow(g_system, ghostwin);
                }
@@ -314,16 +412,45 @@ void window_set_cursor(Window *win, int curs) {
                GHOST_SetCursorVisibility(win->ghostwin, 0);
        } else {
                GHOST_SetCursorVisibility(win->ghostwin, 1);
-               GHOST_SetCursorShape(win->ghostwin, convert_cursor(curs));
+               
+               /* detect if we use system cursor or Blender cursor */
+               switch(curs) {
+                       case CURSOR_TEXTEDIT:
+                               SetBlenderCursor(BC_TEXTEDITCURSOR);
+                               break;
+                       case CURSOR_VPAINT:
+                               SetBlenderCursor(BC_PAINTBRUSHCURSOR);
+                               break;
+                       default:
+                               GHOST_SetCursorShape(win->ghostwin, convert_cursor(curs));
+               }
        }
 }
 
-void window_set_custom_cursor(Window *win, unsigned char mask[16][2], unsigned char bitmap[16][2]) {
-       GHOST_SetCustomCursorShape(win->ghostwin, bitmap, mask, 7, 7);
+void window_set_custom_cursor(Window *win, unsigned char mask[16][2], 
+                                       unsigned char bitmap[16][2], int hotx, int hoty) {
+       GHOST_SetCustomCursorShape(win->ghostwin, bitmap, mask, hotx, hoty);
+}
+
+void window_set_custom_cursor_ex(Window *win, BCursor *cursor, int useBig) {
+       if (useBig) {
+               GHOST_SetCustomCursorShapeEx(win->ghostwin, 
+                       cursor->big_bm, cursor->big_mask, 
+                       cursor->big_sizex,cursor->big_sizey,
+                       cursor->big_hotx,cursor->big_hoty,
+                       cursor->fg_color, cursor->bg_color);
+       } else {
+               GHOST_SetCustomCursorShapeEx(win->ghostwin, 
+                       cursor->small_bm, cursor->small_mask, 
+                       cursor->small_sizex,cursor->small_sizey,
+                       cursor->small_hotx,cursor->small_hoty,
+                       cursor->fg_color, cursor->bg_color);
+       }
 }
 
 void window_make_active(Window *win) {
        if (win != active_gl_window) {
+               win->lmbut= 0;  /* keeps hanging when mousepressed while other window opened */
                active_gl_window= win;
                GHOST_ActivateWindowDrawingContext(win->ghostwin);
        }
@@ -361,7 +488,8 @@ static int change_bit(int val, int bit, int to_on) {
        return to_on?(val|bit):(val&~bit);
 }
 
-static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) {
+static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) 
+{
        GHOST_TEventType type= GHOST_GetEventType(evt);
 
        if (type == GHOST_kEventQuit) {
@@ -372,10 +500,14 @@ static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) {
                Window *win;
                
                if (!ghostwin) {
-                       printf("GHOST event error - no window - type: %d\n", type);
+                       // XXX - should be checked, why are we getting an event here, and
+                       //      what is it?
+
                        return 1;
                } else if (!GHOST_ValidWindow(g_system, ghostwin)) {
-                       printf("GHOST event error - invalid window - win: %p\n", ghostwin);
+                       // XXX - should be checked, why are we getting an event here, and
+                       //      what is it?
+
                        return 1;
                } else {
                        win= GHOST_GetWindowUserData(ghostwin);
@@ -383,16 +515,17 @@ static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) {
                
                switch (type) {
                case GHOST_kEventCursorMove: {
-                       GHOST_TEventCursorData *cd= data;
-                       int cx, cy;
-                       
-                       GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy);
-                       win->lmouse[0]= cx;
-                       win->lmouse[1]= (win->size[1]-1) - cy;
-
-                       window_handle(win, MOUSEX, win->lmouse[0]);
-                       window_handle(win, MOUSEY, win->lmouse[1]);
-                       
+                       if(win->active == 1) {
+                               GHOST_TEventCursorData *cd= data;
+                               int cx, cy;
+                               
+                               GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy);
+                               win->lmouse[0]= cx;
+                               win->lmouse[1]= (win->size[1]-1) - cy;
+                               
+                               window_handle(win, MOUSEX, win->lmouse[0]);
+                               window_handle(win, MOUSEY, win->lmouse[1]);
+                       }
                        break;
                }
                case GHOST_kEventButtonDown:
@@ -403,9 +536,10 @@ static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) {
                
                        if (bbut==LEFTMOUSE) {
                                if (val) {
-                                       if (win->commandqual) {
+                                       if (win->lqual & LR_COMMANDKEY) {
                                                bbut= win->faked_mbut= RIGHTMOUSE;
-                                       } else if (win->lqual & LR_ALTKEY) {
+                                       } else if ((win->lqual & LR_ALTKEY) && (U.flag & USER_TWOBUTTONMOUSE)) {
+                                               /* finally, it actually USES the userpref! :) -intrr */
                                                bbut= win->faked_mbut= MIDDLEMOUSE;
                                        }
                                } else {
@@ -434,10 +568,6 @@ static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) {
                        int val= (type==GHOST_kEventKeyDown);
                        int bkey= convert_key(kd->key);
 
-                       if (kd->key == GHOST_kKeyCommand) {
-                               win->commandqual= val;
-                       }
-
                        if (bkey) {
                                if (bkey==LEFTSHIFTKEY || bkey==RIGHTSHIFTKEY) {
                                        win->lqual= change_bit(win->lqual, LR_SHIFTKEY, val);
@@ -445,6 +575,8 @@ static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) {
                                        win->lqual= change_bit(win->lqual, LR_CTRLKEY, val);
                                } else if (bkey==LEFTALTKEY || bkey==RIGHTALTKEY) {
                                        win->lqual= change_bit(win->lqual, LR_ALTKEY, val);
+                               } else if (bkey==COMMANDKEY) {
+                                       win->lqual= change_bit(win->lqual, LR_COMMANDKEY, val);
                                }
 
                                window_handle_ext(win, bkey, val, kd->ascii);
@@ -481,14 +613,30 @@ static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) {
                                        win->lqual= change_bit(win->lqual, LR_ALTKEY, 0);
                                        window_handle(win, LEFTALTKEY, 0);
                                }
-                               win->commandqual= query_qual('C');
+                               if ((win->lqual & LR_COMMANDKEY) && !query_qual('C')) {
+                                       win->lqual= change_bit(win->lqual, LR_COMMANDKEY, 0);
+                                       window_handle(win, LR_COMMANDKEY, 0);
+                               }
 
                                /* 
                                 * XXX quick hack so OSX version works better
-                                * when the window is clicked on (focused). 
+                                * when the window is clicked on (focused).
+                                *
+                                * it used to pass on the old win->lmouse value,
+                                * which causes a wrong click in Blender.
+                                * Actually, a 'focus' click should not be passed
+                                * on to blender... (ton)
                                 */
-                               window_handle(win, MOUSEX, win->lmouse[0]);
-                               window_handle(win, MOUSEY, win->lmouse[1]);
+                               if(1) { /* enables me to add locals */
+                                       int cx, cy, wx, wy;
+                                       GHOST_GetCursorPosition(g_system, &wx, &wy);
+
+                                       GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy);
+                                       win->lmouse[0]= cx;
+                                       win->lmouse[1]= (win->size[1]-1) - cy;
+                                       window_handle(win, MOUSEX, win->lmouse[0]);
+                                       window_handle(win, MOUSEY, win->lmouse[1]);
+                               }
                        }
                        
                        break;
@@ -519,9 +667,13 @@ static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) {
                        window_handle(win, RESHAPE, 1);
                        break;
                }
-               }
+               case GHOST_kEventUnknown:
+               case GHOST_kEventQuit:
+               case GHOST_kNumEventTypes:
+                       break;
        }
-
+       }
+       
        return 1;
 }
 
@@ -537,8 +689,15 @@ void window_set_title(Window *win, char *title) {
        GHOST_SetTitle(win->ghostwin, title);
 }
 
-short window_get_qual(Window *win) {
-       return win->lqual;
+short window_get_qual(Window *win) 
+{
+       int qual= 0;
+       
+       if( query_qual('s')) qual |= LR_SHIFTKEY;
+       if( query_qual('a')) qual |= LR_ALTKEY;
+       if( query_qual('c')) qual |= LR_CTRLKEY;
+       return qual;
+//     return win->lqual;
 }
 
 short window_get_mbut(Window *win) {
@@ -555,6 +714,11 @@ void window_get_position(Window *win, int *posx_r, int *posy_r) {
        *posy_r= win->position[1];
 }
 
+const GHOST_TabletData* window_get_tablet_data(Window *win)
+{
+       return GHOST_GetTabletData(win->ghostwin);
+}
+
 void window_get_size(Window *win, int *width_r, int *height_r) {
        *width_r= win->size[0];
        *height_r= win->size[1];
@@ -570,10 +734,18 @@ void window_lower(Window *win) {
 
 void window_raise(Window *win) {
        GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderTop);
+#ifdef _WIN32
+       markdirty_all(); /* to avoid redraw errors in fullscreen mode (aphex) */
+#endif
 }
 
-#ifdef _WIN32  //FULLSCREEN
+#if 0
+//#ifdef _WIN32        //FULLSCREEN
 void window_toggle_fullscreen(Window *win, int fullscreen) {
+       /* these two lines make sure front and backbuffer are equal. for swapbuffers */
+       markdirty_all();
+       screen_swapbuffers();
+
        if(fullscreen)
                GHOST_SetWindowState(win->ghostwin, GHOST_kWindowStateFullScreen);
        else
@@ -582,13 +754,19 @@ void window_toggle_fullscreen(Window *win, int fullscreen) {
 #endif
 
 void window_warp_pointer(Window *win, int x, int y) {
+       int oldx=x, oldy=y;
+       
        y= win->size[1] - y - 1;
        GHOST_ClientToScreen(win->ghostwin, x, y, &x, &y);
        GHOST_SetCursorPosition(g_system, x, y);
+       
+       /* on OSX (for example) the setcursor doesnt create event */
+       win->lmouse[0]= oldx;
+       win->lmouse[1]= oldy;
 }
 
 void window_queue_redraw(Window *win) {
-       GHOST_InvalidateWindow(win->ghostwin);
+       GHOST_InvalidateWindow(win->ghostwin); // ghost will send back a redraw to blender
 }
 
 /***/