Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Fri, 23 Feb 2018 02:10:39 +0000 (13:10 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 23 Feb 2018 02:10:39 +0000 (13:10 +1100)
1  2 
source/blender/blenkernel/BKE_modifier.h
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/windowmanager/intern/wm_event_system.c

index ac9c2c50df2f72d63fc63773ff54a18c2ed27d89,b0917e4f6cdc40494554dec6728a998e216cd48e..e1ce58ba69ba94d358b1d7cc442e16d08843615c
  
  struct ID;
  struct DerivedMesh;
 -struct DagForest;
 -struct DagNode;
 +struct EvaluationContext;
  struct Object;
  struct Scene;
 +struct ViewLayer;
  struct ListBase;
  struct bArmature;
  struct Main;
@@@ -130,6 -130,12 +130,6 @@@ typedef enum ModifierApplyFlag 
  typedef struct ModifierUpdateDepsgraphContext {
        struct Scene *scene;
        struct Object *object;
 -
 -      /* Old depsgraph node handle. */
 -      struct DagForest *forest;
 -      struct DagNode *obNode;
 -
 -      /* new depsgraph node handle. */
        struct DepsNodeHandle *node;
  } ModifierUpdateDepsgraphContext;
  
@@@ -163,27 -169,25 +163,27 @@@ typedef struct ModifierTypeInfo 
         * the object it can obtain it from the derivedData argument if non-NULL,
         * and otherwise the ob argument.
         */
 -      void (*deformVerts)(struct ModifierData *md, struct Object *ob,
 -                          struct DerivedMesh *derivedData,
 +      void (*deformVerts)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
 +                          struct Object *ob, struct DerivedMesh *derivedData,
                            float (*vertexCos)[3], int numVerts,
                            ModifierApplyFlag flag);
  
        /* Like deformMatricesEM but called from object mode (for supporting modifiers in sculpt mode) */
 -      void (*deformMatrices)(struct ModifierData *md, struct Object *ob,
 -                             struct DerivedMesh *derivedData,
 +      void (*deformMatrices)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
 +                             struct Object *ob, struct DerivedMesh *derivedData,
                               float (*vertexCos)[3], float (*defMats)[3][3], int numVerts);
  
        /* Like deformVerts but called during editmode (for supporting modifiers)
         */
 -      void (*deformVertsEM)(struct ModifierData *md, struct Object *ob,
 -                            struct BMEditMesh *editData, struct DerivedMesh *derivedData,
 +      void (*deformVertsEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
 +                            struct Object *ob, struct BMEditMesh *editData,
 +                            struct DerivedMesh *derivedData,
                              float (*vertexCos)[3], int numVerts);
  
        /* Set deform matrix per vertex for crazyspace correction */
 -      void (*deformMatricesEM)(struct ModifierData *md, struct Object *ob,
 -                               struct BMEditMesh *editData, struct DerivedMesh *derivedData,
 +      void (*deformMatricesEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
 +                               struct Object *ob, struct BMEditMesh *editData,
 +                               struct DerivedMesh *derivedData,
                                 float (*vertexCos)[3], float (*defMats)[3][3], int numVerts);
  
        /********************* Non-deform modifier functions *********************/
         * The modifier may reuse the derivedData argument (i.e. return it in
         * modified form), but must not release it.
         */
 -      struct DerivedMesh *(*applyModifier)(struct ModifierData *md, struct Object *ob,
 -                                           struct DerivedMesh *derivedData,
 +      struct DerivedMesh *(*applyModifier)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
 +                                           struct Object *ob, struct DerivedMesh *derivedData,
                                             ModifierApplyFlag flag);
  
        /* Like applyModifier but called during editmode (for supporting
         * are expected from editmode objects. The same qualifications regarding
         * derivedData apply as for applyModifier.
         */
 -      struct DerivedMesh *(*applyModifierEM)(struct ModifierData *md, struct Object *ob,
 -                                             struct BMEditMesh *editData,
 -                                             struct DerivedMesh *derivedData,
 -                                             ModifierApplyFlag flag);
 +      struct DerivedMesh *(*applyModifierEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
 +                                             struct Object *ob, struct BMEditMesh *editData,
 +                                             struct DerivedMesh *derivedData, ModifierApplyFlag flag);
  
  
        /********************* Optional functions *********************/
         */
        bool (*isDisabled)(struct ModifierData *md, int userRenderParams);
  
 -      /* Add the appropriate relations to the DEP graph depending on the
 -       * modifier data. 
 -       *
 -       * This function is optional.
 -       */
 -      void (*updateDepgraph)(struct ModifierData *md,
 -                             const ModifierUpdateDepsgraphContext *ctx);
 -
        /* Add the appropriate relations to the dependency graph.
         *
         * This function is optional.
         */
 -      /* TODO(sergey): Remove once we finally switched to the new depsgraph. */
        void (*updateDepsgraph)(struct ModifierData *md,
-                               const ModifierUpdateDepsgraphContext* ctx);
+                               const ModifierUpdateDepsgraphContext *ctx);
 -
++ 
        /* Should return true if the modifier needs to be recalculated on time
         * changes.
         *
@@@ -375,8 -389,7 +375,8 @@@ struct Object *modifiers_isDeformedByAr
  struct Object *modifiers_isDeformedByLattice(struct Object *ob);
  struct Object *modifiers_isDeformedByCurve(struct Object *ob);
  bool          modifiers_usesArmature(struct Object *ob, struct bArmature *arm);
 -bool          modifiers_isCorrectableDeformed(struct Scene *scene, struct Object *ob);
 +bool          modifiers_isCorrectableDeformed(
 +        const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
  void          modifier_freeTemporaryData(struct ModifierData *md);
  bool          modifiers_isPreview(struct Object *ob);
  
@@@ -422,24 -435,24 +422,24 @@@ const char *modifier_path_relbase(struc
  /* wrappers for modifier callbacks */
  
  struct DerivedMesh *modwrap_applyModifier(
 -        ModifierData *md, struct Object *ob,
 -        struct DerivedMesh *dm,
 +        ModifierData *md, const struct EvaluationContext *eval_ctx,
 +        struct Object *ob, struct DerivedMesh *dm,
          ModifierApplyFlag flag);
  
  struct DerivedMesh *modwrap_applyModifierEM(
 -        ModifierData *md, struct Object *ob,
 -        struct BMEditMesh *em,
 +        ModifierData *md, const struct EvaluationContext *eval_ctx,
 +        struct Object *ob, struct BMEditMesh *em,
          struct DerivedMesh *dm,
          ModifierApplyFlag flag);
  
  void modwrap_deformVerts(
 -        ModifierData *md, struct Object *ob,
 -        struct DerivedMesh *dm,
 +        ModifierData *md, const struct EvaluationContext *eval_ctx,
 +        struct Object *ob, struct DerivedMesh *dm,
          float (*vertexCos)[3], int numVerts,
          ModifierApplyFlag flag);
  
  void modwrap_deformVertsEM(
 -        ModifierData *md, struct Object *ob,
 +        ModifierData *md, const struct EvaluationContext *eval_ctx, struct Object *ob,
          struct BMEditMesh *em, struct DerivedMesh *dm,
          float (*vertexCos)[3], int numVerts);
  
index 9e1d5e4ec93db1ae5bb12a7ecf5e276c65324c16,687a883f7928e3a2558aeb6c3c63977e763691fe..56c3c8ab976fa8c709a8330940e3f19bec33ad35
@@@ -41,7 -41,6 +41,7 @@@
  struct wmWindowManager;
  struct wmWindow;
  
 +struct wmMsgBus;
  struct wmEvent;
  struct wmGesture;
  struct wmOperatorType;
@@@ -157,15 -156,12 +157,15 @@@ typedef struct wmWindowManager 
  
        char is_interface_locked;               /* indicates whether interface is locked for user interaction */
        char par[7];
 +
 +      struct wmMsgBus *message_bus;
 +
  } wmWindowManager;
  
  /* wmWindowManager.initialized */
  enum {
 -      WM_INIT_WINDOW = (1<<0),
 -      WM_INIT_KEYMAP = (1<<1),
 +      WM_WINDOW_IS_INITIALIZED = (1<<0),
 +      WM_KEYMAP_IS_INITIALIZED = (1<<1),
  };
  
  /* IME is win32 only! */
@@@ -180,14 -176,10 +180,14 @@@ typedef struct wmWindow 
        struct wmWindow *next, *prev;
  
        void *ghostwin;             /* don't want to include ghost.h stuff */
 +      void *gwnctx;               /* don't want to include gawin stuff */
 +
 +      struct Scene *scene;     /* The scene displayed in this window. */
 +      struct Scene *new_scene; /* temporary when switching */
  
 -      struct bScreen *screen;     /* active screen */
 -      struct bScreen *newscreen;  /* temporary when switching */
 -      char screenname[64];        /* MAX_ID_NAME for matching window with active screen after file read */
 +      struct WorkSpaceInstanceHook *workspace_hook;
 +
 +      struct bScreen *screen DNA_DEPRECATED;
  
        short posx, posy, sizex, sizey;  /* window coords */
        short windowstate;  /* borderless, full */
        short modalcursor;  /* the current modal cursor */
        short grabcursor;           /* cursor grab mode */
        short addmousemove; /* internal: tag this for extra mousemove event, makes cursors/buttons active on UI switching */
 -      short multisamples; /* amount of samples for OpenGL FSA the ghost window was created with, if zero no FSA */
 -      short pad[3];
 +      short pad[4];
  
        int winid;                  /* winid also in screens, is for retrieving this window after read */
  
  
        struct wmEvent *eventstate;   /* storage for event system */
  
 -      struct wmSubWindow *curswin;  /* internal for wm_subwindow.c only */
 -
        struct wmGesture *tweak;      /* internal for wm_operators.c */
  
        /* Input Method Editor data - complex character input (esp. for asian character input)
        ListBase handlers;            /* window+screen handlers, handled last */
        ListBase modalhandlers;       /* priority handlers, handled first */
  
 -      ListBase subwindows;          /* opengl stuff for sub windows, see notes in wm_subwindow.c */
        ListBase gesture;             /* gesture stuff */
  
        struct Stereo3dFormat *stereo3d_format; /* properties for stereoscopic displays */
@@@ -317,8 -313,10 +317,10 @@@ typedef struct wmKeyMap 
        short kmi_id;     /* last kmi id */
  
        /* runtime */
-       int (*poll)(struct bContext *);  /* verify if enabled in the current context */
-       const void *modal_items;         /* for modal, EnumPropertyItem for now */
+       /** Verify if enabled in the current context, use #WM_keymap_poll instead of direct calls. */
+       int (*poll)(struct bContext *);
+       /** For modal, #EnumPropertyItem for now. */
+       const void *modal_items;
  } wmKeyMap;
  
  /* wmKeyMap.flag */
