Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/windowmanager/intern')
-rw-r--r--source/blender/windowmanager/intern/wm.c8
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c187
-rw-r--r--source/blender/windowmanager/intern/wm_files.c5
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c11
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c33
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c39
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c352
-rw-r--r--source/blender/windowmanager/intern/wm_window.c88
8 files changed, 506 insertions, 217 deletions
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 38cf39c2081..4405b52888d 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -69,15 +69,17 @@ void WM_operator_free(wmOperator *op)
MEM_freeN(op->properties);
}
- if(op->reports && (op->flag & OPERATOR_REPORT_FREE)) {
+ if(op->reports && (op->reports->flag & RPT_FREE)) {
BKE_reports_clear(op->reports);
MEM_freeN(op->reports);
}
if(op->macro.first) {
- wmOperator *opm;
- for(opm= op->macro.first; opm; opm= opm->next)
+ wmOperator *opm, *opmnext;
+ for(opm= op->macro.first; opm; opm= opmnext) {
+ opmnext = opm->next;
WM_operator_free(opm);
+ }
}
MEM_freeN(op);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 3c03d24ca93..b7156a17383 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -239,7 +239,7 @@ void wm_event_do_notifiers(bContext *C)
if(G.rendering==0) { // XXX make lock in future, or separated derivedmesh users in scene
- /* update all objects, ipos, matrices, displists, etc. Flags set by depgraph or manual,
+ /* update all objects, drivers, matrices, displists, etc. Flags set by depgraph or manual,
no layer check here, gets correct flushed */
/* sets first, we allow per definition current scene to have dependencies on sets */
if(scene->set) {
@@ -259,20 +259,23 @@ void wm_event_do_notifiers(bContext *C)
/* ********************* operators ******************* */
-static int wm_operator_poll(bContext *C, wmOperatorType *ot)
+int WM_operator_poll(bContext *C, wmOperatorType *ot)
{
wmOperatorTypeMacro *otmacro;
for(otmacro= ot->macro.first; otmacro; otmacro= otmacro->next) {
wmOperatorType *ot= WM_operatortype_find(otmacro->idname, 0);
- if(0==wm_operator_poll(C, ot))
+ if(0==WM_operator_poll(C, ot))
return 0;
}
- if(ot->poll)
+ /* python needs operator type, so we added exception for it */
+ if(ot->pyop_poll)
+ return ot->pyop_poll(C, ot);
+ else if(ot->poll)
return ot->poll(C);
-
+
return 1;
}
@@ -284,7 +287,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat)
if(op==NULL || op->type==NULL)
return retval;
- if(0==wm_operator_poll(C, op->type))
+ if(0==WM_operator_poll(C, op->type))
return retval;
if(op->type->exec)
@@ -349,8 +352,7 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, P
}
else {
op->reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
- BKE_reports_init(op->reports, RPT_STORE);
- op->flag |= OPERATOR_REPORT_FREE;
+ BKE_reports_init(op->reports, RPT_STORE|RPT_FREE);
}
/* recursive filling of operator macro list */
@@ -398,7 +400,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
wmWindowManager *wm= CTX_wm_manager(C);
int retval= OPERATOR_PASS_THROUGH;
- if(wm_operator_poll(C, ot)) {
+ if(WM_operator_poll(C, ot)) {
wmOperator *op= wm_operator_create(wm, ot, properties, reports); /* if reports==NULL, theyll be initialized */
if((G.f & G_DEBUG) && event && event->type!=MOUSEMOVE)
@@ -413,7 +415,9 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
else
printf("invalid operator call %s\n", ot->idname); /* debug, important to leave a while, should never happen */
- if(!(retval & OPERATOR_RUNNING_MODAL)) {
+ /* Note, if the report is given as an argument then assume the caller will deal with displaying them
+ * currently python only uses this */
+ if(!(retval & OPERATOR_RUNNING_MODAL) && reports==NULL) {
if(op->reports->list.first) /* only show the report if the report list was not given in the function */
uiPupMenuReports(C, op->reports);
@@ -555,6 +559,12 @@ int WM_operator_call_py(bContext *C, wmOperatorType *ot, int context, PointerRNA
retval= wm_operator_call_internal(C, ot, context, properties, reports);
+ /* keep the reports around if needed later */
+ if (retval & OPERATOR_RUNNING_MODAL || ot->flag & OPTYPE_REGISTER)
+ {
+ reports->flag |= RPT_FREE;
+ }
+
return retval;
}
@@ -710,7 +720,7 @@ static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *kmi)
/* the matching rules */
if(kmitype==KM_TEXTINPUT)
- if(ISKEYBOARD(winevent->type)) return 1;
+ if(ISTEXTINPUT(winevent->type) && winevent->ascii) return 1;
if(kmitype!=KM_ANY)
if(winevent->type!=kmitype) return 0;
@@ -733,7 +743,7 @@ static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *kmi)
/* key modifiers always check when event has it */
/* otherwise regular keypresses with keymodifier still work */
if(winevent->keymodifier)
- if(ISKEYBOARD(winevent->type))
+ if(ISTEXTINPUT(winevent->type))
if(winevent->keymodifier!=kmi->keymodifier) return 0;
return 1;
@@ -895,9 +905,7 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
switch(event->val) {
case EVT_FILESELECT_OPEN:
case EVT_FILESELECT_FULL_OPEN:
- {
- char *dir= NULL; char *path= RNA_string_get_alloc(handler->op->ptr, "filename", NULL, 0);
-
+ {
if(event->val==EVT_FILESELECT_OPEN)
ED_area_newspace(C, handler->op_area, SPACE_FILE);
else
@@ -908,8 +916,6 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
sfile->op= handler->op;
ED_fileselect_set_params(sfile);
- dir = NULL;
- MEM_freeN(path);
action= WM_HANDLER_BREAK;
}
@@ -920,7 +926,7 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
{
/* XXX validate area and region? */
bScreen *screen= CTX_wm_screen(C);
- char *path= RNA_string_get_alloc(handler->op->ptr, "filename", NULL, 0);
+ char *path= RNA_string_get_alloc(handler->op->ptr, "path", NULL, 0);
if(screen != handler->filescreen)
ED_screen_full_prevspace(C);
@@ -937,7 +943,7 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
/* XXX also extension code in image-save doesnt work for this yet */
if(strncmp(handler->op->type->name, "Save", 4)==0) {
/* this gives ownership to pupmenu */
- uiPupMenuSaveOver(C, handler->op, path);
+ uiPupMenuSaveOver(C, handler->op, (path)? path: "");
}
else {
int retval= handler->op->type->exec(C, handler->op);
@@ -955,7 +961,8 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
WM_operator_free(handler->op);
wm_event_free_handler(handler);
- MEM_freeN(path);
+ if(path)
+ MEM_freeN(path);
action= WM_HANDLER_BREAK;
}
@@ -998,7 +1005,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
int always_pass;
if(handlers==NULL) return action;
-
+
/* modal handlers can get removed in this loop, we keep the loop this way */
for(handler= handlers->first; handler; handler= nexthandler) {
nexthandler= handler->next;
@@ -1013,16 +1020,19 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
action= WM_HANDLER_BREAK;
if(handler->keymap) {
+ wmKeyMap *keymap= handler->keymap;
wmKeymapItem *kmi;
- for(kmi= handler->keymap->first; kmi; kmi= kmi->next) {
- if(wm_eventmatch(event, kmi)) {
-
- event->keymap_idname= kmi->idname; /* weak, but allows interactive callback to not use rawkey */
-
- action= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr);
- if(action==WM_HANDLER_BREAK) /* not wm_event_always_pass(event) here, it denotes removed handler */
- break;
+ if(!keymap->poll || keymap->poll(C)) {
+ for(kmi= keymap->keymap.first; kmi; kmi= kmi->next) {
+ if(wm_eventmatch(event, kmi)) {
+
+ event->keymap_idname= kmi->idname; /* weak, but allows interactive callback to not use rawkey */
+
+ action= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr);
+ if(action==WM_HANDLER_BREAK) /* not always_pass here, it denotes removed handler */
+ break;
+ }
}
}
}
@@ -1038,8 +1048,12 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
action= wm_handler_operator_call(C, handlers, handler, event, NULL);
}
- if(!always_pass && action==WM_HANDLER_BREAK)
- break;
+ if(action==WM_HANDLER_BREAK) {
+ if(always_pass)
+ action= WM_HANDLER_CONTINUE;
+ else
+ break;
+ }
}
/* fileread case */
@@ -1051,6 +1065,8 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
static int wm_event_inside_i(wmEvent *event, rcti *rect)
{
+ if(wm_event_always_pass(event))
+ return 1;
if(BLI_in_rcti(rect, event->x, event->y))
return 1;
if(event->type==MOUSEMOVE) {
@@ -1142,7 +1158,7 @@ void wm_event_do_handlers(bContext *C)
while( (event= win->queue.first) ) {
int action;
-
+
CTX_wm_window_set(C, win);
/* we let modal handlers get active area/region, also wm_paintcursor_test needs it */
@@ -1152,61 +1168,73 @@ void wm_event_do_handlers(bContext *C)
/* MVC demands to not draw in event handlers... but we need to leave it for ogl selecting etc */
wm_window_make_drawable(C, win);
- action= wm_handlers_do(C, event, &win->handlers);
+ /* first we do priority handlers, modal + some limited keymaps */
+ action= wm_handlers_do(C, event, &win->modalhandlers);
/* fileread case */
- if(CTX_wm_window(C)==NULL) {
+ if(CTX_wm_window(C)==NULL)
return;
- }
/* builtin tweak, if action is break it removes tweak */
- if(!wm_event_always_pass(event))
- wm_tweakevent_test(C, event, action);
-
- if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) {
+ wm_tweakevent_test(C, event, action);
+
+ if(action==WM_HANDLER_CONTINUE) {
ScrArea *sa;
ARegion *ar;
int doit= 0;
/* XXX to solve, here screen handlers? */
- if(!wm_event_always_pass(event)) {
- if(event->type==MOUSEMOVE) {
- /* state variables in screen, cursors */
- ED_screen_set_subwinactive(win, event);
- /* for regions having custom cursors */
- wm_paintcursor_test(C, event);
- }
+ if(event->type==MOUSEMOVE) {
+ /* state variables in screen, cursors */
+ ED_screen_set_subwinactive(win, event);
+ /* for regions having custom cursors */
+ wm_paintcursor_test(C, event);
}
-
+
for(sa= win->screen->areabase.first; sa; sa= sa->next) {
- if(wm_event_always_pass(event) || wm_event_inside_i(event, &sa->totrct)) {
-
+ if(wm_event_inside_i(event, &sa->totrct)) {
CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, NULL);
- action= wm_handlers_do(C, event, &sa->handlers);
- if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) {
+ if(action==WM_HANDLER_CONTINUE) {
for(ar=sa->regionbase.first; ar; ar= ar->next) {
- if(wm_event_always_pass(event) || wm_event_inside_i(event, &ar->winrct)) {
+ if(wm_event_inside_i(event, &ar->winrct)) {
CTX_wm_region_set(C, ar);
action= wm_handlers_do(C, event, &ar->handlers);
doit |= (BLI_in_rcti(&ar->winrct, event->x, event->y));
- if(!wm_event_always_pass(event)) {
- if(action==WM_HANDLER_BREAK)
- break;
- }
+ if(action==WM_HANDLER_BREAK)
+ break;
}
}
}
+
+ CTX_wm_region_set(C, NULL);
+
+ if(action==WM_HANDLER_CONTINUE)
+ action= wm_handlers_do(C, event, &sa->handlers);
+
+ CTX_wm_area_set(C, NULL);
+
/* NOTE: do not escape on WM_HANDLER_BREAK, mousemove needs handled for previous area */
}
}
+ if(action==WM_HANDLER_CONTINUE) {
+ /* also some non-modal handlers need active area/region */
+ CTX_wm_area_set(C, area_event_inside(C, event->x, event->y));
+ CTX_wm_region_set(C, region_event_inside(C, event->x, event->y));
+
+ action= wm_handlers_do(C, event, &win->handlers);
+
+ /* fileread case */
+ if(CTX_wm_window(C)==NULL)
+ return;
+ }
+
/* XXX hrmf, this gives reliable previous mouse coord for area change, feels bad?
doing it on ghost queue gives errors when mousemoves go over area borders */
- if(doit && win->screen->subwinactive != win->screen->mainwin) {
+ if(doit && win->screen && win->screen->subwinactive != win->screen->mainwin) {
win->eventstate->prevx= event->x;
win->eventstate->prevy= event->y;
}
@@ -1219,7 +1247,7 @@ void wm_event_do_handlers(bContext *C)
}
/* only add mousemove when queue was read entirely */
- if(win->addmousemove) {
+ if(win->addmousemove && win->eventstate) {
wmEvent event= *(win->eventstate);
event.type= MOUSEMOVE;
event.prevx= event.x;
@@ -1250,7 +1278,7 @@ void WM_event_fileselect_event(bContext *C, void *ophandle, int eventval)
}
}
-/* operator is supposed to have a filled "filename" property */
+/* operator is supposed to have a filled "path" property */
/* optional property: filetype (XXX enum?) */
/* Idea is to keep a handler alive on window queue, owning the operator.
@@ -1270,7 +1298,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op)
handler->op_region= CTX_wm_region(C);
handler->filescreen= CTX_wm_screen(C);
- BLI_addhead(&win->handlers, handler);
+ BLI_addhead(&win->modalhandlers, handler);
WM_event_fileselect_event(C, op, full?EVT_FILESELECT_FULL_OPEN:EVT_FILESELECT_OPEN);
}
@@ -1281,9 +1309,10 @@ void WM_event_set_handler_flag(wmEventHandler *handler, int flag)
handler->flag= flag;
}
-wmEventHandler *WM_event_add_modal_handler(bContext *C, ListBase *handlers, wmOperator *op)
+wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op)
{
wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "event modal handler");
+ wmWindow *win= CTX_wm_window(C);
/* operator was part of macro */
if(op->opm) {
@@ -1298,15 +1327,20 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, ListBase *handlers, wmOp
handler->op_area= CTX_wm_area(C); /* means frozen screen context for modal handlers! */
handler->op_region= CTX_wm_region(C);
- BLI_addhead(handlers, handler);
+ BLI_addhead(&win->modalhandlers, handler);
return handler;
}
-wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, ListBase *keymap)
+wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
{
wmEventHandler *handler;
+ if(!keymap) {
+ printf("WM_event_add_keymap_handler called with NULL keymap\n");
+ return NULL;
+ }
+
/* only allow same keymap once */
for(handler= handlers->first; handler; handler= handler->next)
if(handler->keymap==keymap)
@@ -1320,7 +1354,7 @@ wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, ListBase *keymap
}
/* priorities not implemented yet, for time being just insert in begin of list */
-wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers, ListBase *keymap, int priority)
+wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers, wmKeyMap *keymap, int priority)
{
wmEventHandler *handler;
@@ -1333,7 +1367,7 @@ wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers, ListBas
return handler;
}
-wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, ListBase *keymap, rcti *bblocal, rcti *bbwin)
+wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, wmKeyMap *keymap, rcti *bblocal, rcti *bbwin)
{
wmEventHandler *handler= WM_event_add_keymap_handler(handlers, keymap);
@@ -1344,7 +1378,7 @@ wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, ListBase *key
return handler;
}
-void WM_event_remove_keymap_handler(ListBase *handlers, ListBase *keymap)
+void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
{
wmEventHandler *handler;
@@ -1497,10 +1531,10 @@ static void update_tablet_data(wmWindow *win, wmEvent *event)
const GHOST_TabletData *td= GHOST_GetTabletData(win->ghostwin);
/* if there's tablet data from an active tablet device then add it */
- if ((td != NULL) && td->Active) {
+ if ((td != NULL) && td->Active != GHOST_kTabletModeNone) {
struct wmTabletData *wmtab= MEM_mallocN(sizeof(wmTabletData), "customdata tablet");
- wmtab->Active = td->Active;
+ wmtab->Active = (int)td->Active;
wmtab->Pressure = td->Pressure;
wmtab->Xtilt = td->Xtilt;
wmtab->Ytilt = td->Ytilt;
@@ -1542,12 +1576,16 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata)
case GHOST_kEventButtonDown:
case GHOST_kEventButtonUp: {
GHOST_TEventButtonData *bd= customdata;
- event.val= (type==GHOST_kEventButtonDown);
+ event.val= (type==GHOST_kEventButtonDown) ? KM_PRESS:KM_RELEASE; /* Note!, this starts as 0/1 but later is converted to KM_PRESS/KM_RELEASE by tweak */
if (bd->button == GHOST_kButtonMaskLeft)
event.type= LEFTMOUSE;
else if (bd->button == GHOST_kButtonMaskRight)
event.type= RIGHTMOUSE;
+ else if (bd->button == GHOST_kButtonMaskButton4)
+ event.type= BUTTON4MOUSE;
+ else if (bd->button == GHOST_kButtonMaskButton5)
+ event.type= BUTTON5MOUSE;
else
event.type= MIDDLEMOUSE;
@@ -1565,7 +1603,7 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata)
event.val= (type==GHOST_kEventKeyDown)?KM_PRESS:KM_RELEASE;
/* exclude arrow keys, esc, etc from text input */
- if(type==GHOST_kEventKeyUp || (event.ascii<32 && event.ascii>14))
+ if(type==GHOST_kEventKeyUp || (event.ascii<32 && event.ascii>0))
event.ascii= '\0';
/* modifiers */
@@ -1595,6 +1633,13 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata)
else if(event.val==KM_RELEASE && event.keymodifier==event.type)
event.keymodifier= evt->keymodifier= 0;
}
+
+ /* this case happens on some systems that on holding a key pressed,
+ generate press events without release, we still want to keep the
+ modifier in win->eventstate, but for the press event of the same
+ key we don't want the key modifier */
+ if(event.keymodifier == event.type)
+ event.keymodifier= 0;
/* if test_break set, it catches this. XXX Keep global for now? */
if(event.type==ESCKEY)
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 9694a8fa1c6..1aca9a66e57 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -195,6 +195,7 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
/* ensure making new keymaps and set space types */
wm->initialized= 0;
+ wm->winactive= NULL;
/* only first wm in list has ghostwins */
for(win= wm->windows.first; win; win= win->next) {
@@ -202,6 +203,10 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
if(oldwin->winid == win->winid ) {
win->ghostwin= oldwin->ghostwin;
+ win->active= oldwin->active;
+ if(win->active)
+ wm->winactive= win;
+
GHOST_SetWindowUserData(win->ghostwin, win); /* pointer back */
oldwin->ghostwin= NULL;
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index b2cdddf5b63..b4328d12e81 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -78,7 +78,7 @@
#include "ED_armature.h"
#include "ED_keyframing.h"
#include "ED_node.h"
-#include "ED_previewrender.h"
+#include "ED_render.h"
#include "ED_space_api.h"
#include "ED_screen.h"
#include "ED_util.h"
@@ -90,6 +90,7 @@
#include "GPU_extensions.h"
#include "GPU_draw.h"
+#include "BKE_depsgraph.h"
#include "BKE_sound.h"
static void wm_init_reports(bContext *C)
@@ -113,6 +114,7 @@ void WM_init(bContext *C)
set_free_windowmanager_cb(wm_close_and_free); /* library.c */
set_blender_test_break_cb(wm_window_testbreak); /* blender.c */
+ DAG_editors_update_cb(ED_render_id_flush_update); /* depsgraph.c */
ED_spacetypes_init(); /* editors/space_api/spacetype.c */
@@ -129,6 +131,8 @@ void WM_init(bContext *C)
wm_init_reports(C); /* reports cant be initialized before the wm */
+ GPU_extensions_init();
+
UI_init();
// clear_matcopybuf(); /* XXX */
@@ -139,8 +143,6 @@ void WM_init(bContext *C)
ED_preview_init_dbase();
- GPU_extensions_init();
-
G.ndofdevice = -1; /* XXX bad initializer, needs set otherwise buttons show! */
read_Blog();
@@ -167,6 +169,7 @@ extern wchar_t *copybufinfo;
// XXX copy/paste buffer stuff...
extern void free_anim_copybuf();
+extern void free_anim_drivers_copybuf();
extern void free_posebuf();
/* called in creator.c even... tsk, split this! */
@@ -187,6 +190,7 @@ void WM_exit(bContext *C)
CTX_wm_window_set(C, win); /* needed by operator close callbacks */
WM_event_remove_handlers(C, &win->handlers);
+ WM_event_remove_handlers(C, &win->modalhandlers);
ED_screen_exit(C, win, win->screen);
}
}
@@ -213,6 +217,7 @@ void WM_exit(bContext *C)
free_blender(); /* blender.c, does entire library and spacetypes */
// free_matcopybuf();
free_anim_copybuf();
+ free_anim_drivers_copybuf();
free_posebuf();
// free_vertexpaint();
// free_imagepaint();
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index bef3268920d..9e16ce4082f 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -107,6 +107,7 @@ struct wmJob {
/* internal */
void *owner;
+ int flag;
short suspended, running, ready, do_update, stop;
/* once running, we store this separately */
@@ -123,7 +124,7 @@ struct wmJob {
/* returns current or adds new job, but doesnt run it */
/* every owner only gets a single job, adding a new one will stop running stop and
when stopped it starts the new one */
-wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner)
+wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, int flag)
{
wmJob *steve;
@@ -137,6 +138,7 @@ wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner)
BLI_addtail(&wm->jobs, steve);
steve->win= win;
steve->owner= owner;
+ steve->flag= flag;
}
return steve;
@@ -198,20 +200,25 @@ static void *do_job_thread(void *job_v)
}
/* dont allow same startjob to be executed twice */
-static void wm_jobs_test_suspend(wmWindowManager *wm, wmJob *test)
+static void wm_jobs_test_suspend_stop(wmWindowManager *wm, wmJob *test)
{
wmJob *steve;
+ int suspend= 0;
- for(steve= wm->jobs.first; steve; steve= steve->next)
- if(steve!=test)
- if(steve->running)
- if(steve->startjob==test->startjob)
- break;
-
- if(steve)
- test->suspended= 1;
- else
- test->suspended= 0;
+ for(steve= wm->jobs.first; steve; steve= steve->next) {
+ if(steve==test || !steve->running) continue;
+ if(steve->startjob!=test->startjob && !(test->flag & WM_JOB_EXCL_RENDER)) continue;
+ if((test->flag & WM_JOB_EXCL_RENDER) && !(steve->flag & WM_JOB_EXCL_RENDER)) continue;
+
+ suspend= 1;
+
+ /* if this job has higher priority, stop others */
+ if(test->flag & WM_JOB_PRIORITY)
+ steve->stop= 1;
+ }
+
+ /* possible suspend ourselfs, waiting for other jobs, or de-suspend */
+ test->suspended= suspend;
}
/* if job running, the same owner gave it a new job */
@@ -225,7 +232,7 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *steve)
else {
if(steve->customdata && steve->startjob) {
- wm_jobs_test_suspend(wm, steve);
+ wm_jobs_test_suspend_stop(wm, steve);
if(steve->suspended==0) {
/* copy to ensure proper free in end */
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 5566aeba260..7d25fb8172e 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -96,17 +96,17 @@ static void keymap_properties_set(wmKeymapItem *kmi)
}
/* if item was added, then bail out */
-wmKeymapItem *WM_keymap_verify_item(ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier)
+wmKeymapItem *WM_keymap_verify_item(wmKeyMap *keymap, char *idname, short type, short val, int modifier, short keymodifier)
{
wmKeymapItem *kmi;
- for(kmi= lb->first; kmi; kmi= kmi->next)
+ for(kmi= keymap->keymap.first; kmi; kmi= kmi->next)
if(strncmp(kmi->idname, idname, OP_MAX_TYPENAME)==0)
break;
if(kmi==NULL) {
kmi= MEM_callocN(sizeof(wmKeymapItem), "keymap entry");
- BLI_addtail(lb, kmi);
+ BLI_addtail(&keymap->keymap, kmi);
BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
keymap_event_set(kmi, type, val, modifier, keymodifier);
@@ -116,11 +116,11 @@ wmKeymapItem *WM_keymap_verify_item(ListBase *lb, char *idname, short type, shor
}
/* always add item */
-wmKeymapItem *WM_keymap_add_item(ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier)
+wmKeymapItem *WM_keymap_add_item(wmKeyMap *keymap, char *idname, short type, short val, int modifier, short keymodifier)
{
wmKeymapItem *kmi= MEM_callocN(sizeof(wmKeymapItem), "keymap entry");
- BLI_addtail(lb, kmi);
+ BLI_addtail(&keymap->keymap, kmi);
BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
keymap_event_set(kmi, type, val, modifier, keymodifier);
@@ -134,14 +134,14 @@ wmKeymapItem *WM_keymap_add_item(ListBase *lb, char *idname, short type, short v
space/region ids are same as DNA_space_types.h */
/* gets free'd in wm.c */
-static wmKeyMap *wm_keymap_add(wmWindowManager *wm, const char *nameid, short spaceid, short regionid)
+wmKeyMap *WM_keymap_find(wmWindowManager *wm, const char *nameid, short spaceid, short regionid)
{
wmKeyMap *km;
for(km= wm->keymaps.first; km; km= km->next)
if(km->spaceid==spaceid && km->regionid==regionid)
if(0==strncmp(nameid, km->nameid, KMAP_MAX_NAME))
- break;
+ return km;
if(km==NULL) {
km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list");
@@ -154,19 +154,13 @@ static wmKeyMap *wm_keymap_add(wmWindowManager *wm, const char *nameid, short sp
return km;
}
-ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, short spaceid, short regionid)
-{
- wmKeyMap *km= wm_keymap_add(wm, nameid, spaceid, regionid);
- return &km->keymap;
-}
-
/* ****************** modal keymaps ************ */
/* modal maps get linked to a running operator, and filter the keys before sending to modal() callback */
wmKeyMap *WM_modalkeymap_add(wmWindowManager *wm, const char *nameid, EnumPropertyItem *items)
{
- wmKeyMap *km= wm_keymap_add(wm, nameid, 0, 0);
+ wmKeyMap *km= WM_keymap_find(wm, nameid, 0, 0);
km->is_modal= 1;
km->items= items;
@@ -242,15 +236,18 @@ static char *wm_keymap_item_to_string(wmKeymapItem *kmi, char *str, int len)
return str;
}
-static wmKeymapItem *wm_keymap_item_find_handlers(ListBase *handlers, const char *opname, int opcontext, IDProperty *properties, int compare_props)
+static wmKeymapItem *wm_keymap_item_find_handlers(const bContext *C, ListBase *handlers, const char *opname, int opcontext, IDProperty *properties, int compare_props)
{
wmEventHandler *handler;
+ wmKeyMap *keymap;
wmKeymapItem *kmi;
/* find keymap item in handlers */
for(handler=handlers->first; handler; handler=handler->next) {
- if(handler->keymap) {
- for(kmi=handler->keymap->first; kmi; kmi=kmi->next) {
+ keymap= handler->keymap;
+
+ if(keymap && (!keymap->poll || keymap->poll((bContext*)C))) {
+ for(kmi=keymap->keymap.first; kmi; kmi=kmi->next) {
if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) {
if(compare_props) {
if(kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data))
@@ -272,11 +269,11 @@ static wmKeymapItem *wm_keymap_item_find(const bContext *C, const char *opname,
/* look into multiple handler lists to find the item */
if(CTX_wm_window(C))
- found= wm_keymap_item_find_handlers(&CTX_wm_window(C)->handlers, opname, opcontext, properties, compare_props);
+ found= wm_keymap_item_find_handlers(C, &CTX_wm_window(C)->handlers, opname, opcontext, properties, compare_props);
if(CTX_wm_area(C) && found==NULL)
- found= wm_keymap_item_find_handlers(&CTX_wm_area(C)->handlers, opname, opcontext, properties, compare_props);
+ found= wm_keymap_item_find_handlers(C, &CTX_wm_area(C)->handlers, opname, opcontext, properties, compare_props);
if(found==NULL) {
if(ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) {
@@ -287,12 +284,12 @@ static wmKeymapItem *wm_keymap_item_find(const bContext *C, const char *opname,
break;
if(ar)
- found= wm_keymap_item_find_handlers(&ar->handlers, opname, opcontext, properties, compare_props);
+ found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props);
}
}
else {
if(CTX_wm_region(C))
- found= wm_keymap_item_find_handlers(&CTX_wm_region(C)->handlers, opname, opcontext, properties, compare_props);
+ found= wm_keymap_item_find_handlers(C, &CTX_wm_region(C)->handlers, opname, opcontext, properties, compare_props);
}
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 37cd424ac18..2c124437eb2 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -34,6 +34,7 @@
#include <stdio.h>
#include "DNA_ID.h"
+#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
@@ -46,12 +47,16 @@
#include "BLI_blenlib.h"
#include "BLI_dynstr.h" /*for WM_operator_pystring */
+#include "BLO_readfile.h"
+
#include "BKE_blender.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_utildefines.h"
@@ -242,7 +247,7 @@ wmOperatorType *WM_operatortype_append_macro(char *idname, char *name, int flag)
ot->idname= idname;
ot->name= name;
- ot->flag= OPTYPE_MACRO | flag;
+ ot->flag= OPTYPE_MACRO|flag;
ot->exec= wm_macro_exec;
ot->invoke= wm_macro_invoke;
@@ -496,10 +501,10 @@ int WM_operator_confirm(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_CANCELLED;
}
-/* op->invoke, opens fileselect if filename property not set, otherwise executes */
+/* op->invoke, opens fileselect if path property not set, otherwise executes */
int WM_operator_filesel(bContext *C, wmOperator *op, wmEvent *event)
{
- if (RNA_property_is_set(op->ptr, "filename")) {
+ if (RNA_property_is_set(op->ptr, "path")) {
return WM_operator_call(C, op);
}
else {
@@ -509,9 +514,11 @@ int WM_operator_filesel(bContext *C, wmOperator *op, wmEvent *event)
}
/* default properties for fileselect */
-void WM_operator_properties_filesel(wmOperatorType *ot, int filter)
+void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type)
{
- RNA_def_string_file_path(ot->srna, "filename", "", FILE_MAX, "Filename", "Path to file.");
+ RNA_def_string_file_path(ot->srna, "path", "", FILE_MAX, "FilePath", "Path to file.");
+ RNA_def_string_file_name(ot->srna, "filename", "", FILE_MAX, "FileName", "Name of the file.");
+ RNA_def_string_dir_path(ot->srna, "directory", "", FILE_MAX, "Directory", "Directory of the file.");
RNA_def_boolean(ot->srna, "filter_blender", (filter & BLENDERFILE), "Filter .blend files", "");
RNA_def_boolean(ot->srna, "filter_image", (filter & IMAGEFILE), "Filter image files", "");
@@ -521,6 +528,10 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter)
RNA_def_boolean(ot->srna, "filter_sound", (filter & SOUNDFILE), "Filter sound files", "");
RNA_def_boolean(ot->srna, "filter_text", (filter & TEXTFILE), "Filter text files", "");
RNA_def_boolean(ot->srna, "filter_folder", (filter & FOLDERFILE), "Filter folders", "");
+
+ RNA_def_int(ot->srna, "filemode", type, FILE_LOADLIB, FILE_SPECIAL,
+ "File Browser Mode", "The setting for the file browser mode to load a .blend file, a library or a special file.",
+ FILE_LOADLIB, FILE_SPECIAL);
}
/* op->poll */
@@ -531,7 +542,7 @@ int WM_operator_winactive(bContext *C)
}
/* op->invoke */
-static void redo_cb(bContext *C, void *arg_op, void *arg2)
+static void redo_cb(bContext *C, void *arg_op, int event)
{
wmOperator *lastop= arg_op;
@@ -553,7 +564,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op)
block= uiBeginBlock(C, ar, "redo_popup", UI_EMBOSS);
uiBlockClearFlag(block, UI_BLOCK_LOOP);
uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN|UI_BLOCK_RET_1);
- uiBlockSetFunc(block, redo_cb, arg_op, NULL);
+ uiBlockSetHandleFunc(block, redo_cb, arg_op);
if(!op->properties) {
IDPropertyTemplate val = {0};
@@ -671,7 +682,7 @@ static void operator_search_cb(const struct bContext *C, void *arg, char *str, u
for(; ot; ot= ot->next) {
if(BLI_strcasestr(ot->name, str)) {
- if(ot->poll==NULL || ot->poll((bContext *)C)) {
+ if(WM_operator_poll((bContext*)C, ot)) {
char name[256];
int len= strlen(ot->name);
@@ -736,11 +747,12 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
/* op->poll */
-int wm_search_menu_poll(bContext *C)
+static int wm_search_menu_poll(bContext *C)
{
if(CTX_wm_window(C)==NULL) return 0;
if(CTX_wm_area(C) && CTX_wm_area(C)->spacetype==SPACE_CONSOLE) return 0; // XXX - so we can use the shortcut in the console
if(CTX_wm_area(C) && CTX_wm_area(C)->spacetype==SPACE_TEXT) return 0; // XXX - so we can use the spacebar in the text editor
+ if(CTX_data_edit_object(C) && CTX_data_edit_object(C)->type==OB_CURVE) return 0; // XXX - so we can use the spacebar for entering text
return 1;
}
@@ -869,21 +881,9 @@ static void WM_OT_open_recentfile(wmOperatorType *ot)
RNA_def_enum_funcs(prop, open_recentfile_itemf);
}
-/* ********* main file *********** */
+/* *************** open file **************** */
-static void untitled(char *name)
-{
- if (G.save_over == 0 && strlen(name) < FILE_MAX-16) {
- char *c= BLI_last_slash(name);
-
- if (c)
- strcpy(&c[1], "untitled.blend");
- else
- strcpy(name, "untitled.blend");
- }
-}
-
-static void load_set_load_ui(wmOperator *op)
+static void open_set_load_ui(wmOperator *op)
{
if(!RNA_property_is_set(op->ptr, "load_ui"))
RNA_boolean_set(op->ptr, "load_ui", !(U.flag & USER_FILENOUI));
@@ -891,8 +891,8 @@ static void load_set_load_ui(wmOperator *op)
static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
- RNA_string_set(op->ptr, "filename", G.sce);
- load_set_load_ui(op);
+ RNA_string_set(op->ptr, "path", G.sce);
+ open_set_load_ui(op);
WM_event_add_fileselect(C, op);
@@ -901,10 +901,10 @@ static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event)
static int wm_open_mainfile_exec(bContext *C, wmOperator *op)
{
- char filename[FILE_MAX];
+ char path[FILE_MAX];
- RNA_string_get(op->ptr, "filename", filename);
- load_set_load_ui(op);
+ RNA_string_get(op->ptr, "path", path);
+ open_set_load_ui(op);
if(RNA_boolean_get(op->ptr, "load_ui"))
G.fileflags &= ~G_FILE_NO_UI;
@@ -915,7 +915,7 @@ static int wm_open_mainfile_exec(bContext *C, wmOperator *op)
// do it before for now, but is this correct with multiple windows?
WM_event_add_notifier(C, NC_WINDOW, NULL);
- WM_read_file(C, filename, op->reports);
+ WM_read_file(C, path, op->reports);
return 0;
}
@@ -930,11 +930,171 @@ static void WM_OT_open_mainfile(wmOperatorType *ot)
ot->exec= wm_open_mainfile_exec;
ot->poll= WM_operator_winactive;
- WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE);
+ WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER);
RNA_def_boolean(ot->srna, "load_ui", 1, "Load UI", "Load user interface setup in the .blend file.");
}
+/* **************** link/append *************** */
+
+static int wm_link_append_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ if(RNA_property_is_set(op->ptr, "path")) {
+ return WM_operator_call(C, op);
+ }
+ else {
+ /* XXX TODO solve where to get last linked library from */
+ RNA_string_set(op->ptr, "path", G.lib);
+ WM_event_add_fileselect(C, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+}
+
+static short wm_link_append_flag(wmOperator *op)
+{
+ short flag= 0;
+
+ if(RNA_boolean_get(op->ptr, "autoselect")) flag |= FILE_AUTOSELECT;
+ if(RNA_boolean_get(op->ptr, "active_layer")) flag |= FILE_ACTIVELAY;
+ if(RNA_boolean_get(op->ptr, "relative_paths")) flag |= FILE_STRINGCODE;
+ if(RNA_boolean_get(op->ptr, "link")) flag |= FILE_LINK;
+
+ return flag;
+}
+
+static void wm_link_make_library_local(Main *main, const char *libname)
+{
+ Library *lib;
+
+ /* and now find the latest append lib file */
+ for(lib= main->library.first; lib; lib=lib->id.next)
+ if(BLI_streq(libname, lib->filename))
+ break;
+
+ /* make local */
+ if(lib) {
+ all_local(lib, 1);
+ /* important we unset, otherwise these object wont
+ * link into other scenes from this blend file */
+ flag_all_listbases_ids(LIB_APPEND_TAG, 0);
+ }
+}
+
+static int wm_link_append_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain= CTX_data_main(C);
+ Scene *scene= CTX_data_scene(C);
+ Main *mainl= 0;
+ BlendHandle *bh;
+ PropertyRNA *prop;
+ char name[FILE_MAX], dir[FILE_MAX], libname[FILE_MAX], group[GROUP_MAX];
+ int idcode, totfiles=0;
+ short flag;
+
+ name[0] = '\0';
+ RNA_string_get(op->ptr, "filename", name);
+ RNA_string_get(op->ptr, "directory", dir);
+
+ /* test if we have a valid data */
+ if(BLO_is_a_library(dir, libname, group) == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Not a library");
+ return OPERATOR_CANCELLED;
+ }
+ else if(group[0] == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
+ return OPERATOR_CANCELLED;
+ }
+ else if(BLI_streq(bmain->name, libname)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot use current file as library");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* check if something is indicated for append/link */
+ prop = RNA_struct_find_property(op->ptr, "files");
+ if(prop) {
+ totfiles= RNA_property_collection_length(op->ptr, prop);
+ if(totfiles == 0) {
+ if(name[0] == '\0') {
+ BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
+ else if(name[0] == '\0') {
+ BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* now we have or selected, or an indicated file */
+ if(RNA_boolean_get(op->ptr, "autoselect"))
+ scene_deselect_all(scene);
+
+ bh = BLO_blendhandle_from_file(libname);
+ idcode = BLO_idcode_from_name(group);
+
+ flag = wm_link_append_flag(op);
+
+ /* tag everything, all untagged data can be made local */
+ if((flag & FILE_LINK)==0)
+ flag_all_listbases_ids(LIB_APPEND_TAG, 1);
+
+ /* here appending/linking starts */
+ mainl = BLO_library_append_begin(C, &bh, libname);
+ if(totfiles == 0) {
+ BLO_library_append_named_part(C, mainl, &bh, name, idcode, flag);
+ }
+ else {
+ RNA_BEGIN(op->ptr, itemptr, "files") {
+ RNA_string_get(&itemptr, "name", name);
+ BLO_library_append_named_part(C, mainl, &bh, name, idcode, flag);
+ }
+ RNA_END;
+ }
+ BLO_library_append_end(C, mainl, &bh, idcode, flag);
+
+ /* mark all library linked objects to be updated */
+ recalc_all_library_objects(bmain);
+
+ /* append, rather than linking */
+ if((flag & FILE_LINK)==0)
+ wm_link_make_library_local(bmain, libname);
+
+ /* recreate dependency graph to include new objects */
+ DAG_scene_sort(scene);
+ DAG_ids_flush_update(0);
+
+ BLO_blendhandle_close(bh);
+
+ /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */
+ BLI_strncpy(G.lib, dir, FILE_MAX);
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void WM_OT_link_append(wmOperatorType *ot)
+{
+ ot->name= "Link/Append from Library";
+ ot->idname= "WM_OT_link_append";
+ ot->description= "Link or Append from a Library .blend file";
+
+ ot->invoke= wm_link_append_invoke;
+ ot->exec= wm_link_append_exec;
+ ot->poll= WM_operator_winactive;
+
+ WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_LOADLIB);
+
+ RNA_def_boolean(ot->srna, "link", 1, "Link", "Link the objects or datablocks rather than appending.");
+ RNA_def_boolean(ot->srna, "autoselect", 1, "Select", "Select the linked objects.");
+ RNA_def_boolean(ot->srna, "active_layer", 1, "Active Layer", "Put the linked objects on the active layer.");
+ RNA_def_boolean(ot->srna, "relative_paths", 1, "Relative Paths", "Store the library path as a relative path to current .blend file.");
+
+ RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", "");
+}
+
+/* *************** recover last session **************** */
+
static int wm_recover_last_session_exec(bContext *C, wmOperator *op)
{
char scestr[FILE_MAX], filename[FILE_MAX];
@@ -969,6 +1129,20 @@ static void WM_OT_recover_last_session(wmOperatorType *ot)
ot->poll= WM_operator_winactive;
}
+/* *************** save file as **************** */
+
+static void untitled(char *name)
+{
+ if(G.save_over == 0 && strlen(name) < FILE_MAX-16) {
+ char *c= BLI_last_slash(name);
+
+ if(c)
+ strcpy(&c[1], "untitled.blend");
+ else
+ strcpy(name, "untitled.blend");
+ }
+}
+
static void save_set_compress(wmOperator *op)
{
if(!RNA_property_is_set(op->ptr, "compress")) {
@@ -987,7 +1161,7 @@ static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *even
BLI_strncpy(name, G.sce, FILE_MAX);
untitled(name);
- RNA_string_set(op->ptr, "filename", name);
+ RNA_string_set(op->ptr, "path", name);
WM_event_add_fileselect(C, op);
@@ -997,20 +1171,20 @@ static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *even
/* function used for WM_OT_save_mainfile too */
static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
{
- char filename[FILE_MAX];
+ char path[FILE_MAX];
int compress;
save_set_compress(op);
compress= RNA_boolean_get(op->ptr, "compress");
- if(RNA_property_is_set(op->ptr, "filename"))
- RNA_string_get(op->ptr, "filename", filename);
+ if(RNA_property_is_set(op->ptr, "path"))
+ RNA_string_get(op->ptr, "path", path);
else {
- BLI_strncpy(filename, G.sce, FILE_MAX);
- untitled(filename);
+ BLI_strncpy(path, G.sce, FILE_MAX);
+ untitled(path);
}
- WM_write_file(C, filename, compress, op->reports);
+ WM_write_file(C, path, compress, op->reports);
WM_event_add_notifier(C, NC_WM|ND_FILESAVE, NULL);
@@ -1027,11 +1201,11 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot)
ot->exec= wm_save_as_mainfile_exec;
ot->poll= WM_operator_winactive;
- WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE);
+ WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER);
RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file.");
}
-/* *************** Save file directly ******** */
+/* *************** save file directly ******** */
static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
@@ -1041,7 +1215,7 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event)
BLI_strncpy(name, G.sce, FILE_MAX);
untitled(name);
- RNA_string_set(op->ptr, "filename", name);
+ RNA_string_set(op->ptr, "path", name);
uiPupMenuSaveOver(C, op, name);
return OPERATOR_RUNNING_MODAL;
@@ -1057,7 +1231,7 @@ static void WM_OT_save_mainfile(wmOperatorType *ot)
ot->exec= wm_save_as_mainfile_exec;
ot->poll= WM_operator_winactive;
- WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE);
+ WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER);
RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file.");
}
@@ -1194,7 +1368,7 @@ int WM_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
op->customdata= WM_gesture_new(C, event, WM_GESTURE_CROSS_RECT);
/* add modal handler */
- WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+ WM_event_add_modal_handler(C, op);
wm_gesture_tag_redraw(C);
@@ -1258,7 +1432,7 @@ int WM_gesture_circle_invoke(bContext *C, wmOperator *op, wmEvent *event)
op->customdata= WM_gesture_new(C, event, WM_GESTURE_CIRCLE);
/* add modal handler */
- WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+ WM_event_add_modal_handler(C, op);
wm_gesture_tag_redraw(C);
@@ -1311,7 +1485,7 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, wmEvent *event)
case LEFTMOUSE:
case MIDDLEMOUSE:
case RIGHTMOUSE:
- if(event->val==0) { /* key release */
+ if(event->val==KM_RELEASE) { /* key release */
wm_gesture_end(C, op);
return OPERATOR_FINISHED;
}
@@ -1394,7 +1568,7 @@ static void tweak_gesture_modal(bContext *C, wmEvent *event)
if(gesture->event_type==event->type) {
WM_gesture_end(C, gesture);
window->tweak= NULL;
-
+
/* when tweak fails we should give the other keymap entries a chance */
event->val= KM_RELEASE;
}
@@ -1412,7 +1586,7 @@ void wm_tweakevent_test(bContext *C, wmEvent *event, int action)
if(win->tweak==NULL) {
if(CTX_wm_region(C)) {
- if(event->val) { // pressed
+ if(event->val==KM_PRESS) { // pressed
if( ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) )
win->tweak= WM_gesture_new(C, event, WM_GESTURE_TWEAK);
}
@@ -1435,7 +1609,7 @@ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, wmEvent *event)
op->customdata= WM_gesture_new(C, event, WM_GESTURE_LASSO);
/* add modal handler */
- WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+ WM_event_add_modal_handler(C, op);
wm_gesture_tag_redraw(C);
@@ -1450,7 +1624,7 @@ int WM_gesture_lines_invoke(bContext *C, wmOperator *op, wmEvent *event)
op->customdata= WM_gesture_new(C, event, WM_GESTURE_LINES);
/* add modal handler */
- WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+ WM_event_add_modal_handler(C, op);
wm_gesture_tag_redraw(C);
@@ -1512,7 +1686,7 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, wmEvent *event)
case LEFTMOUSE:
case MIDDLEMOUSE:
case RIGHTMOUSE:
- if(event->val==0) { /* key release */
+ if(event->val==KM_RELEASE) { /* key release */
gesture_lasso_apply(C, op, event->type);
return OPERATOR_FINISHED;
}
@@ -1757,7 +1931,7 @@ int WM_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
wm_radial_control_paint, op->customdata);
/* add modal handler */
- WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+ WM_event_add_modal_handler(C, op);
WM_radial_control_modal(C, op, event);
@@ -1805,17 +1979,19 @@ void WM_OT_radial_control_partial(wmOperatorType *ot)
/* uses no type defines, fully local testing function anyway... ;) */
-static int ten_timer_exec(bContext *C, wmOperator *op)
+static int redraw_timer_exec(bContext *C, wmOperator *op)
{
ARegion *ar= CTX_wm_region(C);
double stime= PIL_check_seconds_timer();
int type = RNA_int_get(op->ptr, "type");
- int a, time;
- char tmpstr[128];
+ int iter = RNA_int_get(op->ptr, "iterations");
+ int a;
+ float time;
+ char *infostr= "";
WM_cursor_wait(1);
-
- for(a=0; a<10; a++) {
+
+ for(a=0; a<iter; a++) {
if (type==0) {
ED_region_do_draw(C, ar);
}
@@ -1831,13 +2007,35 @@ static int ten_timer_exec(bContext *C, wmOperator *op)
wmWindow *win= CTX_wm_window(C);
ScrArea *sa;
+ ScrArea *sa_back= CTX_wm_area(C);
+ ARegion *ar_back= CTX_wm_region(C);
+
+ for(sa= CTX_wm_screen(C)->areabase.first; sa; sa= sa->next) {
+ ARegion *ar_iter;
+ CTX_wm_area_set(C, sa);
+
+ for(ar_iter= sa->regionbase.first; ar_iter; ar_iter= ar_iter->next) {
+ CTX_wm_region_set(C, ar_iter);
+ ED_region_do_draw(C, ar_iter);
+ }
+ }
+
+ CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
+
+ CTX_wm_area_set(C, sa_back);
+ CTX_wm_region_set(C, ar_back);
+ }
+ else if (type==3) {
+ wmWindow *win= CTX_wm_window(C);
+ ScrArea *sa;
+
for(sa= CTX_wm_screen(C)->areabase.first; sa; sa= sa->next)
ED_area_tag_redraw(sa);
wm_draw_update(C);
CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
}
- else if (type==3) {
+ else if (type==4) {
Scene *scene= CTX_data_scene(C);
if(a & 1) scene->r.cfra--;
@@ -1850,40 +2048,44 @@ static int ten_timer_exec(bContext *C, wmOperator *op)
}
}
- time= (int) ((PIL_check_seconds_timer()-stime)*1000);
+ time= ((PIL_check_seconds_timer()-stime)*1000);
- if(type==0) sprintf(tmpstr, "10 x Draw Region: %d ms", time);
- if(type==1) sprintf(tmpstr, "10 x Draw Region and Swap: %d ms", time);
- if(type==2) sprintf(tmpstr, "10 x Draw Window and Swap: %d ms", time);
- if(type==3) sprintf(tmpstr, "Anim Step: %d ms", time);
- if(type==4) sprintf(tmpstr, "10 x Undo/Redo: %d ms", time);
+ if(type==0) infostr= "Draw Region";
+ if(type==1) infostr= "Draw Region and Swap";
+ if(type==2) infostr= "Draw Window";
+ if(type==3) infostr= "Draw Window and Swap";
+ if(type==4) infostr= "Animation Steps";
+ if(type==5) infostr= "Undo/Redo";
WM_cursor_wait(0);
- uiPupMenuNotice(C, tmpstr);
+ BKE_reportf(op->reports, RPT_INFO, "%d x %s: %.2f ms, average: %.4f", iter, infostr, time, time/iter);
return OPERATOR_FINISHED;
}
-static void WM_OT_ten_timer(wmOperatorType *ot)
+static void WM_OT_redraw_timer(wmOperatorType *ot)
{
static EnumPropertyItem prop_type_items[] = {
{0, "DRAW", 0, "Draw Region", ""},
- {1, "DRAWSWAP", 0, "Draw Region + Swap", ""},
- {2, "DRAWWINSWAP", 0, "Draw Window + Swap", ""},
- {3, "ANIMSTEP", 0, "Anim Step", ""},
- {4, "UNDO", 0, "Undo/Redo", ""},
+ {1, "DRAW_SWAP", 0, "Draw Region + Swap", ""},
+ {2, "DRAW_WIN", 0, "Draw Window", ""},
+ {3, "DRAW_WIN_SWAP", 0, "Draw Window + Swap", ""},
+ {4, "ANIM_STEP", 0, "Anim Step", ""},
+ {5, "UNDO", 0, "Undo/Redo", ""},
{0, NULL, 0, NULL, NULL}};
- ot->name= "Ten Timer";
- ot->idname= "WM_OT_ten_timer";
+ ot->name= "Redraw Timer";
+ ot->idname= "WM_OT_redraw_timer";
+ ot->description="Simple redraw timer to test the speed of updating the interface.";
ot->description="Ten Timer operator.";
ot->invoke= WM_menu_invoke;
- ot->exec= ten_timer_exec;
+ ot->exec= redraw_timer_exec;
ot->poll= WM_operator_winactive;
RNA_def_enum(ot->srna, "type", prop_type_items, 0, "Type", "");
+ RNA_def_int(ot->srna, "iterations", 10, 1,INT_MAX, "Iterations", "Number of times to redraw", 1,1000);
}
@@ -1913,11 +2115,12 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_exit_blender);
WM_operatortype_append(WM_OT_open_recentfile);
WM_operatortype_append(WM_OT_open_mainfile);
+ WM_operatortype_append(WM_OT_link_append);
WM_operatortype_append(WM_OT_recover_last_session);
WM_operatortype_append(WM_OT_jobs_timer);
WM_operatortype_append(WM_OT_save_as_mainfile);
WM_operatortype_append(WM_OT_save_mainfile);
- WM_operatortype_append(WM_OT_ten_timer);
+ WM_operatortype_append(WM_OT_redraw_timer);
WM_operatortype_append(WM_OT_debug_menu);
WM_operatortype_append(WM_OT_search_menu);
}
@@ -1925,7 +2128,7 @@ void wm_operatortype_init(void)
/* default keymap for windows and screens, only call once per WM */
void wm_window_keymap(wmWindowManager *wm)
{
- ListBase *keymap= WM_keymap_listbase(wm, "Window", 0, 0);
+ wmKeyMap *keymap= WM_keymap_find(wm, "Window", 0, 0);
/* items to make WM work */
WM_keymap_verify_item(keymap, "WM_OT_jobs_timer", TIMERJOBS, KM_ANY, KM_ANY, 0);
@@ -1944,6 +2147,7 @@ void wm_window_keymap(wmWindowManager *wm)
WM_keymap_add_item(keymap, "WM_OT_save_homefile", UKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "WM_OT_open_recentfile", OKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
WM_keymap_add_item(keymap, "WM_OT_open_mainfile", OKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "WM_OT_link_append", OKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
WM_keymap_add_item(keymap, "WM_OT_save_mainfile", SKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "WM_OT_save_as_mainfile", SKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
@@ -1951,7 +2155,7 @@ void wm_window_keymap(wmWindowManager *wm)
WM_keymap_add_item(keymap, "WM_OT_exit_blender", QKEY, KM_PRESS, KM_CTRL, 0);
/* debug/testing */
- WM_keymap_verify_item(keymap, "WM_OT_ten_timer", TKEY, KM_PRESS, KM_ALT|KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "WM_OT_redraw_timer", TKEY, KM_PRESS, KM_ALT|KM_CTRL, 0);
WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT|KM_CTRL, 0);
WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index d70516ef02e..c853afe4507 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -146,6 +146,7 @@ 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) {
@@ -331,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 */
@@ -367,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);
}
@@ -623,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);
@@ -630,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");
- }
- else if(state==GHOST_kWindowStateMaximized) {
- if(G.f & G_DEBUG) printf("window state: maximized\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_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;
}