2.5: gesture code in WM

- Simplified and cleaned previous border code
  It was a bit too complex, too many data manipulations

Original idea was to have WM API calls to manage border, circle, lines, 
lasso, etc. This now means that WM provides callbacks for custom operators,
so it's very easy to make them. Check bottom of screen_edit.c for an
example. 

Currently two borders were coded; with and without cross hair.
Press Bkey in any area-region to test it (note: time window has wrong matrix!)

Some specs to note:
- gestures are in region space, and draw 'over'. That latter still needs some
  work when we do real composites.
- only the active region is redrawn.
- on todo is the generic gesture engine for 'tweak' or like how currently grab
  gestures in Blender work. These will be configurable per area-region, and WM
  then will send the proper "Gesture Event" with properties (N, S, E, W, etc)
  to which you then can assign operators. Such events will be generated with low 
  priority, so other handlers who swallowed mouse events have preference.
This commit is contained in:
Ton Roosendaal 2008-11-19 13:16:05 +00:00
parent ecde558252
commit fd8c94fdb1
14 changed files with 240 additions and 290 deletions

@ -55,7 +55,6 @@ void ED_area_exit(struct bContext *C, ScrArea *sa);
/* screens */ /* screens */
void ED_screens_initialize(struct wmWindowManager *wm); void ED_screens_initialize(struct wmWindowManager *wm);
void ED_screen_draw(struct wmWindow *win); void ED_screen_draw(struct wmWindow *win);
void ED_screen_gesture(struct wmWindow *win);
void ED_screen_refresh(struct wmWindowManager *wm, struct wmWindow *win); void ED_screen_refresh(struct wmWindowManager *wm, struct wmWindow *win);
void ED_screen_do_listen(struct wmWindow *win, struct wmNotifier *note); void ED_screen_do_listen(struct wmWindow *win, struct wmNotifier *note);
bScreen *ED_screen_duplicate(struct wmWindow *win, bScreen *sc); bScreen *ED_screen_duplicate(struct wmWindow *win, bScreen *sc);

