Set unified toolbar height accurately.

Add registerContentBorderArea() to the Cocoa native
interface which allows registering multiple "unified
toolbar" areas for each window.

Use this function in QToolBarLayout::setGeometry()
to register the area for each TopToolBarArea toolbar.

Task-number: QTBUG-36700
Change-Id: I52efcc5662556bb94f25f504be3710d0491f79b9
Reviewed-by: Jake Petroules <jake.petroules@petroules.com>
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
Reviewed-by: Denis Dzyubenko <denis@ddenis.info>
bb10
Morten Johan Sørvig 2014-02-13 14:14:44 +01:00 committed by The Qt Project
parent 2bc7a40048
commit 3b8b47db6a
7 changed files with 121 additions and 12 deletions

View File

@ -136,10 +136,19 @@ private:
// Request a unified title and toolbar look for the window.
static void setContentBorderThickness(QWindow *window, int topThickness, int bottomThickness);
// Request a unified title and toolbar look for the window by registering
// an area. Multiple callers can register areas and the platform plugin
// will extend the "unified" area to cover them.
static void registerContentBorderArea(QWindow *window, quintptr identifer, int upper, int lower);
// Enable the unified title and toolbar area.
static void enableContentBorderArea(QWindow *window, bool enable);
// Sets a NSToolbar instance for the given QWindow. The
// toolbar will be attached to the native NSWindow when
// that is created;
static void setNSToolbar(QWindow *window, void *nsToolbar);
};
QT_END_NAMESPACE

View File

@ -125,6 +125,10 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setEmbeddedInForeignView);
if (resource.toLower() == "setcontentborderthickness")
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setContentBorderThickness);
if (resource.toLower() == "registercontentborderarea")
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::registerContentBorderArea);
if (resource.toLower() == "enablecontentborderarea")
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::enableContentBorderArea);
if (resource.toLower() == "setnstoolbar")
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setNSToolbar);
@ -287,11 +291,28 @@ void QCocoaNativeInterface::setContentBorderThickness(QWindow *window, int topTh
cocoaWindow->setContentBorderThickness(topThickness, bottomThickness);
}
void QCocoaNativeInterface::setNSToolbar(QWindow *window, void *nsToolbar)
void QCocoaNativeInterface::registerContentBorderArea(QWindow *window, quintptr identifier, int upper, int lower)
{
if (!window)
return;
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
if (cocoaWindow)
cocoaWindow->registerContentBorderArea(identifier, upper, lower);
}
void QCocoaNativeInterface::enableContentBorderArea(QWindow *window, bool enable)
{
if (!window)
return;
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
if (cocoaWindow)
cocoaWindow->enableContentBorderArea(enable);
}
void QCocoaNativeInterface::setNSToolbar(QWindow *window, void *nsToolbar)
{
QCocoaIntegration::instance()->setToolbar(window, static_cast<NSToolbar *>(nsToolbar));
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());

View File

@ -208,6 +208,8 @@ public:
void registerTouch(bool enable);
void setContentBorderThickness(int topThickness, int bottomThickness);
void registerContentBorderArea(quintptr identifier, int upper, int lower);
void enableContentBorderArea(bool enable);
void applyContentBorderThickness(NSWindow *window);
void updateNSToolbar();
@ -282,6 +284,16 @@ public: // for QNSView
QRect m_normalGeometry;
Qt::WindowFlags m_oldWindowFlags;
NSApplicationPresentationOptions m_presentationOptions;
struct BorderRange {
BorderRange(int u, int l) : upper(u), lower(l) { }
int upper;
int lower;
bool operator<(BorderRange const& right) const {
return upper < right.upper;
}
};
QHash<quintptr, BorderRange> m_contentBorderAreas; // identifer -> uppper/lower
};
QT_END_NAMESPACE

View File

