From d6b2b5d0c5b414dff6da052e1ef0416b40b4992c Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 3 Oct 2023 17:03:55 -0300 Subject: [PATCH] Fix #112978: MacOS no longer has a path associated with the window The problem was introduced in 636f3697ee MacOS has a different way of handling the title. In this OS the directory is searched and taken from the title string which is then formatted. This limits the title format and makes it prone to errors. This commit makes the code more generic by splitting each component of the title beforehand and allowing the associated directory to be informed with `GHOST_SetTitle`. --- intern/ghost/GHOST_C-api.h | 7 +++ intern/ghost/GHOST_IWindow.hh | 6 ++ intern/ghost/intern/GHOST_C-api.cc | 7 +++ intern/ghost/intern/GHOST_Window.hh | 5 ++ intern/ghost/intern/GHOST_WindowCocoa.hh | 6 ++ intern/ghost/intern/GHOST_WindowCocoa.mm | 58 ++++++++----------- intern/ghost/intern/GHOST_WindowNULL.hh | 4 ++ .../blender/windowmanager/intern/wm_window.cc | 48 ++++++++------- 8 files changed, 87 insertions(+), 54 deletions(-) diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 5bfa96d4cb0..63fadd3e728 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -588,6 +588,13 @@ extern void GHOST_SetTitle(GHOST_WindowHandle windowhandle, const char *title); */ extern char *GHOST_GetTitle(GHOST_WindowHandle windowhandle); +/** + * Sets the file name represented by this window. + * \param filepath: The file directory. + * \return Indication if the backend implements file associated with window. + */ +extern GHOST_TSuccess GHOST_SetPath(GHOST_WindowHandle windowhandle, const char *filepath); + /** * Returns the window rectangle dimensions. * These are screen coordinates. diff --git a/intern/ghost/GHOST_IWindow.hh b/intern/ghost/GHOST_IWindow.hh index a88b1be1a2b..3899324ff15 100644 --- a/intern/ghost/GHOST_IWindow.hh +++ b/intern/ghost/GHOST_IWindow.hh @@ -81,6 +81,12 @@ class GHOST_IWindow { */ virtual std::string getTitle() const = 0; + /** + * Sets the file name represented by this window. + * \param filepath: The file directory. + */ + virtual GHOST_TSuccess setPath(const char *filepath) = 0; + /** * Returns the window rectangle dimensions. * These are screen coordinates. diff --git a/intern/ghost/intern/GHOST_C-api.cc b/intern/ghost/intern/GHOST_C-api.cc index 5dcc9bbe9db..a9d9281e673 100644 --- a/intern/ghost/intern/GHOST_C-api.cc +++ b/intern/ghost/intern/GHOST_C-api.cc @@ -600,6 +600,13 @@ char *GHOST_GetTitle(GHOST_WindowHandle windowhandle) return ctitle; } +GHOST_TSuccess GHOST_SetPath(GHOST_WindowHandle windowhandle, const char *filepath) +{ + GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; + + return window->setPath(filepath); +} + GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle) { const GHOST_IWindow *window = (const GHOST_IWindow *)windowhandle; diff --git a/intern/ghost/intern/GHOST_Window.hh b/intern/ghost/intern/GHOST_Window.hh index c059418b508..bccfe43814d 100644 --- a/intern/ghost/intern/GHOST_Window.hh +++ b/intern/ghost/intern/GHOST_Window.hh @@ -84,6 +84,11 @@ class GHOST_Window : public GHOST_IWindow { */ virtual void *getOSWindow() const override; + virtual GHOST_TSuccess setPath(const char * /*filepath*/) override + { + return GHOST_kFailure; + } + /** * Returns the current cursor shape. * \return The current cursor shape. diff --git a/intern/ghost/intern/GHOST_WindowCocoa.hh b/intern/ghost/intern/GHOST_WindowCocoa.hh index 4d4389c3448..e773681812a 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.hh +++ b/intern/ghost/intern/GHOST_WindowCocoa.hh @@ -85,6 +85,12 @@ class GHOST_WindowCocoa : public GHOST_Window { */ std::string getTitle() const; + /** + * Sets the file name represented by this window. + * \param filepath: The file directory. + */ + GHOST_TSuccess setPath(const char *filepath); + /** * Returns the window rectangle dimensions. * The dimensions are given in screen coordinates that are diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 29df49961bc..e6ef790de20 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -494,39 +494,7 @@ void GHOST_WindowCocoa::setTitle(const char *title) NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *windowTitle = [[NSString alloc] initWithCString:title encoding:NSUTF8StringEncoding]; - - // Set associated file if applicable - if (windowTitle && [windowTitle hasPrefix:@"Blender"]) { - NSRange fileStrRange; - NSString *associatedFileName; - int len; - - fileStrRange.location = [windowTitle rangeOfString:@"["].location + 1; - len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location; - - if (len > 0) { - fileStrRange.length = len; - associatedFileName = [windowTitle substringWithRange:fileStrRange]; - [m_window setTitle:[associatedFileName lastPathComponent]]; - - @try - { - [m_window setRepresentedFilename:associatedFileName]; - } - @catch (NSException *e) - { - printf("\nInvalid file path given in window title"); - } - } - else { - [m_window setTitle:windowTitle]; - [m_window setRepresentedFilename:@""]; - } - } - else { - [m_window setTitle:windowTitle]; - [m_window setRepresentedFilename:@""]; - } + [m_window setTitle:windowTitle]; [windowTitle release]; [pool drain]; @@ -550,6 +518,30 @@ std::string GHOST_WindowCocoa::getTitle() const return title; } +GHOST_TSuccess GHOST_WindowCocoa::setPath(const char *filepath) +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setAssociatedFile(): window invalid"); + GHOST_TSuccess success = GHOST_kSuccess; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSString *associatedFileName = [[NSString alloc] initWithCString:filepath encoding:NSUTF8StringEncoding]; + + @try + { + [m_window setRepresentedFilename:associatedFileName]; + } + @catch (NSException *e) + { + printf("\nInvalid file path given for window"); + success = GHOST_kFailure; + } + + [associatedFileName release]; + [pool drain]; + + return success; +} + void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect &bounds) const { NSRect rect; diff --git a/intern/ghost/intern/GHOST_WindowNULL.hh b/intern/ghost/intern/GHOST_WindowNULL.hh index 1340cc4965d..7e302b1ee88 100644 --- a/intern/ghost/intern/GHOST_WindowNULL.hh +++ b/intern/ghost/intern/GHOST_WindowNULL.hh @@ -75,6 +75,10 @@ class GHOST_WindowNULL : public GHOST_Window { { return "untitled"; } + GHOST_TSuccess setPath(const char * /*filepath*/) override + { + return GHOST_kFailure; + } void getWindowBounds(GHOST_Rect &bounds) const override { getClientBounds(bounds); diff --git a/source/blender/windowmanager/intern/wm_window.cc b/source/blender/windowmanager/intern/wm_window.cc index e7b58a6e4f2..9d0ccf4a635 100644 --- a/source/blender/windowmanager/intern/wm_window.cc +++ b/source/blender/windowmanager/intern/wm_window.cc @@ -485,28 +485,34 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) * because #WM_window_open always sets window title. */ } else if (win->ghostwin) { - char str[sizeof(Main::filepath) + 24]; - const char *filepath = BKE_main_blendfile_path_from_global(); - const char *filename = BLI_path_basename(filepath); - const bool has_filepath = filepath[0] != '\0'; - const bool has_directory = has_filepath && (filepath != filename); - SNPRINTF(str, - "%s %s%s%s%.*s%s - Blender %s", - wm->file_saved ? "" : "*", - has_filepath ? filename : IFACE_("(Unsaved)"), - G_MAIN->recovered ? IFACE_(" (Recovered)") : "", - has_directory ? " [" : "", - has_directory ? int(filename - filepath) : 0, - has_directory ? filepath : "", - has_directory ? "]" : "", - BKE_blender_version_string_compact()); - GHOST_SetTitle(static_cast(win->ghostwin), str); + GHOST_WindowHandle handle = static_cast(win->ghostwin); - /* Informs GHOST of unsaved changes, to set window modified visual indicator (macOS) - * and to give hint of unsaved changes for a user warning mechanism in case of OS application - * terminate request (e.g. OS Shortcut Alt+F4, Command+Q, (...), or session end). */ - GHOST_SetWindowModifiedState(static_cast(win->ghostwin), - bool(!wm->file_saved)); + std::string filepath = BKE_main_blendfile_path_from_global(); + std::string filename = BLI_path_basename(filepath.c_str()); + bool has_filepath = !filepath.empty(); + bool include_directory = has_filepath && (filepath != filename) && + GHOST_SetPath(handle, filepath.c_str()) == GHOST_kFailure; + + std::string str; + str += wm->file_saved ? " " : "* "; + str += has_filepath ? filename : IFACE_("(Unsaved)"); + if (G_MAIN->recovered) { + str += IFACE_(" (Recovered)"); + } + + if (include_directory) { + str += " [" + filepath.substr(0, filepath.length() - filename.length()) + "]"; + } + + str += " - Blender "; + str += BKE_blender_version_string_compact(); + + GHOST_SetTitle(handle, str.c_str()); + + /* Informs GHOST of unsaved changes to set the window modified visual indicator (macOS) + * and to give a hint of unsaved changes for a user warning mechanism in case of OS application + * terminate request (e.g., OS Shortcut Alt+F4, Command+Q, (...) or session end). */ + GHOST_SetWindowModifiedState(handle, static_cast(!wm->file_saved)); } }