@ -95,6 +95,11 @@ void ED_region_do_listen(ARegion *ar, wmNotifier *note)
/* generic notes first */ /* generic notes first */
switch(note->type) { switch(note->type) {
case WM_NOTE_WINDOW_REDRAW: case WM_NOTE_WINDOW_REDRAW:
case WM_NOTE_AREA_REDRAW:
case WM_NOTE_REGION_REDRAW:
ar->do_draw= 1;
break;
case WM_NOTE_GESTURE_REDRAW:
ar->do_draw= 1; ar->do_draw= 1;
break; break;
case WM_NOTE_SCREEN_CHANGED: case WM_NOTE_SCREEN_CHANGED:

@ -53,23 +53,6 @@
#include "screen_intern.h" /* own module include */ #include "screen_intern.h" /* own module include */
/* ******************* gesture manager ******************* */
void ed_gesture_draw_rect(wmWindow *win, wmGesture *gt)
{
wmGestureRect *rect= (wmGestureRect *)gt;
sdrawbox(rect->x1, rect->y1, rect->x2, rect->y2);
}
void ed_gesture_update(wmWindow *win)
{
wmGesture *gt= (wmGesture *)win->gesture.first;
while(gt) {
if(gt->type==GESTURE_RECT)
ed_gesture_draw_rect(win, gt);
gt= gt->next;
}
}
/* ******************* screen vert, edge, area managing *********************** */ /* ******************* screen vert, edge, area managing *********************** */
@ -1163,15 +1146,8 @@ void ED_screen_do_listen(wmWindow *win, wmNotifier *note)
case WM_NOTE_SCREEN_CHANGED: case WM_NOTE_SCREEN_CHANGED:
win->screen->do_draw= win->screen->do_refresh= 1; win->screen->do_draw= win->screen->do_refresh= 1;
break; break;
case WM_NOTE_AREA_SPLIT: case WM_NOTE_GESTURE_REDRAW:
printf("WM_NOTE_AREA_SPLIT\n"); win->screen->do_gesture= 1; /* XXX gestures are stored in window, draw per region... a bit weak? wait for proper composite? (ton) */
break;
case WM_NOTE_AREA_DRAG:
printf("WM_NOTE_AREA_DRAG\n");
break;
case WM_NOTE_GESTURE_CHANGED:
printf("WM_NOTE_GESTURE_CHANGED\n");
win->screen->do_gesture= 1;
break; break;
} }
} }
@ -1222,16 +1198,6 @@ void ED_screen_draw(wmWindow *win)
win->screen->do_draw= 0; win->screen->do_draw= 0;
} }
void ED_screen_gesture(wmWindow *win)
{
if(G.f & G_DEBUG) printf("gesture draw screen\n");
if(win->gesture.first) {
ed_gesture_update(win);
}
win->screen->do_gesture= 0;
}
/* make this screen usable */ /* make this screen usable */
/* for file read and first use, for scaling window, area moves */ /* for file read and first use, for scaling window, area moves */
void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
@ -1309,11 +1275,6 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
WM_event_remove_handlers(&window->handlers); WM_event_remove_handlers(&window->handlers);
} }
void placeholder()
{
removenotused_scrverts(NULL);
removenotused_scredges(NULL);
}
/* called in wm_event_system.c. sets state var in screen */ /* called in wm_event_system.c. sets state var in screen */
void ED_screen_set_subwinactive(wmWindow *win) void ED_screen_set_subwinactive(wmWindow *win)
@ -2118,9 +2079,49 @@ void ED_SCR_OT_join_areas(wmOperatorType *ot)
/* api callbacks */ /* api callbacks */
ot->exec= join_areas_exec; ot->exec= join_areas_exec;
ot->invoke= join_areas_invoke; ot->invoke= join_areas_invoke;
ot->cancel= join_areas_cancel;
ot->modal= join_areas_modal; ot->modal= join_areas_modal;
ot->poll= ED_operator_screenactive; ot->poll= ED_operator_screenactive;
} }
/* ************** border select operator (test only) ***************************** */
/* operator state vars used: (added by default WM callbacks)
xmin, ymin
xmax, ymax
customdata: the wmGesture pointer
callbacks:
exec() has to be filled in by user
invoke() default WM function
adds modal handler
modal() default WM function
accept modal events while doing it, calls exec(), handles ESC and border drawing
poll() has to be filled in by user for context
*/
static int border_select_do(bContext *C, wmOperator *op)
{
printf("border select do\n");
return 1;
}
void ED_SCR_OT_border_select(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Border select";
ot->idname= "ED_SCR_OT_border_select";
/* api callbacks */
ot->exec= border_select_do;
ot->invoke= WM_border_select_invoke;
ot->modal= WM_border_select_modal;
ot->poll= ED_operator_areaactive;
}

@ -45,6 +45,8 @@ void ED_SCR_OT_join_areas(wmOperatorType *ot);
void ED_SCR_OT_actionzone(wmOperatorType *ot); void ED_SCR_OT_actionzone(wmOperatorType *ot);
void ED_SCR_OT_area_rip(wmOperatorType *ot); void ED_SCR_OT_area_rip(wmOperatorType *ot);
void ED_SCR_OT_border_select(wmOperatorType *ot);
#endif /* ED_SCREEN_INTERN_H */ #endif /* ED_SCREEN_INTERN_H */

@ -91,6 +91,9 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(ED_SCR_OT_split_area); WM_operatortype_append(ED_SCR_OT_split_area);
WM_operatortype_append(ED_SCR_OT_join_areas); WM_operatortype_append(ED_SCR_OT_join_areas);
WM_operatortype_append(ED_SCR_OT_area_rip); WM_operatortype_append(ED_SCR_OT_area_rip);
/* for test only */
WM_operatortype_append(ED_SCR_OT_border_select);
} }
/* called in spacetypes.c */ /* called in spacetypes.c */
@ -103,5 +106,9 @@ void ED_keymap_screen(wmWindowManager *wm)
WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_split_area", EVT_ACTIONZONE, 0, 0, 0); /* action tria */ WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_split_area", EVT_ACTIONZONE, 0, 0, 0); /* action tria */
WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_join_areas", EVT_ACTIONZONE, 0, 0, 0); /* action tria */ WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_join_areas", EVT_ACTIONZONE, 0, 0, 0); /* action tria */
WM_keymap_verify_item(&wm->windowkeymap, "ED_SCR_OT_area_rip", RKEY, KM_PRESS, KM_ALT, 0); WM_keymap_verify_item(&wm->windowkeymap, "ED_SCR_OT_area_rip", RKEY, KM_PRESS, KM_ALT, 0);
/* for test only */
WM_keymap_verify_item(&wm->windowkeymap, "ED_SCR_OT_border_select", BKEY, KM_PRESS, 0, 0);
} }

