Blender V2.61 - r43446

wm.c

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