diff options
| author | Mikolaj Boc <mikolaj.boc@qt.io> | 2022-08-12 11:13:45 +0200 |
|---|---|---|
| committer | Mikolaj Boc <mikolaj.boc@qt.io> | 2022-08-25 16:53:47 +0200 |
| commit | 6cd0dc213b784ce21997d2691a54f37313e439c8 (patch) | |
| tree | 96098a4e3464df951d348249741637a46fe6e163 /src/plugins/platforms/wasm/qwasmwindow.cpp | |
| parent | 713f1c633a0560664705268e43307d5dba9fad42 (diff) | |
Move titlebar drawing routines to QWasmWindow
The title bar drawing routines belong in QWasmWindow, not in the
compositor. This provides better encapsulation as many properties
don't have to be leaked from QWasmWindow. Extensibility will also
improve.
Change-Id: If73dd4e87602f62bff0de92e1405f89e7a9f3b43
Pick-to: 6.4
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Diffstat (limited to 'src/plugins/platforms/wasm/qwasmwindow.cpp')
| -rw-r--r-- | src/plugins/platforms/wasm/qwasmwindow.cpp | 293 |
1 files changed, 246 insertions, 47 deletions
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp index 4fc9af4b5ce..54c174e9742 100644 --- a/src/plugins/platforms/wasm/qwasmwindow.cpp +++ b/src/plugins/platforms/wasm/qwasmwindow.cpp @@ -6,9 +6,11 @@ #include <QtGui/private/qopenglcontext_p.h> #include <QtGui/private/qwindow_p.h> #include <QtGui/qopenglcontext.h> +#include <private/qpixmapcache_p.h> #include "qwasmwindow.h" #include "qwasmscreen.h" +#include "qwasmstylepixmaps_p.h" #include "qwasmcompositor.h" #include "qwasmeventdispatcher.h" @@ -19,6 +21,61 @@ QT_BEGIN_NAMESPACE Q_GUI_EXPORT int qt_defaultDpiX(); +namespace { +// from commonstyle.cpp +static QPixmap cachedPixmapFromXPM(const char *const *xpm) +{ + QPixmap result; + const QString tag = QString::asprintf("xpm:0x%p", static_cast<const void *>(xpm)); + if (!QPixmapCache::find(tag, &result)) { + result = QPixmap(xpm); + QPixmapCache::insert(tag, result); + } + return result; +} + +QPalette makePalette() +{ + QPalette palette; + palette.setColor(QPalette::Active, QPalette::Highlight, + palette.color(QPalette::Active, QPalette::Highlight)); + palette.setColor(QPalette::Active, QPalette::Base, + palette.color(QPalette::Active, QPalette::Highlight)); + palette.setColor(QPalette::Inactive, QPalette::Highlight, + palette.color(QPalette::Inactive, QPalette::Dark)); + palette.setColor(QPalette::Inactive, QPalette::Base, + palette.color(QPalette::Inactive, QPalette::Dark)); + palette.setColor(QPalette::Inactive, QPalette::HighlightedText, + palette.color(QPalette::Inactive, QPalette::Window)); + + return palette; +} + +void drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) +{ + qreal scale = pixmap.devicePixelRatio(); + QSize size = pixmap.size() / scale; + int x = rect.x(); + int y = rect.y(); + int w = size.width(); + int h = size.height(); + if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter) + y += rect.size().height() / 2 - h / 2; + else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom) + y += rect.size().height() - h; + if ((alignment & Qt::AlignRight) == Qt::AlignRight) + x += rect.size().width() - w; + else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter) + x += rect.size().width() / 2 - w / 2; + + QRect aligned = QRect(x, y, w, h); + QRect inter = aligned.intersected(rect); + + painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), + inter.y() - aligned.y(), inter.width() * scale, inter.height() * scale); +} +} + QWasmWindow::QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore) : QPlatformWindow(w), m_window(w), @@ -162,14 +219,16 @@ void QWasmWindow::injectMousePressed(const QPoint &local, const QPoint &global, if (!hasTitleBar() || button != Qt::LeftButton) return; - if (maxButtonRect().contains(global)) - m_activeControl = QWasmCompositor::SC_TitleBarMaxButton; - else if (minButtonRect().contains(global)) - m_activeControl = QWasmCompositor::SC_TitleBarMinButton; - else if (closeButtonRect().contains(global)) - m_activeControl = QWasmCompositor::SC_TitleBarCloseButton; - else if (normButtonRect().contains(global)) - m_activeControl = QWasmCompositor::SC_TitleBarNormalButton; + const auto pointInFrameCoords = global - windowFrameGeometry().topLeft(); + const auto options = makeTitleBarOptions(); + if (getTitleBarControlRect(options, SC_TitleBarMaxButton).contains(pointInFrameCoords)) + m_activeControl = SC_TitleBarMaxButton; + else if (getTitleBarControlRect(options, SC_TitleBarMinButton).contains(pointInFrameCoords)) + m_activeControl = SC_TitleBarMinButton; + else if (getTitleBarControlRect(options, SC_TitleBarCloseButton).contains(pointInFrameCoords)) + m_activeControl = SC_TitleBarCloseButton; + else if (getTitleBarControlRect(options, SC_TitleBarNormalButton).contains(pointInFrameCoords)) + m_activeControl = SC_TitleBarNormalButton; invalidate(); } @@ -183,20 +242,25 @@ void QWasmWindow::injectMouseReleased(const QPoint &local, const QPoint &global, if (!hasTitleBar() || button != Qt::LeftButton) return; - if (closeButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarCloseButton) { + const auto pointInFrameCoords = global - windowFrameGeometry().topLeft(); + const auto options = makeTitleBarOptions(); + if (getTitleBarControlRect(options, SC_TitleBarCloseButton).contains(pointInFrameCoords) + && m_activeControl == SC_TitleBarCloseButton) { window()->close(); return; } - if (maxButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarMaxButton) { + if (getTitleBarControlRect(options, SC_TitleBarMaxButton).contains(pointInFrameCoords) + && m_activeControl == SC_TitleBarMaxButton) { window()->setWindowState(Qt::WindowMaximized); } - if (normButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarNormalButton) { + if (getTitleBarControlRect(options, SC_TitleBarNormalButton).contains(pointInFrameCoords) + && m_activeControl == SC_TitleBarNormalButton) { window()->setWindowState(Qt::WindowNoState); } - m_activeControl = QWasmCompositor::SC_None; + m_activeControl = SC_None; invalidate(); } @@ -265,48 +329,75 @@ Qt::Edges QWasmWindow::resizeEdgesAtPoint(QPoint point) const return edges | (right.contains(point) ? Qt::Edge::RightEdge : Qt::Edge(0)); } -QRect getSubControlRect(const QWasmWindow *window, QWasmCompositor::SubControls subControl) -{ - QWasmCompositor::QWasmTitleBarOptions options = QWasmCompositor::makeTitleBarOptions(window); +QRect QWasmWindow::getTitleBarControlRect(const TitleBarOptions &tb, TitleBarControl control) const +{ + QRect ret; + const int controlMargin = 2; + const int controlHeight = tb.rect.height() - controlMargin * 2; + const int delta = controlHeight + controlMargin; + int offset = 0; + + bool isMinimized = tb.state & Qt::WindowMinimized; + bool isMaximized = tb.state & Qt::WindowMaximized; + + ret = tb.rect; + switch (control) { + case SC_TitleBarLabel: + if (tb.flags & Qt::WindowSystemMenuHint) + ret.adjust(delta, 0, -delta, 0); + break; + case SC_TitleBarCloseButton: + if (tb.flags & Qt::WindowSystemMenuHint) { + ret.adjust(0, 0, -delta, 0); + offset += delta; + } + break; + case SC_TitleBarMaxButton: + if (!isMaximized && tb.flags & Qt::WindowMaximizeButtonHint) { + ret.adjust(0, 0, -delta * 2, 0); + offset += (delta + delta); + } + break; + case SC_TitleBarNormalButton: + if (isMinimized && (tb.flags & Qt::WindowMinimizeButtonHint)) { + offset += delta; + } else if (isMaximized && (tb.flags & Qt::WindowMaximizeButtonHint)) { + ret.adjust(0, 0, -delta * 2, 0); + offset += (delta + delta); + } + break; + case SC_TitleBarSysMenu: + if (tb.flags & Qt::WindowSystemMenuHint) { + ret.setRect(tb.rect.left() + controlMargin, tb.rect.top() + controlMargin, + controlHeight, controlHeight); + } + break; + default: + break; + }; + + if (control != SC_TitleBarLabel && control != SC_TitleBarSysMenu) { + ret.setRect(tb.rect.right() - offset, tb.rect.top() + controlMargin, controlHeight, + controlHeight); + } - QRect r = QWasmCompositor::titlebarRect(options, subControl); - r.translate(window->window()->frameGeometry().x(), window->window()->frameGeometry().y()); + if (qApp->layoutDirection() == Qt::LeftToRight) + return ret; - return r; -} + QRect rect = ret; + rect.translate(2 * (tb.rect.right() - ret.right()) + ret.width() - tb.rect.width(), 0); -QRect QWasmWindow::maxButtonRect() const -{ - return getSubControlRect(this, QWasmCompositor::SC_TitleBarMaxButton); -} - -QRect QWasmWindow::minButtonRect() const -{ - return getSubControlRect(this, QWasmCompositor::SC_TitleBarMinButton); -} - -QRect QWasmWindow::closeButtonRect() const -{ - return getSubControlRect(this, QWasmCompositor::SC_TitleBarCloseButton); -} - -QRect QWasmWindow::normButtonRect() const -{ - return getSubControlRect(this, QWasmCompositor::SC_TitleBarNormalButton); -} - -QRect QWasmWindow::sysMenuRect() const -{ - return getSubControlRect(this, QWasmCompositor::SC_TitleBarSysMenu); + return rect; } QRegion QWasmWindow::titleControlRegion() const { QRegion result; - result += closeButtonRect(); - result += minButtonRect(); - result += maxButtonRect(); - result += sysMenuRect(); + const auto options = makeTitleBarOptions(); + result += getTitleBarControlRect(options, SC_TitleBarCloseButton); + result += getTitleBarControlRect(options, SC_TitleBarMinButton); + result += getTitleBarControlRect(options, SC_TitleBarMaxButton); + result += getTitleBarControlRect(options, SC_TitleBarSysMenu); return result; } @@ -316,7 +407,7 @@ void QWasmWindow::invalidate() m_compositor->requestUpdateWindow(this); } -QWasmCompositor::SubControls QWasmWindow::activeSubControl() const +QWasmWindow::TitleBarControl QWasmWindow::activeTitleBarControl() const { return m_activeControl; } @@ -366,6 +457,114 @@ void QWasmWindow::applyWindowState() setGeometry(newGeom); } +void QWasmWindow::drawTitleBar(QPainter *painter) const +{ + const auto tb = makeTitleBarOptions(); + QRect ir; + if (tb.subControls.testFlag(SC_TitleBarLabel)) { + QColor left = tb.palette.highlight().color(); + QColor right = tb.palette.base().color(); + + QBrush fillBrush(left); + if (left != right) { + QPoint p1(tb.rect.x(), tb.rect.top() + tb.rect.height() / 2); + QPoint p2(tb.rect.right(), tb.rect.top() + tb.rect.height() / 2); + QLinearGradient lg(p1, p2); + lg.setColorAt(0, left); + lg.setColorAt(1, right); + fillBrush = lg; + } + + painter->fillRect(tb.rect, fillBrush); + ir = getTitleBarControlRect(tb, SC_TitleBarLabel); + painter->setPen(tb.palette.highlightedText().color()); + painter->drawText(ir.x() + 2, ir.y(), ir.width() - 2, ir.height(), + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, + tb.titleBarOptionsString); + } // SC_TitleBarLabel + + QPixmap pixmap; + + if (tb.subControls.testFlag(SC_TitleBarCloseButton) && tb.flags & Qt::WindowSystemMenuHint) { + ir = getTitleBarControlRect(tb, SC_TitleBarCloseButton); + pixmap = cachedPixmapFromXPM(qt_close_xpm).scaled(QSize(10, 10)); + drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap); + } // SC_TitleBarCloseButton + + if (tb.subControls.testFlag(SC_TitleBarMaxButton) && tb.flags & Qt::WindowMaximizeButtonHint + && !(tb.state & Qt::WindowMaximized)) { + ir = getTitleBarControlRect(tb, SC_TitleBarMaxButton); + pixmap = cachedPixmapFromXPM(qt_maximize_xpm).scaled(QSize(10, 10)); + drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap); + } // SC_TitleBarMaxButton + + bool drawNormalButton = (tb.subControls & SC_TitleBarNormalButton) + && (((tb.flags & Qt::WindowMinimizeButtonHint) && (tb.flags & Qt::WindowMinimized)) + || ((tb.flags & Qt::WindowMaximizeButtonHint) && (tb.flags & Qt::WindowMaximized))); + + if (drawNormalButton) { + ir = getTitleBarControlRect(tb, SC_TitleBarNormalButton); + pixmap = cachedPixmapFromXPM(qt_normalizeup_xpm).scaled(QSize(10, 10)); + + drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap); + } // SC_TitleBarNormalButton + + if (tb.subControls & SC_TitleBarSysMenu && tb.flags & Qt::WindowSystemMenuHint) { + ir = getTitleBarControlRect(tb, SC_TitleBarSysMenu); + if (!tb.windowIcon.isNull()) { + tb.windowIcon.paint(painter, ir, Qt::AlignCenter); + } else { + pixmap = cachedPixmapFromXPM(qt_menu_xpm).scaled(QSize(10, 10)); + drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap); + } + } +} + +QWasmWindow::TitleBarOptions QWasmWindow::makeTitleBarOptions() const +{ + int width = windowFrameGeometry().width(); + int border = borderWidth(); + + TitleBarOptions titleBarOptions; + + titleBarOptions.rect = QRect(border, border, width - 2 * border, titleHeight()); + titleBarOptions.flags = window()->flags(); + titleBarOptions.state = window()->windowState(); + + bool isMaximized = + titleBarOptions.state & Qt::WindowMaximized; // this gets reset when maximized + + if (titleBarOptions.flags & (Qt::WindowTitleHint)) + titleBarOptions.subControls |= SC_TitleBarLabel; + if (titleBarOptions.flags & Qt::WindowMaximizeButtonHint) { + if (isMaximized) + titleBarOptions.subControls |= SC_TitleBarNormalButton; + else + titleBarOptions.subControls |= SC_TitleBarMaxButton; + } + if (titleBarOptions.flags & Qt::WindowSystemMenuHint) { + titleBarOptions.subControls |= SC_TitleBarCloseButton; + titleBarOptions.subControls |= SC_TitleBarSysMenu; + } + + titleBarOptions.palette = makePalette(); + + if (window()->isActive()) + titleBarOptions.palette.setCurrentColorGroup(QPalette::Active); + else + titleBarOptions.palette.setCurrentColorGroup(QPalette::Inactive); + + if (activeTitleBarControl() != SC_None) + titleBarOptions.subControls = activeTitleBarControl(); + + if (!window()->title().isEmpty()) + titleBarOptions.titleBarOptionsString = window()->title(); + + titleBarOptions.windowIcon = window()->icon(); + + return titleBarOptions; +} + QRect QWasmWindow::normalGeometry() const { return m_normalGeometry; |