@ -80,7 +80,7 @@ void WM_event_add_notifier(wmWindowManager *wm, wmWindow *window,
int swinid, int type, int swinid, int type,
int value, void *data); int value, void *data);
void wm_event_add(wmWindow *win, struct wmEvent *event_to_add); /* XXX only for warning */ void wm_event_add (wmWindow *win, struct wmEvent *event_to_add); /* XXX only for warning */
/* one-shot timer, returns wmTimerData.handle */ /* one-shot timer, returns wmTimerData.handle */
struct wmTimerHandle *WM_event_add_window_timer(wmWindow *win, int delay_ms, int interval_ms); struct wmTimerHandle *WM_event_add_window_timer(wmWindow *win, int delay_ms, int interval_ms);
@ -94,10 +94,14 @@ int WM_operator_winactive (struct bContext *C);
/* operator api */ /* operator api */
wmOperatorType *WM_operatortype_find(const char *idname); wmOperatorType *WM_operatortype_find(const char *idname);
void WM_operatortype_append(void (*opfunc)(wmOperatorType*)); void WM_operatortype_append (void (*opfunc)(wmOperatorType*));
int WM_operator_invoke(struct bContext *C, wmOperatorType *ot, struct wmEvent *event); int WM_operator_invoke (struct bContext *C, wmOperatorType *ot, struct wmEvent *event);
void WM_operator_cancel(struct bContext *C, ListBase *modalops, wmOperatorType *ot); void WM_operator_cancel (struct bContext *C, ListBase *modalops, wmOperatorType *ot);
/* default operator callbacks for border/lasso */
int WM_border_select_invoke (struct bContext *C, wmOperator *op, struct wmEvent *event);
int WM_border_select_modal (struct bContext *C, wmOperator *op, struct wmEvent *event);
/* /*
* Operator property api * Operator property api
@ -160,14 +164,12 @@ void OP_verify_float_array(wmOperator *op, char *name, float *array, short len,
void OP_free_property(wmOperator *op); void OP_free_property(wmOperator *op);
/* Gesture manager API */ /* Gesture manager API */
void WM_gesture_init(struct bContext *C, int type); struct wmGesture *WM_gesture_new(struct bContext *C, struct wmEvent *event, int type);
void WM_gesture_update(struct bContext *C, struct wmGesture *from); void WM_gesture_end(struct bContext *C, struct wmGesture *gesture);
void WM_gesture_end(struct bContext *C, int type);
void WM_gesture_free(wmWindow *win);
/* Reporting information and errors */ /* Reporting information and errors */
void WM_report(struct bContext *C, int type, const char *message); void WM_report(struct bContext *C, int type, const char *message);
void WM_reportf(struct bContext *C, int type, const char *format, ...); void WM_reportf(struct bContext *C, int type, const char *format, ...);
/* OpenGL wrappers, mimicing opengl syntax */ /* OpenGL wrappers, mimicing opengl syntax */
void wmLoadMatrix (wmWindow *win, float mat[][4]); void wmLoadMatrix (wmWindow *win, float mat[][4]);

