merge with/from trunk at r35190
[blender.git] / source / blender / windowmanager / intern / wm_window.c
index 09610a2829ed30ce0f75949bbdc64df301e425c3..44200294b6c1f19cab2c4ae4799df46bf2e65f52 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/windowmanager/intern/wm_window.c
+ *  \ingroup wm
+ */
+
+
 #include <math.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include "GHOST_C-api.h"
 
 #include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
 
 #include "BKE_blender.h"
 #include "BKE_context.h"
+#include "BKE_library.h"
 #include "BKE_global.h"
-#include "BKE_utildefines.h"
+#include "BKE_main.h"
+
 
 #include "BIF_gl.h"
 
 #include "wm_event_system.h"
 
 #include "ED_screen.h"
+#include "ED_fileselect.h"
 
 #include "PIL_time.h"
 
 #include "GPU_draw.h"
+#include "GPU_extensions.h"
 
 /* the global to talk to ghost */
 GHOST_SystemHandle g_system= NULL;
 
 /* set by commandline */
-static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0;
+static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0, initialstate= GHOST_kWindowStateNormal;
+static unsigned short useprefsize= 0;
 
 /* ******** win open & close ************ */
 
@@ -144,10 +155,9 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
                        CTX_wm_window_set(C, NULL);
        }       
 