@ -1540,15 +1540,46 @@ void QCocoaWindow::setContentBorderThickness(int topThickness, int bottomThickne
applyContentBorderThickness(m_nsWindow);
}
void QCocoaWindow::registerContentBorderArea(quintptr identifier, int upper, int lower)
{
m_contentBorderAreas.insert(identifier, BorderRange(upper, lower));
// Find consecutive registered border areas, starting from the top.
QList<BorderRange> ranges = m_contentBorderAreas.values();
std::sort(ranges.begin(), ranges.end());
m_topContentBorderThickness = 0;
foreach (BorderRange range, ranges) {
// Is this sub-range adjacent to or overlaping the
// existing total border area range? If so merge
// it into the total range,
if (range.upper <= (m_topContentBorderThickness + 1))
m_topContentBorderThickness = qMax(m_topContentBorderThickness, range.lower);
else
break;
}
m_bottomContentBorderThickness = 0; // (not supported)
if (m_drawContentBorderGradient)
applyContentBorderThickness(m_nsWindow);
}
void QCocoaWindow::enableContentBorderArea(bool enable)
{
m_drawContentBorderGradient = enable;
applyContentBorderThickness(m_nsWindow);
}
void QCocoaWindow::applyContentBorderThickness(NSWindow *window)
{
if (!window)
return;
if (m_drawContentBorderGradient)
[window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask];
else
if (!m_drawContentBorderGradient) {
[window setStyleMask:[window styleMask] & ~NSTexturedBackgroundWindowMask];
return;
}
[window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask];
if (m_topContentBorderThickness > 0) {
[window setContentBorderThickness:m_topContentBorderThickness forEdge:NSMaxYEdge];

View File

@ -1508,19 +1508,17 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set)
#ifdef Q_OS_OSX
Q_D(QMainWindow);
if (isWindow()) {
d->useUnifiedToolBar = set;
createWinId();
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
QPlatformNativeInterface::NativeResourceForIntegrationFunction function =
nativeInterface->nativeResourceFunctionForIntegration("setContentBorderThickness");
nativeInterface->nativeResourceFunctionForIntegration("enableContentBorderArea");
if (!function)
return; // Not Cocoa platform plugin.
createWinId();
d->useUnifiedToolBar = set;
const int toolBarHeight = 50;
typedef void (*SetContentBorderThicknessFunction)(QWindow *window, int topThickness, int bottomThickness);
(reinterpret_cast<SetContentBorderThicknessFunction>(function))(window()->windowHandle(), toolBarHeight, 0);
typedef void (*EnableContentBorderAreaFunction)(QWindow *window, bool enable);
(reinterpret_cast<EnableContentBorderAreaFunction>(function))(window()->windowHandle(), set);
}
#endif

View File

@ -39,6 +39,7 @@
**
****************************************************************************/
#include <qapplication.h>
#include <qaction.h>
#include <qwidgetaction.h>
#include <qtoolbar.h>
@ -47,6 +48,9 @@
#include <qmenu.h>
#include <qdebug.h>
#include <qmath.h>
#ifdef Q_OS_OSX
#include <qpa/qplatformnativeinterface.h>
#endif
#include "qmainwindowlayout_p.h"
#include "qtoolbarextension_p.h"
@ -341,6 +345,37 @@ static bool defaultWidgetAction(QToolBarItem *item)
return a != 0 && a->defaultWidget() == item->widget();
}
void QToolBarLayout::updateMacBorderMetrics()
{
#ifdef Q_OS_OSX
QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
if (!tb)
return;
QRect rect = geometry();
QMainWindow *mainWindow = qobject_cast<QMainWindow*>(tb->parentWidget());
if (!mainWindow || !mainWindow->isWindow() || !mainWindow->unifiedTitleAndToolBarOnMac())
return;
QPlatformNativeInterface *nativeInterface = QApplication::platformNativeInterface();
QPlatformNativeInterface::NativeResourceForIntegrationFunction function =
nativeInterface->nativeResourceFunctionForIntegration("registerContentBorderArea");
if (!function)
return; // Not Cocoa platform plugin.
QPoint upper = tb->mapToParent(rect.topLeft());
QPoint lower = tb->mapToParent(rect.bottomLeft() + QPoint(0, 1));
typedef void (*RegisterContentBorderAreaFunction)(QWindow *window, void *identifier, int upper, int lower);
if (mainWindow->toolBarArea(tb) == Qt::TopToolBarArea) {
(reinterpret_cast<RegisterContentBorderAreaFunction>(function))(tb->window()->windowHandle(), this, upper.y(), lower.y());
} else {
(reinterpret_cast<RegisterContentBorderAreaFunction>(function))(tb->window()->windowHandle(), this, 0, 0);
}
#endif
}
void QToolBarLayout::setGeometry(const QRect &rect)
{
QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
@ -355,6 +390,8 @@ void QToolBarLayout::setGeometry(const QRect &rect)
QLayout::setGeometry(rect);
updateMacBorderMetrics();
bool ranOutOfSpace = false;
if (!animating)
ranOutOfSpace = layoutActions(rect.size());

View File

@ -111,6 +111,7 @@ public:
void updateMarginAndSpacing();
bool hasExpandFlag() const;
void updateMacBorderMetrics();
public Q_SLOTS:
void setExpanded(bool b);