@ -32,7 +32,6 @@
#include "wm_cursors.h" #include "wm_cursors.h"
#include "wm_event_types.h" #include "wm_event_types.h"
#include "wm_gesture_types.h"
/* ************** wmOperatorType ************************ */ /* ************** wmOperatorType ************************ */
@ -104,23 +103,33 @@ typedef struct wmNotifier {
enum { enum {
WM_NOTE_WINDOW_REDRAW, WM_NOTE_WINDOW_REDRAW,
WM_NOTE_SCREEN_CHANGED, WM_NOTE_SCREEN_CHANGED,
WM_NOTE_AREA_REDRAW,
WM_NOTE_REGION_REDRAW,
WM_NOTE_GESTURE_REDRAW,
WM_NOTE_OBJECT_CHANGED, WM_NOTE_OBJECT_CHANGED,
WM_NOTE_AREA_SPLIT,
WM_NOTE_AREA_DRAG,
WM_NOTE_GESTURE_CHANGED,
WM_NOTE_LAST WM_NOTE_LAST
}; };
/* ************** Gesture Manager data ************** */ /* ************** Gesture Manager data ************** */
typedef struct wmGestureRect {
/* always this first!! */
wmGesture gesture;
short x1, x2; /* wmGesture->type */
short y1, y2; #define WM_GESTURE_LINE 0
} wmGestureRect; #define WM_GESTURE_RECT 1
#define WM_GESTURE_CROSS_RECT 2
#define WM_GESTURE_LASSO 3
#define WM_GESTURE_CIRCLE 4
/* wmGesture is registered to window listbase, handled by operator callbacks */
typedef struct wmGesture {
struct wmGesture *next, *prev;
int eventtype, mode;
int type, swinid;
void *customdata;
/* customdata for border is a recti */
} wmGesture;
#define GESTURE_RECT 0
/* ************** custom wmEvent data ************** */ /* ************** custom wmEvent data ************** */
@ -134,11 +143,6 @@ typedef struct wmTabletData {
float Ytilt; /* as above */ float Ytilt; /* as above */
} wmTabletData; } wmTabletData;
typedef struct wmBorderSelect {
short x1, y1;
short x2, y2;
} wmBorderSelect;
struct wmTimerHandle; struct wmTimerHandle;
typedef struct wmTimerHandle wmTimerHandle; typedef struct wmTimerHandle wmTimerHandle;

@ -84,7 +84,6 @@ static void wm_window_keymap(wmWindowManager *wm)
WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_save_homefile", UKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_save_homefile", UKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_window_fullscreen_toggle", FKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_window_fullscreen_toggle", FKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_exit_blender", QKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_exit_blender", QKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_border_select", BKEY, KM_PRESS, 0, 0);
} }
/* ****************************************** */ /* ****************************************** */

@ -257,7 +257,7 @@ void wm_draw_update(bContext *C)
} }
if(win->screen->do_gesture) if(win->screen->do_gesture)
ED_screen_gesture(win); wm_gesture_draw(win);
wm_window_swap_buffers(win); wm_window_swap_buffers(win);

