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:
authorTon Roosendaal <ton@blender.org>2009-02-16 15:14:04 +0300
committerTon Roosendaal <ton@blender.org>2009-02-16 15:14:04 +0300
commit4154e48c053caf947f2668a168ce38aa10b8481b (patch)
tree294c3173648572d6669a8c85e08a459ba0075ce1 /source/blender/windowmanager
parentf6df8e1860d44d6b4d2c9048b0fb0ebdbfd850d3 (diff)
2.5
Proper integration of File-selecting in WM. The communication flow was flawed. :) Main problem was that filewindow can change the screen context entirely, and should not do this directly on a call inside an operator. Another problem was that the operator ownership was handed over to SpaceFile, which is asking for problems if you want to execute the operator with proper context later on. Solution is simple; window handlers already are valid owners of operators and can manage context, so instead of directly talking to the 'file space', you give the operator to a new handler this way: WM_event_add_fileselect(C, op); This handler then listens to events (OPEN, EXEC, CANCEL) sent by the WM or by the filewindow itself. This way local context operators (like "open new image in imagewindow") will survive a full-window fileselector fine, and in future also secondary windows browsing files. Two bugfixes included in this commit too: - Add sequence menus in Sequencer used wrong context. - When handler executes operators, it sets stored context now by first checking if this is still valid.
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r--source/blender/windowmanager/WM_api.h8
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c167
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c41
-rw-r--r--source/blender/windowmanager/wm_event_system.h5
-rw-r--r--source/blender/windowmanager/wm_event_types.h15
5 files changed, 189 insertions, 47 deletions
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index f0f8996cca9..45dd2f3aee2 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -161,11 +161,15 @@ struct wmGesture *WM_gesture_new(struct bContext *C, struct wmEvent *event, int
void WM_gesture_end(struct bContext *C, struct wmGesture *gesture);
/* radial control operator */
-int WM_radial_control_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int WM_radial_control_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+int WM_radial_control_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+int WM_radial_control_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
void WM_OT_radial_control_partial(struct wmOperatorType *ot);
void WM_radial_control_string(struct wmOperator *op, char str[], int maxlen);
+ /* fileselecting support */
+void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op);
+void WM_event_fileselect_event(struct bContext *C, void *ophandle, int eventval);
+
/* OpenGL wrappers, mimicking opengl syntax */
void wmSubWindowSet (struct wmWindow *win, int swinid);
void wmSubWindowScissorSet (struct wmWindow *win, int swinid, struct rcti *srct);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 1f417860e0c..80cef611974 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -50,6 +50,7 @@
#include "BKE_scene.h"
#include "BKE_utildefines.h"
+#include "ED_fileselect.h"
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_util.h"
@@ -455,10 +456,36 @@ int WM_operator_call_py(bContext *C, wmOperatorType *ot, PointerRNA *properties,
/* ********************* handlers *************** */
-/* not handler itself, is called by UI to move handlers to other queues, so don't close modal ones */
+/* future extra customadata free? */
static void wm_event_free_handler(wmEventHandler *handler)
{
+ MEM_freeN(handler);
+}
+
+/* only set context when area/region is part of screen */
+static void wm_handler_op_context(bContext *C, wmEventHandler *handler)
+{
+ bScreen *screen= CTX_wm_screen(C);
+ if(screen && handler->op) {
+ ScrArea *sa;
+
+ for(sa= screen->areabase.first; sa; sa= sa->next)
+ if(sa==handler->op_area)
+ break;
+ if(sa==NULL)
+ printf("internal error: handler (%s) has invalid area\n", handler->op->type->idname);
+ else {
+ ARegion *ar;
+ CTX_wm_area_set(C, sa);
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar==handler->op_region)
+ break;
+ /* XXX no warning print here, after full-area and back regions are remade */
+ if(ar)
+ CTX_wm_region_set(C, ar);
+ }
+ }
}
/* called on exit or remove area, only here call cancel callback */
@@ -475,8 +502,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
ScrArea *area= CTX_wm_area(C);
ARegion *region= CTX_wm_region(C);
- CTX_wm_area_set(C, handler->op_area);
- CTX_wm_region_set(C, handler->op_region);
+ wm_handler_op_context(C, handler);
handler->op->type->cancel(C, handler->op);
@@ -500,7 +526,6 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
}
wm_event_free_handler(handler);
- MEM_freeN(handler);
}
}
@@ -597,8 +622,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
ScrArea *area= CTX_wm_area(C);
ARegion *region= CTX_wm_region(C);
- CTX_wm_area_set(C, handler->op_area);
- CTX_wm_region_set(C, handler->op_region);
+ wm_handler_op_context(C, handler);
retval= ot->modal(C, op, event);
@@ -641,7 +665,6 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
BLI_remlink(handlers, handler);
wm_event_free_handler(handler);
- MEM_freeN(handler);
/* prevent silly errors from operator users */
//retval &= ~OPERATOR_PASS_THROUGH;
@@ -693,6 +716,87 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve
return WM_HANDLER_CONTINUE;
}
+/* fileselect handlers are only in the window queue, so it's save to switch screens or area types */
+static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHandler *handler, wmEvent *event)
+{
+ SpaceFile *sfile;
+ int action= WM_HANDLER_CONTINUE;
+
+ if(event->type != EVT_FILESELECT)
+ return action;
+ if(handler->op != (wmOperator *)event->customdata)
+ return action;
+
+ switch(event->val) {
+ case EVT_FILESELECT_OPEN:
+ case EVT_FILESELECT_FULL_OPEN:
+ {
+ int filetype= FILE_BLENDER;
+ char *path= RNA_string_get_alloc(handler->op->ptr, "filename", NULL, 0);
+
+ if(RNA_struct_find_property(handler->op->ptr, "filetype"))
+ filetype= RNA_int_get(handler->op->ptr, "filetype");
+
+ if(event->val==EVT_FILESELECT_OPEN)
+ ED_area_newspace(C, handler->op_area, SPACE_FILE);
+ else
+ ED_screen_full_newspace(C, handler->op_area, SPACE_FILE);
+
+ /* settings for filebrowser, sfile is not operator owner but sends events */
+ sfile= (SpaceFile*)CTX_wm_space_data(C);
+ sfile->op= handler->op;
+
+ ED_fileselect_set_params(sfile, filetype, handler->op->type->name, path, 0, 0, 0);
+ MEM_freeN(path);
+
+ action= WM_HANDLER_BREAK;
+ }
+ break;
+
+ case EVT_FILESELECT_EXEC:
+ case EVT_FILESELECT_CANCEL:
+ {
+ /* XXX validate area and region? */
+ bScreen *screen= CTX_wm_screen(C);
+ char *path= RNA_string_get_alloc(handler->op->ptr, "filename", NULL, 0);
+
+ if(screen != handler->filescreen)
+ ED_screen_full_prevspace(C);
+ else
+ ED_area_prevspace(C);
+
+ /* remlink now, for load file case */
+ BLI_remlink(handlers, handler);
+
+ if(event->val==EVT_FILESELECT_EXEC) {
+ wm_handler_op_context(C, handler);
+
+ /* a bit weak, might become arg for WM_event_fileselect? */
+ if(strncmp(handler->op->type->name, "Save", 4)==0) {
+ /* this gives ownership to pupmenu */
+ uiPupMenuSaveOver(C, handler->op, path);
+ }
+ else {
+ handler->op->type->exec(C, handler->op);
+ WM_operator_free(handler->op);
+ }
+
+ CTX_wm_area_set(C, NULL);
+ }
+ else
+ WM_operator_free(handler->op);
+
+ wm_event_free_handler(handler);
+ MEM_freeN(path);
+
+ action= WM_HANDLER_BREAK;
+ }
+ break;
+ }
+
+ return action;
+}
+
static int handler_boundbox_test(wmEventHandler *handler, wmEvent *event)
{
if(handler->bbwin) {
@@ -742,6 +846,10 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
else if(handler->ui_handle) {
action= wm_handler_ui_call(C, handler, event);
}
+ else if(handler->type==WM_HANDLER_FILESELECT) {
+ /* screen context changes here */
+ action= wm_handler_fileselect_call(C, handlers, handler, event);
+ }
else {
/* modal, swallows all */
action= wm_handler_operator_call(C, handlers, handler, event, NULL);
@@ -930,6 +1038,49 @@ void wm_event_do_handlers(bContext *C)
}
}
+/* ********** filesector handling ************ */
+
+void WM_event_fileselect_event(bContext *C, void *ophandle, int eventval)
+{
+ /* add to all windows! */
+ wmWindow *win;
+
+ for(win= CTX_wm_manager(C)->windows.first; win; win= win->next) {
+ wmEvent event= *win->eventstate;
+
+ event.type= EVT_FILESELECT;
+ event.val= eventval;
+ event.customdata= ophandle; // only as void pointer type check
+
+ wm_event_add(win, &event);
+ }
+}
+
+/* operator is supposed to have a filled "filename" property */
+/* optional property: filetype (XXX enum?) */
+
+/* Idea is to keep a handler alive on window queue, owning the operator.
+ The filewindow can send event to make it execute, thus ensuring
+ executing happens outside of lower level queues, with UI refreshed.
+ Should also allow multiwin solutions */
+
+void WM_event_add_fileselect(bContext *C, wmOperator *op)
+{
+ wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "fileselect handler");
+ wmWindow *win= CTX_wm_window(C);
+ int full= 1; // XXX preset?
+
+ handler->type= WM_HANDLER_FILESELECT;
+ handler->op= op;
+ handler->op_area= CTX_wm_area(C);
+ handler->op_region= CTX_wm_region(C);
+ handler->filescreen= CTX_wm_screen(C);
+
+ BLI_addhead(&win->handlers, handler);
+
+ WM_event_fileselect_event(C, op, full?EVT_FILESELECT_FULL_OPEN:EVT_FILESELECT_OPEN);
+}
+
/* lets not expose struct outside wm? */
void WM_event_set_handler_flag(wmEventHandler *handler, int flag)
{
@@ -997,7 +1148,6 @@ void WM_event_remove_keymap_handler(ListBase *handlers, ListBase *keymap)
if(handler->keymap==keymap) {
BLI_remlink(handlers, handler);
wm_event_free_handler(handler);
- MEM_freeN(handler);
break;
}
}
@@ -1025,7 +1175,6 @@ void WM_event_remove_ui_handler(ListBase *handlers, wmUIHandlerFunc func, wmUIHa
if(handler->ui_handle == func && handler->ui_remove == remove && handler->ui_userdata == userdata) {
BLI_remlink(handlers, handler);
wm_event_free_handler(handler);
- MEM_freeN(handler);
break;
}
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 8372aa17208..9626fda6ffe 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -53,7 +53,6 @@
#include "BIF_glutil.h" /* for paint cursor */
#include "IMB_imbuf_types.h"
-#include "ED_fileselect.h"
#include "ED_screen.h"
#include "RNA_access.h"
@@ -235,17 +234,9 @@ int WM_operator_filesel(bContext *C, wmOperator *op, wmEvent *event)
{
if (RNA_property_is_set(op->ptr, "filename")) {
return WM_operator_call(C, op);
- } else {
- SpaceFile *sfile;
-
- ED_screen_full_newspace(C, CTX_wm_area(C), SPACE_FILE);
-
- /* settings for filebrowser */
- sfile= (SpaceFile*)CTX_wm_space_data(C);
- sfile->op = op;
- ED_fileselect_set_params(sfile, FILE_BLENDER, op->type->name, "", 0, 0, 0);
-
- /* screen and area have been reset already in ED_screen_full_newspace */
+ }
+ else {
+ WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
}
@@ -368,18 +359,9 @@ static void untitled(char *name)
static int wm_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
- SpaceFile *sfile;
-
- if(0==ED_screen_full_newspace(C, CTX_wm_area(C), SPACE_FILE))
- return OPERATOR_CANCELLED;
-
- /* settings for filebrowser */
- sfile= (SpaceFile*)CTX_wm_space_data(C);
- sfile->op = op;
-
- ED_fileselect_set_params(sfile, FILE_BLENDER, "Load", G.sce, 0, 0, 0);
- /* screen and area have been reset already in ED_screen_full_newspace */
+ RNA_string_set(op->ptr, "filename", G.sce);
+ WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -415,20 +397,13 @@ static void WM_OT_open_mainfile(wmOperatorType *ot)
static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
- SpaceFile *sfile;
char name[FILE_MAX];
- ED_screen_full_newspace(C, CTX_wm_area(C), SPACE_FILE);
-
- /* settings for filebrowser */
- sfile= (SpaceFile*)CTX_wm_space_data(C);
- sfile->op = op;
-
BLI_strncpy(name, G.sce, FILE_MAX);
untitled(name);
- ED_fileselect_set_params(sfile, FILE_BLENDER, "Save As", name, 0, 0, 0);
-
- /* screen and area have been reset already in ED_screen_full_newspace */
+ RNA_string_set(op->ptr, "filename", name);
+
+ WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index d6899d47471..930f20dfa63 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -59,6 +59,9 @@ typedef struct wmEventHandler {
struct ScrArea *ui_area; /* for derived/modal handlers */
struct ARegion *ui_region; /* for derived/modal handlers */
+ /* fileselect handler re-uses modal operator data */
+ struct bScreen *filescreen; /* screen it started in, to validate exec */
+
} wmEventHandler;
@@ -71,7 +74,7 @@ typedef struct wmEventHandler {
/* custom types for handlers, for signalling, freeing */
enum {
WM_HANDLER_DEFAULT,
- WM_HANDLER_TRANSFORM
+ WM_HANDLER_FILESELECT
};
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index a3bf0ca728f..275d8d99810 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -197,7 +197,7 @@
#define ISKEYBOARD(event) (event >='a' && event <=255)
-/* **************** BLENDER QUEUE EVENTS ********************* */
+/* **************** XXX depricated! BLENDER QUEUE EVENTS ********************* */
#define CHANGED 0x4000
#define DRAWEDGES 0x4001
@@ -211,7 +211,6 @@
#define AUTOSAVE_FILE 0x4009
#define UNDOPUSH 0x400A
-/* REDRAWVIEW3D has to be the first one (lowest number) for buttons! */
#define REDRAWVIEW3D 0x4010
#define REDRAWVIEWCAM 0x4011
#define REDRAWVIEW3D_Z 0x4012
@@ -293,5 +292,17 @@
#define EVT_GESTURE_W_S 15
#define EVT_GESTURE_W_N 16
+/* **************** OTHER BLENDER EVENTS ********************* */
+
+/* event->type */
+#define EVT_FILESELECT 0x5020
+
+/* event->val */
+#define EVT_FILESELECT_OPEN 1
+#define EVT_FILESELECT_FULL_OPEN 2
+#define EVT_FILESELECT_EXEC 3
+#define EVT_FILESELECT_CANCEL 4
+
+
#endif /* WM_EVENT_TYPES_H */