Blender  V2.59
wm.c
Go to the documentation of this file.
00001 /*
00002  * $Id: wm.c 39293 2011-08-11 06:06:17Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2007 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * 
00024  * Contributor(s): Blender Foundation
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <string.h>
00035 #include <stddef.h>
00036 
00037 #include "BLO_sys_types.h"
00038 
00039 #include "DNA_windowmanager_types.h"
00040 
00041 #include "GHOST_C-api.h"
00042 
00043 #include "MEM_guardedalloc.h"
00044 
00045 #include "BLI_utildefines.h"
00046 #include "BLI_blenlib.h"
00047 #include "BLI_ghash.h"
00048 
00049 #include "BKE_blender.h"
00050 #include "BKE_context.h"
00051 #include "BKE_idprop.h"
00052 #include "BKE_library.h"
00053 #include "BKE_main.h"
00054 #include "BKE_screen.h"
00055 #include "BKE_report.h"
00056 #include "BKE_global.h"
00057 
00058 #include "WM_api.h"
00059 #include "WM_types.h"
00060 #include "wm_window.h"
00061 #include "wm_event_system.h"
00062 #include "wm_event_types.h"
00063 #include "wm_draw.h"
00064 #include "wm.h"
00065 
00066 #include "ED_screen.h"
00067 
00068 #ifdef WITH_PYTHON
00069 #include "BPY_extern.h"
00070 #endif
00071 
00072 /* ****************************************************** */
00073 
00074 #define MAX_OP_REGISTERED       32
00075 
00076 void WM_operator_free(wmOperator *op)
00077 {
00078 
00079 #ifdef WITH_PYTHON
00080         if(op->py_instance) {
00081                 /* do this first incase there are any __del__ functions or
00082                  * similar that use properties */
00083                 BPY_DECREF(op->py_instance);
00084         }
00085 #endif
00086 
00087         if(op->ptr) {
00088                 op->properties= op->ptr->data;
00089                 MEM_freeN(op->ptr);
00090         }
00091 
00092         if(op->properties) {
00093                 IDP_FreeProperty(op->properties);
00094                 MEM_freeN(op->properties);
00095         }
00096 
00097         if(op->reports && (op->reports->flag & RPT_FREE)) {
00098                 BKE_reports_clear(op->reports);
00099                 MEM_freeN(op->reports);
00100         }
00101 
00102         if(op->macro.first) {
00103                 wmOperator *opm, *opmnext;
00104                 for(opm= op->macro.first; opm; opm= opmnext) {
00105                         opmnext = opm->next;
00106                         WM_operator_free(opm);
00107                 }
00108         }
00109         
00110         MEM_freeN(op);
00111 }
00112 
00113 static void wm_reports_free(wmWindowManager *wm)
00114 {
00115         BKE_reports_clear(&wm->reports);
00116         WM_event_remove_timer(wm, NULL, wm->reports.reporttimer);
00117 }
00118 
00119 /* all operations get registered in the windowmanager here */
00120 /* called on event handling by event_system.c */
00121 void wm_operator_register(bContext *C, wmOperator *op)
00122 {
00123         wmWindowManager *wm= CTX_wm_manager(C);
00124         int tot;
00125 
00126         BLI_addtail(&wm->operators, op);
00127         tot= BLI_countlist(&wm->operators);
00128         
00129         while(tot>MAX_OP_REGISTERED) {
00130                 wmOperator *opt= wm->operators.first;
00131                 BLI_remlink(&wm->operators, opt);
00132                 WM_operator_free(opt);
00133                 tot--;
00134         }
00135         
00136         /* so the console is redrawn */
00137         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_INFO_REPORT, NULL);
00138         WM_event_add_notifier(C, NC_WM|ND_HISTORY, NULL);
00139 }
00140 
00141 
00142 void WM_operator_stack_clear(wmWindowManager *wm)
00143 {
00144         wmOperator *op;
00145         
00146         while((op= wm->operators.first)) {
00147                 BLI_remlink(&wm->operators, op);
00148                 WM_operator_free(op);
00149         }
00150         
00151         WM_main_add_notifier(NC_WM|ND_HISTORY, NULL);
00152 }
00153 
00154 /* ****************************************** */
00155 
00156 static GHash *menutypes_hash= NULL;
00157 
00158 MenuType *WM_menutype_find(const char *idname, int quiet)
00159 {
00160         MenuType* mt;
00161 
00162         if (idname[0]) {
00163                 mt= BLI_ghash_lookup(menutypes_hash, idname);
00164                 if(mt)
00165                         return mt;
00166         }
00167 
00168         if(!quiet)
00169                 printf("search for unknown menutype %s\n", idname);
00170 
00171         return NULL;
00172 }
00173 
00174 int WM_menutype_add(MenuType* mt)
00175 {
00176         BLI_ghash_insert(menutypes_hash, (void *)mt->idname, mt);
00177         return 1;
00178 }
00179 
00180 /* inefficient but only used for tooltip code */
00181 int WM_menutype_contains(MenuType* mt)
00182 {
00183         int found= FALSE;
00184 
00185         if(mt) {
00186                 GHashIterator *iter= BLI_ghashIterator_new(menutypes_hash);
00187 
00188                 for( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
00189                         if(mt == BLI_ghashIterator_getValue(iter)) {
00190                                 found= TRUE;
00191                                 break;
00192                         }
00193                 }
00194                 BLI_ghashIterator_free(iter);
00195         }
00196 
00197         return found;
00198 }
00199 
00200 void WM_menutype_freelink(MenuType* mt)
00201 {
00202         BLI_ghash_remove(menutypes_hash, mt->idname, NULL, (GHashValFreeFP)MEM_freeN);
00203 }
00204 
00205 /* called on initialize WM_init() */
00206 void WM_menutype_init(void)
00207 {
00208         menutypes_hash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "menutypes_hash gh");
00209 }
00210 
00211 void WM_menutype_free(void)
00212 {
00213         GHashIterator *iter= BLI_ghashIterator_new(menutypes_hash);
00214 
00215         for( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
00216                 MenuType *mt= BLI_ghashIterator_getValue(iter);
00217                 if(mt->ext.free) {
00218                         mt->ext.free(mt->ext.data);
00219                 }
00220         }
00221         BLI_ghashIterator_free(iter);
00222 
00223         BLI_ghash_free(menutypes_hash, NULL, (GHashValFreeFP)MEM_freeN);
00224         menutypes_hash= NULL;
00225 }
00226 
00227 /* ****************************************** */
00228 
00229 void WM_keymap_init(bContext *C)
00230 {
00231         wmWindowManager *wm= CTX_wm_manager(C);
00232 
00233         if(!wm->defaultconf)
00234                 wm->defaultconf= WM_keyconfig_new(wm, "Blender");
00235         if(!wm->addonconf)
00236                 wm->addonconf= WM_keyconfig_new(wm, "Blender Addon");
00237         if(!wm->userconf)
00238                 wm->userconf= WM_keyconfig_new(wm, "Blender User");
00239         
00240         if(CTX_py_init_get(C) && (wm->initialized & WM_INIT_KEYMAP) == 0) {
00241                 /* create default key config */
00242                 wm_window_keymap(wm->defaultconf);
00243                 ED_spacetypes_keymap(wm->defaultconf);
00244 
00245                 WM_keyconfig_update_tag(NULL, NULL);
00246                 WM_keyconfig_update(wm);
00247 
00248                 wm->initialized |= WM_INIT_KEYMAP;
00249         }
00250 }
00251 
00252 void WM_check(bContext *C)
00253 {
00254         wmWindowManager *wm= CTX_wm_manager(C);
00255         
00256         /* wm context */
00257         if(wm==NULL) {
00258                 wm= CTX_data_main(C)->wm.first;
00259                 CTX_wm_manager_set(C, wm);
00260         }
00261         if(wm==NULL) return;
00262         if(wm->windows.first==NULL) return;
00263 
00264         if (!G.background) {
00265                 /* case: fileread */
00266                 if((wm->initialized & WM_INIT_WINDOW) == 0) {
00267                         WM_keymap_init(C);
00268                         WM_autosave_init(wm);
00269                 }
00270 
00271                 /* case: no open windows at all, for old file reads */
00272                 wm_window_add_ghostwindows(C, wm);
00273         }
00274 
00275         /* case: fileread */
00276         /* note: this runs in bg mode to set the screen context cb */
00277         if((wm->initialized & WM_INIT_WINDOW) == 0) {
00278                 ED_screens_initialize(wm);
00279                 wm->initialized |= WM_INIT_WINDOW;
00280         }
00281 }
00282 
00283 void wm_clear_default_size(bContext *C)
00284 {
00285         wmWindowManager *wm= CTX_wm_manager(C);
00286         wmWindow *win;
00287         
00288         /* wm context */
00289         if(wm==NULL) {
00290                 wm= CTX_data_main(C)->wm.first;
00291                 CTX_wm_manager_set(C, wm);
00292         }
00293         if(wm==NULL) return;
00294         if(wm->windows.first==NULL) return;
00295         
00296         for(win= wm->windows.first; win; win= win->next) {
00297                 win->sizex = 0;
00298                 win->sizey = 0;
00299                 win->posx = 0;
00300                 win->posy = 0;
00301         }
00302 
00303 }
00304 
00305 /* on startup, it adds all data, for matching */
00306 void wm_add_default(bContext *C)
00307 {
00308         wmWindowManager *wm= alloc_libblock(&CTX_data_main(C)->wm, ID_WM, "WinMan");
00309         wmWindow *win;
00310         bScreen *screen= CTX_wm_screen(C); /* XXX from file read hrmf */
00311         
00312         CTX_wm_manager_set(C, wm);
00313         win= wm_window_new(C);
00314         win->screen= screen;
00315         screen->winid= win->winid;
00316         BLI_strncpy(win->screenname, screen->id.name+2, sizeof(win->screenname));
00317         
00318         wm->winactive= win;
00319         wm->file_saved= 1;
00320         wm_window_make_drawable(C, win); 
00321 }
00322 
00323 
00324 /* context is allowed to be NULL, do not free wm itself (library.c) */
00325 void wm_close_and_free(bContext *C, wmWindowManager *wm)
00326 {
00327         wmWindow *win;
00328         wmOperator *op;
00329         wmKeyConfig *keyconf;
00330 
00331         if(wm->autosavetimer)
00332                 wm_autosave_timer_ended(wm);
00333 
00334         while((win= wm->windows.first)) {
00335                 BLI_remlink(&wm->windows, win);
00336                 win->screen= NULL; /* prevent draw clear to use screen */
00337                 wm_draw_window_clear(win);
00338                 wm_window_free(C, wm, win);
00339         }
00340         
00341         while((op= wm->operators.first)) {
00342                 BLI_remlink(&wm->operators, op);
00343                 WM_operator_free(op);
00344         }
00345 
00346         while((keyconf=wm->keyconfigs.first)) {
00347                 BLI_remlink(&wm->keyconfigs, keyconf);
00348                 WM_keyconfig_free(keyconf);
00349         }
00350 
00351         BLI_freelistN(&wm->queue);
00352         
00353         BLI_freelistN(&wm->paintcursors);
00354         BLI_freelistN(&wm->drags);
00355         
00356         wm_reports_free(wm);
00357         
00358         if(C && CTX_wm_manager(C)==wm) CTX_wm_manager_set(C, NULL);
00359 }
00360 
00361 void wm_close_and_free_all(bContext *C, ListBase *wmlist)
00362 {
00363         wmWindowManager *wm;
00364         
00365         while((wm=wmlist->first)) {
00366                 wm_close_and_free(C, wm);
00367                 BLI_remlink(wmlist, wm);
00368                 MEM_freeN(wm);
00369         }
00370 }
00371 
00372 void WM_main(bContext *C)
00373 {
00374         while(1) {
00375                 
00376                 /* get events from ghost, handle window events, add to window queues */
00377                 wm_window_process_events(C); 
00378                 
00379                 /* per window, all events to the window, screen, area and region handlers */
00380                 wm_event_do_handlers(C);
00381                 
00382                 /* events have left notes about changes, we handle and cache it */
00383                 wm_event_do_notifiers(C);
00384                 
00385                 /* execute cached changes draw */
00386                 wm_draw_update(C);
00387         }
00388 }
00389 
00390