@ -26,6 +26,8 @@
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
*/ */
#include "DNA_screen_types.h"
#include "DNA_vec_types.h"
#include "DNA_windowmanager_types.h" #include "DNA_windowmanager_types.h"
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
@ -33,114 +35,104 @@
#include "BLI_blenlib.h" #include "BLI_blenlib.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_utildefines.h"
#include "WM_api.h" #include "WM_api.h"
#include "WM_types.h" #include "WM_types.h"
#include "wm_event_system.h" #include "wm_event_system.h"
#include "wm_subwindow.h"
#include "BIF_gl.h" #include "BIF_gl.h"
#include "BIF_glutil.h" #include "BIF_glutil.h"
/* context checked on having screen, window and area */
wmGesture *wm_gesture_find(ListBase *list, int type) wmGesture *WM_gesture_new(bContext *C, wmEvent *event, int type)
{ {
wmGesture *gt= list->first; wmGesture *gesture= MEM_callocN(sizeof(wmGesture), "new gesture");
while(gt) { int sx, sy;
if(gt->type==type)
return(gt); BLI_addtail(&C->window->gesture, gesture);
gt= gt->next;
gesture->type= type;
gesture->eventtype= event->type;
gesture->swinid= C->screen->subwinactive; /* means only in area-region context! */
wm_subwindow_getorigin(C->window, gesture->swinid, &sx, &sy);
if( ELEM(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT)) {
rcti *rect= MEM_callocN(sizeof(rcti), "gesture rect new");
gesture->customdata= rect;
rect->xmin= event->x - sx;
rect->ymin= event->y - sy;
rect->xmax= event->x - sx;
rect->ymax= event->y - sy;
} }
return(NULL);
return gesture;
} }
wmGesture *wm_gesture_new(int type) void WM_gesture_end(bContext *C, wmGesture *gesture)
{ {
wmGesture *gesture= NULL; BLI_remlink(&C->window->gesture, gesture);
wmGestureRect *rect; MEM_freeN(gesture->customdata);
MEM_freeN(gesture);
if(type==GESTURE_RECT) {
rect= MEM_mallocN(sizeof(wmGestureRect), "gesture rect new");
gesture= (wmGesture*) rect;
gesture->type= type;
rect->x1= 0;
rect->y1= 0;
rect->x2= 1;
rect->y2= 1;
}
return(gesture);
} }
void WM_gesture_init(bContext *C, int type)
{
wmGesture *gt= NULL;
if(C->window) {
gt= wm_gesture_find(&C->window->gesture, type); /* ******************* gesture draw ******************* */
if(!gt) {
gt= wm_gesture_new(type); static void wm_gesture_draw_rect(wmWindow *win, wmGesture *gt)
BLI_addtail(&C->window->gesture, gt); {
rcti *rect= (rcti *)gt->customdata;
glEnable(GL_LINE_STIPPLE);
glColor3ub(0, 0, 0);
glLineStipple(1, 0xAAAA);
sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
glColor3ub(255, 255, 255);
glLineStipple(1, 0x3333);
sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
glDisable(GL_LINE_STIPPLE);
}
static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
{
rcti *rect= (rcti *)gt->customdata;
glEnable(GL_LINE_STIPPLE);
glColor3ub(0, 0, 0);
glLineStipple(1, 0xAAAA);
sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
glColor3ub(255, 255, 255);
glLineStipple(1, 0x3333);
sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
glDisable(GL_LINE_STIPPLE);
}
/* called in wm_event_system.c */
void wm_gesture_draw(wmWindow *win)
{
wmGesture *gt= (wmGesture *)win->gesture.first;
for(; gt; gt= gt->next) {
/* all in subwindow space */
wm_subwindow_set(win, gt->swinid);
if(gt->type==WM_GESTURE_RECT)
wm_gesture_draw_rect(win, gt);
else if(gt->type==WM_GESTURE_CROSS_RECT) {
if(gt->mode==1)
wm_gesture_draw_rect(win, gt);
else
wm_gesture_draw_cross(win, gt);
} }
} }
} }
void wm_gesture_rect_copy(wmGestureRect *to, wmGestureRect *from)
{
to->x1= from->x1;
to->x2= from->x2;
to->y1= from->y1;
to->y2= from->y2;
}
void WM_gesture_update(bContext *C, wmGesture *from)
{
wmGesture *to;
if(!C->window)
return;
to= wm_gesture_find(&C->window->gesture, from->type);
if(!to)
return;
if(to->type==GESTURE_RECT)
wm_gesture_rect_copy((wmGestureRect*)to, (wmGestureRect*)from);
}
void WM_gesture_free(wmWindow *win)
{
/* Now don't have multiple struct so
* a simple BLI_freelistN is what we need.
*/
BLI_freelistN(&win->gesture);
}
void WM_gesture_end(bContext *C, int type)
{
wmGesture *gt;
wmGestureRect *rect;
wmBorderSelect *wmbor;
wmEvent event;
if(!C->window)
return;
gt= wm_gesture_find(&C->window->gesture, type);
if(!gt)
return;
if(gt->type==GESTURE_RECT) {
rect= (wmGestureRect*)gt;
wmbor= MEM_mallocN(sizeof(wmBorderSelect), "border select");
wmbor->x1= rect->x1;
wmbor->y1= rect->y1;
wmbor->x2= rect->x2;
wmbor->y2= rect->y2;
event.type= BORDERSELECT;
event.custom= EVT_GESTURE;
event.customdata= wmbor;
wm_event_add(C->window, &event);
}
}

