diff options
Diffstat (limited to 'source/blender/windowmanager/intern/wm_window.c')
-rw-r--r-- | source/blender/windowmanager/intern/wm_window.c | 287 |
1 files changed, 227 insertions, 60 deletions
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 2d320458543..c853afe4507 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -26,6 +26,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <math.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -70,7 +71,7 @@ static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0; /* ******** win open & close ************ */ - +/* XXX this one should correctly check for apple top header... */ static void wm_get_screensize(int *width_r, int *height_r) { unsigned int uiwidth; @@ -81,6 +82,44 @@ static void wm_get_screensize(int *width_r, int *height_r) *height_r= uiheight; } +/* keeps offset and size within monitor bounds */ +/* XXX solve dual screen... */ +static void wm_window_check_position(rcti *rect) +{ + int width, height, d; + + wm_get_screensize(&width, &height); + +#ifdef __APPLE__ + height -= 70; +#endif + + if(rect->xmin < 0) { + d= rect->xmin; + rect->xmax -= d; + rect->xmin -= d; + } + if(rect->ymin < 0) { + d= rect->ymin; + rect->ymax -= d; + rect->ymin -= d; + } + if(rect->xmax > width) { + d= rect->xmax - width; + rect->xmax -= d; + rect->xmin -= d; + } + if(rect->ymax > height) { + d= rect->ymax - height; + rect->ymax -= d; + rect->ymin -= d; + } + + if(rect->xmin < 0) rect->xmin= 0; + if(rect->ymin < 0) rect->ymin= 0; +} + + static void wm_ghostwindow_destroy(wmWindow *win) { if(win->ghostwin) { @@ -93,7 +132,7 @@ static void wm_ghostwindow_destroy(wmWindow *win) ED_screen_exit should have been called */ void wm_window_free(bContext *C, wmWindow *win) { - wmTimer *wt; + wmTimer *wt, *wtnext; /* update context */ if(C) { @@ -107,14 +146,21 @@ void wm_window_free(bContext *C, wmWindow *win) CTX_wm_window_set(C, NULL); WM_event_remove_handlers(C, &win->handlers); + WM_event_remove_handlers(C, &win->modalhandlers); + + /* end running jobs, a job end also removes its timer */ + for(wt= win->timers.first; wt; wt= wtnext) { + wtnext= wt->next; + if(wt->event_type==TIMERJOBS) + wm_jobs_timer_ended(wm, wt); + } } if(win->eventstate) MEM_freeN(win->eventstate); - for(wt= win->timers.first; wt; wt= wt->next) - if(wt->customdata) - MEM_freeN(wt->customdata); - BLI_freelistN(&win->timers); + /* timer removing, need to call this api function */ + while((wt= win->timers.first)) + WM_event_remove_window_timer(win, wt); wm_event_free_all(win); wm_subwindows_free(win); @@ -163,7 +209,10 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig) win->sizey= winorig->sizey; /* duplicate assigns to window */ - ED_screen_duplicate(win, winorig->screen); + win->screen= ED_screen_duplicate(win, winorig->screen); + BLI_strncpy(win->screenname, win->screen->id.name+2, 21); + win->screen->winid= win->winid; + win->screen->do_refresh= 1; win->screen->do_draw= 1; @@ -174,7 +223,7 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig) } /* this is event from ghost, or exit-blender op */ -static void wm_window_close(bContext *C, wmWindow *win) +void wm_window_close(bContext *C, wmWindow *win) { wmWindowManager *wm= CTX_wm_manager(C); BLI_remlink(&wm->windows, win); @@ -183,35 +232,50 @@ static void wm_window_close(bContext *C, wmWindow *win) ED_screen_exit(C, win, win->screen); wm_window_free(C, win); - if(wm->windows.first==NULL) + /* check remaining windows */ + if(wm->windows.first) { + for(win= wm->windows.first; win; win= win->next) + if(win->screen->full!=SCREENTEMP) + break; + /* in this case we close all */ + if(win==NULL) + WM_exit(C); + } + else WM_exit(C); } void wm_window_title(wmWindowManager *wm, wmWindow *win) { - /* this is set to 1 if you don't have .B.blend open */ - if(G.save_over) { - char *str= MEM_mallocN(strlen(G.sce) + 16, "title"); + /* handle the 'temp' window */ + if(win->screen && win->screen->full==SCREENTEMP) { + GHOST_SetTitle(win->ghostwin, "Blender"); + } + else { - if(wm->file_saved) - sprintf(str, "Blender [%s]", G.sce); + /* this is set to 1 if you don't have .B.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); + + GHOST_SetTitle(win->ghostwin, str); + + MEM_freeN(str); + } else - sprintf(str, "Blender* [%s]", G.sce); - - GHOST_SetTitle(win->ghostwin, str); - - MEM_freeN(str); - } - else - GHOST_SetTitle(win->ghostwin, "Blender"); + GHOST_SetTitle(win->ghostwin, "Blender"); #ifdef __APPLE__ - if(wm->file_saved) - GHOST_SetWindowState(win->ghostwin, GHOST_kWindowStateUnModified); - else - GHOST_SetWindowState(win->ghostwin, GHOST_kWindowStateModified); + if(wm->file_saved) + GHOST_SetWindowState(win->ghostwin, GHOST_kWindowStateUnModified); + else + GHOST_SetWindowState(win->ghostwin, GHOST_kWindowStateModified); #endif - + } } /* belongs to below */ @@ -268,7 +332,7 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, char *title, wmWindow /* called in wm_check, also inits stuff after file read */ void wm_window_add_ghostwindows(wmWindowManager *wm) { - ListBase *keymap; + wmKeyMap *keymap; wmWindow *win; /* no commandline prefsize? then we set this */ @@ -304,11 +368,14 @@ void wm_window_add_ghostwindows(wmWindowManager *wm) win->eventstate= MEM_callocN(sizeof(wmEvent), "window event state"); /* add keymap handlers (1 handler for all keys in map!) */ - keymap= WM_keymap_listbase(wm, "Window", 0, 0); + keymap= WM_keymap_find(wm, "Window", 0, 0); WM_event_add_keymap_handler(&win->handlers, keymap); - keymap= WM_keymap_listbase(wm, "Screen", 0, 0); + keymap= WM_keymap_find(wm, "Screen", 0, 0); WM_event_add_keymap_handler(&win->handlers, keymap); + + keymap= WM_keymap_find(wm, "Screen Editing", 0, 0); + WM_event_add_keymap_handler(&win->modalhandlers, keymap); wm_window_title(wm, win); } @@ -334,6 +401,71 @@ wmWindow *WM_window_open(bContext *C, rcti *rect) return win; } +/* uses screen->full 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 */ + +void WM_window_open_temp(bContext *C, rcti *position, int type) +{ + wmWindow *win; + ScrArea *sa; + + /* changes rect to fit within desktop */ + wm_window_check_position(position); + + /* 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) + break; + + /* add new window? */ + if(win==NULL) { + win= wm_window_new(C); + + win->posx= position->xmin; + win->posy= position->ymin; + } + + win->sizex= position->xmax - position->xmin; + win->sizey= position->ymax - position->ymin; + + if(win->ghostwin) { + wm_window_set_size(win, win->sizex, win->sizey) ; + wm_window_raise(win); + } + + /* add new screen? */ + if(win->screen==NULL) + win->screen= ED_screen_add(win, CTX_data_scene(C), "temp"); + win->screen->full = SCREENTEMP; + + /* make window active, and validate/resize */ + CTX_wm_window_set(C, win); + wm_check(C); + + /* ensure it shows the right spacetype editor */ + sa= win->screen->areabase.first; + CTX_wm_area_set(C, sa); + + if(type==WM_WINDOW_RENDER) { + ED_area_newspace(C, sa, SPACE_IMAGE); + } + else { + ED_area_newspace(C, sa, SPACE_USERPREF); + } + + ED_screen_set(C, win->screen); + + if(sa->spacetype==SPACE_IMAGE) + GHOST_SetTitle(win->ghostwin, "Blender Render"); + else if(ELEM(sa->spacetype, SPACE_OUTLINER, SPACE_USERPREF)) + GHOST_SetTitle(win->ghostwin, "Blender User Preferences"); + else if(sa->spacetype==SPACE_FILE) + GHOST_SetTitle(win->ghostwin, "Blender File View"); + else + GHOST_SetTitle(win->ghostwin, "Blender"); +} + /* ****************** Operators ****************** */ @@ -461,6 +593,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) kdata.key= GHOST_kKeyCommand; wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata); } + /* keymodifier zero, it hangs on hotkeys that open windows otherwise */ + win->eventstate->keymodifier= 0; /* entering window, update mouse pos. but no event */ GHOST_GetCursorPosition(g_system, &wx, &wy); @@ -493,6 +627,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) if(state!=GHOST_kWindowStateMinimized) { GHOST_RectangleHandle client_rect; int l, t, r, b, scr_w, scr_h; + int sizex, sizey, posx, posy; client_rect= GHOST_GetClientBounds(win->ghostwin); GHOST_GetRectangle(client_rect, &l, &t, &r, &b); @@ -500,37 +635,56 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) GHOST_DisposeRectangle(client_rect); wm_get_screensize(&scr_w, &scr_h); - win->sizex= r-l; - win->sizey= b-t; - win->posx= l; - win->posy= scr_h - t - win->sizey; - - /* debug prints */ - if(0) { - state = GHOST_GetWindowState(win->ghostwin); - - if(state==GHOST_kWindowStateNormal) { - if(G.f & G_DEBUG) printf("window state: normal\n"); - } - else if(state==GHOST_kWindowStateMinimized) { - if(G.f & G_DEBUG) printf("window state: minimized\n"); + sizex= r-l; + sizey= b-t; + posx= l; + posy= scr_h - t - win->sizey; + + /* + * Ghost sometimes send size or move events when the window hasn't changed. + * One case of this is using compiz on linux. To alleviate the problem + * we ignore all such event here. + * + * It might be good to eventually do that at Ghost level, but that is for + * another time. + */ + if (win->sizex != sizex || + win->sizey != sizey || + win->posx != posx || + win->posy != posy) + { + win->sizex= sizex; + win->sizey= sizey; + win->posx= posx; + win->posy= posy; + + /* debug prints */ + if(0) { + state = GHOST_GetWindowState(win->ghostwin); + + if(state==GHOST_kWindowStateNormal) { + if(G.f & G_DEBUG) printf("window state: normal\n"); + } + else if(state==GHOST_kWindowStateMinimized) { + if(G.f & G_DEBUG) printf("window state: minimized\n"); + } + else if(state==GHOST_kWindowStateMaximized) { + if(G.f & G_DEBUG) printf("window state: maximized\n"); + } + else if(state==GHOST_kWindowStateFullScreen) { + if(G.f & G_DEBUG) printf("window state: fullscreen\n"); + } + + if(type!=GHOST_kEventWindowSize) { + if(G.f & G_DEBUG) printf("win move event pos %d %d size %d %d\n", win->posx, win->posy, win->sizex, win->sizey); + } + } - else if(state==GHOST_kWindowStateMaximized) { - if(G.f & G_DEBUG) printf("window state: maximized\n"); - } - else if(state==GHOST_kWindowStateFullScreen) { - if(G.f & G_DEBUG) printf("window state: fullscreen\n"); - } - - if(type!=GHOST_kEventWindowSize) { - if(G.f & G_DEBUG) printf("win move event pos %d %d size %d %d\n", win->posx, win->posy, win->sizex, win->sizey); - } - + + wm_window_make_drawable(C, win); + wm_draw_window_clear(win); + WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); } - - wm_window_make_drawable(C, win); - wm_draw_window_clear(win); - WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); } break; } @@ -561,12 +715,13 @@ static int wm_window_timer(const bContext *C) wmTimer *wt; for(wt= win->timers.first; wt; wt= wt->next) { if(wt->sleep==0) { - if(wt->timestep < time - wt->ltime) { + if(time > wt->ntime) { wmEvent event= *(win->eventstate); wt->delta= time - wt->ltime; wt->duration += wt->delta; wt->ltime= time; + wt->ntime= wt->stime + wt->timestep*ceil(wt->duration/wt->timestep); event.type= wt->event_type; event.custom= EVT_DATA_TIMER; @@ -632,6 +787,14 @@ void wm_ghost_init(bContext *C) } } +void wm_ghost_exit(void) +{ + if(g_system) + GHOST_DisposeSystem(g_system); + + g_system= NULL; +} + /* **************** timer ********************** */ /* to (de)activate running timers temporary */ @@ -653,6 +816,8 @@ wmTimer *WM_event_add_window_timer(wmWindow *win, int event_type, double timeste wt->event_type= event_type; wt->ltime= PIL_check_seconds_timer(); + wt->ntime= wt->ltime + timestep; + wt->stime= wt->ltime; wt->timestep= timestep; BLI_addtail(&win->timers, wt); @@ -664,10 +829,12 @@ void WM_event_remove_window_timer(wmWindow *win, wmTimer *timer) { wmTimer *wt; + /* extra security check */ for(wt= win->timers.first; wt; wt= wt->next) if(wt==timer) break; if(wt) { + BLI_remlink(&win->timers, wt); if(wt->customdata) MEM_freeN(wt->customdata); |