index 38f9a2bccae1d5a2f170f088d03b307f4e668388,d62327a83a9d93fe494dd048274ea7bdcebc541b..b6a9115cca45797a5ce8faaa6bfe6a9ff429c5b6
  #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"
  
  
  #include "RNA_access.h"
  
 -#include "GPU_debug.h"
 -
  #include "UI_interface.h"
  
  #include "PIL_time.h"
  
  #include "WM_api.h"
  #include "WM_types.h"
 +#include "WM_message.h"
  #include "wm.h"
  #include "wm_window.h"
  #include "wm_event_system.h"
@@@ -84,8 -83,6 +84,8 @@@
  
  #include "RNA_enum_types.h"
  
 +#include "DEG_depsgraph.h"
 +
  /* Motion in pixels allowed before we don't consider single/double click. */
  #define WM_EVENT_CLICK_WIGGLE_ROOM 2
  
@@@ -182,6 -179,7 +182,6 @@@ static bool wm_test_duplicate_notifier(
  /* XXX: in future, which notifiers to send to other windows? */
  void WM_event_add_notifier(const bContext *C, unsigned int type, void *reference)
  {
 -      ARegion *ar;
        wmWindowManager *wm = CTX_wm_manager(C);
        wmNotifier *note;
  
        
        note->window = CTX_wm_window(C);
        
 -      ar = CTX_wm_region(C);
 -      if (ar)
 -              note->swinid = ar->swinid;
 -      
        note->category = type & NOTE_CATEGORY;
        note->data = type & NOTE_DATA;
        note->subtype = type & NOTE_SUBTYPE;
@@@ -245,14 -247,6 +245,14 @@@ void WM_main_remove_notifier_reference(
                                wm_notifier_clear(note);
                        }
                }
 +
 +              /* Remap instead. */
 +#if 0
 +              if (wm->message_bus) {
 +                      WM_msg_id_remove(wm->message_bus, reference);
 +              }
 +#endif
 +
        }
  }
  