@ -29,6 +29,7 @@
#include <string.h> #include <string.h>
#include "DNA_ID.h" #include "DNA_ID.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h" #include "DNA_windowmanager_types.h"
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
@ -43,7 +44,9 @@
#include "WM_api.h" #include "WM_api.h"
#include "WM_types.h" #include "WM_types.h"
#include "wm_window.h" #include "wm_window.h"
#include "wm_subwindow.h"
#include "wm_event_system.h" #include "wm_event_system.h"
static ListBase global_ops= {NULL, NULL}; static ListBase global_ops= {NULL, NULL};
@ -130,121 +133,93 @@ static void WM_OT_exit_blender(wmOperatorType *ot)
ot->poll= WM_operator_winactive; ot->poll= WM_operator_winactive;
} }
/* ************ window / screen border operator definitions ************** */ /* ************ window gesture operator-callback definitions ************** */
/* /*
* This is and example of global operator working with * These are default callbacks for use in operators requiring gesture input
* the gesture system.
*/ */
static int border_select_init(bContext *C, wmOperator *op)
static void border_select_apply(bContext *C, wmOperator *op)
{ {
int x, y; wmGesture *gesture= op->customdata;
rcti *rect= gesture->customdata;
if(!(OP_get_int(op, "start_x", &x) && OP_get_int(op, "start_y", &y)))
return 0;
WM_gesture_init(C, GESTURE_RECT);
return 1;
}
static int border_select_apply(bContext *C, wmOperator *op)
{
wmGestureRect rect;
int x, y, endx, endy;
OP_get_int(op, "start_x", &x);
OP_get_int(op, "start_y", &y);
OP_get_int(op, "end_x", &endx);
OP_get_int(op, "end_y", &endy);
rect.gesture.next= rect.gesture.prev= NULL;
rect.gesture.type= GESTURE_RECT;
rect.x1= x;
rect.y1= y;
rect.x2= endx;
rect.y2= endy;
WM_gesture_update(C, (wmGesture *) &rect);
WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_GESTURE_CHANGED, GESTURE_RECT, NULL);
return 1;
}
static int border_select_exit(bContext *C, wmOperator *op)
{
WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
OP_free_property(op);
return 1;
}
static int border_select_exec(bContext *C, wmOperator *op)
{
if(!border_select_init(C, op))
return OPERATOR_CANCELLED;
border_select_apply(C, op); /* operator arguments and storage. */
border_select_exit(C, op); OP_verify_int(op, "xmin", rect->xmin, NULL);
OP_verify_int(op, "ymin", rect->ymin, NULL);
return OPERATOR_FINISHED; OP_verify_int(op, "xmax", rect->xmax, NULL);
OP_verify_int(op, "ymax", rect->ymax, NULL);
op->type->exec(C, op);
} }
static int border_select_invoke(bContext *C, wmOperator *op, wmEvent *event) static void border_select_end(bContext *C, wmOperator *op)
{ {
/* operator arguments and storage. */ wmGesture *gesture= op->customdata;
OP_verify_int(op, "start_x", event->x, NULL);
OP_verify_int(op, "start_y", event->y, NULL); WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */
op->customdata= NULL;
WM_event_remove_modal_handler(&C->window->handlers, op);
WM_event_add_notifier(C->wm, C->window, gesture->swinid, WM_NOTE_AREA_REDRAW, 0, NULL);
}
if(!border_select_init(C, op)) int WM_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_CANCELLED; {
op->customdata= WM_gesture_new(C, event, WM_GESTURE_CROSS_RECT);
/* add temp handler */ /* add modal handler */
WM_event_add_modal_handler(&C->window->handlers, op); WM_event_add_modal_handler(&C->window->handlers, op);
WM_event_add_notifier(C->wm, C->window, C->screen->subwinactive, WM_NOTE_GESTURE_REDRAW, 0, NULL);
return OPERATOR_RUNNING_MODAL; return OPERATOR_RUNNING_MODAL;
} }
static int border_select_cancel(bContext *C, wmOperator *op) int WM_border_select_modal(bContext *C, wmOperator *op, wmEvent *event)
{
WM_event_remove_modal_handler(&C->window->handlers, op);
border_select_exit(C, op);
return OPERATOR_CANCELLED;
}
static int border_select_modal(bContext *C, wmOperator *op, wmEvent *event)
{ {
wmGesture *gesture= op->customdata;
rcti *rect= gesture->customdata;
int sx, sy;
switch(event->type) { switch(event->type) {
case MOUSEMOVE: case MOUSEMOVE:
OP_set_int(op, "end_x", event->x);
OP_set_int(op, "end_y", event->y); wm_subwindow_getorigin(C->window, gesture->swinid, &sx, &sy);
border_select_apply(C, op);
WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_GESTURE_CHANGED, GESTURE_RECT, NULL); if(gesture->type==WM_GESTURE_CROSS_RECT && gesture->mode==0) {
WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL); rect->xmin= rect->xmax= event->x - sx;
rect->ymin= rect->ymax= event->y - sy;
}
else {
rect->xmax= event->x - sx;
rect->ymax= event->y - sy;
}
WM_event_add_notifier(C->wm, C->window, gesture->swinid, WM_NOTE_GESTURE_REDRAW, 0, NULL);
break; break;
case LEFTMOUSE: case LEFTMOUSE:
if(event->val==0) { if(event->val==1) {
if(gesture->type==WM_GESTURE_CROSS_RECT && gesture->mode==0) {
gesture->mode= 1;
WM_event_add_notifier(C->wm, C->window, gesture->swinid, WM_NOTE_GESTURE_REDRAW, 0, NULL);
}
}
else {
border_select_apply(C, op); border_select_apply(C, op);
WM_gesture_end(C, GESTURE_RECT); border_select_end(C, op);
border_select_exit(C, op);
WM_event_remove_modal_handler(&C->window->handlers, op);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
break; break;
case ESCKEY: case ESCKEY:
return border_select_cancel(C, op); border_select_end(C, op);
return OPERATOR_CANCELLED;
} }
return OPERATOR_RUNNING_MODAL; return OPERATOR_RUNNING_MODAL;
} }
void WM_OT_border_select(wmOperatorType *ot) /* ******************************************************* */
{
/* identifiers */
ot->name= "Border select";
ot->idname= "WM_OT_border_select";
ot->exec= border_select_exec;
ot->invoke= border_select_invoke;
ot->cancel= border_select_cancel;
ot->modal= border_select_modal;
ot->poll= WM_operator_winactive;
}
/* called on initialize WM_exit() */ /* called on initialize WM_exit() */
void wm_operatortype_free(void) void wm_operatortype_free(void)
@ -259,9 +234,10 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_save_homefile); WM_operatortype_append(WM_OT_save_homefile);
WM_operatortype_append(WM_OT_window_fullscreen_toggle); WM_operatortype_append(WM_OT_window_fullscreen_toggle);
WM_operatortype_append(WM_OT_exit_blender); WM_operatortype_append(WM_OT_exit_blender);
WM_operatortype_append(WM_OT_border_select);
} }
/* ******************************************************* */
/* wrapped to get property from a operator. */ /* wrapped to get property from a operator. */
IDProperty *op_get_property(wmOperator *op, char *name) IDProperty *op_get_property(wmOperator *op, char *name)
{ {

@ -103,7 +103,6 @@ void wm_window_free(bContext *C, wmWindow *win)
if(win->eventstate) MEM_freeN(win->eventstate); if(win->eventstate) MEM_freeN(win->eventstate);
WM_gesture_free(win);
wm_event_free_all(win); wm_event_free_all(win);
wm_subwindows_free(win); wm_subwindows_free(win);

@ -28,6 +28,8 @@
#ifndef WM_H #ifndef WM_H
#define WM_H #define WM_H
struct wmWindow;
extern void wm_close_and_free(bContext *C, wmWindowManager *); extern void wm_close_and_free(bContext *C, wmWindowManager *);
extern void wm_close_and_free_all(bContext *C, ListBase *); extern void wm_close_and_free_all(bContext *C, ListBase *);
@ -44,6 +46,8 @@ extern void wm_report_free(wmReport *report);
void wm_operatortype_free(void); void wm_operatortype_free(void);
void wm_operatortype_init(void); void wm_operatortype_init(void);
/* wm_gesture.c */
void wm_gesture_draw(struct wmWindow *win);
#endif /* WM_H */ #endif /* WM_H */

@ -1,40 +0,0 @@
/*
* $Id: wm_gesture_types.h
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
*
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef WM_GESTURE_TYPES_H
#define WM_GESTURE_TYPES_H
typedef struct wmGesture {
struct wmGesture *next, *prev;
/* gesture type. */
int type;
} wmGesture;
#endif /* WM_GESTURE_TYPES_H */