macOS: Tighten up window icon and represented filename handling
Window icons on macOS are tied to document windows, and should not show up unless a represented filename has also been set according to the HIG. We follow this, and no longer create a document button based on the window title if one did no exists. We also fall back to using the filename of the file if a title has not been set, including being able to restore this default title after setting a custom title. The icon is no longer reset to nil after setting a QIcon(), which would remove the icon completely, but instead we restore the default behavior of showing the default filetype icon of the file. Finally, the two callbacks in QNSWindowDelegate dealing with the document icon/title popups and drags have been taught to look for spaces in the represented filename. This allows clients who really want the old behavior of setting an icon without caring about the filename to set the filename to a single space character, which will prevent the dropdowna and drag from occurring. The reason for not tying this behavior to the existence of the file in the filesystem is that being able to represent a file that is yet to be saved is a valid usecase. Task-number: QTBUG-63338 Change-Id: I7d4377c6358226fb6058f8c2b3c28588eec77ce5 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
parent
d892292409
commit
bccbb52b7a
@ -971,6 +971,11 @@ QString QWindow::filePath() const
|
||||
|
||||
The window icon might be used by the windowing system for example to
|
||||
decorate the window, and/or in the task switcher.
|
||||
|
||||
\note On \macos, the window title bar icon is meant for windows representing
|
||||
documents, and will only show up if a file path is also set.
|
||||
|
||||
\sa setFilePath()
|
||||
*/
|
||||
void QWindow::setIcon(const QIcon &icon)
|
||||
{
|
||||
@ -983,7 +988,7 @@ void QWindow::setIcon(const QIcon &icon)
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Sets the window's icon in the windowing system
|
||||
\brief Returns the window's icon in the windowing system
|
||||
|
||||
\sa setIcon()
|
||||
*/
|
||||
|
@ -285,8 +285,6 @@ public: // for QNSView
|
||||
};
|
||||
QHash<quintptr, BorderRange> m_contentBorderAreas; // identifer -> uppper/lower
|
||||
QHash<quintptr, bool> m_enabledContentBorderAreas; // identifer -> enabled state (true/false)
|
||||
|
||||
bool m_hasWindowFilePath;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
@ -157,7 +157,6 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
|
||||
, m_drawContentBorderGradient(false)
|
||||
, m_topContentBorderThickness(0)
|
||||
, m_bottomContentBorderThickness(0)
|
||||
, m_hasWindowFilePath(false)
|
||||
{
|
||||
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::QCocoaWindow" << window();
|
||||
|
||||
@ -594,6 +593,11 @@ void QCocoaWindow::setWindowTitle(const QString &title)
|
||||
|
||||
QMacAutoReleasePool pool;
|
||||
m_view.window.title = title.toNSString();
|
||||
|
||||
if (title.isEmpty() && !window()->filePath().isEmpty()) {
|
||||
// Clearing the title should restore the default filename
|
||||
setWindowFilePath(window()->filePath());
|
||||
}
|
||||
}
|
||||
|
||||
void QCocoaWindow::setWindowFilePath(const QString &filePath)
|
||||
@ -602,9 +606,14 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath)
|
||||
return;
|
||||
|
||||
QMacAutoReleasePool pool;
|
||||
QFileInfo fi(filePath);
|
||||
[m_view.window setRepresentedFilename:fi.exists() ? filePath.toNSString() : @""];
|
||||
m_hasWindowFilePath = fi.exists();
|
||||
|
||||
if (window()->title().isNull())
|
||||
[m_view.window setTitleWithRepresentedFilename:filePath.toNSString()];
|
||||
else
|
||||
m_view.window.representedFilename = filePath.toNSString();
|
||||
|
||||
// Changing the file path may affect icon visibility
|
||||
setWindowIcon(window()->icon());
|
||||
}
|
||||
|
||||
void QCocoaWindow::setWindowIcon(const QIcon &icon)
|
||||
@ -612,23 +621,21 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon)
|
||||
if (!isContentView())
|
||||
return;
|
||||
|
||||
NSButton *iconButton = [m_view.window standardWindowButton:NSWindowDocumentIconButton];
|
||||
if (!iconButton) {
|
||||
// Window icons are only supported on macOS in combination with a document filePath
|
||||
return;
|
||||
}
|
||||
|
||||
QMacAutoReleasePool pool;
|
||||
|
||||
NSButton *iconButton = [m_view.window standardWindowButton:NSWindowDocumentIconButton];
|
||||
if (iconButton == nil) {
|
||||
if (icon.isNull())
|
||||
return;
|
||||
NSString *title = window()->title().toNSString();
|
||||
[m_view.window setRepresentedURL:[NSURL fileURLWithPath:title]];
|
||||
iconButton = [m_view.window standardWindowButton:NSWindowDocumentIconButton];
|
||||
}
|
||||
if (icon.isNull()) {
|
||||
[iconButton setImage:nil];
|
||||
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
|
||||
[iconButton setImage:[workspace iconForFile:m_view.window.representedFilename]];
|
||||
} else {
|
||||
QPixmap pixmap = icon.pixmap(QSize(22, 22));
|
||||
NSImage *image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
|
||||
[iconButton setImage:image];
|
||||
[image release];
|
||||
[iconButton setImage:[image autorelease]];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include <qpa/qplatformscreen.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
static QRegExp whitespaceRegex = QRegExp(QStringLiteral("\\s*"));
|
||||
|
||||
@implementation QNSWindowDelegate
|
||||
|
||||
- (id)initWithQCocoaWindow:(QCocoaWindow *)cocoaWindow
|
||||
@ -98,7 +100,10 @@
|
||||
{
|
||||
Q_UNUSED(window);
|
||||
Q_UNUSED(menu);
|
||||
return m_cocoaWindow && m_cocoaWindow->m_hasWindowFilePath;
|
||||
|
||||
// Only pop up document path if the filename is non-empty. We allow whitespace, to
|
||||
// allow faking a window icon by setting the file path to a single space character.
|
||||
return !whitespaceRegex.exactMatch(m_cocoaWindow->window()->filePath());
|
||||
}
|
||||
|
||||
- (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard
|
||||
@ -107,6 +112,9 @@
|
||||
Q_UNUSED(event);
|
||||
Q_UNUSED(dragImageLocation);
|
||||
Q_UNUSED(pasteboard);
|
||||
return m_cocoaWindow && m_cocoaWindow->m_hasWindowFilePath;
|
||||
|
||||
// Only allow drag if the filename is non-empty. We allow whitespace, to
|
||||
// allow faking a window icon by setting the file path to a single space.
|
||||
return !whitespaceRegex.exactMatch(m_cocoaWindow->window()->filePath());
|
||||
}
|
||||
@end
|
||||
|
Loading…
Reference in New Issue
Block a user