@@@ -272,17 -266,6 +272,17 @@@ void WM_main_remap_editor_id_reference(
                        }
                }
        }
 +
 +      wmWindowManager *wm = bmain->wm.first;
 +      if (wm && wm->message_bus) {
 +              struct wmMsgBus *mbus = wm->message_bus;
 +              if (new_id != NULL) {
 +                      WM_msg_id_update(mbus, old_id, new_id);
 +              }
 +              else {
 +                      WM_msg_id_remove(mbus, old_id);
 +              }
 +      }
  }
  
  static void wm_notifier_clear(wmNotifier *note)
@@@ -302,20 -285,15 +302,20 @@@ void wm_event_do_refresh_wm_and_depsgra
  
        /* combine datamasks so 1 win doesn't disable UV's in another [#26448] */
        for (wmWindow *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 (wmWindow *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;
 +
 +                      WorkSpace *workspace = WM_window_get_active_workspace(win);
  
 -                      BKE_scene_update_tagged(bmain->eval_ctx, bmain, win->screen->scene);
 +                      BKE_workspace_update_object_mode(bmain->eval_ctx, workspace);
 +
 +                      BKE_workspace_update_tagged(bmain->eval_ctx, bmain, workspace, scene);
                }
        }
  
@@@ -353,12 -327,9 +353,12 @@@ void wm_event_do_notifiers(bContext *C
        
        if (wm == NULL)
                return;
 -      
 +
 +      /* disable? - keep for now since its used for window level notifiers. */
 +#if 1
        /* 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, 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);
 +                              ViewLayer *view_layer = CTX_data_view_layer(C);
 +                              ED_info_stats_clear(view_layer);
                                WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
                        }
                }
                if (do_anim) {
  
                        /* XXX, quick frame changes can cause a crash if framechange and rendering
 -                       * collide (happens on slow scenes), BKE_scene_update_for_newframe can be called
 +                       * collide (happens on slow scenes), BKE_scene_graph_update_for_newframe can be called
                         * twice which can depgraph update the same object at once */
                        if (G.is_rendering == false) {
 -
                                /* depsgraph gets called, might send more notifiers */
 -                              ED_update_for_newframe(CTX_data_main(C), win->screen->scene, 1);
 +                              ViewLayer *view_layer = CTX_data_view_layer(C);
 +                              Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +                              ED_update_for_newframe(CTX_data_main(C), scene, view_layer, depsgraph);
                        }
                }
        }
        /* 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);
 +                      WorkSpace *workspace = WM_window_get_active_workspace(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 != workspace &&
 +                          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, workspace);
                                        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);
        }
 -      
 +#endif /* if 1 (postpone disabling for in favor of message-bus), eventually. */
 +
 +      /* Handle message bus. */
 +      {
 +              for (win = wm->windows.first; win; win = win->next) {
 +                      CTX_wm_window_set(C, win);
 +                      WM_msgbus_handle(wm->message_bus, C);
 +              }
 +              CTX_wm_window_set(C, NULL);
 +      }
 +
        wm_event_do_refresh_wm_and_depsgraph(C);
  }
  
