Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Tue, 18 Jul 2017 08:10:19 +0000 (18:10 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 18 Jul 2017 08:10:19 +0000 (18:10 +1000)
1  2 
source/blender/editors/animation/anim_markers.c
source/blender/editors/space_view3d/view3d_walk.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_event_system.c

index e563d3f8cf0be14de14b3135a7e83096b56998dd,be01f8cbe692fe7ffc6ac534b635e458aabce397..dfe7edde3371c40ecd7a62800fe22416d31e7d80
  #include "DNA_object_types.h"
  
  #include "BLI_blenlib.h"
 -#include "BLI_math_base.h"
 +#include "BLI_math.h"
  #include "BLI_utildefines.h"
  
  #include "BLT_translation.h"
  
  #include "BKE_context.h"
  #include "BKE_fcurve.h"
 +#include "BKE_layer.h"
  #include "BKE_main.h"
  #include "BKE_report.h"
  #include "BKE_scene.h"
  #include "WM_api.h"
  #include "WM_types.h"
  
 -#include "BIF_gl.h"
  #include "BIF_glutil.h"
  
 +#include "GPU_immediate.h"
 +#include "GPU_matrix.h"
 +
  #include "UI_interface.h"
  #include "UI_interface_icons.h"
  #include "UI_view2d.h"
@@@ -351,30 -348,19 +351,30 @@@ static void draw_marker
        if (flag & DRAW_MARKERS_LINES)
  #endif
        {
 -              setlinestyle(3);
 -              
 -              if (marker->flag & SELECT)
 -                      glColor4ub(255, 255, 255, 96);
 -              else
 -                      glColor4ub(0, 0, 0, 96);
 -              
 -              glBegin(GL_LINES);
 -              glVertex2f(xpos + 0.5f, 12.0f);
 -              glVertex2f(xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
 -              glEnd();
 -              
 -              setlinestyle(0);
 +              Gwn_VertFormat *format = immVertexFormat();
 +              uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +              immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
 +
 +              float viewport_size[4];
 +              glGetFloatv(GL_VIEWPORT, viewport_size);
 +              immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
 +
 +              if (marker->flag & SELECT) {
 +                      immUniformColor4f(1.0f, 1.0f, 1.0f, 0.38f);
 +              }
 +              else {
 +                      immUniformColor4f(0.0f, 0.0f, 0.0f, 0.38f);
 +              }
 +              immUniform1f("dash_width", 6.0f);
 +              immUniform1f("dash_factor", 0.5f);
 +
 +              immBegin(GWN_PRIM_LINES, 2);
 +              immVertex2f(pos, xpos + 0.5f, 12.0f);
 +              immVertex2f(pos, xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
 +              immEnd();
 +
 +              immUnbindProgram();
        }
        
        /* 5 px to offset icon to align properly, space / pixels corrects for zoom */
        
        /* and the marker name too, shifted slightly to the top-right */
        if (marker->name[0]) {
 +              unsigned char text_col[4];
                float x, y;
  
                /* minimal y coordinate which wouldn't be occluded by scroll */
                int min_y = 17.0f * UI_DPI_FAC;
                
                if (marker->flag & SELECT) {
 -                      UI_ThemeColor(TH_TEXT_HI);
 +                      UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
                        x = xpos + 4.0f * UI_DPI_FAC;
                        y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
                        y = max_ii(y, min_y);
                }
                else {
 -                      UI_ThemeColor(TH_TEXT);
 +                      UI_GetThemeColor4ubv(TH_TEXT, text_col);
                        if ((marker->frame <= cfra) && (marker->frame + 5 > cfra)) {
                                x = xpos + 8.0f * UI_DPI_FAC;
                                y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
  
  #ifdef DURIAN_CAMERA_SWITCH
                if (marker->camera && (marker->camera->restrictflag & OB_RESTRICT_RENDER)) {
 -                      float col[4];
 -                      glGetFloatv(GL_CURRENT_COLOR, col);
 -                      col[3] = 0.4;
 -                      glColor4fv(col);
 +                      text_col[3] = 100;
                }
  #endif
  
 -              UI_fontstyle_draw_simple(fstyle, x, y, marker->name);
 +              UI_fontstyle_draw_simple(fstyle, x, y, marker->name, text_col);
        }
  }
  
@@@ -452,27 -440,21 +452,27 @@@ void ED_markers_draw(const bContext *C
        v2d = UI_view2d_fromcontext(C);
  
        if (flag & DRAW_MARKERS_MARGIN) {
 +              unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +              immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 +
                const unsigned char shade[4] = {0, 0, 0, 16};
 -              glColor4ubv(shade);
 +              immUniformColor4ubv(shade);
  
                glEnable(GL_BLEND);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  
 -              glRectf(v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y);
 +              immRectf(pos, v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y);
  
                glDisable(GL_BLEND);
 +
 +              immUnbindProgram();
        }
  
        /* no time correction for framelen! space is drawn with old values */
        ypixels = BLI_rcti_size_y(&v2d->mask);
        UI_view2d_scale_get(v2d, &xscale, &yscale);
 -      glScalef(1.0f / xscale, 1.0f, 1.0f);
 +      gpuPushMatrix();
 +      gpuScale2f(1.0f / xscale, 1.0f);
  
        /* x-bounds with offset for text (adjust for long string, avoid checking string width) */
        font_width_max = (10 * UI_DPI_FAC) / xscale;
                }
        }
  
 -      glScalef(xscale, 1.0f, 1.0f);
 +      gpuPopMatrix();
  }
  
  /* ************************ Marker Wrappers API ********************* */
@@@ -859,7 -841,7 +859,7 @@@ static void ed_marker_move_apply(bConte
        BKE_scene_camera_switch_update(scene);
  
        if (camera != scene->camera) {
 -              BKE_screen_view3d_scene_sync(sc);
 +              BKE_screen_view3d_scene_sync(sc, scene);
                WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
        }
  #endif
@@@ -913,7 -895,7 +913,7 @@@ static int ed_marker_move_modal(bContex
                        case PADENTER:
                        case LEFTMOUSE:
                        case MIDDLEMOUSE:
-                               if (WM_modal_tweak_exit(event, mm->event_type)) {
+                               if (WM_event_is_modal_tweak_exit(event, mm->event_type)) {
                                        ed_marker_move_exit(C, op);
                                        WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
                                        WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
@@@ -1143,7 -1125,6 +1143,7 @@@ static int ed_marker_select(bContext *C
  
        if (camera) {
                Scene *scene = CTX_data_scene(C);
 +              SceneLayer *sl = CTX_data_scene_layer(C);
                Base *base;
                TimeMarker *marker;
                int sel = 0;
                for (marker = markers->first; marker; marker = marker->next) {
                        if (marker->camera) {
                                if (marker->frame == cfra) {
 -                                      base = BKE_scene_base_find(scene, marker->camera);
 +                                      base = BKE_scene_layer_base_find(sl, marker->camera);
                                        if (base) {
 -                                              ED_base_object_select(base, sel);
 +                                              ED_object_base_select(base, sel);
                                                if (sel)
 -                                                      ED_base_object_activate(C, base);
 +                                                      ED_object_base_activate(C, base);
                                        }
                                }
                        }
@@@ -1550,7 -1531,7 +1550,7 @@@ static int ed_marker_camera_bind_exec(b
  
        /* camera may have changes */
        BKE_scene_camera_switch_update(scene);
 -      BKE_screen_view3d_scene_sync(sc);
 +      BKE_screen_view3d_scene_sync(sc, scene);
  
        WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
        WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
index 71a4980d4a6f6f1e36d720670febc5694f71e78c,c6b73056a9a1cdfb7c3f830a436f517020d69e63..812e7eba758596c1b774230461cbe21c4faee256
@@@ -57,8 -57,6 +57,8 @@@
  #include "UI_interface.h"
  #include "UI_resources.h"
  
 +#include "GPU_immediate.h"
 +
  #include "view3d_intern.h"  /* own include */
  
  #ifdef WITH_INPUT_NDOF
@@@ -249,7 -247,6 +249,7 @@@ typedef struct WalkInfo 
        View3D *v3d;
        ARegion *ar;
        Scene *scene;
 +      SceneLayer *scene_layer;
  
        wmTimer *timer; /* needed for redraws */
  
@@@ -341,33 -338,24 +341,33 @@@ static void drawWalkPixel(const struct 
                yoff = walk->ar->winy / 2;
        }
  
 -      UI_ThemeColor(TH_VIEW_OVERLAY);
 -      glBegin(GL_LINES);
 +      Gwn_VertFormat *format = immVertexFormat();
 +      unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
 +
 +      immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 +
 +      immUniformThemeColor(TH_VIEW_OVERLAY);
 +
 +      immBegin(GWN_PRIM_LINES, 8);
 +
        /* North */
 -      glVertex2i(xoff, yoff + inner_length);
 -      glVertex2i(xoff, yoff + outter_length);
 +      immVertex2i(pos, xoff, yoff + inner_length);
 +      immVertex2i(pos, xoff, yoff + outter_length);
  
        /* East */
 -      glVertex2i(xoff + inner_length, yoff);
 -      glVertex2i(xoff + outter_length, yoff);
 +      immVertex2i(pos, xoff + inner_length, yoff);
 +      immVertex2i(pos, xoff + outter_length, yoff);
  
        /* South */
 -      glVertex2i(xoff, yoff - inner_length);
 -      glVertex2i(xoff, yoff - outter_length);
 +      immVertex2i(pos, xoff, yoff - inner_length);
 +      immVertex2i(pos, xoff, yoff - outter_length);
  
        /* West */
 -      glVertex2i(xoff - inner_length, yoff);
 -      glVertex2i(xoff - outter_length, yoff);
 -      glEnd();
 +      immVertex2i(pos, xoff - inner_length, yoff);
 +      immVertex2i(pos, xoff - outter_length, yoff);
 +
 +      immEnd();
 +      immUnbindProgram();
  }
  
  static void walk_update_header(bContext *C, wmOperator *op, WalkInfo *walk)
@@@ -512,7 -500,6 +512,7 @@@ static bool initWalkInfo(bContext *C, W
        walk->v3d = CTX_wm_view3d(C);
        walk->ar = CTX_wm_region(C);
        walk->scene = CTX_data_scene(C);
 +      walk->scene_layer = CTX_data_scene_layer(C);
  
  #ifdef NDOF_WALK_DEBUG
        puts("\n-- walk begin --");
        walk->rv3d->rflag |= RV3D_NAVIGATING;
  
        walk->snap_context = ED_transform_snap_object_context_create_view3d(
 -              CTX_data_main(C), walk->scene, 0,
 +              CTX_data_main(C), walk->scene, walk->scene_layer, 0,
                walk->ar, walk->v3d);
  
        walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
@@@ -687,16 -674,6 +687,6 @@@ static int walkEnd(bContext *C, WalkInf
        return OPERATOR_CANCELLED;
  }
  
- static bool wm_event_is_last_mousemove(const wmEvent *event)
- {
-       while ((event = event->next)) {
-               if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
-                       return false;
-               }
-       }
-       return true;
- }
  static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent *event)
  {
        if (event->type == TIMER && event->customdata == walk->timer) {
                        }
                        else
  #endif
-                       if (wm_event_is_last_mousemove(event)) {
+                       if (WM_event_is_last_mousemove(event)) {
                                wmWindow *win = CTX_wm_window(C);
  
  #ifdef __APPLE__
index a8c67a296afbf0ee870a59af63da80e633e2a7ce,a91c30c280750817255b640e859904fd9615b74d..6dee20eb261710a74744bc03e87dbb5761543a03
@@@ -42,9 -42,6 +42,9 @@@
  #include "WM_keymap.h"
  #include "BLI_compiler_attrs.h"
  
 +/* Include external manipulator API's */
 +#include "manipulators/WM_manipulator_api.h"
 +
  #ifdef __cplusplus
  extern "C" {
  #endif
@@@ -67,16 -64,12 +67,16 @@@ struct wmDrag
  struct ImBuf;
  struct ImageFormatData;
  struct ARegion;
 +struct ScrArea;
  
  #ifdef WITH_INPUT_NDOF
  struct wmNDOFMotionData;
  #endif
  
  typedef struct wmJob wmJob;
 +typedef struct wmManipulator wmManipulator;
 +typedef struct wmManipulatorMap wmManipulatorMap;
 +typedef struct wmManipulatorMapType wmManipulatorMapType;
  
  /* general API */
  void          WM_init_state_size_set          (int stax, int stay, int sizx, int sizy);
@@@ -101,21 -94,6 +101,21 @@@ int                       WM_window_pixels_x              (struct wmWin
  int                   WM_window_pixels_y              (struct wmWindow *win);
  bool          WM_window_is_fullscreen (struct wmWindow *win);
  
 +void WM_windows_scene_data_sync(const ListBase *win_lb, struct Scene *scene) ATTR_NONNULL();
 +struct Scene *WM_windows_scene_get_from_screen(const struct wmWindowManager *wm, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 +
 +struct Scene *WM_window_get_active_scene(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 +void          WM_window_change_active_scene(struct Main *bmain, struct bContext *C, struct wmWindow *win,
 +                                            struct Scene *scene_new) ATTR_NONNULL();
 +struct WorkSpace *WM_window_get_active_workspace(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 +void              WM_window_set_active_workspace(struct wmWindow *win, struct WorkSpace *workspace) ATTR_NONNULL(1);
 +struct WorkSpaceLayout *WM_window_get_active_layout(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 +void                    WM_window_set_active_layout(
 +        struct wmWindow *win, struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL(1);
 +struct bScreen *WM_window_get_active_screen(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 +void            WM_window_set_active_screen(struct wmWindow *win, struct WorkSpace *workspace, struct bScreen *screen) ATTR_NONNULL(1);
 +bool WM_window_is_temp_screen(const struct wmWindow *win) ATTR_WARN_UNUSED_RESULT;
 +
  /* defines for 'type' WM_window_open_temp */
  enum {
        WM_WINDOW_RENDER = 1,
@@@ -194,9 -172,6 +194,9 @@@ void WM_event_free_ui_handler_all
          wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove);
  
  struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op);
 +void WM_event_modal_handler_area_replace(wmWindow *win, const struct ScrArea *old_area, struct ScrArea *new_area);
 +void WM_event_modal_handler_region_replace(wmWindow *win, const struct ARegion *old_region, struct ARegion *new_region);
 +
  void          WM_event_remove_handlers(struct bContext *C, ListBase *handlers);
  
  /* handler flag */
@@@ -212,8 -187,9 +212,9 @@@ struct wmEventHandler *WM_event_add_dro
  
                        /* mouse */
  void          WM_event_add_mousemove(struct bContext *C);
- bool        WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
+ bool          WM_event_is_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
  bool          WM_event_is_absolute(const struct wmEvent *event);
+ bool          WM_event_is_last_mousemove(const struct wmEvent *event);
  
  #ifdef WITH_INPUT_NDOF
                        /* 3D mouse */
@@@ -254,7 -230,6 +255,7 @@@ void               WM_operator_view3d_unit_defaults(
  int                   WM_operator_smooth_viewtx_get(const struct wmOperator *op);
  int                   WM_menu_invoke_ex(struct bContext *C, struct wmOperator *op, int opcontext);
  int                   WM_menu_invoke                  (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
 +int         WM_enum_search_invoke_previews(struct bContext *C, struct wmOperator *op, short prv_cols, short prv_rows);
  int                   WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
                        /* invoke callback, confirm menu + exec */
  int                   WM_operator_confirm             (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
@@@ -438,7 -413,9 +439,7 @@@ ListBase   *WM_dropboxmap_find(const cha
  void          wmSubWindowSet                  (struct wmWindow *win, int swinid);
  void          wmSubWindowScissorSet   (struct wmWindow *win, int swinid, const struct rcti *srct, bool srct_pad);
  
 -                      /* OpenGL utilities with safety check + working in modelview matrix mode */
 -void          wmFrustum                       (float x1, float x2, float y1, float y2, float n, float f);
 -void          wmOrtho                         (float x1, float x2, float y1, float y2, float n, float f);
 +                      /* OpenGL utilities with safety check */
  void          wmOrtho2                        (float x1, float x2, float y1, float y2);
                        /* use for conventions (avoid hard-coded offsets all over) */
  void          wmOrtho2_region_pixelspace(const struct ARegion *ar);
index 6a1be83291886230caf70c342f61a9519b836289,32f978ae891e948fb0a6000e60e623fa76c005e2..dad6a6ec317f2229a931014353386b76e643ec30
@@@ -39,7 -39,6 +39,7 @@@
  #include "DNA_screen_types.h"
  #include "DNA_scene_types.h"
  #include "DNA_windowmanager_types.h"
 +#include "DNA_workspace_types.h"
  #include "DNA_userdef_types.h"
  
  #include "MEM_guardedalloc.h"
  #include "BKE_context.h"
  #include "BKE_idprop.h"
  #include "BKE_global.h"
 +#include "BKE_layer.h"
  #include "BKE_main.h"
  #include "BKE_report.h"
  #include "BKE_scene.h"
  #include "BKE_screen.h"
 +#include "BKE_workspace.h"
  
  #include "BKE_sound.h"
  
@@@ -71,6 -68,8 +71,6 @@@
  
  #include "RNA_access.h"
  
 -#include "GPU_debug.h"
 -
  #include "UI_interface.h"
  
  #include "PIL_time.h"
@@@ -277,7 -276,6 +277,7 @@@ void wm_event_do_notifiers(bContext *C
        
        /* cache & catch WM level notifiers, such as frame change, scene/screen set */
        for (win = wm->windows.first; win; win = win->next) {
 +              Scene *scene = WM_window_get_active_scene(win);
                bool do_anim = false;
                
                CTX_wm_window_set(C, win);
                        }
                        if (note->window == win) {
                                if (note->category == NC_SCREEN) {
 -                                      if (note->data == ND_SCREENBROWSE) {
 +                                      if (note->data == ND_WORKSPACE_SET) {
 +                                              WorkSpace *ref_ws = note->reference;
 +
 +                                              UI_popup_handlers_remove_all(C, &win->modalhandlers);
 +
 +                                              ED_workspace_change(ref_ws, C, wm, win);
 +                                              if (G.debug & G_DEBUG_EVENTS)
 +                                                      printf("%s: Workspace set %p\n", __func__, note->reference);
 +                                      }
 +                                      else if (note->data == ND_LAYOUTBROWSE) {
 +                                              bScreen *ref_screen = BKE_workspace_layout_screen_get(note->reference);
 +
                                                /* free popup handlers only [#35434] */
                                                UI_popup_handlers_remove_all(C, &win->modalhandlers);
  
  
 -                                              ED_screen_set(C, note->reference);  // XXX hrms, think this over!
 +                                              ED_screen_change(C, ref_screen);  /* XXX hrms, think this over! */
                                                if (G.debug & G_DEBUG_EVENTS)
                                                        printf("%s: screen set %p\n", __func__, note->reference);
                                        }
 -                                      else if (note->data == ND_SCREENDELETE) {
 -                                              ED_screen_delete(C, note->reference);   // XXX hrms, think this over!
 +                                      else if (note->data == ND_LAYOUTDELETE) {
 +                                              WorkSpace *workspace = WM_window_get_active_workspace(win);
 +                                              WorkSpaceLayout *layout = note->reference;
 +
 +                                              ED_workspace_layout_delete(workspace, layout, C);   // XXX hrms, think this over!
                                                if (G.debug & G_DEBUG_EVENTS)
                                                        printf("%s: screen delete %p\n", __func__, note->reference);
                                        }
                        }
  
                        if (note->window == win ||
 -                          (note->window == NULL && (note->reference == NULL || note->reference == win->screen->scene)))
 +                          (note->window == NULL && (note->reference == NULL || note->reference == scene)))
                        {
                                if (note->category == NC_SCENE) {
                                        if (note->data == ND_FRAME)
                                }
                        }
                        if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_WM)) {
 -                              ED_info_stats_clear(win->screen->scene);
 +                              SceneLayer *sl = BKE_scene_layer_context_active_PLACEHOLDER(scene);
 +                              ED_info_stats_clear(sl);
                                WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
                        }
                }
                        if (G.is_rendering == false) {
  
                                /* depsgraph gets called, might send more notifiers */
 -                              ED_update_for_newframe(CTX_data_main(C), win->screen->scene, 1);
 +                              ED_update_for_newframe(CTX_data_main(C), scene, 1);
                        }
                }
        }
        /* the notifiers are sent without context, to keep it clean */
        while ((note = BLI_pophead(&wm->queue))) {
                for (win = wm->windows.first; win; win = win->next) {
 -                      
 +                      Scene *scene = WM_window_get_active_scene(win);
 +                      bScreen *screen = WM_window_get_active_screen(win);
 +
                        /* filter out notifiers */
 -                      if (note->category == NC_SCREEN && note->reference && note->reference != win->screen) {
 +                      if (note->category == NC_SCREEN &&
 +                          note->reference &&
 +                          note->reference != screen &&
 +                          note->reference != WM_window_get_active_workspace(win) &&
 +                          note->reference != WM_window_get_active_layout(win))
 +                      {
                                /* pass */
                        }
 -                      else if (note->category == NC_SCENE && note->reference && note->reference != win->screen->scene) {
 +                      else if (note->category == NC_SCENE && note->reference && note->reference != scene) {
                                /* pass */
                        }
                        else {
                                /* printf("notifier win %d screen %s cat %x\n", win->winid, win->screen->id.name + 2, note->category); */
                                ED_screen_do_listen(C, note);
  
 -                              for (ar = win->screen->regionbase.first; ar; ar = ar->next) {
 -                                      ED_region_do_listen(win->screen, NULL, ar, note);
 +                              for (ar = screen->regionbase.first; ar; ar = ar->next) {
 +                                      ED_region_do_listen(screen, NULL, ar, note, scene);
                                }
                                
 -                              for (sa = win->screen->areabase.first; sa; sa = sa->next) {
 -                                      ED_area_do_listen(win->screen, sa, note);
 +                              for (sa = screen->areabase.first; sa; sa = sa->next) {
 +                                      ED_area_do_listen(screen, sa, note, scene);
                                        for (ar = sa->regionbase.first; ar; ar = ar->next) {
 -                                              ED_region_do_listen(win->screen, sa, ar, note);
 +                                              ED_region_do_listen(screen, sa, ar, note, scene);
                                        }
                                }
                        }
                
                MEM_freeN(note);
        }
 -      
 +
        /* combine datamasks so 1 win doesn't disable UV's in another [#26448] */
        for (win = wm->windows.first; win; win = win->next) {
 -              win_combine_v3d_datamask |= ED_view3d_screen_datamask(win->screen);
 +              const Scene *scene = WM_window_get_active_scene(win);
 +              const bScreen *screen = WM_window_get_active_screen(win);
 +
 +              win_combine_v3d_datamask |= ED_view3d_screen_datamask(scene, screen);
        }
  
        /* cached: editor refresh callbacks now, they get context */
        for (win = wm->windows.first; win; win = win->next) {
 +              const bScreen *screen = WM_window_get_active_screen(win);
 +              Scene *scene = WM_window_get_active_scene(win);
                ScrArea *sa;
                
                CTX_wm_window_set(C, win);
 -              for (sa = win->screen->areabase.first; sa; sa = sa->next) {
 +              for (sa = screen->areabase.first; sa; sa = sa->next) {
                        if (sa->do_refresh) {
                                CTX_wm_area_set(C, sa);
                                ED_area_do_refresh(C, sa);
                        Main *bmain = CTX_data_main(C);
  
                        /* copied to set's in scene_update_tagged_recursive() */
 -                      win->screen->scene->customdata_mask = win_combine_v3d_datamask;
 +                      scene->customdata_mask = win_combine_v3d_datamask;
  
                        /* XXX, hack so operators can enforce datamasks [#26482], gl render */
 -                      win->screen->scene->customdata_mask |= win->screen->scene->customdata_mask_modal;
 +                      scene->customdata_mask |= scene->customdata_mask_modal;
  
 -                      BKE_scene_update_tagged(bmain->eval_ctx, bmain, win->screen->scene);
 +                      BKE_scene_update_tagged(bmain->eval_ctx, bmain, scene);
                }
        }
  
@@@ -644,6 -615,16 +644,16 @@@ bool WM_event_is_absolute(const wmEven
        return (event->tablet_data != NULL);
  }
  
+ bool WM_event_is_last_mousemove(const wmEvent *event)
+ {
+       while ((event = event->next)) {
+               if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+                       return false;
+               }
+       }
+       return true;
+ }
  #ifdef WITH_INPUT_NDOF
  void WM_ndof_deadzone_set(float deadzone)
  {
@@@ -1722,7 -1703,7 +1732,7 @@@ static int wm_handler_operator_call(bCo
                        wm_handler_op_context(C, handler, event);
                        wm_region_mouse_co(C, event);
                        wm_event_modalkeymap(C, op, event, &dbl_click_disabled);
 -                      
 +
                        if (ot->flag & OPTYPE_UNDO)
                                wm->op_undo_depth++;
  
                                        CTX_wm_region_set(C, NULL);
                                }
  
 +                              /* update manipulators during modal handlers */
 +                              wm_manipulatormaps_handled_modal_update(C, event, handler);
 +
                                /* remove modal handler, operator itself should have been canceled and freed */
                                if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) {
                                        WM_cursor_grab_disable(CTX_wm_window(C), NULL);
@@@ -2146,71 -2124,6 +2156,71 @@@ static int wm_handlers_do_intern(bConte
                                        }
                                }
                        }
 +                      else if (handler->manipulator_map) {
 +                              ScrArea *area = CTX_wm_area(C);
 +                              ARegion *region = CTX_wm_region(C);
 +                              wmManipulatorMap *mmap = handler->manipulator_map;
 +                              wmManipulator *mpr = wm_manipulatormap_highlight_get(mmap);
 +
 +                              wm_manipulatormap_handler_context(C, handler);
 +                              wm_region_mouse_co(C, event);
 +
 +                              /* handle manipulator highlighting */
 +                              if (event->type == MOUSEMOVE && !wm_manipulatormap_active_get(mmap)) {
 +                                      int part;
 +                                      mpr = wm_manipulatormap_highlight_find(mmap, C, event, &part);
 +                                      wm_manipulatormap_highlight_set(mmap, C, mpr, part);
 +                              }
 +                              /* handle user configurable manipulator-map keymap */
 +                              else if (mpr) {
 +                                      /* get user customized keymap from default one */
 +                                      const wmManipulatorGroup *highlightgroup = mpr->parent_mgroup;
 +                                      const wmKeyMap *keymap = WM_keymap_active(wm, highlightgroup->type->keymap);
 +                                      wmKeyMapItem *kmi;
 +
 +                                      PRINT("%s:   checking '%s' ...", __func__, keymap->idname);
 +
 +                                      if (!keymap->poll || keymap->poll(C)) {
 +                                              PRINT("pass\n");
 +                                              for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
 +                                                      if (wm_eventmatch(event, kmi)) {
 +                                                              wmOperator *op = handler->op;
 +
 +                                                              PRINT("%s:     item matched '%s'\n", __func__, kmi->idname);
 +
 +                                                              /* weak, but allows interactive callback to not use rawkey */
 +                                                              event->keymap_idname = kmi->idname;
 +
 +                                                              /* handler->op is called later, we want keymap op to be triggered here */
 +                                                              handler->op = NULL;
 +                                                              action |= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr);
 +                                                              handler->op = op;
 +
 +                                                              if (action & WM_HANDLER_BREAK) {
 +                                                                      if (action & WM_HANDLER_HANDLED) {
 +                                                                              if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS))
 +                                                                                      printf("%s:       handled - and pass on! '%s'\n", __func__, kmi->idname);
 +                                                                      }
 +                                                                      else {
 +                                                                              PRINT("%s:       un-handled '%s'\n", __func__, kmi->idname);
 +                                                                      }
 +                                                              }
 +                                                      }
 +                                              }
 +                                      }
 +                                      else {
 +                                              PRINT("fail\n");
 +                                      }
 +                              }
 +
 +                              /* restore the area */
 +                              CTX_wm_area_set(C, area);
 +                              CTX_wm_region_set(C, region);
 +
 +                              if (handler->op) {
 +                                      action |= wm_handler_operator_call(C, handlers, handler, event, NULL);
 +                              }
 +                      }
                        else {
                                /* modal, swallows all */
                                action |= wm_handler_operator_call(C, handlers, handler, event, NULL);
@@@ -2384,19 -2297,17 +2394,19 @@@ static void wm_paintcursor_test(bContex
  
  static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *event)
  {
 +      bScreen *screen = WM_window_get_active_screen(win);
 +
        if (BLI_listbase_is_empty(&wm->drags)) {
                return;
        }
        
        if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) {
 -              win->screen->do_draw_drag = true;
 +              screen->do_draw_drag = true;
        }
        else if (event->type == ESCKEY) {
                WM_drag_free_list(&wm->drags);
  
 -              win->screen->do_draw_drag = true;
 +              screen->do_draw_drag = true;
        }
        else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
                event->type = EVT_DROP;
                event->customdatafree = 1;
                
                /* clear drop icon */
 -              win->screen->do_draw_drag = true;
 +              screen->do_draw_drag = true;
                
                /* restore cursor (disabled, see wm_dragdrop.c) */
                // WM_cursor_modal_restore(win);
        }
        
        /* overlap fails otherwise */
 -      if (win->screen->do_draw_drag)
 +      if (screen->do_draw_drag)
                if (win->drawmethod == USER_DRAW_OVERLAP)
 -                      win->screen->do_draw = true;
 +                      screen->do_draw = true;
        
  }
  
@@@ -2451,28 -2362,22 +2461,28 @@@ void wm_event_do_handlers(bContext *C
  
        /* update key configuration before handling events */
        WM_keyconfig_update(wm);
 +      WM_manipulatorconfig_update(CTX_data_main(C));
  
        for (win = wm->windows.first; win; win = win->next) {
 +              bScreen *screen = WM_window_get_active_screen(win);
                wmEvent *event;
 -              
 -              if (win->screen == NULL)
 +
 +              /* some safty checks - these should always be set! */
 +              BLI_assert(WM_window_get_active_scene(win));
 +              BLI_assert(WM_window_get_active_screen(win));
 +              BLI_assert(WM_window_get_active_workspace(win));
 +
 +              if (screen == NULL)
                        wm_event_free_all(win);
                else {
 -                      Scene *scene = win->screen->scene;
 +                      Scene *scene = WM_window_get_active_scene(win);
                        
                        if (scene) {
 -                              int is_playing_sound = BKE_sound_scene_playing(win->screen->scene);
 +                              int is_playing_sound = BKE_sound_scene_playing(scene);
                                
                                if (is_playing_sound != -1) {
                                        bool is_playing_screen;
                                        CTX_wm_window_set(C, win);
 -                                      CTX_wm_screen_set(C, win->screen);
                                        CTX_data_scene_set(C, scene);
                                        
                                        is_playing_screen = (ED_screen_animation_playing(wm) != NULL);
                while ( (event = win->queue.first) ) {
                        int action = WM_HANDLER_CONTINUE;
  
 +                      /* active screen might change during handlers, update pointer */
 +                      screen = WM_window_get_active_screen(win);
 +
                        if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
                                printf("\n%s: Handling event\n", __func__);
                                WM_event_print(event);
                                }
  #endif
  
 -                              for (sa = win->screen->areabase.first; sa; sa = sa->next) {
 +                              for (sa = screen->areabase.first; sa; sa = sa->next) {
                                        /* after restoring a screen from SCREENMAXIMIZED we have to wait
                                         * with the screen handling till the region coordinates are updated */
 -                                      if (win->screen->skip_handling == true) {
 +                                      if (screen->skip_handling == true) {
                                                /* restore for the next iteration of wm_event_do_handlers */
 -                                              win->screen->skip_handling = false;
 +                                              screen->skip_handling = false;
                                                break;
                                        }
  
  
        /* update key configuration after handling events */
        WM_keyconfig_update(wm);
 -
 -      GPU_ASSERT_NO_GL_ERRORS("wm_event_do_handlers");
 +      WM_manipulatorconfig_update(CTX_data_main(C));
  }
  
  /* ********** filesector handling ************ */
@@@ -2701,7 -2604,7 +2711,7 @@@ void WM_event_add_fileselect(bContext *
        wmWindow *win = CTX_wm_window(C);
  
        /* only allow 1 file selector open per window */
 -      for (handler = win->modalhandlers.first; handler; handler = handlernext) {
 +      for (handler = win->handlers.first; handler; handler = handlernext) {
                handlernext = handler->next;
                
                if (handler->type == WM_HANDLER_FILESELECT) {
  
                                        if (sfile->op == handler->op) {
                                                CTX_wm_area_set(C, sa);
 -                                              wm_handler_fileselect_do(C, &win->modalhandlers, handler, EVT_FILESELECT_CANCEL);
 +                                              wm_handler_fileselect_do(C, &win->handlers, handler, EVT_FILESELECT_CANCEL);
                                                break;
                                        }
                                }
  
                        /* if not found we stop the handler without changing the screen */
                        if (!sa)
 -                              wm_handler_fileselect_do(C, &win->modalhandlers, handler, EVT_FILESELECT_EXTERNAL_CANCEL);
 +                              wm_handler_fileselect_do(C, &win->handlers, handler, EVT_FILESELECT_EXTERNAL_CANCEL);
                }
        }
        
        handler->op_area = CTX_wm_area(C);
        handler->op_region = CTX_wm_region(C);
        
 -      BLI_addhead(&win->modalhandlers, handler);
 +      BLI_addhead(&win->handlers, handler);
        
        /* check props once before invoking if check is available
         * ensures initial properties are valid */
@@@ -2777,33 -2680,6 +2787,33 @@@ wmEventHandler *WM_event_add_modal_hand
        return handler;
  }
  
 +/**
 + * Modal handlers store a pointer to an area which might be freed while the handler runs.
 + * Use this function to NULL all handler pointers to \a old_area.
 + */
 +void WM_event_modal_handler_area_replace(wmWindow *win, const ScrArea *old_area, ScrArea *new_area)
 +{
 +      for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) {
 +              if (handler->op_area == old_area) {
 +                      handler->op_area = new_area;
 +              }
 +      }
 +}
 +
 +/**
 + * Modal handlers store a pointer to a region which might be freed while the handler runs.
 + * Use this function to NULL all handler pointers to \a old_region.
 + */
 +void WM_event_modal_handler_region_replace(wmWindow *win, const ARegion *old_region, ARegion *new_region)
 +{
 +      for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) {
 +              if (handler->op_region == old_region) {
 +                      handler->op_region = new_region;
 +                      handler->op_region_type = new_region ? new_region->regiontype : RGN_TYPE_WINDOW;
 +              }
 +      }
 +}
 +
  wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
  {
        wmEventHandler *handler;
@@@ -2986,7 -2862,7 +2996,7 @@@ void WM_event_add_mousemove(bContext *C
  
  
  /* for modal callbacks, check configuration for how to interpret exit with tweaks  */
- bool WM_modal_tweak_exit(const wmEvent *event, int tweak_event)
+ bool WM_event_is_modal_tweak_exit(const wmEvent *event, int tweak_event)
  {
        /* if the release-confirm userpref setting is enabled, 
         * tweak events can be canceled when mouse is released