-       if(wm->windrawable==win)
-               wm->windrawable= NULL;
-       if(wm->winactive==win)
-               wm->winactive= NULL;
+       /* always set drawable and active to NULL, prevents non-drawable state of main windows (bugs #22967 and #25071, possibly #22477 too) */
+       wm->windrawable= NULL;
+       wm->winactive= NULL;
 
        /* end running jobs, a job end also removes its timer */
        for(wt= wm->timers.first; wt; wt= wtnext) {
@@ -213,7 +223,7 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
        
        /* duplicate assigns to window */
        win->screen= ED_screen_duplicate(win, winorig->screen);
-       BLI_strncpy(win->screenname, win->screen->id.name+2, 21);
+       BLI_strncpy(win->screenname, win->screen->id.name+2, sizeof(win->screenname));
        win->screen->winid= win->winid;
 
        win->screen->do_refresh= 1;
@@ -234,13 +244,20 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
        CTX_wm_window_set(C, win);      /* needed by handlers */
        WM_event_remove_handlers(C, &win->handlers);
        WM_event_remove_handlers(C, &win->modalhandlers);
-       ED_screen_exit(C, win, win->screen); /* will free the current screen if it is a temp layout */
+       ED_screen_exit(C, win, win->screen); 
+       
+       /* if temp screen, delete it */
+       if(win->screen->temp) {
+               Main *bmain= CTX_data_main(C);
+               free_libblock(&bmain->screen, win->screen);
+       }
+       
        wm_window_free(C, wm, win);
        
        /* check remaining windows */
        if(wm->windows.first) {
                for(win= wm->windows.first; win; win= win->next)
-                       if(win->screen->full!=SCREENTEMP)
+                       if(win->screen->temp == 0)
                                break;
                /* in this case we close all */
                if(win==NULL)
@@ -253,23 +270,16 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
 void wm_window_title(wmWindowManager *wm, wmWindow *win)
 {
        /* handle the 'temp' window */
-       if(win->screen && win->screen->full==SCREENTEMP) {
+       if(win->screen && win->screen->temp) {
                GHOST_SetTitle(win->ghostwin, "Blender");
        }
        else {
                
                /* this is set to 1 if you don't have startup.blend open */
-               if(G.save_over) {
-                       char *str= MEM_mallocN(strlen(G.sce) + 16, "title");
-                       
-                       if(wm->file_saved)
-                               sprintf(str, "Blender [%s]", G.sce);
-                       else
-                               sprintf(str, "Blender* [%s]", G.sce);
-                       
+               if(G.save_over && G.main->name[0]) {
+                       char str[sizeof(G.main->name) + 12];
+                       BLI_snprintf(str, sizeof(str), "Blender%s [%s]", wm->file_saved ? "":"*", G.main->name);
                        GHOST_SetTitle(win->ghostwin, str);
-                       
-                       MEM_freeN(str);
                }
                else
                        GHOST_SetTitle(win->ghostwin, "Blender");
@@ -289,36 +299,43 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
 }
 
 /* belongs to below */
-static void wm_window_add_ghostwindow(wmWindowManager *wm, char *title, wmWindow *win)
+static void wm_window_add_ghostwindow(bContext *C, const char *title, wmWindow *win)
 {
        GHOST_WindowHandle ghostwin;
-       GHOST_TWindowState inital_state;
        int scr_w, scr_h, posy;
+       GHOST_TWindowState initial_state;
+
+       /* when there is no window open uses the initial state */
+       if(!CTX_wm_window(C))
+               initial_state= initialstate;
+       else
+               initial_state= GHOST_kWindowStateNormal;
        
        wm_get_screensize(&scr_w, &scr_h);
        posy= (scr_h - win->posy - win->sizey);
        
-       //              inital_state = GHOST_kWindowStateFullScreen;
-       //              inital_state = GHOST_kWindowStateMaximized;
-       inital_state = GHOST_kWindowStateNormal;
-       
 #if defined(__APPLE__) && !defined(GHOST_COCOA)
        {
                extern int macPrefState; /* creator.c */
-               inital_state += macPrefState;
+               initial_state += macPrefState;
        }
 #endif
        /* Disable AA for now, as GL_SELECT (used for border, lasso, ... select)
         doesn't work well when AA is initialized, even if not used. */
        ghostwin= GHOST_CreateWindow(g_system, title, 
                                                                 win->posx, posy, win->sizex, win->sizey, 
-                                                                inital_state, 
+                                                                initial_state, 
                                                                 GHOST_kDrawingContextTypeOpenGL,
                                                                 0 /* no stereo */,
                                                                 0 /* no AA */);
        
        if (ghostwin) {
+               /* needed so we can detect the graphics card below */
+               GPU_extensions_init();
                
+               /* set the state*/
+               GHOST_SetWindowState(ghostwin, initial_state);
+
                win->ghostwin= ghostwin;
                GHOST_SetWindowUserData(ghostwin, win); /* pointer back */
                
@@ -327,7 +344,11 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, char *title, wmWindow
                
                /* until screens get drawn, make it nice grey */
                glClearColor(.55, .55, .55, 0.0);
-               glClear(GL_COLOR_BUFFER_BIT);
+               /* Crash on OSS ATI: bugs.launchpad.net/ubuntu/+source/mesa/+bug/656100 */
+               if(!GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) {
+                       glClear(GL_COLOR_BUFFER_BIT);
+               }
+
                wm_window_swap_buffers(win);
                
                //GHOST_SetWindowState(ghostwin, GHOST_kWindowStateModified);
@@ -342,12 +363,15 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, char *title, wmWindow
 /* for wmWindows without ghostwin, open these and clear */
 /* window size is read from window, if 0 it uses prefsize */
 /* called in WM_check, also inits stuff after file read */
-void wm_window_add_ghostwindows(wmWindowManager *wm)
+void wm_window_add_ghostwindows(bContext* C, wmWindowManager *wm)
 {
        wmKeyMap *keymap;
        wmWindow *win;
        
-       /* no commandline prefsize? then we set this */
+       /* no commandline prefsize? then we set this.
+        * Note that these values will be used only
+        * when there is no startup.blend yet.
+        */
        if (!prefsizx) {
                wm_get_screensize(&prefsizx, &prefsizy);
                
@@ -367,18 +391,19 @@ void wm_window_add_ghostwindows(wmWindowManager *wm)
        
        for(win= wm->windows.first; win; win= win->next) {
                if(win->ghostwin==NULL) {
-                       if(win->sizex==0 || prefsizx || prefsizy) {
+                       if(win->sizex==0 || useprefsize) {
                                win->posx= prefstax;
                                win->posy= prefstay;
                                win->sizex= prefsizx;
                                win->sizey= prefsizy;
-                               win->windowstate= 0;
+                               win->windowstate= initialstate;
+                               useprefsize= 0;
                        }
-                       wm_window_add_ghostwindow(wm, "Blender", win);
+                       wm_window_add_ghostwindow(C, "Blender", win);
                }
                /* happens after fileread */
                if(win->eventstate==NULL)
-                  win->eventstate= MEM_callocN(sizeof(wmEvent), "window event state");
+                       win->eventstate= MEM_callocN(sizeof(wmEvent), "window event state");
 
                /* add keymap handlers (1 handler for all keys in map!) */
                keymap= WM_keymap_find(wm->defaultconf, "Window", 0, 0);
@@ -390,6 +415,11 @@ void wm_window_add_ghostwindows(wmWindowManager *wm)
                keymap= WM_keymap_find(wm->defaultconf, "Screen Editing", 0, 0);
                WM_event_add_keymap_handler(&win->modalhandlers, keymap);
                
+               /* add drop boxes */
+               {
+                       ListBase *lb= WM_dropboxmap_find("Window", 0, 0);
+                       WM_event_add_dropbox_handler(&win->handlers, lb);
+               }
                wm_window_title(wm, win);
        }
 }
@@ -414,7 +444,7 @@ wmWindow *WM_window_open(bContext *C, rcti *rect)
        return win;
 }
 
-/* uses screen->full tag to define what to do, currently it limits
+/* uses screen->temp tag to define what to do, currently it limits
    to only one "temp" window for render out, preferences, filewindow, etc */
 /* type is #define in WM_api.h */
 
@@ -428,7 +458,7 @@ void WM_window_open_temp(bContext *C, rcti *position, int type)
        
        /* test if we have a temp screen already */
        for(win= CTX_wm_manager(C)->windows.first; win; win= win->next)
-               if(win->screen->full == SCREENTEMP)
+               if(win->screen->temp)
                        break;
        
        /* add new window? */
@@ -450,7 +480,7 @@ void WM_window_open_temp(bContext *C, rcti *position, int type)
        /* add new screen? */
        if(win->screen==NULL)
                win->screen= ED_screen_add(win, CTX_data_scene(C), "temp");
-       win->screen->full = SCREENTEMP
+       win->screen->temp = 1
        
        /* make window active, and validate/resize */
        CTX_wm_window_set(C, win);
@@ -483,7 +513,7 @@ void WM_window_open_temp(bContext *C, rcti *position, int type)
 /* ****************** Operators ****************** */
 
 /* operator callback */
-int wm_window_duplicate_op(bContext *C, wmOperator *op)
+int wm_window_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
 {
        wm_window_copy(C, CTX_wm_window(C));
        WM_check(C);
@@ -495,7 +525,7 @@ int wm_window_duplicate_op(bContext *C, wmOperator *op)
 
 
 /* fullscreen operator callback */
-int wm_window_fullscreen_toggle_op(bContext *C, wmOperator *op)
+int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op))
 {
        wmWindow *window= CTX_wm_window(C);
        GHOST_TWindowState state = GHOST_GetWindowState(window->ghostwin);
@@ -511,22 +541,37 @@ int wm_window_fullscreen_toggle_op(bContext *C, wmOperator *op)
 
 /* ************ events *************** */
 
-static int query_qual(char qual) 
+typedef enum
+{
+       SHIFT = 's',
+       CONTROL = 'c',
+       ALT = 'a',
+       OS = 'C'
+} modifierKeyType;
+
+/* check if specified modifier key type is pressed */
+static int query_qual(modifierKeyType qual) 
 {
        GHOST_TModifierKeyMask left, right;
        int val= 0;
        
-       if (qual=='s') {
-               left= GHOST_kModifierKeyLeftShift;
-               right= GHOST_kModifierKeyRightShift;
-       } else if (qual=='c') {
-               left= GHOST_kModifierKeyLeftControl;
-               right= GHOST_kModifierKeyRightControl;
-       } else if (qual=='C') {
-               left= right= GHOST_kModifierKeyCommand;
-       } else {
-               left= GHOST_kModifierKeyLeftAlt;
-               right= GHOST_kModifierKeyRightAlt;
+       switch(qual) {
+               case SHIFT:
+                       left= GHOST_kModifierKeyLeftShift;
+                       right= GHOST_kModifierKeyRightShift;
+                       break;
+               case CONTROL:
+                       left= GHOST_kModifierKeyLeftControl;
+                       right= GHOST_kModifierKeyRightControl;
+                       break;
+               case OS:
+                       left= right= GHOST_kModifierKeyOS;
+                       break;
+               case ALT:
+               default:
+                       left= GHOST_kModifierKeyLeftAlt;
+                       right= GHOST_kModifierKeyRightAlt;
+                       break;
        }
        
        GHOST_GetModifierKeyState(g_system, left, &val);
@@ -595,20 +640,20 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
                                
                                /* bad ghost support for modifier keys... so on activate we set the modifiers again */
                                kdata.ascii= 0;
-                               if (win->eventstate->shift && !query_qual('s')) {
+                               if (win->eventstate->shift && !query_qual(SHIFT)) {
                                        kdata.key= GHOST_kKeyLeftShift;
                                        wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata);
                                }
-                               if (win->eventstate->ctrl && !query_qual('c')) {
+                               if (win->eventstate->ctrl && !query_qual(CONTROL)) {
                                        kdata.key= GHOST_kKeyLeftControl;
                                        wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata);
                                }
-                               if (win->eventstate->alt && !query_qual('a')) {
+                               if (win->eventstate->alt && !query_qual(ALT)) {
                                        kdata.key= GHOST_kKeyLeftAlt;
                                        wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata);
                                }
-                               if (win->eventstate->oskey && !query_qual('C')) {
-                                       kdata.key= GHOST_kKeyCommand;
+                               if (win->eventstate->oskey && !query_qual(OS)) {
+                                       kdata.key= GHOST_kKeyOS;
                                        wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata);
                                }
                                /* keymodifier zero, it hangs on hotkeys that open windows otherwise */
@@ -782,15 +827,17 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
                                /* printf("Drop detected\n"); */
                                
                                /* add drag data to wm for paths: */
-                               /* need icon type, some dropboxes check for that... see filesel code for this */
                                
                                if(ddd->dataType == GHOST_kDragnDropTypeFilenames) {
                                        GHOST_TStringArray *stra= ddd->data;
-                                       int a;
+                                       int a, icon;
                                        
                                        for(a=0; a<stra->count; a++) {
                                                printf("drop file %s\n", stra->strings[a]);
-                                               WM_event_start_drag(C, 0, WM_DRAG_PATH, stra->strings[a], 0.0);
+                                               /* try to get icon type from extension */
+                                               icon= ED_file_extension_icon((char *)stra->strings[a]);
+                                               
+                                               WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0);
                                                /* void poin should point to string, it makes a copy */
                                                break; // only one drop element supported now 
                                        }
@@ -872,7 +919,7 @@ void wm_window_process_events(const bContext *C)
                PIL_sleep_ms(5);
 }
 
-void wm_window_process_events_nosleep(const bContext *C
+void wm_window_process_events_nosleep(void
 {
        if(GHOST_ProcessEvents(g_system, 0))
                GHOST_DispatchEvents(g_system);
@@ -920,7 +967,7 @@ void wm_ghost_exit(void)
 /* **************** timer ********************** */
 
 /* to (de)activate running timers temporary */
-void WM_event_timer_sleep(wmWindowManager *wm, wmWindow *win, wmTimer *timer, int dosleep)
+void WM_event_timer_sleep(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *timer, int dosleep)
 {
        wmTimer *wt;
        
@@ -948,7 +995,7 @@ wmTimer *WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type,
        return wt;
 }
 
-void WM_event_remove_timer(wmWindowManager *wm, wmWindow *win, wmTimer *timer)
+void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *timer)
 {
        wmTimer *wt;
        
@@ -971,6 +1018,9 @@ char *WM_clipboard_text_get(int selection)
 {
        char *p, *p2, *buf, *newbuf;
 
+       if(G.background)
+               return NULL;
+
        buf= (char*)GHOST_getClipboard(selection);
        if(!buf)
                return NULL;
@@ -991,33 +1041,35 @@ char *WM_clipboard_text_get(int selection)
 
 void WM_clipboard_text_set(char *buf, int selection)
 {
+       if(!G.background) {
 #ifdef _WIN32
-       /* do conversion from \n to \r\n on Windows */
-       char *p, *p2, *newbuf;
-       int newlen= 0;
-       
-       for(p= buf; *p; p++) {
-               if(*p == '\n')
-                       newlen += 2;
-               else
-                       newlen++;
-       }
+               /* do conversion from \n to \r\n on Windows */
+               char *p, *p2, *newbuf;
+               int newlen= 0;
+               
+               for(p= buf; *p; p++) {
+                       if(*p == '\n')
+                               newlen += 2;
+                       else
+                               newlen++;
+               }
+               
+               newbuf= MEM_callocN(newlen+1, "WM_clipboard_text_set");
        
-       newbuf= MEM_callocN(newlen+1, "WM_clipboard_text_set");
-
-       for(p= buf, p2= newbuf; *p; p++, p2++) {
-               if(*p == '\n') { 
-                       *(p2++)= '\r'; *p2= '\n';
+               for(p= buf, p2= newbuf; *p; p++, p2++) {
+                       if(*p == '\n') { 
+                               *(p2++)= '\r'; *p2= '\n';
+                       }
+                       else *p2= *p;
                }
-               else *p2= *p;
-       }
-       *p2= '\0';
-
-       GHOST_putClipboard((GHOST_TInt8*)newbuf, selection);
-       MEM_freeN(newbuf);
+               *p2= '\0';
+       
+               GHOST_putClipboard((GHOST_TInt8*)newbuf, selection);
+               MEM_freeN(newbuf);
 #else
-       GHOST_putClipboard((GHOST_TInt8*)buf, selection);
+               GHOST_putClipboard((GHOST_TInt8*)buf, selection);
 #endif
+       }
 }
 
 /* ******************* progress bar **************** */
@@ -1106,6 +1158,18 @@ void WM_setprefsize(int stax, int stay, int sizx, int sizy)
        prefstay= stay;
        prefsizx= sizx;
        prefsizy= sizy;
+       useprefsize= 1;
+}
+
+/* for borderless and border windows set from command-line */
+void WM_setinitialstate_fullscreen(void)
+{
+       initialstate= GHOST_kWindowStateFullScreen;
+}
+
+void WM_setinitialstate_normal(void)
+{
+       initialstate= GHOST_kWindowStateNormal;
 }
 
 /* This function requires access to the GHOST_SystemHandle (g_system) */