@@@ -1204,8 -1141,8 +1204,8 @@@ static int wm_operator_invoke
                }
  
                if ((G.debug & G_DEBUG_HANDLERS) && ((event == NULL) || (event->type != MOUSEMOVE))) {
 -                      printf("%s: handle evt %d win %d op %s\n",
 -                             __func__, event ? event->type : 0, CTX_wm_screen(C)->subwinactive, ot->idname);
 +                      printf("%s: handle evt %d region %p op %s\n",
 +                             __func__, event ? event->type : 0, CTX_wm_screen(C)->active_region, ot->idname);
                }
                
                if (op->type->invoke && event) {
@@@ -1660,36 -1597,6 +1660,36 @@@ int WM_userdef_event_map(int kmitype
        return kmitype;
  }
  
 +/**
 + * Use so we can check if 'wmEvent.type' is released in modal operators.
 + *
 + * An alternative would be to add a 'wmEvent.type_nokeymap'... or similar.
 + */
 +int WM_userdef_event_type_from_keymap_type(int kmitype)
 +{
 +      switch (kmitype) {
 +              case SELECTMOUSE:
 +                      return (U.flag & USER_LMOUSESELECT) ? LEFTMOUSE : RIGHTMOUSE;
 +              case ACTIONMOUSE:
 +                      return (U.flag & USER_LMOUSESELECT) ? RIGHTMOUSE : LEFTMOUSE;
 +              case EVT_TWEAK_S:
 +                      return (U.flag & USER_LMOUSESELECT) ? LEFTMOUSE : RIGHTMOUSE;
 +              case EVT_TWEAK_A:
 +                      return (U.flag & USER_LMOUSESELECT) ? RIGHTMOUSE : LEFTMOUSE;
 +              case EVT_TWEAK_L:
 +                      return LEFTMOUSE;
 +              case EVT_TWEAK_M:
 +                      return MIDDLEMOUSE;
 +              case EVT_TWEAK_R:
 +                      return RIGHTMOUSE;
 +              case WHEELOUTMOUSE:
 +                      return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELUPMOUSE : WHEELDOWNMOUSE;
 +              case WHEELINMOUSE:
 +                      return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELDOWNMOUSE : WHEELUPMOUSE;
 +      }
 +
 +      return kmitype;
 +}
  
  static int wm_eventmatch(const wmEvent *winevent, wmKeyMapItem *kmi)
  {
@@@ -1838,7 -1745,7 +1838,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);
@@@ -2180,7 -2084,7 +2180,7 @@@ static int wm_handlers_do_intern(bConte
  
                                PRINT("%s:   checking '%s' ...", __func__, keymap->idname);
  
-                               if (!keymap->poll || keymap->poll(C)) {
+                               if (WM_keymap_poll(C, keymap)) {
  
                                        PRINT("pass\n");
  
                                        }
                                }
                        }
 +                      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);
 +
 +                              if (region->manipulator_map != handler->manipulator_map) {
 +                                      WM_manipulatormap_tag_refresh(handler->manipulator_map);
 +                              }
 +
 +                              wm_manipulatormap_handler_context(C, handler);
 +                              wm_region_mouse_co(C, event);
 +
 +                              /* handle manipulator highlighting */
 +                              if (event->type == MOUSEMOVE && !wm_manipulatormap_modal_get(mmap)) {
 +                                      int part;
 +                                      mpr = wm_manipulatormap_highlight_find(mmap, C, event, &part);
 +                                      wm_manipulatormap_highlight_set(mmap, C, mpr, part);
 +                                      if (mpr != NULL) {
 +                                              WM_tooltip_timer_init(C, CTX_wm_window(C), region, WM_manipulatormap_tooltip_init);
 +                                      }
 +                              }
 +                              else {
 +                                      /* Either we operate on a single highlighted item
 +                                       * or groups attached to the selected manipulators.
 +                                       * To simplify things both cases loop over an array of items. */
 +                                      wmManipulatorGroup *mgroup_first;
 +                                      bool is_mgroup_single;
 +
 +                                      if (ISMOUSE(event->type)) {
 +                                              /* Keep mpr set as-is, just fake single selection. */
 +                                              if (mpr) {
 +                                                      mgroup_first = mpr->parent_mgroup;
 +                                              }
 +                                              else {
 +                                                      mgroup_first = NULL;
 +                                              }
 +                                              is_mgroup_single = true;
 +                                      }
 +                                      else {
 +                                              if (WM_manipulatormap_is_any_selected(mmap)) {
 +                                                      const ListBase *groups = WM_manipulatormap_group_list(mmap);
 +                                                      mgroup_first = groups->first;
 +                                              }
 +                                              else {
 +                                                      mgroup_first = NULL;
 +                                              }
 +                                              is_mgroup_single = false;
 +                                      }
 +
 +                                      /* Don't use from now on. */
 +                                      mpr = NULL;
 +
 +                                      for (wmManipulatorGroup *mgroup = mgroup_first; mgroup; mgroup = mgroup->next) {
 +                                              /* get user customized keymap from default one */
 +
 +                                              if ((is_mgroup_single == false) &&
 +                                                  /* We might want to change the logic here and use some kind of manipulator edit-mode.
 +                                                   * For now just use keymap when a selection exists. */
 +                                                  wm_manipulatorgroup_is_any_selected(mgroup) == false)
 +                                              {
 +                                                      continue;
 +                                              }
 +
 +                                              const wmKeyMap *keymap = WM_keymap_active(wm, mgroup->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;
 +
 +                                                                      CTX_wm_manipulator_group_set(C, mgroup);
 +
 +                                                                      /* 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;
 +
 +                                                                      CTX_wm_manipulator_group_set(C, NULL);
 +
 +                                                                      if (action & WM_HANDLER_BREAK) {
 +                                                                              if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) {
 +                                                                                      printf("%s:       handled - and pass on! '%s'\n",
 +                                                                                             __func__, kmi->idname);
 +                                                                              }
 +                                                                              break;
 +                                                                      }
 +                                                                      else {
 +                                                                              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");
 +                                              }
 +
 +                                              if (action & WM_HANDLER_BREAK) {
 +                                                      break;
 +                                              }
 +
 +                                              if (is_mgroup_single) {
 +                                                      break;
 +                                              }
 +                                      }
 +                              }
 +
 +                              /* 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);
@@@ -2575,19 -2346,17 +2575,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;
        
  }
  
@@@ -2642,28 -2411,22 +2642,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);
                                                        int ncfra = time * (float)FPS + 0.5f;
                                                        if (ncfra != scene->r.cfra) {
                                                                scene->r.cfra = ncfra;
 -                                                              ED_update_for_newframe(CTX_data_main(C), scene, 1);
 +                                                              ViewLayer *view_layer = CTX_data_view_layer(C);
 +                                                              Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +                                                              ED_update_for_newframe(CTX_data_main(C), scene, view_layer, depsgraph);
                                                                WM_event_add_notifier(C, NC_WINDOW, 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);
                        CTX_wm_window_set(C, win);
  
                        /* Clear tool-tip on mouse move. */
 -                      if (win->screen->tool_tip && win->screen->tool_tip->exit_on_event) {
 +                      if (screen->tool_tip && screen->tool_tip->exit_on_event) {
                                if (ISMOUSE(event->type)) {
                                        WM_tooltip_clear(C, win);
                                }
                                return;
  
                        /* check for a tooltip */
 -                      {
 -                              bScreen *screen = CTX_wm_window(C)->screen;
 +                      if (screen == WM_window_get_active_screen(win)) {
                                if (screen->tool_tip && screen->tool_tip->timer) {
                                        if ((event->type == TIMER) && (event->customdata == screen->tool_tip->timer)) {
                                                WM_tooltip_init(C, win);
                                /* Note: setting subwin active should be done here, after modal handlers have been done */
                                if (event->type == MOUSEMOVE) {
                                        /* state variables in screen, cursors. Also used in wm_draw.c, fails for modal handlers though */
 -                                      ED_screen_set_subwinactive(C, event);
 +                                      ED_screen_set_active_region(C, event);
                                        /* for regions having custom cursors */
                                        wm_paintcursor_test(C, 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;
                                        }
  
                                                                                        wm_drags_check_ops(C, event);
                                                                                }
                                                                        }
 -                                                                      
 +
 +#ifdef USE_WORKSPACE_TOOL
 +                                                                      /* How to solve properly?
 +                                                                       *
 +                                                                       * Handlers are stored in each region,
 +                                                                       * however the tool-system swaps keymaps often and isn't stored
 +                                                                       * per region.
 +                                                                       *
 +                                                                       * Need to investigate how this could be done better.
 +                                                                       * We might need to add a more dynamic handler type that uses a callback
 +                                                                       * to fetch its current keymap.
 +                                                                       */
 +                                                                      wmEventHandler sneaky_handler = {NULL};
 +                                                                      if (ar->regiontype == RGN_TYPE_WINDOW) {
 +                                                                              WorkSpace *workspace = WM_window_get_active_workspace(win);
 +                                                                              if (workspace->tool.keymap[0] &&
 +                                                                                  workspace->tool.spacetype == sa->spacetype)
 +                                                                              {
 +                                                                                      wmKeyMap *km = WM_keymap_find_all(
 +                                                                                              C, workspace->tool.keymap, sa->spacetype, RGN_TYPE_WINDOW);
 +                                                                                      if (km != NULL) {
 +                                                                                              sneaky_handler.keymap = km;
 +                                                                                              /* Handle widgets first. */
 +                                                                                              wmEventHandler *handler_last = ar->handlers.last;
 +                                                                                              while (handler_last && handler_last->manipulator_map == NULL) {
 +                                                                                                      handler_last = handler_last->prev;
 +                                                                                              }
 +                                                                                              /* Head of list or after last manipulator. */
 +                                                                                              BLI_insertlinkafter(&ar->handlers, handler_last, &sneaky_handler);
 +                                                                                      }
 +                                                                              }
 +                                                                      }
 +#endif /* USE_WORKSPACE_TOOL */
 +
                                                                        action |= wm_handlers_do(C, event, &ar->handlers);
  
 +#ifdef USE_WORKSPACE_TOOL
 +                                                                      if (sneaky_handler.keymap) {
 +                                                                              BLI_remlink(&ar->handlers, &sneaky_handler);
 +                                                                      }
 +#endif /* USE_WORKSPACE_TOOL */
 +
                                                                        /* fileread case (python), [#29489] */
                                                                        if (CTX_wm_window(C) == NULL)
                                                                                return;
  
        /* 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 ************ */
@@@ -3025,34 -2746,6 +3025,34 @@@ 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) {
 +              /* fileselect handler is quite special... it needs to keep old area stored in handler, so don't change it */
 +              if ((handler->op_area == old_area) && (handler->type != WM_HANDLER_FILESELECT)) {
 +                      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;