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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/windowmanager/intern')
-rw-r--r--source/blender/windowmanager/intern/wm.c6
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c20
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c98
-rw-r--r--source/blender/windowmanager/intern/wm_files.c126
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c2
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c5
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c71
-rw-r--r--source/blender/windowmanager/intern/wm_window.c14
8 files changed, 222 insertions, 120 deletions
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 67e961b9cd0..a09cc4aeb31 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -430,7 +430,7 @@ void wm_clear_default_size(bContext *C)
/* on startup, it adds all data, for matching */
void wm_add_default(bContext *C)
{
- wmWindowManager *wm = BKE_libblock_alloc(CTX_data_main(C), ID_WM, "WinMan");
+ wmWindowManager *wm = BKE_libblock_alloc(CTX_data_main(C), ID_WM, "WinMan", 0);
wmWindow *win;
bScreen *screen = CTX_wm_screen(C); /* XXX from file read hrmf */
@@ -495,6 +495,10 @@ void wm_close_and_free_all(bContext *C, ListBase *wmlist)
void WM_main(bContext *C)
{
+ /* Single refresh before handling events.
+ * This ensures we don't run operators before the depsgraph has been evaluated. */
+ wm_event_do_refresh_wm_and_depsgraph(C);
+
while (1) {
/* get events from ghost, handle window events, add to window queues */
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 25c6980f58e..2b695c95258 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -867,25 +867,13 @@ static bool wm_draw_update_test_window(wmWindow *win)
static int wm_automatic_draw_method(wmWindow *win)
{
- /* Ideally all cards would work well with triple buffer, since if it works
- * well gives the least redraws and is considerably faster at partial redraw
- * for sculpting or drawing overlapping menus. For typically lower end cards
- * copy to texture is slow though and so we use overlap instead there. */
-
+ /* We assume all supported GPUs now support triple buffer well. */
if (win->drawmethod == USER_DRAW_AUTOMATIC) {
- /* Windows software driver darkens color on each redraw */
- if (GPU_type_matches(GPU_DEVICE_SOFTWARE, GPU_OS_WIN, GPU_DRIVER_SOFTWARE))
- return USER_DRAW_OVERLAP_FLIP;
- else if (GPU_type_matches(GPU_DEVICE_SOFTWARE, GPU_OS_UNIX, GPU_DRIVER_SOFTWARE))
- return USER_DRAW_OVERLAP;
- /* drawing lower color depth again degrades colors each time */
- else if (GPU_color_depth() < 24)
- return USER_DRAW_OVERLAP;
- else
- return USER_DRAW_TRIPLE;
+ return USER_DRAW_TRIPLE;
}
- else
+ else {
return win->drawmethod;
+ }
}
bool WM_is_draw_triple(wmWindow *win)
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index f26ee0e73ec..7e7314cc0c8 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -263,13 +263,56 @@ static void wm_notifier_clear(wmNotifier *note)
memset(((char *)note) + sizeof(Link), 0, sizeof(*note) - sizeof(Link));
}
+/**
+ * Was part of #wm_event_do_notifiers, split out so it can be called once before entering the #WM_main loop.
+ * This ensures operators don't run before the UI and depsgraph are initialized.
+ */
+void wm_event_do_refresh_wm_and_depsgraph(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ uint64_t win_combine_v3d_datamask = 0;
+
+ /* 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);
+ }
+
+ /* cached: editor refresh callbacks now, they get context */
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ ScrArea *sa;
+
+ CTX_wm_window_set(C, win);
+ for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ if (sa->do_refresh) {
+ CTX_wm_area_set(C, sa);
+ ED_area_do_refresh(C, sa);
+ }
+ }
+
+ /* XXX make lock in future, or separated derivedmesh users in scene */
+ if (G.is_rendering == false) {
+ /* depsgraph & animation: update tagged datablocks */
+ Main *bmain = CTX_data_main(C);
+
+ /* copied to set's in scene_update_tagged_recursive() */
+ win->screen->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;
+
+ BKE_scene_update_tagged(bmain->eval_ctx, bmain, win->screen->scene);
+ }
+ }
+
+ CTX_wm_window_set(C, NULL);
+}
+
/* called in mainloop */
void wm_event_do_notifiers(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmNotifier *note, *next;
wmWindow *win;
- uint64_t win_combine_v3d_datamask = 0;
if (wm == NULL)
return;
@@ -373,39 +416,7 @@ void wm_event_do_notifiers(bContext *C)
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);
- }
-
- /* cached: editor refresh callbacks now, they get context */
- for (win = wm->windows.first; win; win = win->next) {
- ScrArea *sa;
-
- CTX_wm_window_set(C, win);
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- if (sa->do_refresh) {
- CTX_wm_area_set(C, sa);
- ED_area_do_refresh(C, sa);
- }
- }
-
- /* XXX make lock in future, or separated derivedmesh users in scene */
- if (G.is_rendering == false) {
- /* depsgraph & animation: update tagged datablocks */
- Main *bmain = CTX_data_main(C);
-
- /* copied to set's in scene_update_tagged_recursive() */
- win->screen->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;
-
- BKE_scene_update_tagged(bmain->eval_ctx, bmain, win->screen->scene);
- }
- }
-
- CTX_wm_window_set(C, NULL);
+ wm_event_do_refresh_wm_and_depsgraph(C);
}
static int wm_event_always_pass(const wmEvent *event)
@@ -615,6 +626,16 @@ bool WM_event_is_absolute(const wmEvent *event)
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)
{
@@ -1079,6 +1100,9 @@ bool WM_operator_last_properties_store(wmOperator *UNUSED(op))
#endif
+/**
+ * Also used for exec when 'event' is NULL.
+ */
static int wm_operator_invoke(
bContext *C, wmOperatorType *ot, wmEvent *event,
PointerRNA *properties, ReportList *reports, const bool poll_only)
@@ -1094,7 +1118,9 @@ static int wm_operator_invoke(
wmOperator *op = wm_operator_create(wm, ot, properties, reports); /* if reports == NULL, they'll be initialized */
const bool is_nested_call = (wm->op_undo_depth != 0);
- op->flag |= OP_IS_INVOKE;
+ if (event != NULL) {
+ op->flag |= OP_IS_INVOKE;
+ }
/* initialize setting from previous run */
if (!is_nested_call) { /* not called by py script */
@@ -2852,7 +2878,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
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index b4a6366fb4e..637ace9cd82 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -449,7 +449,7 @@ void wm_file_read_report(bContext *C)
* Logic shared between #WM_file_read & #wm_homefile_read,
* updates to make after reading a file.
*/
-static void wm_file_read_post(bContext *C, bool is_startup_file)
+static void wm_file_read_post(bContext *C, const bool is_startup_file, const bool use_userdef)
{
bool addons_loaded = false;
wmWindowManager *wm = CTX_wm_manager(C);
@@ -468,13 +468,14 @@ static void wm_file_read_post(bContext *C, bool is_startup_file)
if (is_startup_file) {
/* possible python hasn't been initialized */
if (CTX_py_init_get(C)) {
- /* Only run when we have a template path found. */
- if (BKE_appdir_app_template_any()) {
- BPY_execute_string(C, "__import__('bl_app_template_utils').reset()");
+ if (use_userdef) {
+ /* Only run when we have a template path found. */
+ if (BKE_appdir_app_template_any()) {
+ BPY_execute_string(C, "__import__('bl_app_template_utils').reset()");
+ }
+ /* sync addons, these may have changed from the defaults */
+ BPY_execute_string(C, "__import__('addon_utils').reset_all()");
}
- /* sync addons, these may have changed from the defaults */
- BPY_execute_string(C, "__import__('addon_utils').reset_all()");
-
BPY_python_reset(C);
addons_loaded = true;
}
@@ -588,7 +589,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
}
- wm_file_read_post(C, false);
+ wm_file_read_post(C, false, false);
success = true;
}
@@ -636,13 +637,15 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
*
* \param use_factory_settings: Ignore on-disk startup file, use bundled ``datatoc_startup_blend`` instead.
* Used for "Restore Factory Settings".
+ * \param use_userdef: Load factory settings as well as startup file.
+ * Disabled for "File New" we don't want to reload preferences.
* \param filepath_startup_override: Optional path pointing to an alternative blend file (may be NULL).
* \param app_template_override: Template to use instead of the template defined in user-preferences.
* When not-null, this is written into the user preferences.
*/
int wm_homefile_read(
bContext *C, ReportList *reports,
- bool use_factory_settings, bool use_empty_data,
+ bool use_factory_settings, bool use_empty_data, bool use_userdef,
const char *filepath_startup_override, const char *app_template_override)
{
ListBase wmbase;
@@ -666,7 +669,7 @@ int wm_homefile_read(
* And in this case versioning code is to be run.
*/
bool read_userdef_from_memory = false;
- eBLOReadSkip skip_flags = 0;
+ eBLOReadSkip skip_flags = use_userdef ? 0 : BLO_READ_SKIP_USERDEF;
/* options exclude eachother */
BLI_assert((use_factory_settings && filepath_startup_override) == 0);
@@ -693,7 +696,9 @@ int wm_homefile_read(
if (!use_factory_settings) {
if (cfgdir) {
BLI_path_join(filepath_startup, sizeof(filepath_startup), cfgdir, BLENDER_STARTUP_FILE, NULL);
- BLI_path_join(filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE, NULL);
+ if (use_userdef) {
+ BLI_path_join(filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE, NULL);
+ }
}
else {
use_factory_settings = true;
@@ -705,14 +710,16 @@ int wm_homefile_read(
}
/* load preferences before startup.blend */
- if (!use_factory_settings && BLI_exists(filepath_userdef)) {
- UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL);
- if (userdef != NULL) {
- BKE_blender_userdef_set_data(userdef);
- MEM_freeN(userdef);
-
- skip_flags |= BLO_READ_SKIP_USERDEF;
- printf("Read prefs: %s\n", filepath_userdef);
+ if (use_userdef) {
+ if (!use_factory_settings && BLI_exists(filepath_userdef)) {
+ UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL);
+ if (userdef != NULL) {
+ BKE_blender_userdef_set_data(userdef);
+ MEM_freeN(userdef);
+
+ skip_flags |= BLO_READ_SKIP_USERDEF;
+ printf("Read prefs: %s\n", filepath_userdef);
+ }
}
}
@@ -721,23 +728,23 @@ int wm_homefile_read(
if (filepath_startup_override != NULL) {
/* pass */
}
- else if (app_template_override && app_template_override[0]) {
+ else if (app_template_override) {
+ /* This may be clearing the current template by setting to an empty string. */
app_template = app_template_override;
}
else if (!use_factory_settings && U.app_template[0]) {
app_template = U.app_template;
}
- if (app_template != NULL) {
+ if ((app_template != NULL) && (app_template[0] != '\0')) {
BKE_appdir_app_template_id_search(app_template, app_template_system, sizeof(app_template_system));
- BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template, NULL);
- }
- /* insert template name into startup file */
- if (app_template != NULL) {
+ /* Insert template name into startup file. */
+
/* note that the path is being set even when 'use_factory_settings == true'
* this is done so we can load a templates factory-settings */
if (!use_factory_settings) {
+ BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template, NULL);
BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_config, BLENDER_STARTUP_FILE, NULL);
if (BLI_access(filepath_startup, R_OK) != 0) {
filepath_startup[0] = '\0';
@@ -772,8 +779,12 @@ int wm_homefile_read(
success = BKE_blendfile_read_from_memory(
C, datatoc_startup_blend, datatoc_startup_blend_size,
NULL, skip_flags, true);
- if (success && !(skip_flags & BLO_READ_SKIP_USERDEF)) {
- read_userdef_from_memory = true;
+ if (success) {
+ if (use_userdef) {
+ if ((skip_flags & BLO_READ_SKIP_USERDEF) == 0) {
+ read_userdef_from_memory = true;
+ }
+ }
}
if (BLI_listbase_is_empty(&wmbase)) {
wm_clear_default_size(C);
@@ -801,21 +812,23 @@ int wm_homefile_read(
BLI_path_join(temp_path, sizeof(temp_path), app_template_system, BLENDER_USERPREF_FILE, NULL);
}
- UserDef *userdef_template = NULL;
- /* just avoids missing file warning */
- if (BLI_exists(temp_path)) {
- userdef_template = BKE_blendfile_userdef_read(temp_path, NULL);
- }
- if (userdef_template == NULL) {
- /* we need to have preferences load to overwrite preferences from previous template */
- userdef_template = BKE_blendfile_userdef_read_from_memory(
- datatoc_startup_blend, datatoc_startup_blend_size, NULL);
- read_userdef_from_memory = true;
- }
- if (userdef_template) {
- BKE_blender_userdef_set_app_template(userdef_template);
- BKE_blender_userdef_free_data(userdef_template);
- MEM_freeN(userdef_template);
+ if (use_userdef) {
+ UserDef *userdef_template = NULL;
+ /* just avoids missing file warning */
+ if (BLI_exists(temp_path)) {
+ userdef_template = BKE_blendfile_userdef_read(temp_path, NULL);
+ }
+ if (userdef_template == NULL) {
+ /* we need to have preferences load to overwrite preferences from previous template */
+ userdef_template = BKE_blendfile_userdef_read_from_memory(
+ datatoc_startup_blend, datatoc_startup_blend_size, NULL);
+ read_userdef_from_memory = true;
+ }
+ if (userdef_template) {
+ BKE_blender_userdef_set_app_template(userdef_template);
+ BKE_blender_userdef_free_data(userdef_template);
+ MEM_freeN(userdef_template);
+ }
}
}
@@ -827,8 +840,10 @@ int wm_homefile_read(
* can remove this eventually, only in a 2.53 and older, now its not written */
G.fileflags &= ~G_FILE_RELATIVE_REMAP;
- /* check userdef before open window, keymaps etc */
- wm_init_userdef(C, read_userdef_from_memory);
+ if (use_userdef) {
+ /* check userdef before open window, keymaps etc */
+ wm_init_userdef(C, read_userdef_from_memory);
+ }
/* match the read WM with current WM */
wm_window_match_do(C, &wmbase);
@@ -836,9 +851,11 @@ int wm_homefile_read(
G.main->name[0] = '\0';
- /* When loading factory settings, the reset solid OpenGL lights need to be applied. */
- if (!G.background) {
- GPU_default_lights();
+ if (use_userdef) {
+ /* When loading factory settings, the reset solid OpenGL lights need to be applied. */
+ if (!G.background) {
+ GPU_default_lights();
+ }
}
/* start with save preference untitled.blend */
@@ -846,7 +863,7 @@ int wm_homefile_read(
/* disable auto-play in startup.blend... */
G.fileflags &= ~G_FILE_AUTOPLAY;
- wm_file_read_post(C, true);
+ wm_file_read_post(C, true, use_userdef);
return true;
}
@@ -1528,6 +1545,7 @@ void WM_OT_read_history(wmOperatorType *ot)
static int wm_homefile_read_exec(bContext *C, wmOperator *op)
{
const bool use_factory_settings = (STREQ(op->type->idname, "WM_OT_read_factory_settings"));
+ bool use_userdef = false;
char filepath_buf[FILE_MAX];
const char *filepath = NULL;
@@ -1551,6 +1569,8 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
else {
/* always load UI for factory settings (prefs will re-init) */
G.fileflags &= ~G_FILE_NO_UI;
+ /* Always load preferences with factory settings. */
+ use_userdef = true;
}
char app_template_buf[sizeof(U.app_template)];
@@ -1562,17 +1582,15 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
if (prop_app_template && RNA_property_is_set(op->ptr, prop_app_template)) {
RNA_property_string_get(op->ptr, prop_app_template, app_template_buf);
app_template = app_template_buf;
- }
- else if (!use_factory_settings) {
- /* TODO: dont reset prefs on 'New File' */
- BLI_strncpy(app_template_buf, U.app_template, sizeof(app_template_buf));
- app_template = app_template_buf;
+
+ /* Always load preferences when switching templates. */
+ use_userdef = true;
}
else {
app_template = NULL;
}
- if (wm_homefile_read(C, op->reports, use_factory_settings, use_empty_data, filepath, app_template)) {
+ if (wm_homefile_read(C, op->reports, use_factory_settings, use_empty_data, use_userdef, filepath, app_template)) {
if (use_splash) {
WM_init_splash(C);
}
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 46203333eb5..e04571fe572 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -137,7 +137,7 @@ int wm_gesture_evaluate(wmGesture *gesture)
int dx = BLI_rcti_size_x(rect);
int dy = BLI_rcti_size_y(rect);
if (abs(dx) + abs(dy) > U.tweak_threshold) {
- int theta = iroundf(4.0f * atan2f((float)dy, (float)dx) / (float)M_PI);
+ int theta = round_fl_to_int(4.0f * atan2f((float)dy, (float)dx) / (float)M_PI);
int val = EVT_GESTURE_W;
if (theta == 0) val = EVT_GESTURE_E;
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 00a9976e8be..e73ec2b081a 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -184,15 +184,12 @@ void WM_init(bContext *C, int argc, const char **argv)
BLF_init(); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */
BLT_lang_init();
- /* Enforce loading the UI for the initial homefile */
- G.fileflags &= ~G_FILE_NO_UI;
-
/* reports cant be initialized before the wm,
* but keep before file reading, since that may report errors */
wm_init_reports(C);
/* get the default database, plus a wm */
- wm_homefile_read(C, NULL, G.factory_startup, false, NULL, NULL);
+ wm_homefile_read(C, NULL, G.factory_startup, false, true, NULL, NULL);
BLT_lang_set(NULL);
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index d3ebd3e4d2c..51c551cd9a5 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -177,7 +177,7 @@ void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
/* XXX All ops should have a description but for now allow them not to. */
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP);
- RNA_def_struct_identifier(ot->srna, ot->idname);
+ RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
}
@@ -193,7 +193,7 @@ void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *
ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT;
opfunc(ot, userdata);
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP);
- RNA_def_struct_identifier(ot->srna, ot->idname);
+ RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
}
@@ -398,7 +398,7 @@ wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *nam
ot->description = UNDOCUMENTED_OPERATOR_TIP;
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description);
- RNA_def_struct_identifier(ot->srna, ot->idname);
+ RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
/* Use i18n context from ext.srna if possible (py operators). */
i18n_context = ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) : BLT_I18NCONTEXT_OPERATOR_DEFAULT;
RNA_def_struct_translation_context(ot->srna, i18n_context);
@@ -432,7 +432,7 @@ void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType *, void *),
opfunc(ot, userdata);
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description);
- RNA_def_struct_identifier(ot->srna, ot->idname);
+ RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
}
@@ -573,6 +573,46 @@ void WM_operator_bl_idname(char *to, const char *from)
}
/**
+ * Sanity check to ensure #WM_operator_bl_idname won't fail.
+ * \returns true when there are no problems with \a idname, otherwise report an error.
+ */
+bool WM_operator_py_idname_ok_or_report(ReportList *reports, const char *classname, const char *idname)
+{
+ const char *ch = idname;
+ int dot = 0;
+ int i;
+ for (i = 0; *ch; i++, ch++) {
+ if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
+ /* pass */
+ }
+ else if (*ch == '.') {
+ dot++;
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR,
+ "Registering operator class: '%s', invalid bl_idname '%s', at position %d",
+ classname, idname, i);
+ return false;
+ }
+ }
+
+ if (i > (MAX_NAME - 3)) {
+ BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s', invalid bl_idname '%s', "
+ "is too long, maximum length is %d", classname, idname,
+ MAX_NAME - 3);
+ return false;
+ }
+
+ if (dot != 1) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character",
+ classname, idname);
+ return false;
+ }
+ return true;
+}
+
+/**
* Print a string representation of the operator, with the args that it runs so python can run it again.
*
* When calling from an existing wmOperator, better to use simple version:
@@ -806,9 +846,19 @@ static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, Propert
} \
} (void)0
+#define CTX_TEST_SPACE_TYPE(space_data_type, member_full, dataptr_cmp) \
+ { \
+ const char *ctx_member_full = member_full; \
+ if (space_data->spacetype == space_data_type && ptr->data == dataptr_cmp) { \
+ member_id = ctx_member_full; \
+ break; \
+ } \
+ } (void)0
+
switch (GS(((ID *)ptr->id.data)->name)) {
case ID_SCE:
{
+ CTX_TEST_PTR_DATA_TYPE(C, "active_gpencil_brush", RNA_GPencilBrush, ptr, CTX_data_active_gpencil_brush(C));
CTX_TEST_PTR_ID(C, "scene", ptr->id.data);
break;
}
@@ -843,12 +893,22 @@ static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, Propert
{
CTX_TEST_PTR_ID(C, "screen", ptr->id.data);
- CTX_TEST_PTR_DATA_TYPE(C, "space_data", RNA_Space, ptr, CTX_wm_space_data(C));
+ SpaceLink *space_data = CTX_wm_space_data(C);
+
+ CTX_TEST_PTR_DATA_TYPE(C, "space_data", RNA_Space, ptr, space_data);
CTX_TEST_PTR_DATA_TYPE(C, "area", RNA_Area, ptr, CTX_wm_area(C));
CTX_TEST_PTR_DATA_TYPE(C, "region", RNA_Region, ptr, CTX_wm_region(C));
+ CTX_TEST_SPACE_TYPE(SPACE_IMAGE, "space_data.uv_editor", space_data);
+ CTX_TEST_SPACE_TYPE(SPACE_VIEW3D, "space_data.fx_settings", &(CTX_wm_view3d(C)->fx_settings));
+ CTX_TEST_SPACE_TYPE(SPACE_NLA, "space_data.dopesheet", CTX_wm_space_nla(C)->ads);
+ CTX_TEST_SPACE_TYPE(SPACE_IPO, "space_data.dopesheet", CTX_wm_space_graph(C)->ads);
+ CTX_TEST_SPACE_TYPE(SPACE_ACTION, "space_data.dopesheet", &(CTX_wm_space_action(C)->ads));
+ CTX_TEST_SPACE_TYPE(SPACE_FILE, "space_data.params", CTX_wm_space_file(C)->params);
break;
}
+ default:
+ break;
}
if (member_id) {
@@ -860,6 +920,7 @@ static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, Propert
}
#undef CTX_TEST_PTR_ID
#undef CTX_TEST_PTR_ID_CAST
+#undef CTX_TEST_SPACE_TYPE
}
return ret;
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 8afeb8e7b3d..9fe215f7712 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -377,7 +377,12 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
void WM_window_set_dpi(wmWindow *win)
{
- int auto_dpi = GHOST_GetDPIHint(win->ghostwin);
+ float auto_dpi = GHOST_GetDPIHint(win->ghostwin);
+
+ /* Clamp auto DPI to 96, since our font/interface drawing does not work well
+ * with lower sizes. The main case we are interested in supporting is higher
+ * DPI. If a smaller UI is desired it is still possible to adjust UI scale. */
+ auto_dpi = max_ff(auto_dpi, 96.0f);
/* Lazily init UI scale size, preserving backwards compatibility by
* computing UI scale from ratio of previous DPI and auto DPI */
@@ -397,13 +402,16 @@ void WM_window_set_dpi(wmWindow *win)
/* Blender's UI drawing assumes DPI 72 as a good default following macOS
* while Windows and Linux use DPI 96. GHOST assumes a default 96 so we
* remap the DPI to Blender's convention. */
+ auto_dpi *= GHOST_GetNativePixelSize(win->ghostwin);
int dpi = auto_dpi * U.ui_scale * (72.0 / 96.0f);
/* Automatically set larger pixel size for high DPI. */
- int pixelsize = MAX2(1, dpi / 54);
+ int pixelsize = max_ii(1, (int)(dpi / 64));
+ /* User adjustment for pixel size. */
+ pixelsize = max_ii(1, pixelsize + U.ui_line_width);
/* Set user preferences globals for drawing, and for forward compatibility. */
- U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin) * pixelsize;
+ U.pixelsize = pixelsize;
U.dpi = dpi / pixelsize;
U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE;
U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72;