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`.
This commit is contained in:
Germano Cavalcante 2023-10-03 17:03:55 -03:00
parent 2f71d9f807
commit d6b2b5d0c5
8 changed files with 87 additions and 54 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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<GHOST_WindowHandle>(win->ghostwin), str);
GHOST_WindowHandle handle = static_cast<GHOST_WindowHandle>(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<GHOST_WindowHandle>(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<bool>(!wm->file_saved));
}
}