Advance Wayland and KDE package bring-up
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
add_definitions(-DTRANSLATION_DOMAIN=\"kdecoration\")
|
||||
|
||||
add_subdirectory(private)
|
||||
|
||||
set(libkdecoration3_SRCS
|
||||
decoratedwindow.cpp
|
||||
decoratedwindow.h
|
||||
decoration.cpp
|
||||
decoration.h
|
||||
decoration_p.h
|
||||
decorationbutton.cpp
|
||||
decorationbutton.h
|
||||
decorationbutton_p.h
|
||||
decorationbuttongroup.cpp
|
||||
decorationbuttongroup.h
|
||||
decorationbuttongroup_p.h
|
||||
decorationdefines.h
|
||||
decorationsettings.cpp
|
||||
decorationsettings.h
|
||||
decorationshadow.cpp
|
||||
decorationshadow.h
|
||||
decorationshadow_p.h
|
||||
decorationthemeprovider.cpp
|
||||
decorationthemeprovider.h
|
||||
|
||||
)
|
||||
|
||||
add_library(kdecorations3 SHARED ${libkdecoration3_SRCS})
|
||||
ecm_generate_export_header(kdecorations3
|
||||
VERSION ${PROJECT_VERSION}
|
||||
EXPORT_FILE_NAME kdecoration3/kdecoration3_export.h
|
||||
DEPRECATION_VERSIONS 5.21
|
||||
EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT}
|
||||
)
|
||||
|
||||
add_library(KDecoration3::KDecoration ALIAS kdecorations3)
|
||||
|
||||
target_link_libraries(kdecorations3
|
||||
PUBLIC
|
||||
Qt::Core
|
||||
Qt::Gui
|
||||
PRIVATE
|
||||
kdecorations3private
|
||||
KF6::I18n
|
||||
)
|
||||
|
||||
target_include_directories(kdecorations3 INTERFACE "$<INSTALL_INTERFACE:${KDECORATION3_INCLUDEDIR}>" )
|
||||
|
||||
set_target_properties(kdecorations3 PROPERTIES VERSION ${KDECORATION3_VERSION}
|
||||
SOVERSION ${KDECORATION3_SOVERSION}
|
||||
EXPORT_NAME KDecoration
|
||||
)
|
||||
|
||||
ecm_generate_headers(KDecoration3_CamelCase_HEADERS
|
||||
HEADER_NAMES
|
||||
DecoratedWindow
|
||||
Decoration
|
||||
DecorationButton
|
||||
DecorationButtonGroup
|
||||
DecorationSettings
|
||||
DecorationShadow
|
||||
DecorationThemeProvider
|
||||
ScaleHelpers
|
||||
PREFIX
|
||||
KDecoration3
|
||||
REQUIRED_HEADERS KDecoration3_HEADERS
|
||||
)
|
||||
install(FILES ${KDecoration3_CamelCase_HEADERS}
|
||||
DESTINATION ${KDECORATION3_INCLUDEDIR}/KDecoration3
|
||||
COMPONENT Devel)
|
||||
|
||||
install(TARGETS kdecorations3 EXPORT KDecoration3Targets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/kdecoration3/kdecoration3_export.h
|
||||
${KDecoration3_HEADERS}
|
||||
decorationdefines.h
|
||||
DESTINATION
|
||||
${KDECORATION3_INCLUDEDIR}/kdecoration3
|
||||
COMPONENT
|
||||
Devel
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
#! /usr/bin/env bash
|
||||
$XGETTEXT *.cpp -o $podir/kdecoration.pot
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "decoratedwindow.h"
|
||||
#include "private/decoratedwindowprivate.h"
|
||||
#include "private/decorationbridge.h"
|
||||
#include "scalehelpers.h"
|
||||
|
||||
#include <QColor>
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
DecoratedWindow::DecoratedWindow(Decoration *parent, DecorationBridge *bridge)
|
||||
: QObject()
|
||||
, d(bridge->createClient(this, parent))
|
||||
{
|
||||
}
|
||||
|
||||
DecoratedWindow::~DecoratedWindow() = default;
|
||||
|
||||
bool DecoratedWindow::isActive() const
|
||||
{
|
||||
return d->isActive();
|
||||
}
|
||||
|
||||
QString DecoratedWindow::caption() const
|
||||
{
|
||||
return d->caption();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isOnAllDesktops() const
|
||||
{
|
||||
return d->isOnAllDesktops();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isShaded() const
|
||||
{
|
||||
return d->isShaded();
|
||||
}
|
||||
|
||||
QIcon DecoratedWindow::icon() const
|
||||
{
|
||||
return d->icon();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isMaximized() const
|
||||
{
|
||||
return d->isMaximized();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isMaximizedHorizontally() const
|
||||
{
|
||||
return d->isMaximizedHorizontally();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isMaximizedVertically() const
|
||||
{
|
||||
return d->isMaximizedVertically();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isKeepAbove() const
|
||||
{
|
||||
return d->isKeepAbove();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isKeepBelow() const
|
||||
{
|
||||
return d->isKeepBelow();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isCloseable() const
|
||||
{
|
||||
return d->isCloseable();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isMaximizeable() const
|
||||
{
|
||||
return d->isMaximizeable();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isMinimizeable() const
|
||||
{
|
||||
return d->isMinimizeable();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::providesContextHelp() const
|
||||
{
|
||||
return d->providesContextHelp();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isModal() const
|
||||
{
|
||||
return d->isModal();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isShadeable() const
|
||||
{
|
||||
return d->isShadeable();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isMoveable() const
|
||||
{
|
||||
return d->isMoveable();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isResizeable() const
|
||||
{
|
||||
return d->isResizeable();
|
||||
}
|
||||
|
||||
qreal DecoratedWindow::width() const
|
||||
{
|
||||
return d->width();
|
||||
}
|
||||
|
||||
qreal DecoratedWindow::height() const
|
||||
{
|
||||
return d->height();
|
||||
}
|
||||
|
||||
QSizeF DecoratedWindow::size() const
|
||||
{
|
||||
return d->size();
|
||||
}
|
||||
|
||||
QPalette DecoratedWindow::palette() const
|
||||
{
|
||||
return d->palette();
|
||||
}
|
||||
|
||||
Qt::Edges DecoratedWindow::adjacentScreenEdges() const
|
||||
{
|
||||
return d->adjacentScreenEdges();
|
||||
}
|
||||
|
||||
QString DecoratedWindow::windowClass() const
|
||||
{
|
||||
return d->windowClass();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::hasApplicationMenu() const
|
||||
{
|
||||
return d->hasApplicationMenu();
|
||||
}
|
||||
|
||||
bool DecoratedWindow::isApplicationMenuActive() const
|
||||
{
|
||||
return d->isApplicationMenuActive();
|
||||
}
|
||||
|
||||
Decoration *DecoratedWindow::decoration() const
|
||||
{
|
||||
return d->decoration();
|
||||
}
|
||||
|
||||
QColor DecoratedWindow::color(QPalette::ColorGroup group, QPalette::ColorRole role) const
|
||||
{
|
||||
return d->palette().color(group, role);
|
||||
}
|
||||
|
||||
QColor DecoratedWindow::color(ColorGroup group, ColorRole role) const
|
||||
{
|
||||
return d->color(group, role);
|
||||
}
|
||||
|
||||
void DecoratedWindow::showApplicationMenu(int actionId)
|
||||
{
|
||||
d->showApplicationMenu(actionId);
|
||||
}
|
||||
|
||||
qreal DecoratedWindow::scale() const
|
||||
{
|
||||
return d->scale();
|
||||
}
|
||||
|
||||
qreal DecoratedWindow::nextScale() const
|
||||
{
|
||||
return d->nextScale();
|
||||
}
|
||||
|
||||
qreal DecoratedWindow::pixelSize() const
|
||||
{
|
||||
return ::KDecoration3::pixelSize(scale());
|
||||
}
|
||||
|
||||
qreal DecoratedWindow::snapToPixelGrid(qreal value) const
|
||||
{
|
||||
return ::KDecoration3::snapToPixelGrid(value, d->scale());
|
||||
}
|
||||
|
||||
QPointF DecoratedWindow::snapToPixelGrid(const QPointF &value) const
|
||||
{
|
||||
return ::KDecoration3::snapToPixelGrid(value, d->scale());
|
||||
}
|
||||
|
||||
QSizeF DecoratedWindow::snapToPixelGrid(const QSizeF &value) const
|
||||
{
|
||||
return ::KDecoration3::snapToPixelGrid(value, d->scale());
|
||||
}
|
||||
|
||||
QRectF DecoratedWindow::snapToPixelGrid(const QRectF &value) const
|
||||
{
|
||||
return ::KDecoration3::snapToPixelGrid(value, d->scale());
|
||||
}
|
||||
|
||||
QString DecoratedWindow::applicationMenuServiceName() const
|
||||
{
|
||||
if (auto impl = dynamic_cast<DecoratedWindowPrivateV2 *>(d.get())) {
|
||||
return impl->applicationMenuServiceName();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString DecoratedWindow::applicationMenuObjectPath() const
|
||||
{
|
||||
if (auto impl = dynamic_cast<DecoratedWindowPrivateV2 *>(d.get())) {
|
||||
return impl->applicationMenuObjectPath();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "moc_decoratedwindow.cpp"
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "decoration.h"
|
||||
#include "decorationdefines.h"
|
||||
#include <kdecoration3/kdecoration3_export.h>
|
||||
|
||||
#include <QFont>
|
||||
#include <QIcon>
|
||||
#include <QObject>
|
||||
#include <QPalette>
|
||||
#include <QPointer>
|
||||
#include <QtGui/qwindowdefs.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class DecorationBridge;
|
||||
class DecoratedWindowPrivate;
|
||||
|
||||
/**
|
||||
* @brief The Client which gets decorated.
|
||||
*
|
||||
* The DecoratedWindow provides access to all the properties relevant for decorating the Client.
|
||||
* Each DecoratedWindow is bound to one Decoration and each Decoration is bound to this one
|
||||
* DecoratedWindow.
|
||||
*
|
||||
* The DecoratedWindow only exports properties, it does not provide any means to change the state.
|
||||
* To change state one needs to call the methods on Decoration. This is as the backend might
|
||||
* disallow state changes. Therefore any changes should be bound to the change signals of the
|
||||
* DecoratedWindow and not be bound to state changes of input elements (such as a button).
|
||||
*/
|
||||
class KDECORATIONS3_EXPORT DecoratedWindow : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
* The Decoration of this DecoratedWindow
|
||||
**/
|
||||
Q_PROPERTY(KDecoration3::Decoration *decoration READ decoration CONSTANT)
|
||||
/**
|
||||
* Whether the DecoratedWindow is active (has focus) or is inactive.
|
||||
**/
|
||||
Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
|
||||
/**
|
||||
* The caption of the DecoratedWindow.
|
||||
**/
|
||||
Q_PROPERTY(QString caption READ caption NOTIFY captionChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow is on all desktops or on just one.
|
||||
**/
|
||||
Q_PROPERTY(bool onAllDesktops READ isOnAllDesktops NOTIFY onAllDesktopsChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow is shaded. Shaded means that the actual content is
|
||||
* not visible, only the Decoration is visible.
|
||||
**/
|
||||
Q_PROPERTY(bool shaded READ isShaded NOTIFY shadedChanged)
|
||||
/**
|
||||
* The icon of the DecoratedWindow. This can be used as the icon for the window menu button.
|
||||
**/
|
||||
Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow is maximized. A DecoratedWindow is maximized if it is both
|
||||
* maximizedHorizontally and maximizedVertically. The Decoration of a maximized DecoratedWindow
|
||||
* should only consist of the title bar area.
|
||||
**/
|
||||
Q_PROPERTY(bool maximized READ isMaximized NOTIFY maximizedChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow is maximized horizontally. A horizontally maximized DecoratedWindow
|
||||
* uses the maximal possible width.
|
||||
**/
|
||||
Q_PROPERTY(bool maximizedHorizontally READ isMaximizedHorizontally NOTIFY maximizedHorizontallyChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow is maximized vertically. A vertically maximized DecoratedWindow
|
||||
* uses the maximal possible height.
|
||||
**/
|
||||
Q_PROPERTY(bool maximizedVertically READ isMaximizedVertically NOTIFY maximizedVerticallyChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow is set to be kept above other DecoratedWindows. There can be multiple
|
||||
* DecoratedWindows which are set to be kept above.
|
||||
**/
|
||||
Q_PROPERTY(bool keepAbove READ isKeepAbove NOTIFY keepAboveChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow is set to be kept below other DecoratedWindows. There can be multiple
|
||||
* DecoratedWindows which are set to be kept below.
|
||||
**/
|
||||
Q_PROPERTY(bool keepBelow READ isKeepBelow NOTIFY keepBelowChanged)
|
||||
|
||||
/**
|
||||
* Whether the DecoratedWindow can be closed. If this property is @c false a DecorationButton
|
||||
* for closing the DecoratedWindow should be disabled.
|
||||
**/
|
||||
Q_PROPERTY(bool closeable READ isCloseable NOTIFY closeableChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow can be maximized. If this property is @c false a DecorationButton
|
||||
* for maximizing the DecoratedWindow should be disabled.
|
||||
**/
|
||||
Q_PROPERTY(bool maximizeable READ isMaximizeable NOTIFY maximizeableChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow can be minimized. If this property is @c false a DecorationButton
|
||||
* for minimizing the DecoratedWindow should be disabled.
|
||||
**/
|
||||
Q_PROPERTY(bool minimizeable READ isMinimizeable NOTIFY minimizeableChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow provides context help.
|
||||
* The Decoration should only show a context help button if this property is @c true.
|
||||
**/
|
||||
Q_PROPERTY(bool providesContextHelp READ providesContextHelp NOTIFY providesContextHelpChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow is a modal dialog.
|
||||
**/
|
||||
Q_PROPERTY(bool modal READ isModal CONSTANT)
|
||||
/**
|
||||
* Whether the DecoratedWindow can be shaded. If this property is @c false a DecorationButton
|
||||
* for shading the DecoratedWindow should be disabled.
|
||||
**/
|
||||
Q_PROPERTY(bool shadeable READ isShadeable NOTIFY shadeableChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow can be moved.
|
||||
**/
|
||||
Q_PROPERTY(bool moveable READ isMoveable NOTIFY moveableChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow can be resized.
|
||||
**/
|
||||
Q_PROPERTY(bool resizeable READ isResizeable NOTIFY resizeableChanged)
|
||||
|
||||
/**
|
||||
* The width of the DecoratedWindow.
|
||||
**/
|
||||
Q_PROPERTY(qreal width READ width NOTIFY widthChanged)
|
||||
/**
|
||||
* The height of the DecoratedWindow.
|
||||
**/
|
||||
Q_PROPERTY(qreal height READ height NOTIFY heightChanged)
|
||||
/**
|
||||
* The size of the DecoratedWindow.
|
||||
**/
|
||||
Q_PROPERTY(QSizeF size READ size NOTIFY sizeChanged)
|
||||
/**
|
||||
* The palette this DecoratedWindow uses. The palette might be different for each
|
||||
* DecoratedWindow and the Decoration should honor the palette.
|
||||
**/
|
||||
Q_PROPERTY(QPalette palette READ palette NOTIFY paletteChanged)
|
||||
/**
|
||||
* The Edges which are adjacent to a screen edge. E.g. for a maximized DecoratedWindow this
|
||||
* will include all Edges. The Decoration can use this information to hide borders.
|
||||
**/
|
||||
Q_PROPERTY(Qt::Edges adjacentScreenEdges READ adjacentScreenEdges NOTIFY adjacentScreenEdgesChanged)
|
||||
/**
|
||||
* Whether the DecoratedWindow has an application menu
|
||||
* @since 5.9
|
||||
*/
|
||||
Q_PROPERTY(bool hasApplicationMenu READ hasApplicationMenu NOTIFY hasApplicationMenuChanged)
|
||||
/**
|
||||
* Whether the application menu for this DecoratedWindow is currently shown to the user
|
||||
* The Decoration can use this information to highlight the respective button.
|
||||
* @since 5.9
|
||||
*/
|
||||
Q_PROPERTY(bool applicationMenuActive READ isApplicationMenuActive NOTIFY applicationMenuActiveChanged)
|
||||
/**
|
||||
* Returns the DBus service name of the application menu. If the window has no application
|
||||
* menu associated with it, an empty string will be returned.
|
||||
*
|
||||
* @since 6.3.2
|
||||
*/
|
||||
Q_PROPERTY(QString applicationMenuServiceName READ applicationMenuServiceName NOTIFY applicationMenuChanged)
|
||||
/**
|
||||
* Returns the DBus object path of the application menu. If the window has no application
|
||||
* menu associated with it, an empty string will be returned.
|
||||
*
|
||||
* @since 6.3.2
|
||||
*/
|
||||
Q_PROPERTY(QString applicationMenuObjectPath READ applicationMenuObjectPath NOTIFY applicationMenuChanged)
|
||||
|
||||
/**
|
||||
* The current scale this decorated window is targeting.
|
||||
* @since 6.3
|
||||
*/
|
||||
Q_PROPERTY(qreal scale READ scale NOTIFY scaleChanged);
|
||||
|
||||
/**
|
||||
* The next scale this decorated window is going to target.
|
||||
* @since 6.3
|
||||
*/
|
||||
Q_PROPERTY(qreal nextScale READ nextScale NOTIFY nextScaleChanged)
|
||||
|
||||
public:
|
||||
DecoratedWindow() = delete;
|
||||
~DecoratedWindow() override;
|
||||
bool isActive() const;
|
||||
QString caption() const;
|
||||
bool isOnAllDesktops() const;
|
||||
bool isShaded() const;
|
||||
QIcon icon() const;
|
||||
bool isMaximized() const;
|
||||
bool isMaximizedHorizontally() const;
|
||||
bool isMaximizedVertically() const;
|
||||
bool isKeepAbove() const;
|
||||
bool isKeepBelow() const;
|
||||
|
||||
bool isCloseable() const;
|
||||
bool isMaximizeable() const;
|
||||
bool isMinimizeable() const;
|
||||
bool providesContextHelp() const;
|
||||
bool isModal() const;
|
||||
bool isShadeable() const;
|
||||
bool isMoveable() const;
|
||||
bool isResizeable() const;
|
||||
|
||||
Qt::Edges adjacentScreenEdges() const;
|
||||
|
||||
QString windowClass() const;
|
||||
|
||||
qreal width() const;
|
||||
qreal height() const;
|
||||
QSizeF size() const;
|
||||
|
||||
Decoration *decoration() const;
|
||||
QPalette palette() const;
|
||||
/**
|
||||
* Used to get colors in QPalette.
|
||||
* @param group The color group
|
||||
* @param role The color role
|
||||
* @return palette().color(group, role)
|
||||
* @since 5.3
|
||||
**/
|
||||
QColor color(QPalette::ColorGroup group, QPalette::ColorRole role) const;
|
||||
/**
|
||||
* Used to get additional colors that are not in QPalette.
|
||||
* @param group The color group
|
||||
* @param role The color role
|
||||
* @return The color if provided for combination of group and role, otherwise invalid QColor.
|
||||
* @since 5.3
|
||||
**/
|
||||
QColor color(ColorGroup group, ColorRole role) const;
|
||||
|
||||
/**
|
||||
* Whether the DecoratedWindow has an application menu
|
||||
* @since 5.9
|
||||
*/
|
||||
bool hasApplicationMenu() const;
|
||||
/**
|
||||
* Returns the DBus service name of the application menu. If the window has no application
|
||||
* menu associated with it, an empty string will be returned.
|
||||
*
|
||||
* @since 6.3.2
|
||||
*/
|
||||
QString applicationMenuServiceName() const;
|
||||
/**
|
||||
* Returns the DBus object path of the application menu. If the window has no application
|
||||
* menu associated with it, an empty string will be returned.
|
||||
*
|
||||
* @since 6.3.2
|
||||
*/
|
||||
QString applicationMenuObjectPath() const;
|
||||
/**
|
||||
* Whether the application menu for this DecoratedWindow is currently shown to the user
|
||||
* The Decoration can use this information to highlight the respective button.
|
||||
* @since 5.9
|
||||
*/
|
||||
bool isApplicationMenuActive() const;
|
||||
|
||||
/**
|
||||
* Request the application menu to be shown to the user
|
||||
* @param actionId The DBus menu ID of the action that should be highlighted, 0 for none.
|
||||
*/
|
||||
void showApplicationMenu(int actionId);
|
||||
|
||||
/**
|
||||
* Returns the current scale this decorated window is targeting
|
||||
* @since 6.3
|
||||
*/
|
||||
qreal scale() const;
|
||||
/**
|
||||
* Returns the next scale this decorated window is going to target.
|
||||
*/
|
||||
qreal nextScale() const;
|
||||
/**
|
||||
* @returns the logical size of a device pixel with the current scale
|
||||
* @since 6.3
|
||||
*/
|
||||
qreal pixelSize() const;
|
||||
/**
|
||||
* snaps the logical geometry value to a fractional logical geometry value
|
||||
* that aligns to the pixel grid with the current scale factor
|
||||
* @since 6.3
|
||||
*/
|
||||
qreal snapToPixelGrid(qreal value) const;
|
||||
/**
|
||||
* snaps the logical geometry value to a fractional logical geometry value
|
||||
* that aligns to the pixel grid with the current scale factor
|
||||
* @since 6.3
|
||||
*/
|
||||
QPointF snapToPixelGrid(const QPointF &value) const;
|
||||
/**
|
||||
* snaps the logical geometry value to a fractional logical geometry value
|
||||
* that aligns to the pixel grid with the current scale factor
|
||||
* @since 6.3
|
||||
*/
|
||||
QSizeF snapToPixelGrid(const QSizeF &value) const;
|
||||
/**
|
||||
* snaps the logical geometry value to a fractional logical geometry value
|
||||
* that aligns to the pixel grid with the current scale factor
|
||||
* @since 6.3
|
||||
*/
|
||||
QRectF snapToPixelGrid(const QRectF &value) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void activeChanged(bool);
|
||||
void captionChanged(QString);
|
||||
void onAllDesktopsChanged(bool);
|
||||
void shadedChanged(bool);
|
||||
void iconChanged(QIcon);
|
||||
void maximizedChanged(bool);
|
||||
void maximizedHorizontallyChanged(bool);
|
||||
void maximizedVerticallyChanged(bool);
|
||||
void keepAboveChanged(bool);
|
||||
void keepBelowChanged(bool);
|
||||
|
||||
void closeableChanged(bool);
|
||||
void maximizeableChanged(bool);
|
||||
void minimizeableChanged(bool);
|
||||
void providesContextHelpChanged(bool);
|
||||
void shadeableChanged(bool);
|
||||
void moveableChanged(bool);
|
||||
void resizeableChanged(bool);
|
||||
|
||||
void widthChanged(qreal);
|
||||
void heightChanged(qreal);
|
||||
void sizeChanged(const QSizeF &size);
|
||||
void paletteChanged(const QPalette &palette);
|
||||
void adjacentScreenEdgesChanged(Qt::Edges edges);
|
||||
|
||||
void hasApplicationMenuChanged(bool);
|
||||
void applicationMenuActiveChanged(bool);
|
||||
void scaleChanged();
|
||||
void nextScaleChanged();
|
||||
void applicationMenuChanged();
|
||||
|
||||
private:
|
||||
friend class Decoration;
|
||||
DecoratedWindow(Decoration *parent, DecorationBridge *bridge);
|
||||
const std::unique_ptr<DecoratedWindowPrivate> d;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "decoration.h"
|
||||
#include "decoratedwindow.h"
|
||||
#include "decoration_p.h"
|
||||
#include "decorationbutton.h"
|
||||
#include "decorationsettings.h"
|
||||
#include "private/decoratedwindowprivate.h"
|
||||
#include "private/decorationbridge.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QHoverEvent>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
namespace
|
||||
{
|
||||
DecorationBridge *findBridge(const QVariantList &args)
|
||||
{
|
||||
for (const auto &arg : args) {
|
||||
if (auto bridge = arg.toMap().value(QStringLiteral("bridge")).value<DecorationBridge *>()) {
|
||||
return bridge;
|
||||
}
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
class DecorationStateData : public QSharedData
|
||||
{
|
||||
public:
|
||||
QMarginsF borders;
|
||||
};
|
||||
|
||||
DecorationState::DecorationState()
|
||||
: d(new DecorationStateData)
|
||||
{
|
||||
}
|
||||
|
||||
DecorationState::DecorationState(const DecorationState &other)
|
||||
: d(other.d)
|
||||
{
|
||||
}
|
||||
|
||||
DecorationState::~DecorationState()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<DecorationState> DecorationState::clone() const
|
||||
{
|
||||
return std::make_shared<DecorationState>(*this);
|
||||
}
|
||||
|
||||
QMarginsF DecorationState::borders() const
|
||||
{
|
||||
return d->borders;
|
||||
}
|
||||
|
||||
void DecorationState::setBorders(const QMarginsF &borders)
|
||||
{
|
||||
d->borders = borders;
|
||||
}
|
||||
|
||||
Decoration::Private::Private(Decoration *deco, const QVariantList &args)
|
||||
: sectionUnderMouse(Qt::NoSection)
|
||||
, bridge(findBridge(args))
|
||||
, client(std::shared_ptr<DecoratedWindow>(new DecoratedWindow(deco, bridge)))
|
||||
, opaque(false)
|
||||
, q(deco)
|
||||
{
|
||||
}
|
||||
|
||||
void Decoration::Private::setSectionUnderMouse(Qt::WindowFrameSection section)
|
||||
{
|
||||
if (sectionUnderMouse == section) {
|
||||
return;
|
||||
}
|
||||
sectionUnderMouse = section;
|
||||
Q_EMIT q->sectionUnderMouseChanged(sectionUnderMouse);
|
||||
}
|
||||
|
||||
void Decoration::Private::updateSectionUnderMouse(const QPoint &mousePosition)
|
||||
{
|
||||
if (titleBar.toRect().contains(mousePosition)) {
|
||||
setSectionUnderMouse(Qt::TitleBarArea);
|
||||
return;
|
||||
}
|
||||
const QSizeF size = q->size();
|
||||
const QMarginsF borders = current->borders();
|
||||
const int corner = 2 * settings->largeSpacing();
|
||||
const bool left = mousePosition.x() < borders.left();
|
||||
const bool top = mousePosition.y() < borders.top();
|
||||
const bool bottom = mousePosition.y() >= size.height() - borders.bottom();
|
||||
const bool right = mousePosition.x() >= size.width() - borders.right();
|
||||
if (left) {
|
||||
if (top && mousePosition.y() < titleBar.top() + corner) {
|
||||
setSectionUnderMouse(Qt::TopLeftSection);
|
||||
} else if (mousePosition.y() >= size.height() - borders.bottom() - corner && mousePosition.y() >= titleBar.bottom()) {
|
||||
setSectionUnderMouse(Qt::BottomLeftSection);
|
||||
} else {
|
||||
setSectionUnderMouse(Qt::LeftSection);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (right) {
|
||||
if (top && mousePosition.y() < titleBar.top() + corner) {
|
||||
setSectionUnderMouse(Qt::TopRightSection);
|
||||
} else if (mousePosition.y() >= size.height() - borders.bottom() - corner && mousePosition.y() >= titleBar.bottom()) {
|
||||
setSectionUnderMouse(Qt::BottomRightSection);
|
||||
} else {
|
||||
setSectionUnderMouse(Qt::RightSection);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (bottom) {
|
||||
if (mousePosition.y() >= titleBar.bottom()) {
|
||||
if (mousePosition.x() < borders.left() + corner) {
|
||||
setSectionUnderMouse(Qt::BottomLeftSection);
|
||||
} else if (mousePosition.x() >= size.width() - borders.right() - corner) {
|
||||
setSectionUnderMouse(Qt::BottomRightSection);
|
||||
} else {
|
||||
setSectionUnderMouse(Qt::BottomSection);
|
||||
}
|
||||
} else {
|
||||
setSectionUnderMouse(Qt::TitleBarArea);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (top) {
|
||||
if (mousePosition.y() < titleBar.top()) {
|
||||
if (mousePosition.x() < borders.left() + corner) {
|
||||
setSectionUnderMouse(Qt::TopLeftSection);
|
||||
} else if (mousePosition.x() >= size.width() - borders.right() - corner) {
|
||||
setSectionUnderMouse(Qt::TopRightSection);
|
||||
} else {
|
||||
setSectionUnderMouse(Qt::TopSection);
|
||||
}
|
||||
} else {
|
||||
setSectionUnderMouse(Qt::TitleBarArea);
|
||||
}
|
||||
return;
|
||||
}
|
||||
setSectionUnderMouse(Qt::NoSection);
|
||||
}
|
||||
|
||||
void Decoration::Private::addButton(DecorationButton *button)
|
||||
{
|
||||
Q_ASSERT(!buttons.contains(button));
|
||||
buttons << button;
|
||||
QObject::connect(button, &QObject::destroyed, q, [this](QObject *o) {
|
||||
auto it = buttons.begin();
|
||||
while (it != buttons.end()) {
|
||||
if (*it == static_cast<DecorationButton *>(o)) {
|
||||
it = buttons.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Decoration::Decoration(QObject *parent, const QVariantList &args)
|
||||
: QObject(parent)
|
||||
, d(new Private(this, args))
|
||||
{
|
||||
}
|
||||
|
||||
Decoration::~Decoration() = default;
|
||||
|
||||
DecoratedWindow *Decoration::window() const
|
||||
{
|
||||
return d->client.get();
|
||||
}
|
||||
|
||||
void Decoration::requestClose()
|
||||
{
|
||||
d->client->d->requestClose();
|
||||
}
|
||||
|
||||
void Decoration::requestContextHelp()
|
||||
{
|
||||
d->client->d->requestContextHelp();
|
||||
}
|
||||
|
||||
void Decoration::requestMinimize()
|
||||
{
|
||||
d->client->d->requestMinimize();
|
||||
}
|
||||
|
||||
void Decoration::requestToggleOnAllDesktops()
|
||||
{
|
||||
d->client->d->requestToggleOnAllDesktops();
|
||||
}
|
||||
|
||||
void Decoration::requestToggleShade()
|
||||
{
|
||||
d->client->d->requestToggleShade();
|
||||
}
|
||||
|
||||
void Decoration::requestToggleKeepAbove()
|
||||
{
|
||||
d->client->d->requestToggleKeepAbove();
|
||||
}
|
||||
|
||||
void Decoration::requestToggleKeepBelow()
|
||||
{
|
||||
d->client->d->requestToggleKeepBelow();
|
||||
}
|
||||
|
||||
#if KDECORATIONS3_ENABLE_DEPRECATED_SINCE(5, 21)
|
||||
void Decoration::requestShowWindowMenu()
|
||||
{
|
||||
requestShowWindowMenu(QRect());
|
||||
}
|
||||
#endif
|
||||
|
||||
void Decoration::requestShowWindowMenu(const QRect &rect)
|
||||
{
|
||||
d->client->d->requestShowWindowMenu(rect);
|
||||
}
|
||||
|
||||
void Decoration::requestShowToolTip(const QString &text)
|
||||
{
|
||||
d->client->d->requestShowToolTip(text);
|
||||
}
|
||||
|
||||
void Decoration::requestHideToolTip()
|
||||
{
|
||||
d->client->d->requestHideToolTip();
|
||||
}
|
||||
|
||||
void Decoration::requestToggleMaximization(Qt::MouseButtons buttons)
|
||||
{
|
||||
d->client->d->requestToggleMaximization(buttons);
|
||||
}
|
||||
|
||||
void Decoration::showApplicationMenu(int actionId)
|
||||
{
|
||||
const auto it = std::find_if(d->buttons.constBegin(), d->buttons.constEnd(), [](DecorationButton *button) {
|
||||
return button->type() == DecorationButtonType::ApplicationMenu;
|
||||
});
|
||||
if (it != d->buttons.constEnd()) {
|
||||
requestShowApplicationMenu((*it)->geometry().toRect(), actionId);
|
||||
}
|
||||
}
|
||||
|
||||
void Decoration::requestShowApplicationMenu(const QRect &rect, int actionId)
|
||||
{
|
||||
d->client->d->requestShowApplicationMenu(rect, actionId);
|
||||
}
|
||||
|
||||
void Decoration::setBlurRegion(const QRegion ®ion)
|
||||
{
|
||||
if (d->blurRegion != region) {
|
||||
d->blurRegion = region;
|
||||
Q_EMIT blurRegionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Decoration::setBorders(const QMarginsF &borders)
|
||||
{
|
||||
if (d->next->borders() != borders) {
|
||||
setState([borders](DecorationState *state) {
|
||||
state->setBorders(borders);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Decoration::setResizeOnlyBorders(const QMarginsF &borders)
|
||||
{
|
||||
if (d->resizeOnlyBorders != borders) {
|
||||
d->resizeOnlyBorders = borders;
|
||||
Q_EMIT resizeOnlyBordersChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Decoration::setTitleBar(const QRectF &rect)
|
||||
{
|
||||
if (d->titleBar != rect) {
|
||||
d->titleBar = rect;
|
||||
Q_EMIT titleBarChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Decoration::setOpaque(bool opaque)
|
||||
{
|
||||
if (d->opaque != opaque) {
|
||||
d->opaque = opaque;
|
||||
Q_EMIT opaqueChanged(opaque);
|
||||
}
|
||||
}
|
||||
|
||||
void Decoration::setShadow(const std::shared_ptr<DecorationShadow> &shadow)
|
||||
{
|
||||
if (d->shadow != shadow) {
|
||||
d->shadow = shadow;
|
||||
Q_EMIT shadowChanged(shadow);
|
||||
}
|
||||
}
|
||||
|
||||
QRegion Decoration::blurRegion() const
|
||||
{
|
||||
return d->blurRegion;
|
||||
}
|
||||
|
||||
QMarginsF Decoration::borders() const
|
||||
{
|
||||
return d->current->borders();
|
||||
}
|
||||
|
||||
QMarginsF Decoration::resizeOnlyBorders() const
|
||||
{
|
||||
return d->resizeOnlyBorders;
|
||||
}
|
||||
|
||||
QRectF Decoration::titleBar() const
|
||||
{
|
||||
return d->titleBar;
|
||||
}
|
||||
|
||||
Qt::WindowFrameSection Decoration::sectionUnderMouse() const
|
||||
{
|
||||
return d->sectionUnderMouse;
|
||||
}
|
||||
|
||||
std::shared_ptr<DecorationShadow> Decoration::shadow() const
|
||||
{
|
||||
return d->shadow;
|
||||
}
|
||||
|
||||
bool Decoration::isOpaque() const
|
||||
{
|
||||
return d->opaque;
|
||||
}
|
||||
|
||||
qreal Decoration::borderLeft() const
|
||||
{
|
||||
return d->current->borders().left();
|
||||
}
|
||||
|
||||
qreal Decoration::resizeOnlyBorderLeft() const
|
||||
{
|
||||
return d->resizeOnlyBorders.left();
|
||||
}
|
||||
|
||||
qreal Decoration::borderRight() const
|
||||
{
|
||||
return d->current->borders().right();
|
||||
}
|
||||
|
||||
qreal Decoration::resizeOnlyBorderRight() const
|
||||
{
|
||||
return d->resizeOnlyBorders.right();
|
||||
}
|
||||
|
||||
qreal Decoration::borderTop() const
|
||||
{
|
||||
return d->current->borders().top();
|
||||
}
|
||||
|
||||
qreal Decoration::resizeOnlyBorderTop() const
|
||||
{
|
||||
return d->resizeOnlyBorders.top();
|
||||
}
|
||||
|
||||
qreal Decoration::borderBottom() const
|
||||
{
|
||||
return d->current->borders().bottom();
|
||||
}
|
||||
|
||||
qreal Decoration::resizeOnlyBorderBottom() const
|
||||
{
|
||||
return d->resizeOnlyBorders.bottom();
|
||||
}
|
||||
|
||||
QSizeF Decoration::size() const
|
||||
{
|
||||
const QMarginsF b = d->current->borders();
|
||||
return QSizeF(d->client->width() + b.left() + b.right(), (d->client->isShaded() ? 0 : d->client->height()) + b.top() + b.bottom());
|
||||
}
|
||||
|
||||
QRectF Decoration::rect() const
|
||||
{
|
||||
return QRectF(QPointF(0, 0), size());
|
||||
}
|
||||
|
||||
bool Decoration::event(QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::HoverEnter:
|
||||
hoverEnterEvent(static_cast<QHoverEvent *>(event));
|
||||
return true;
|
||||
case QEvent::HoverLeave:
|
||||
hoverLeaveEvent(static_cast<QHoverEvent *>(event));
|
||||
return true;
|
||||
case QEvent::HoverMove:
|
||||
hoverMoveEvent(static_cast<QHoverEvent *>(event));
|
||||
return true;
|
||||
case QEvent::MouseButtonPress:
|
||||
mousePressEvent(static_cast<QMouseEvent *>(event));
|
||||
return true;
|
||||
case QEvent::MouseButtonRelease:
|
||||
mouseReleaseEvent(static_cast<QMouseEvent *>(event));
|
||||
return true;
|
||||
case QEvent::MouseMove:
|
||||
mouseMoveEvent(static_cast<QMouseEvent *>(event));
|
||||
return true;
|
||||
case QEvent::Wheel:
|
||||
wheelEvent(static_cast<QWheelEvent *>(event));
|
||||
return true;
|
||||
default:
|
||||
return QObject::event(event);
|
||||
}
|
||||
}
|
||||
|
||||
void Decoration::hoverEnterEvent(QHoverEvent *event)
|
||||
{
|
||||
for (DecorationButton *button : d->buttons) {
|
||||
QCoreApplication::instance()->sendEvent(button, event);
|
||||
}
|
||||
auto flooredPos = QPoint(std::floor(event->position().x()), std::floor(event->position().y()));
|
||||
d->updateSectionUnderMouse(flooredPos);
|
||||
}
|
||||
|
||||
void Decoration::hoverLeaveEvent(QHoverEvent *event)
|
||||
{
|
||||
for (DecorationButton *button : d->buttons) {
|
||||
QCoreApplication::instance()->sendEvent(button, event);
|
||||
}
|
||||
d->setSectionUnderMouse(Qt::NoSection);
|
||||
}
|
||||
|
||||
void Decoration::hoverMoveEvent(QHoverEvent *event)
|
||||
{
|
||||
for (DecorationButton *button : d->buttons) {
|
||||
if (!button->isEnabled() || !button->isVisible()) {
|
||||
continue;
|
||||
}
|
||||
const bool hovered = button->isHovered();
|
||||
const bool contains = button->contains(event->position());
|
||||
if (!hovered && contains) {
|
||||
QHoverEvent e(QEvent::HoverEnter, event->position(), event->oldPosF(), event->modifiers());
|
||||
QCoreApplication::instance()->sendEvent(button, &e);
|
||||
} else if (hovered && !contains) {
|
||||
QHoverEvent e(QEvent::HoverLeave, event->position(), event->oldPosF(), event->modifiers());
|
||||
QCoreApplication::instance()->sendEvent(button, &e);
|
||||
} else if (hovered && contains) {
|
||||
QCoreApplication::instance()->sendEvent(button, event);
|
||||
}
|
||||
}
|
||||
auto flooredPos = QPoint(std::floor(event->position().x()), std::floor(event->position().y()));
|
||||
d->updateSectionUnderMouse(flooredPos);
|
||||
}
|
||||
|
||||
void Decoration::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
for (DecorationButton *button : d->buttons) {
|
||||
if (button->isPressed()) {
|
||||
QCoreApplication::instance()->sendEvent(button, event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// not handled, take care ourselves
|
||||
}
|
||||
|
||||
void Decoration::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
for (DecorationButton *button : d->buttons) {
|
||||
if (button->isHovered()) {
|
||||
if (button->acceptedButtons().testFlag(event->button())) {
|
||||
QCoreApplication::instance()->sendEvent(button, event);
|
||||
}
|
||||
event->setAccepted(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Decoration::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
for (DecorationButton *button : d->buttons) {
|
||||
if (button->isPressed() && button->acceptedButtons().testFlag(event->button())) {
|
||||
QCoreApplication::instance()->sendEvent(button, event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// not handled, take care ourselves
|
||||
d->updateSectionUnderMouse(event->pos());
|
||||
}
|
||||
|
||||
void Decoration::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
for (DecorationButton *button : d->buttons) {
|
||||
if (button->contains(event->position())) {
|
||||
QCoreApplication::instance()->sendEvent(button, event);
|
||||
event->setAccepted(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Decoration::update(const QRectF &r)
|
||||
{
|
||||
Q_EMIT damaged(r.isNull() ? rect().toAlignedRect() : r.toAlignedRect());
|
||||
}
|
||||
|
||||
void Decoration::update()
|
||||
{
|
||||
update(QRect());
|
||||
}
|
||||
|
||||
void Decoration::setSettings(const std::shared_ptr<DecorationSettings> &settings)
|
||||
{
|
||||
d->settings = settings;
|
||||
}
|
||||
|
||||
std::shared_ptr<DecorationSettings> Decoration::settings() const
|
||||
{
|
||||
return d->settings;
|
||||
}
|
||||
|
||||
std::shared_ptr<DecorationState> Decoration::createState()
|
||||
{
|
||||
return std::make_shared<DecorationState>();
|
||||
}
|
||||
|
||||
std::shared_ptr<DecorationState> Decoration::currentState() const
|
||||
{
|
||||
return d->current;
|
||||
}
|
||||
|
||||
std::shared_ptr<DecorationState> Decoration::nextState() const
|
||||
{
|
||||
return d->next;
|
||||
}
|
||||
|
||||
void Decoration::create()
|
||||
{
|
||||
d->next = createState();
|
||||
d->current = createState();
|
||||
}
|
||||
|
||||
void Decoration::setState(std::function<void(DecorationState *state)> callback)
|
||||
{
|
||||
callback(d->next.get());
|
||||
Q_EMIT nextStateChanged(d->next);
|
||||
}
|
||||
|
||||
void Decoration::apply(std::shared_ptr<DecorationState> state)
|
||||
{
|
||||
if (d->current == state) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto previous = d->current;
|
||||
d->current = state;
|
||||
update();
|
||||
|
||||
if (previous->borders() != state->borders()) {
|
||||
Q_EMIT bordersChanged();
|
||||
}
|
||||
|
||||
Q_EMIT currentStateChanged(state);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "moc_decoration.cpp"
|
||||
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "decorationshadow.h"
|
||||
#include <kdecoration3/kdecoration3_export.h>
|
||||
|
||||
#include <QMarginsF>
|
||||
#include <QObject>
|
||||
#include <QRectF>
|
||||
#include <QSharedDataPointer>
|
||||
|
||||
class QHoverEvent;
|
||||
class QMouseEvent;
|
||||
class QPainter;
|
||||
class QWheelEvent;
|
||||
|
||||
/**
|
||||
* @brief Framework for creating window decorations.
|
||||
*
|
||||
**/
|
||||
namespace KDecoration3
|
||||
{
|
||||
class DecorationPrivate;
|
||||
class DecoratedWindow;
|
||||
class DecorationButton;
|
||||
class DecorationSettings;
|
||||
class DecorationStateData;
|
||||
|
||||
/**
|
||||
* \brief Decoration state.
|
||||
*
|
||||
* The DecorationState type represents double bufferred state associated with a decoration.
|
||||
*
|
||||
* \note Sub-classes of DecorationState must override the clone() function.
|
||||
*/
|
||||
class KDECORATIONS3_EXPORT DecorationState
|
||||
{
|
||||
public:
|
||||
DecorationState();
|
||||
DecorationState(const DecorationState &other);
|
||||
virtual ~DecorationState();
|
||||
|
||||
virtual std::shared_ptr<DecorationState> clone() const;
|
||||
|
||||
QMarginsF borders() const;
|
||||
void setBorders(const QMarginsF &margins);
|
||||
|
||||
private:
|
||||
QSharedDataPointer<DecorationStateData> d;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Base class for the Decoration.
|
||||
*
|
||||
* To provide a Decoration one needs to inherit from this class. The framework will instantiate
|
||||
* an instance of the inherited class for each DecoratedWindow.
|
||||
*
|
||||
* The main tasks of the Decoration is to provide borders around the DecoratedWindow. For this
|
||||
* the Deocration provides border sizes: those should be adjusted depending on the state of the
|
||||
* DecoratedWindow. E.g. commonly a maximized DecoratedWindow does not have borders on the side,
|
||||
* only the title bar.
|
||||
*
|
||||
* Whenever the visual representation of the Decoration changes the slot @link Decoration::update @endlink
|
||||
* should be invoked to request a repaint. The framework will in return invoke the
|
||||
* @link Decoration::paint @endlink method. This method needs to be implemented by inheriting
|
||||
* classes.
|
||||
*
|
||||
* A Decoration commonly provides buttons for interaction. E.g. a close button to close the
|
||||
* DecoratedWindow. For such actions the Decoration provides slots which should be connected to
|
||||
* the clicked signals of the buttons. For convenience the framework provides the @link DecorationButton @endlink
|
||||
* and the @link DecorationButtonGroup @endlink for easier layout. It is not required to use those,
|
||||
* if one uses different ways to represent the actions one needs to filter the events accordingly.
|
||||
*
|
||||
* @see DecoratedWindow
|
||||
* @see DecorationButton
|
||||
* @see DecorationButtonGroup
|
||||
**/
|
||||
class KDECORATIONS3_EXPORT Decoration : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QMarginsF borders READ borders NOTIFY bordersChanged)
|
||||
Q_PROPERTY(qreal borderLeft READ borderLeft NOTIFY bordersChanged)
|
||||
Q_PROPERTY(qreal borderRight READ borderRight NOTIFY bordersChanged)
|
||||
Q_PROPERTY(qreal borderTop READ borderTop NOTIFY bordersChanged)
|
||||
Q_PROPERTY(qreal borderBottom READ borderBottom NOTIFY bordersChanged)
|
||||
Q_PROPERTY(QMarginsF resizeOnlyBorders READ resizeOnlyBorders NOTIFY resizeOnlyBordersChanged)
|
||||
Q_PROPERTY(qreal resizeOnlyBorderLeft READ resizeOnlyBorderLeft NOTIFY resizeOnlyBordersChanged)
|
||||
Q_PROPERTY(qreal resizeOnlyBorderRight READ resizeOnlyBorderRight NOTIFY resizeOnlyBordersChanged)
|
||||
Q_PROPERTY(qreal resizeOnlyBorderTop READ resizeOnlyBorderTop NOTIFY resizeOnlyBordersChanged)
|
||||
Q_PROPERTY(qreal resizeOnlyBorderBottom READ resizeOnlyBorderBottom NOTIFY resizeOnlyBordersChanged)
|
||||
/**
|
||||
* This property denotes the part of the Decoration which is currently under the mouse pointer.
|
||||
* It gets automatically updated whenever a QMouseEvent or QHoverEvent gets processed.
|
||||
**/
|
||||
Q_PROPERTY(Qt::WindowFrameSection sectionUnderMouse READ sectionUnderMouse NOTIFY sectionUnderMouseChanged)
|
||||
/**
|
||||
* The titleBar is the area inside the Decoration containing all controls (e.g. Buttons)
|
||||
* and the caption. The titleBar is the main interaction area, while all other areas of the
|
||||
* Decoration are normally used as resize areas.
|
||||
**/
|
||||
Q_PROPERTY(QRectF titleBar READ titleBar NOTIFY titleBarChanged)
|
||||
/**
|
||||
* Whether the Decoration is fully opaque. By default a Decoration is considered to
|
||||
* use the alpha channel and this property has the value @c false. But for e.g. a maximized
|
||||
* DecoratedWindow it is possible that the Decoration is fully opaque. In this case the
|
||||
* Decoration should set this property to @c true.
|
||||
**/
|
||||
Q_PROPERTY(bool opaque READ isOpaque NOTIFY opaqueChanged)
|
||||
public:
|
||||
~Decoration() override;
|
||||
|
||||
/**
|
||||
* The DecoratedWindow for this Decoration.
|
||||
**/
|
||||
DecoratedWindow *window() const;
|
||||
|
||||
QMarginsF borders() const;
|
||||
qreal borderLeft() const;
|
||||
qreal borderRight() const;
|
||||
qreal borderTop() const;
|
||||
qreal borderBottom() const;
|
||||
QMarginsF resizeOnlyBorders() const;
|
||||
qreal resizeOnlyBorderLeft() const;
|
||||
qreal resizeOnlyBorderRight() const;
|
||||
qreal resizeOnlyBorderTop() const;
|
||||
qreal resizeOnlyBorderBottom() const;
|
||||
Qt::WindowFrameSection sectionUnderMouse() const;
|
||||
QRectF titleBar() const;
|
||||
bool isOpaque() const;
|
||||
|
||||
/**
|
||||
* DecorationShadow for this Decoration. It is recommended that multiple Decorations share
|
||||
* the same DecorationShadow. E.g one DecorationShadow for all inactive Decorations and one
|
||||
* for the active Decoration.
|
||||
**/
|
||||
std::shared_ptr<DecorationShadow> shadow() const;
|
||||
|
||||
/**
|
||||
* The decoration's geometry in local coordinates.
|
||||
*
|
||||
* Basically the size of the DecoratedWindow combined with the borders.
|
||||
**/
|
||||
QRectF rect() const;
|
||||
QSizeF size() const;
|
||||
|
||||
/**
|
||||
* The decoration's blur region in local coordinates
|
||||
*/
|
||||
QRegion blurRegion() const;
|
||||
|
||||
/**
|
||||
* Invoked by the framework to set the Settings for this Decoration before
|
||||
* init is invoked.
|
||||
* @internal
|
||||
**/
|
||||
void setSettings(const std::shared_ptr<DecorationSettings> &settings);
|
||||
/**
|
||||
* @returns The DecorationSettings used for this Decoration.
|
||||
**/
|
||||
std::shared_ptr<DecorationSettings> settings() const;
|
||||
|
||||
/**
|
||||
* Implement this method in inheriting classes to provide the rendering.
|
||||
*
|
||||
* The @p painter is set up to paint on an internal QPaintDevice. The painting is
|
||||
* implicitly double buffered.
|
||||
*
|
||||
* @param painter The painter which needs to be used for rendering
|
||||
* @param repaintArea The region which needs to be repainted.
|
||||
**/
|
||||
virtual void paint(QPainter *painter, const QRectF &repaintArea) = 0;
|
||||
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
/**
|
||||
* \internal
|
||||
*
|
||||
* Allocates the resources associated with the decoration, for example state containers.
|
||||
*
|
||||
* \note This method gets invoked by the compositor before init(), the decoration implementation
|
||||
* must not call it.
|
||||
*/
|
||||
void create();
|
||||
|
||||
/**
|
||||
* \internal
|
||||
*
|
||||
* Make the specified \a state current.
|
||||
*
|
||||
* The decoration maintains a double-buffered state. If a double-buffered property needs
|
||||
* to be changed, the next state will be updated and the nextStateChanged() signal will be
|
||||
* emitted to notify the compositor about it.
|
||||
*
|
||||
* When the next state gets applied is subject to compositor policies. For example, the
|
||||
* compositor may apply the new state immediately, or it can synchronize double-buffered
|
||||
* decoration state with double-buffered toplevel state.
|
||||
*
|
||||
* \sa currentState(), nextState(), createState()
|
||||
*/
|
||||
void apply(std::shared_ptr<DecorationState> state);
|
||||
|
||||
/**
|
||||
* Returns the currently applied state.
|
||||
*
|
||||
* \sa apply()
|
||||
*/
|
||||
std::shared_ptr<DecorationState> currentState() const;
|
||||
|
||||
/**
|
||||
* Returns the next state, i.e. the state that the decoration implementation wants to be current.
|
||||
*
|
||||
* \sa apply()
|
||||
*/
|
||||
std::shared_ptr<DecorationState> nextState() const;
|
||||
|
||||
/**
|
||||
* Notifies the framework that the decoration state has changed. When the new state is applied
|
||||
* is subject to compositor policies. For example, the compositor may re-configure the window
|
||||
* and apply the new state when the window is repainted.
|
||||
*/
|
||||
void setState(std::function<void(DecorationState *state)> callback);
|
||||
|
||||
public Q_SLOTS:
|
||||
void requestClose();
|
||||
void requestToggleMaximization(Qt::MouseButtons buttons);
|
||||
void requestMinimize();
|
||||
void requestContextHelp();
|
||||
void requestToggleOnAllDesktops();
|
||||
void requestToggleShade();
|
||||
void requestToggleKeepAbove();
|
||||
void requestToggleKeepBelow();
|
||||
|
||||
#if KDECORATIONS3_ENABLE_DEPRECATED_SINCE(5, 21)
|
||||
/**
|
||||
* @deprecated
|
||||
* @see requestShowWindowMenu(const QRect &rect)
|
||||
*/
|
||||
KDECORATIONS3_DEPRECATED_VERSION(5, 21, "Use Decoration::requestShowWindowMenu(QRect)")
|
||||
void requestShowWindowMenu();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @param rect the location at which to show the window menu
|
||||
*/
|
||||
void requestShowWindowMenu(const QRect &rect);
|
||||
void requestShowToolTip(const QString &text);
|
||||
void requestHideToolTip();
|
||||
|
||||
void showApplicationMenu(int actionId);
|
||||
void requestShowApplicationMenu(const QRect &rect, int actionId);
|
||||
|
||||
void update(const QRectF &rect);
|
||||
void update();
|
||||
|
||||
/**
|
||||
* This method gets invoked from the framework once the Decoration is created and
|
||||
* completely setup.
|
||||
*
|
||||
* An inheriting class should override this method and perform all initialization in
|
||||
* this method instead of the constructor.
|
||||
*
|
||||
* @return true if initialization has been successful,
|
||||
* false otherwise (for example, a QML component could not be loaded)
|
||||
**/
|
||||
virtual bool init() = 0;
|
||||
|
||||
Q_SIGNALS:
|
||||
void blurRegionChanged();
|
||||
void bordersChanged();
|
||||
void resizeOnlyBordersChanged();
|
||||
void sectionUnderMouseChanged(Qt::WindowFrameSection);
|
||||
void titleBarChanged();
|
||||
void opaqueChanged(bool);
|
||||
void shadowChanged(const std::shared_ptr<DecorationShadow> &shadow);
|
||||
void damaged(const QRegion ®ion);
|
||||
void currentStateChanged(std::shared_ptr<DecorationState> state);
|
||||
void nextStateChanged(std::shared_ptr<DecorationState> state);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructor for the Decoration.
|
||||
*
|
||||
* The @p args are used by the decoration framework to pass meta information
|
||||
* to the Decoration. An inheriting class is supposed to pass the args to the
|
||||
* parent class.
|
||||
*
|
||||
* @param parent The parent of the Decoration
|
||||
* @param args Additional arguments passed in from the framework
|
||||
**/
|
||||
explicit Decoration(QObject *parent, const QVariantList &args);
|
||||
void setBorders(const QMarginsF &borders);
|
||||
void setResizeOnlyBorders(const QMarginsF &borders);
|
||||
void setBlurRegion(const QRegion ®ion);
|
||||
/**
|
||||
* An implementation has to invoke this method whenever the area
|
||||
* containing the controls and caption changes.
|
||||
* @param rect The new geometry of the titleBar in Decoration coordinates
|
||||
**/
|
||||
void setTitleBar(const QRectF &rect);
|
||||
void setOpaque(bool opaque);
|
||||
void setShadow(const std::shared_ptr<DecorationShadow> &shadow);
|
||||
|
||||
virtual void hoverEnterEvent(QHoverEvent *event);
|
||||
virtual void hoverLeaveEvent(QHoverEvent *event);
|
||||
virtual void hoverMoveEvent(QHoverEvent *event);
|
||||
virtual void mouseMoveEvent(QMouseEvent *event);
|
||||
virtual void mousePressEvent(QMouseEvent *event);
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event);
|
||||
virtual void wheelEvent(QWheelEvent *event);
|
||||
|
||||
/**
|
||||
* Create a state container. The decoration implementation can override this method to attach
|
||||
* its own properties to the decoration state.
|
||||
*
|
||||
* The default implementation simply creates an instance of the DecorationState type.
|
||||
*
|
||||
* \sa currentState(), nextState()
|
||||
*/
|
||||
virtual std::shared_ptr<DecorationState> createState();
|
||||
|
||||
private:
|
||||
friend class DecorationButton;
|
||||
class Private;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
Q_DECLARE_METATYPE(KDecoration3::Decoration *)
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
#include "decoration.h"
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the KDecoration3 API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class Decoration;
|
||||
class DecorationBridge;
|
||||
class DecorationButton;
|
||||
class DecoratedWindow;
|
||||
class DecorationSettings;
|
||||
class DecorationShadow;
|
||||
|
||||
class Q_DECL_HIDDEN Decoration::Private
|
||||
{
|
||||
public:
|
||||
Private(Decoration *decoration, const QVariantList &args);
|
||||
|
||||
QMarginsF resizeOnlyBorders;
|
||||
|
||||
Qt::WindowFrameSection sectionUnderMouse;
|
||||
void setSectionUnderMouse(Qt::WindowFrameSection section);
|
||||
void updateSectionUnderMouse(const QPoint &mousePosition);
|
||||
|
||||
QRectF titleBar;
|
||||
QRegion blurRegion;
|
||||
|
||||
void addButton(DecorationButton *button);
|
||||
|
||||
std::shared_ptr<DecorationSettings> settings;
|
||||
DecorationBridge *bridge;
|
||||
std::shared_ptr<DecoratedWindow> client;
|
||||
bool opaque;
|
||||
QList<DecorationButton *> buttons;
|
||||
std::shared_ptr<DecorationShadow> shadow;
|
||||
std::shared_ptr<DecorationState> next;
|
||||
std::shared_ptr<DecorationState> current;
|
||||
|
||||
private:
|
||||
Decoration *q;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,601 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "decorationbutton.h"
|
||||
#include "decoratedwindow.h"
|
||||
#include "decoration.h"
|
||||
#include "decoration_p.h"
|
||||
#include "decorationbutton_p.h"
|
||||
#include "decorationsettings.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QElapsedTimer>
|
||||
#include <QGuiApplication>
|
||||
#include <QHoverEvent>
|
||||
#include <QStyleHints>
|
||||
#include <QTimer>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#ifndef K_DOXYGEN
|
||||
size_t qHash(const KDecoration3::DecorationButtonType &type, size_t seed)
|
||||
{
|
||||
return qHash(uint(type), seed);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
|
||||
DecorationButton::Private::Private(DecorationButtonType type, const QPointer<Decoration> &decoration, DecorationButton *parent)
|
||||
: decoration(decoration)
|
||||
, type(type)
|
||||
, hovered(false)
|
||||
, enabled(true)
|
||||
, checkable(false)
|
||||
, checked(false)
|
||||
, visible(true)
|
||||
, acceptedButtons(Qt::LeftButton)
|
||||
, doubleClickEnabled(false)
|
||||
, pressAndHold(false)
|
||||
, q(parent)
|
||||
, m_pressed(Qt::NoButton)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
DecorationButton::Private::~Private() = default;
|
||||
|
||||
void DecorationButton::Private::init()
|
||||
{
|
||||
auto c = decoration->window();
|
||||
auto settings = decoration->settings();
|
||||
switch (type) {
|
||||
case DecorationButtonType::Menu:
|
||||
QObject::connect(
|
||||
q,
|
||||
&DecorationButton::clicked,
|
||||
decoration.data(),
|
||||
[this](Qt::MouseButton button) {
|
||||
Q_UNUSED(button)
|
||||
decoration->requestShowWindowMenu(q->geometry().toRect());
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
QObject::connect(q, &DecorationButton::doubleClicked, decoration.data(), &Decoration::requestClose, Qt::QueuedConnection);
|
||||
QObject::connect(
|
||||
settings.get(),
|
||||
&DecorationSettings::closeOnDoubleClickOnMenuChanged,
|
||||
q,
|
||||
[this](bool enabled) {
|
||||
doubleClickEnabled = enabled;
|
||||
setPressAndHold(enabled);
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
doubleClickEnabled = settings->isCloseOnDoubleClickOnMenu();
|
||||
setPressAndHold(settings->isCloseOnDoubleClickOnMenu());
|
||||
setAcceptedButtons(Qt::LeftButton | Qt::RightButton);
|
||||
break;
|
||||
case DecorationButtonType::ApplicationMenu:
|
||||
setVisible(c->hasApplicationMenu());
|
||||
setCheckable(true); // will be "checked" whilst the menu is opened
|
||||
// FIXME TODO connect directly and figure out the button geometry/offset stuff
|
||||
QObject::connect(
|
||||
q,
|
||||
&DecorationButton::clicked,
|
||||
decoration.data(),
|
||||
[this] {
|
||||
decoration->requestShowApplicationMenu(q->geometry().toRect(), 0 /* actionId */);
|
||||
},
|
||||
Qt::QueuedConnection); //&Decoration::requestShowApplicationMenu, Qt::QueuedConnection);
|
||||
QObject::connect(c, &DecoratedWindow::hasApplicationMenuChanged, q, &DecorationButton::setVisible);
|
||||
QObject::connect(c, &DecoratedWindow::applicationMenuActiveChanged, q, &DecorationButton::setChecked);
|
||||
break;
|
||||
case DecorationButtonType::OnAllDesktops:
|
||||
setVisible(settings->isOnAllDesktopsAvailable());
|
||||
setCheckable(true);
|
||||
setChecked(c->isOnAllDesktops());
|
||||
QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestToggleOnAllDesktops, Qt::QueuedConnection);
|
||||
QObject::connect(settings.get(), &DecorationSettings::onAllDesktopsAvailableChanged, q, &DecorationButton::setVisible);
|
||||
QObject::connect(c, &DecoratedWindow::onAllDesktopsChanged, q, &DecorationButton::setChecked);
|
||||
break;
|
||||
case DecorationButtonType::Minimize:
|
||||
setEnabled(c->isMinimizeable());
|
||||
QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestMinimize, Qt::QueuedConnection);
|
||||
QObject::connect(c, &DecoratedWindow::minimizeableChanged, q, &DecorationButton::setEnabled);
|
||||
break;
|
||||
case DecorationButtonType::Maximize:
|
||||
setEnabled(c->isMaximizeable());
|
||||
setCheckable(true);
|
||||
setChecked(c->isMaximized());
|
||||
setAcceptedButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton);
|
||||
QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestToggleMaximization, Qt::QueuedConnection);
|
||||
QObject::connect(c, &DecoratedWindow::maximizeableChanged, q, &DecorationButton::setEnabled);
|
||||
QObject::connect(c, &DecoratedWindow::maximizedChanged, q, &DecorationButton::setChecked);
|
||||
break;
|
||||
case DecorationButtonType::Close:
|
||||
setEnabled(c->isCloseable());
|
||||
QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestClose, Qt::QueuedConnection);
|
||||
QObject::connect(c, &DecoratedWindow::closeableChanged, q, &DecorationButton::setEnabled);
|
||||
break;
|
||||
case DecorationButtonType::ContextHelp:
|
||||
setVisible(c->providesContextHelp());
|
||||
QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestContextHelp, Qt::QueuedConnection);
|
||||
QObject::connect(c, &DecoratedWindow::providesContextHelpChanged, q, &DecorationButton::setVisible);
|
||||
break;
|
||||
case DecorationButtonType::KeepAbove:
|
||||
setCheckable(true);
|
||||
setChecked(c->isKeepAbove());
|
||||
QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestToggleKeepAbove, Qt::QueuedConnection);
|
||||
QObject::connect(c, &DecoratedWindow::keepAboveChanged, q, &DecorationButton::setChecked);
|
||||
break;
|
||||
case DecorationButtonType::KeepBelow:
|
||||
setCheckable(true);
|
||||
setChecked(c->isKeepBelow());
|
||||
QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestToggleKeepBelow, Qt::QueuedConnection);
|
||||
QObject::connect(c, &DecoratedWindow::keepBelowChanged, q, &DecorationButton::setChecked);
|
||||
break;
|
||||
case DecorationButtonType::Shade:
|
||||
setEnabled(c->isShadeable());
|
||||
setCheckable(true);
|
||||
setChecked(c->isShaded());
|
||||
QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestToggleShade, Qt::QueuedConnection);
|
||||
QObject::connect(c, &DecoratedWindow::shadedChanged, q, &DecorationButton::setChecked);
|
||||
QObject::connect(c, &DecoratedWindow::shadeableChanged, q, &DecorationButton::setEnabled);
|
||||
break;
|
||||
case DecorationButtonType::Spacer:
|
||||
setEnabled(false);
|
||||
break;
|
||||
default:
|
||||
// nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationButton::Private::setHovered(bool set)
|
||||
{
|
||||
if (hovered == set) {
|
||||
return;
|
||||
}
|
||||
hovered = set;
|
||||
Q_EMIT q->hoveredChanged(hovered);
|
||||
}
|
||||
|
||||
void DecorationButton::Private::setEnabled(bool set)
|
||||
{
|
||||
if (enabled == set) {
|
||||
return;
|
||||
}
|
||||
enabled = set;
|
||||
Q_EMIT q->enabledChanged(enabled);
|
||||
if (!enabled) {
|
||||
setHovered(false);
|
||||
if (isPressed()) {
|
||||
m_pressed = Qt::NoButton;
|
||||
Q_EMIT q->pressedChanged(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationButton::Private::setVisible(bool set)
|
||||
{
|
||||
if (visible == set) {
|
||||
return;
|
||||
}
|
||||
visible = set;
|
||||
Q_EMIT q->visibilityChanged(set);
|
||||
if (!visible) {
|
||||
setHovered(false);
|
||||
if (isPressed()) {
|
||||
m_pressed = Qt::NoButton;
|
||||
Q_EMIT q->pressedChanged(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationButton::Private::setChecked(bool set)
|
||||
{
|
||||
if (!checkable || checked == set) {
|
||||
return;
|
||||
}
|
||||
checked = set;
|
||||
Q_EMIT q->checkedChanged(checked);
|
||||
}
|
||||
|
||||
void DecorationButton::Private::setCheckable(bool set)
|
||||
{
|
||||
if (checkable == set) {
|
||||
return;
|
||||
}
|
||||
if (!set) {
|
||||
setChecked(false);
|
||||
}
|
||||
checkable = set;
|
||||
Q_EMIT q->checkableChanged(checkable);
|
||||
}
|
||||
|
||||
void DecorationButton::Private::setPressed(Qt::MouseButton button, bool pressed)
|
||||
{
|
||||
if (pressed) {
|
||||
m_pressed = m_pressed | button;
|
||||
} else {
|
||||
m_pressed = m_pressed & ~button;
|
||||
}
|
||||
Q_EMIT q->pressedChanged(isPressed());
|
||||
}
|
||||
|
||||
void DecorationButton::Private::setAcceptedButtons(Qt::MouseButtons buttons)
|
||||
{
|
||||
if (acceptedButtons == buttons) {
|
||||
return;
|
||||
}
|
||||
acceptedButtons = buttons;
|
||||
Q_EMIT q->acceptedButtonsChanged(acceptedButtons);
|
||||
}
|
||||
|
||||
void DecorationButton::Private::startDoubleClickTimer()
|
||||
{
|
||||
if (!doubleClickEnabled) {
|
||||
return;
|
||||
}
|
||||
if (!m_doubleClickTimer) {
|
||||
m_doubleClickTimer = std::make_unique<QElapsedTimer>();
|
||||
}
|
||||
m_doubleClickTimer->start();
|
||||
}
|
||||
|
||||
void DecorationButton::Private::invalidateDoubleClickTimer()
|
||||
{
|
||||
if (!m_doubleClickTimer) {
|
||||
return;
|
||||
}
|
||||
m_doubleClickTimer->invalidate();
|
||||
}
|
||||
|
||||
bool DecorationButton::Private::wasDoubleClick() const
|
||||
{
|
||||
if (!m_doubleClickTimer || !m_doubleClickTimer->isValid()) {
|
||||
return false;
|
||||
}
|
||||
return !m_doubleClickTimer->hasExpired(QGuiApplication::styleHints()->mouseDoubleClickInterval());
|
||||
}
|
||||
|
||||
void DecorationButton::Private::setPressAndHold(bool enable)
|
||||
{
|
||||
if (pressAndHold == enable) {
|
||||
return;
|
||||
}
|
||||
pressAndHold = enable;
|
||||
if (!pressAndHold) {
|
||||
m_pressAndHoldTimer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationButton::Private::startPressAndHold()
|
||||
{
|
||||
if (!pressAndHold) {
|
||||
return;
|
||||
}
|
||||
if (!m_pressAndHoldTimer) {
|
||||
m_pressAndHoldTimer.reset(new QTimer());
|
||||
m_pressAndHoldTimer->setSingleShot(true);
|
||||
QObject::connect(m_pressAndHoldTimer.get(), &QTimer::timeout, q, [this]() {
|
||||
q->clicked(Qt::LeftButton);
|
||||
});
|
||||
}
|
||||
m_pressAndHoldTimer->start(QGuiApplication::styleHints()->mousePressAndHoldInterval());
|
||||
}
|
||||
|
||||
void DecorationButton::Private::stopPressAndHold()
|
||||
{
|
||||
if (m_pressAndHoldTimer) {
|
||||
m_pressAndHoldTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
QString DecorationButton::Private::typeToString(DecorationButtonType type)
|
||||
{
|
||||
switch (type) {
|
||||
case DecorationButtonType::Menu:
|
||||
return i18n("More actions for this window");
|
||||
case DecorationButtonType::ApplicationMenu:
|
||||
return i18n("Application menu");
|
||||
case DecorationButtonType::OnAllDesktops:
|
||||
if (this->q->isChecked())
|
||||
return i18n("On one desktop");
|
||||
else
|
||||
return i18n("On all desktops");
|
||||
case DecorationButtonType::Minimize:
|
||||
return i18n("Minimize");
|
||||
case DecorationButtonType::Maximize:
|
||||
if (this->q->isChecked())
|
||||
return i18n("Restore");
|
||||
else
|
||||
return i18n("Maximize");
|
||||
case DecorationButtonType::Close:
|
||||
return i18n("Close");
|
||||
case DecorationButtonType::ContextHelp:
|
||||
return i18n("Context help");
|
||||
case DecorationButtonType::Shade:
|
||||
if (this->q->isChecked())
|
||||
return i18n("Unshade");
|
||||
else
|
||||
return i18n("Shade");
|
||||
case DecorationButtonType::KeepBelow:
|
||||
if (this->q->isChecked())
|
||||
return i18n("Don't keep below other windows");
|
||||
else
|
||||
return i18n("Keep below other windows");
|
||||
case DecorationButtonType::KeepAbove:
|
||||
if (this->q->isChecked())
|
||||
return i18n("Don't keep above other windows");
|
||||
else
|
||||
return i18n("Keep above other windows");
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
DecorationButton::DecorationButton(DecorationButtonType type, Decoration *decoration, QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new Private(type, decoration, this))
|
||||
{
|
||||
decoration->d->addButton(this);
|
||||
connect(this, &DecorationButton::geometryChanged, this, static_cast<void (DecorationButton::*)(const QRectF &)>(&DecorationButton::update));
|
||||
auto updateSlot = static_cast<void (DecorationButton::*)()>(&DecorationButton::update);
|
||||
connect(this, &DecorationButton::hoveredChanged, this, updateSlot);
|
||||
connect(this, &DecorationButton::hoveredChanged, this, [this](bool hovered) {
|
||||
if (hovered) {
|
||||
// TODO: show tooltip if hovered and hide if not
|
||||
const QString type = this->d->typeToString(this->type());
|
||||
this->decoration()->requestShowToolTip(type);
|
||||
} else {
|
||||
this->decoration()->requestHideToolTip();
|
||||
}
|
||||
});
|
||||
connect(this, &DecorationButton::pressedChanged, this, updateSlot);
|
||||
connect(this, &DecorationButton::pressedChanged, this, [this](bool pressed) {
|
||||
if (pressed) {
|
||||
this->decoration()->requestHideToolTip();
|
||||
}
|
||||
});
|
||||
connect(this, &DecorationButton::checkedChanged, this, updateSlot);
|
||||
connect(this, &DecorationButton::enabledChanged, this, updateSlot);
|
||||
connect(this, &DecorationButton::visibilityChanged, this, updateSlot);
|
||||
connect(this, &DecorationButton::hoveredChanged, this, [this](bool hovered) {
|
||||
if (hovered) {
|
||||
Q_EMIT pointerEntered();
|
||||
} else {
|
||||
Q_EMIT pointerLeft();
|
||||
}
|
||||
});
|
||||
connect(this, &DecorationButton::pressedChanged, this, [this](bool p) {
|
||||
if (p) {
|
||||
Q_EMIT pressed();
|
||||
} else {
|
||||
Q_EMIT released();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
DecorationButton::~DecorationButton() = default;
|
||||
|
||||
void DecorationButton::update(const QRectF &rect)
|
||||
{
|
||||
decoration()->update(rect.isNull() ? geometry().toRect() : rect.toRect());
|
||||
}
|
||||
|
||||
void DecorationButton::update()
|
||||
{
|
||||
update(QRectF());
|
||||
}
|
||||
|
||||
QSizeF DecorationButton::size() const
|
||||
{
|
||||
return d->geometry.size();
|
||||
}
|
||||
|
||||
bool DecorationButton::isPressed() const
|
||||
{
|
||||
return d->isPressed();
|
||||
}
|
||||
|
||||
bool DecorationButton::isHovered() const
|
||||
{
|
||||
return d->hovered;
|
||||
}
|
||||
|
||||
bool DecorationButton::isEnabled() const
|
||||
{
|
||||
return d->enabled;
|
||||
}
|
||||
|
||||
bool DecorationButton::isChecked() const
|
||||
{
|
||||
return d->checked;
|
||||
}
|
||||
|
||||
bool DecorationButton::isCheckable() const
|
||||
{
|
||||
return d->checkable;
|
||||
}
|
||||
|
||||
bool DecorationButton::isVisible() const
|
||||
{
|
||||
return d->visible;
|
||||
}
|
||||
|
||||
QRectF DecorationButton::geometry() const
|
||||
{
|
||||
return d->geometry;
|
||||
}
|
||||
|
||||
Decoration *DecorationButton::decoration() const
|
||||
{
|
||||
return d->decoration;
|
||||
}
|
||||
|
||||
Qt::MouseButtons DecorationButton::acceptedButtons() const
|
||||
{
|
||||
return d->acceptedButtons;
|
||||
}
|
||||
|
||||
DecorationButtonType DecorationButton::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
void DecorationButton::setAcceptedButtons(Qt::MouseButtons value)
|
||||
{
|
||||
d->setAcceptedButtons(value);
|
||||
}
|
||||
|
||||
void DecorationButton::setEnabled(bool value)
|
||||
{
|
||||
d->setEnabled(value);
|
||||
}
|
||||
|
||||
void DecorationButton::setChecked(bool value)
|
||||
{
|
||||
d->setChecked(value);
|
||||
}
|
||||
|
||||
void DecorationButton::setCheckable(bool value)
|
||||
{
|
||||
d->setCheckable(value);
|
||||
}
|
||||
|
||||
void DecorationButton::setVisible(bool value)
|
||||
{
|
||||
d->setVisible(value);
|
||||
}
|
||||
|
||||
void DecorationButton::setGeometry(const QRectF &geometry)
|
||||
{
|
||||
if (d->geometry == geometry) {
|
||||
return;
|
||||
}
|
||||
d->geometry = geometry;
|
||||
Q_EMIT geometryChanged(d->geometry);
|
||||
}
|
||||
|
||||
bool DecorationButton::contains(const QPointF &pos) const
|
||||
{
|
||||
auto flooredPoint = QPoint(std::floor(pos.x()), std::floor(pos.y()));
|
||||
return d->geometry.toRect().contains(flooredPoint);
|
||||
}
|
||||
|
||||
bool DecorationButton::event(QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::HoverEnter:
|
||||
hoverEnterEvent(static_cast<QHoverEvent *>(event));
|
||||
return true;
|
||||
case QEvent::HoverLeave:
|
||||
hoverLeaveEvent(static_cast<QHoverEvent *>(event));
|
||||
return true;
|
||||
case QEvent::HoverMove:
|
||||
hoverMoveEvent(static_cast<QHoverEvent *>(event));
|
||||
return true;
|
||||
case QEvent::MouseButtonPress:
|
||||
mousePressEvent(static_cast<QMouseEvent *>(event));
|
||||
return true;
|
||||
case QEvent::MouseButtonRelease:
|
||||
mouseReleaseEvent(static_cast<QMouseEvent *>(event));
|
||||
return true;
|
||||
case QEvent::MouseMove:
|
||||
mouseMoveEvent(static_cast<QMouseEvent *>(event));
|
||||
return true;
|
||||
case QEvent::Wheel:
|
||||
wheelEvent(static_cast<QWheelEvent *>(event));
|
||||
return true;
|
||||
default:
|
||||
return QObject::event(event);
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationButton::hoverEnterEvent(QHoverEvent *event)
|
||||
{
|
||||
if (!d->enabled || !d->visible || !contains(event->position())) {
|
||||
return;
|
||||
}
|
||||
d->setHovered(true);
|
||||
event->setAccepted(true);
|
||||
}
|
||||
|
||||
void DecorationButton::hoverLeaveEvent(QHoverEvent *event)
|
||||
{
|
||||
if (!d->enabled || !d->visible || !d->hovered || contains(event->position())) {
|
||||
return;
|
||||
}
|
||||
d->setHovered(false);
|
||||
event->setAccepted(true);
|
||||
}
|
||||
|
||||
void DecorationButton::hoverMoveEvent(QHoverEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
}
|
||||
|
||||
void DecorationButton::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (!d->enabled || !d->visible || !d->hovered) {
|
||||
return;
|
||||
}
|
||||
if (!contains(event->position())) {
|
||||
d->setHovered(false);
|
||||
event->setAccepted(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationButton::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (!d->enabled || !d->visible || !contains(event->position()) || !d->acceptedButtons.testFlag(event->button())) {
|
||||
return;
|
||||
}
|
||||
d->setPressed(event->button(), true);
|
||||
event->setAccepted(true);
|
||||
if (d->doubleClickEnabled && event->button() == Qt::LeftButton) {
|
||||
// check for double click
|
||||
if (d->wasDoubleClick()) {
|
||||
event->setAccepted(true);
|
||||
Q_EMIT doubleClicked();
|
||||
}
|
||||
d->invalidateDoubleClickTimer();
|
||||
}
|
||||
if (d->pressAndHold && event->button() == Qt::LeftButton) {
|
||||
d->startPressAndHold();
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationButton::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (!d->enabled || !d->visible || !d->isPressed(event->button())) {
|
||||
return;
|
||||
}
|
||||
if (contains(event->position())) {
|
||||
if (!d->pressAndHold || event->button() != Qt::LeftButton) {
|
||||
Q_EMIT clicked(event->button());
|
||||
} else {
|
||||
d->stopPressAndHold();
|
||||
}
|
||||
}
|
||||
d->setPressed(event->button(), false);
|
||||
event->setAccepted(true);
|
||||
|
||||
if (d->doubleClickEnabled && event->button() == Qt::LeftButton) {
|
||||
d->startDoubleClickTimer();
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationButton::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "moc_decorationbutton.cpp"
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "decorationdefines.h"
|
||||
#include <kdecoration3/kdecoration3_export.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QRect>
|
||||
|
||||
class QHoverEvent;
|
||||
class QMouseEvent;
|
||||
class QPainter;
|
||||
class QWheelEvent;
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class DecorationButtonPrivate;
|
||||
class Decoration;
|
||||
|
||||
/**
|
||||
* @brief A button to be used in a Decoration.
|
||||
*
|
||||
* The DecorationButton is a simple Button which can be used (but doesn't have to) in a Decoration.
|
||||
* It takes care of the input handling and triggers the correct state change methods on the
|
||||
* Decoration.
|
||||
*
|
||||
* This simplifies the handling of DecorationButtons. A Decoration implementation just needs to
|
||||
* subclass DecorationButton and implement the paint method. Everything else is handled by the
|
||||
* DecorationButton.
|
||||
*
|
||||
* For positioning the DecorationButtons it's recommended to use a DecorationButtonGroup.
|
||||
*
|
||||
* @see Decoration
|
||||
* @see DecorationButtonGroup
|
||||
**/
|
||||
class KDECORATIONS3_EXPORT DecorationButton : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
* Whether the DecorationButton is visible. By default this is @c true, OnAllDesktops and
|
||||
* QuickHelp depend on the DecoratedWindow's state.
|
||||
**/
|
||||
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibilityChanged)
|
||||
/**
|
||||
* Whether the DecorationButton is currently pressed.
|
||||
**/
|
||||
Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged)
|
||||
/**
|
||||
* Whether the DecorationButton is currently hovered.
|
||||
**/
|
||||
Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged)
|
||||
/**
|
||||
* Whether the DecorationButton is enabled. Only an enabled button accepts hover and mouse
|
||||
* press events.
|
||||
**/
|
||||
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
|
||||
/**
|
||||
* Whether the DecorationButton can be checked. This is used for state aware DecorationButtons
|
||||
* like Maximize, Shade, KeepAbove, KeepBelow and OnAllDesktops.
|
||||
**/
|
||||
Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged)
|
||||
/**
|
||||
* Whether the DecorationButton is checked. A DecorationButton can only be checked if the
|
||||
* DecorationButton is checkable. Note: the checked state is not changed by clicking the
|
||||
* DecorationButton. It gets changed if the DecoratedWindow changes it's state, though.
|
||||
**/
|
||||
Q_PROPERTY(bool checked READ isChecked WRITE setChecked NOTIFY checkedChanged)
|
||||
/**
|
||||
* The geometry of the DecorationButton in Decoration-local coordinates.
|
||||
**/
|
||||
Q_PROPERTY(QRectF geometry READ geometry NOTIFY geometryChanged)
|
||||
/**
|
||||
* The mouse buttons the DecorationButton accepts. By default the Qt::LeftButton gets accepted,
|
||||
* for some types more buttons are accepted.
|
||||
**/
|
||||
Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged)
|
||||
public:
|
||||
~DecorationButton() override;
|
||||
|
||||
QRectF geometry() const;
|
||||
QSizeF size() const;
|
||||
void setGeometry(const QRectF &geometry);
|
||||
|
||||
bool isVisible() const;
|
||||
bool isPressed() const;
|
||||
bool isHovered() const;
|
||||
bool isEnabled() const;
|
||||
bool isChecked() const;
|
||||
bool isCheckable() const;
|
||||
DecorationButtonType type() const;
|
||||
|
||||
/**
|
||||
* Returns @c true if @p pos is inside of the button, otherwise returns @c false.
|
||||
**/
|
||||
bool contains(const QPointF &pos) const;
|
||||
|
||||
Qt::MouseButtons acceptedButtons() const;
|
||||
void setAcceptedButtons(Qt::MouseButtons buttons);
|
||||
|
||||
/**
|
||||
* Invoked for painting this DecorationButtons. Implementing sub-classes need to implement
|
||||
* this method. The coordinate system of the QPainter is set to Decoration coordinates.
|
||||
*
|
||||
* This method will be invoked from the rendering thread.
|
||||
*
|
||||
* @param painter The QPainter to paint this DecorationButton.
|
||||
* @param repaintArea The area which is going to be repainted in Decoration coordinates
|
||||
**/
|
||||
virtual void paint(QPainter *painter, const QRectF &repaintArea) = 0;
|
||||
|
||||
Decoration *decoration() const;
|
||||
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setEnabled(bool enabled);
|
||||
void setCheckable(bool checkable);
|
||||
void setChecked(bool checked);
|
||||
void setVisible(bool visible);
|
||||
|
||||
/**
|
||||
* Schedules a repaint of the DecorationButton.
|
||||
* Calling update will eventually result in paint being invoked.
|
||||
*
|
||||
* @param rect The area to repaint in Decoration local coordinates, a null QRect updates the complete geometry
|
||||
* @see paint
|
||||
**/
|
||||
void update(const QRectF &rect);
|
||||
/**
|
||||
* Schedules a repaint of the DecorationButton.
|
||||
*
|
||||
* Overloaded method for convenience.
|
||||
**/
|
||||
void update();
|
||||
|
||||
Q_SIGNALS:
|
||||
void clicked(Qt::MouseButton);
|
||||
void pressed();
|
||||
void released();
|
||||
void pointerEntered();
|
||||
void pointerLeft();
|
||||
void doubleClicked();
|
||||
|
||||
void pressedChanged(bool);
|
||||
void hoveredChanged(bool);
|
||||
void enabledChanged(bool);
|
||||
void checkableChanged(bool);
|
||||
void checkedChanged(bool);
|
||||
void geometryChanged(const QRectF &);
|
||||
void acceptedButtonsChanged(Qt::MouseButtons);
|
||||
void visibilityChanged(bool);
|
||||
|
||||
protected:
|
||||
explicit DecorationButton(DecorationButtonType type, Decoration *decoration, QObject *parent = nullptr);
|
||||
|
||||
virtual void hoverEnterEvent(QHoverEvent *event);
|
||||
virtual void hoverLeaveEvent(QHoverEvent *event);
|
||||
virtual void hoverMoveEvent(QHoverEvent *event);
|
||||
virtual void mouseMoveEvent(QMouseEvent *event);
|
||||
virtual void mousePressEvent(QMouseEvent *event);
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event);
|
||||
virtual void wheelEvent(QWheelEvent *event);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifndef K_DOXYGEN
|
||||
size_t KDECORATIONS3_EXPORT qHash(const KDecoration3::DecorationButtonType &type, size_t seed = 0);
|
||||
#endif
|
||||
|
||||
Q_DECLARE_METATYPE(KDecoration3::DecorationButtonType)
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "decorationbutton.h"
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
class QElapsedTimer;
|
||||
class QTimer;
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the KDecoration3 API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class Q_DECL_HIDDEN DecorationButton::Private
|
||||
{
|
||||
public:
|
||||
explicit Private(DecorationButtonType type, const QPointer<Decoration> &decoration, DecorationButton *parent);
|
||||
~Private();
|
||||
|
||||
bool isPressed() const
|
||||
{
|
||||
return m_pressed != Qt::NoButton;
|
||||
}
|
||||
bool isPressed(Qt::MouseButton button) const
|
||||
{
|
||||
return m_pressed.testFlag(button);
|
||||
}
|
||||
|
||||
void setHovered(bool hovered);
|
||||
void setPressed(Qt::MouseButton, bool pressed);
|
||||
void setAcceptedButtons(Qt::MouseButtons buttons);
|
||||
void setEnabled(bool enabled);
|
||||
void setChecked(bool checked);
|
||||
void setCheckable(bool checkable);
|
||||
void setVisible(bool visible);
|
||||
void startDoubleClickTimer();
|
||||
void invalidateDoubleClickTimer();
|
||||
bool wasDoubleClick() const;
|
||||
void setPressAndHold(bool enable);
|
||||
void startPressAndHold();
|
||||
void stopPressAndHold();
|
||||
|
||||
QString typeToString(DecorationButtonType type);
|
||||
|
||||
QPointer<Decoration> decoration;
|
||||
DecorationButtonType type;
|
||||
QRectF geometry;
|
||||
bool hovered;
|
||||
bool enabled;
|
||||
bool checkable;
|
||||
bool checked;
|
||||
bool visible;
|
||||
Qt::MouseButtons acceptedButtons;
|
||||
bool doubleClickEnabled;
|
||||
bool pressAndHold;
|
||||
|
||||
private:
|
||||
void init();
|
||||
DecorationButton *q;
|
||||
Qt::MouseButtons m_pressed;
|
||||
std::unique_ptr<QElapsedTimer> m_doubleClickTimer;
|
||||
std::unique_ptr<QTimer> m_pressAndHoldTimer;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "decorationbuttongroup.h"
|
||||
#include "decoration.h"
|
||||
#include "decorationbuttongroup_p.h"
|
||||
#include "decorationsettings.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QGuiApplication>
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
DecorationButtonGroup::Private::Private(Decoration *decoration, DecorationButtonGroup *parent)
|
||||
: decoration(decoration)
|
||||
, spacing(0.0)
|
||||
, q(parent)
|
||||
{
|
||||
}
|
||||
|
||||
DecorationButtonGroup::Private::~Private() = default;
|
||||
|
||||
void DecorationButtonGroup::Private::setGeometry(const QRectF &geo)
|
||||
{
|
||||
if (geometry == geo) {
|
||||
return;
|
||||
}
|
||||
geometry = geo;
|
||||
Q_EMIT q->geometryChanged(geometry);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
static bool s_layoutRecursion = false;
|
||||
}
|
||||
|
||||
void DecorationButtonGroup::Private::updateLayout()
|
||||
{
|
||||
if (s_layoutRecursion) {
|
||||
return;
|
||||
}
|
||||
s_layoutRecursion = true;
|
||||
const QPointF &pos = geometry.topLeft();
|
||||
// first calculate new size
|
||||
qreal height = 0;
|
||||
qreal width = 0;
|
||||
for (auto it = buttons.constBegin(); it != buttons.constEnd(); ++it) {
|
||||
if (!(*it)->isVisible()) {
|
||||
continue;
|
||||
}
|
||||
height = qMax(height, qreal((*it)->size().height()));
|
||||
width += (*it)->size().width();
|
||||
if (it + 1 != buttons.constEnd()) {
|
||||
width += spacing;
|
||||
}
|
||||
}
|
||||
setGeometry(QRectF(pos, QSizeF(width, height)));
|
||||
|
||||
QGuiApplication* app = qobject_cast<QGuiApplication*>(QCoreApplication::instance());
|
||||
const auto layoutDirection = app ? app->layoutDirection() : Qt::LeftToRight;
|
||||
|
||||
qreal leftPosition = pos.x();
|
||||
qreal rightPosition = pos.x() + width;
|
||||
|
||||
if (layoutDirection == Qt::LeftToRight)
|
||||
for (auto button : std::as_const(buttons)) {
|
||||
if (!button->isVisible()) {
|
||||
continue;
|
||||
}
|
||||
const auto size = button->size();
|
||||
const auto buttonPos = QPointF(leftPosition, pos.y());
|
||||
button->setGeometry(QRectF(buttonPos, size));
|
||||
leftPosition += size.width() + spacing;
|
||||
}
|
||||
else if (layoutDirection == Qt::RightToLeft)
|
||||
for (auto button : std::as_const(buttons)) {
|
||||
if (!button->isVisible()) {
|
||||
continue;
|
||||
}
|
||||
const auto size = button->size();
|
||||
const auto buttonPos = QPointF(rightPosition - size.width(), pos.y());
|
||||
button->setGeometry(QRectF(buttonPos, size));
|
||||
rightPosition -= size.width() + spacing;
|
||||
}
|
||||
else {
|
||||
qCritical() << "There's an unhandled layout direction! This is likely an issue of KDecoration3 not being updated to handle it\n"
|
||||
<< "or the application having an invalid layout direction set. Either way, this is a critical bug.";
|
||||
}
|
||||
|
||||
s_layoutRecursion = false;
|
||||
}
|
||||
|
||||
DecorationButtonGroup::DecorationButtonGroup(Decoration *parent)
|
||||
: QObject(parent)
|
||||
, d(new Private(parent, this))
|
||||
{
|
||||
}
|
||||
|
||||
DecorationButtonGroup::DecorationButtonGroup(DecorationButtonGroup::Position type,
|
||||
Decoration *parent,
|
||||
std::function<DecorationButton *(DecorationButtonType, Decoration *, QObject *)> buttonCreator)
|
||||
: QObject(parent)
|
||||
, d(new Private(parent, this))
|
||||
{
|
||||
auto createButtons = [this, buttonCreator, type] {
|
||||
const Qt::LayoutDirection layoutDirection = QGuiApplication::layoutDirection();
|
||||
const DecorationSettings *settings = d->decoration->settings().get();
|
||||
const auto &buttons =
|
||||
(type == Position::Left) ?
|
||||
(layoutDirection == Qt::LeftToRight ? settings->decorationButtonsLeft() : settings->decorationButtonsRight()) :
|
||||
(layoutDirection == Qt::LeftToRight ? settings->decorationButtonsRight() : settings->decorationButtonsLeft());
|
||||
for (DecorationButtonType type : buttons) {
|
||||
if (DecorationButton *b = buttonCreator(type, d->decoration, this)) {
|
||||
addButton(b);
|
||||
}
|
||||
}
|
||||
};
|
||||
createButtons();
|
||||
auto changed = type == Position::Left ? &DecorationSettings::decorationButtonsLeftChanged : &DecorationSettings::decorationButtonsRightChanged;
|
||||
connect(parent->settings().get(), changed, this, [this, createButtons] {
|
||||
qDeleteAll(d->buttons);
|
||||
d->buttons.clear();
|
||||
createButtons();
|
||||
});
|
||||
}
|
||||
|
||||
DecorationButtonGroup::~DecorationButtonGroup() = default;
|
||||
|
||||
Decoration *DecorationButtonGroup::decoration() const
|
||||
{
|
||||
return d->decoration;
|
||||
}
|
||||
|
||||
QRectF DecorationButtonGroup::geometry() const
|
||||
{
|
||||
return d->geometry;
|
||||
}
|
||||
|
||||
bool DecorationButtonGroup::hasButton(DecorationButtonType type) const
|
||||
{
|
||||
// TODO: check for deletion of button
|
||||
auto it = std::find_if(d->buttons.begin(), d->buttons.end(), [type](DecorationButton *button) {
|
||||
return button->type() == type;
|
||||
});
|
||||
return it != d->buttons.end();
|
||||
}
|
||||
|
||||
qreal DecorationButtonGroup::spacing() const
|
||||
{
|
||||
return d->spacing;
|
||||
}
|
||||
|
||||
QPointF DecorationButtonGroup::pos() const
|
||||
{
|
||||
return d->geometry.topLeft();
|
||||
}
|
||||
|
||||
void DecorationButtonGroup::setPos(const QPointF &pos)
|
||||
{
|
||||
if (d->geometry.topLeft() == pos) {
|
||||
return;
|
||||
}
|
||||
d->setGeometry(QRectF(pos, d->geometry.size()));
|
||||
d->updateLayout();
|
||||
}
|
||||
|
||||
void DecorationButtonGroup::setSpacing(qreal spacing)
|
||||
{
|
||||
if (d->spacing == spacing) {
|
||||
return;
|
||||
}
|
||||
d->spacing = spacing;
|
||||
Q_EMIT spacingChanged(d->spacing);
|
||||
d->updateLayout();
|
||||
}
|
||||
|
||||
void DecorationButtonGroup::addButton(DecorationButton *button)
|
||||
{
|
||||
Q_ASSERT(button);
|
||||
connect(button, &DecorationButton::visibilityChanged, this, [this]() {
|
||||
d->updateLayout();
|
||||
});
|
||||
connect(button, &DecorationButton::geometryChanged, this, [this]() {
|
||||
d->updateLayout();
|
||||
});
|
||||
d->buttons.append(button);
|
||||
d->updateLayout();
|
||||
}
|
||||
|
||||
QList<DecorationButton *> DecorationButtonGroup::buttons() const
|
||||
{
|
||||
return d->buttons;
|
||||
}
|
||||
|
||||
void DecorationButtonGroup::removeButton(DecorationButtonType type)
|
||||
{
|
||||
bool needUpdate = false;
|
||||
auto it = d->buttons.begin();
|
||||
while (it != d->buttons.end()) {
|
||||
if ((*it)->type() == type) {
|
||||
it = d->buttons.erase(it);
|
||||
needUpdate = true;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
if (needUpdate) {
|
||||
d->updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationButtonGroup::removeButton(DecorationButton *button)
|
||||
{
|
||||
bool needUpdate = false;
|
||||
auto it = d->buttons.begin();
|
||||
while (it != d->buttons.end()) {
|
||||
if (*it == button) {
|
||||
it = d->buttons.erase(it);
|
||||
needUpdate = true;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
if (needUpdate) {
|
||||
d->updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationButtonGroup::paint(QPainter *painter, const QRectF &repaintArea)
|
||||
{
|
||||
const auto &buttons = d->buttons;
|
||||
for (auto button : buttons) {
|
||||
if (!button->isVisible()) {
|
||||
continue;
|
||||
}
|
||||
button->paint(painter, repaintArea);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "moc_decorationbuttongroup.cpp"
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
#include "decorationbutton.h"
|
||||
#include <functional>
|
||||
#include <kdecoration3/kdecoration3_export.h>
|
||||
|
||||
class QPainter;
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class Decoration;
|
||||
class DecorationButtonGroupPrivate;
|
||||
|
||||
/**
|
||||
* @brief Helper class to layout DecorationButton.
|
||||
*
|
||||
* A Decoration normally has two groups of DecorationButtons: one left of the caption and one
|
||||
* right of the caption. The DecorationButtonGroup helps in positioning the DecorationButtons in
|
||||
* these groups and to update the position of each of the DecorationButtons whenever the state
|
||||
* changes in a way that they should be repositioned.
|
||||
*
|
||||
* A DecorationButtonGroup is a visual layout element not accepting input events. As a visual
|
||||
* element it provides a paint method allowing a sub class to provide custom painting for the
|
||||
* DecorationButtonGroup.
|
||||
**/
|
||||
class KDECORATIONS3_EXPORT DecorationButtonGroup : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
* The spacing to use between the DecorationButtons
|
||||
**/
|
||||
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
|
||||
/**
|
||||
* The geometry of the DecorationButtonGroup in Decoration-local coordinates.
|
||||
* The size of the DecorationButtonGroup depends on the sizes of the individual
|
||||
* DecorationButtons and the spacing.
|
||||
**/
|
||||
Q_PROPERTY(QRectF geometry READ geometry NOTIFY geometryChanged)
|
||||
// TODO: pos must consider whether it's left or right
|
||||
/**
|
||||
* The top left Position of the DecorationButtonGroup. This property needs to be
|
||||
* changed to reposition the DecorationButtonGroup. An update should normally be
|
||||
* triggered after e.g. a state change like maximization.
|
||||
**/
|
||||
Q_PROPERTY(QPointF pos READ pos WRITE setPos NOTIFY posChanged)
|
||||
public:
|
||||
enum class Position {
|
||||
Left,
|
||||
Right,
|
||||
};
|
||||
explicit DecorationButtonGroup(Position type,
|
||||
Decoration *parent,
|
||||
std::function<DecorationButton *(DecorationButtonType, Decoration *, QObject *)> buttonCreator);
|
||||
explicit DecorationButtonGroup(Decoration *parent);
|
||||
~DecorationButtonGroup() override;
|
||||
|
||||
/**
|
||||
* Paints the DecorationButtonGroup. This method should normally be invoked from the
|
||||
* Decoration's paint method. Base implementation just calls the paint method on each
|
||||
* of the DecorationButtons. Overwriting sub classes need to either call the base
|
||||
* implementation or ensure that the DecorationButtons are painted.
|
||||
*
|
||||
* @param painter The QPainter which is used to paint this DecorationButtonGroup
|
||||
* @param repaintArea The area which is going to be repainted in Decoration coordinates
|
||||
**/
|
||||
virtual void paint(QPainter *painter, const QRectF &repaintArea);
|
||||
|
||||
Decoration *decoration() const;
|
||||
|
||||
qreal spacing() const;
|
||||
void setSpacing(qreal spacing);
|
||||
|
||||
QRectF geometry() const;
|
||||
QPointF pos() const;
|
||||
void setPos(const QPointF &pos);
|
||||
|
||||
/**
|
||||
* Adds @p button to the DecorationButtonGroup and triggers a re-layout of all
|
||||
* DecorationButtons.
|
||||
**/
|
||||
void addButton(DecorationButton *button);
|
||||
/**
|
||||
* Removes @p button from the DecorationButtonGroup and triggers a re-layout of all
|
||||
* DecorationButtons.
|
||||
**/
|
||||
void removeButton(DecorationButton *button);
|
||||
/**
|
||||
* Removes all DecorationButtons with @p type from the DecorationButtonGroup and
|
||||
* triggers a re-layout of all DecorationButtons.
|
||||
**/
|
||||
void removeButton(DecorationButtonType type);
|
||||
/**
|
||||
* @returns @c true if the DecorationButtonGroup contains a DecorationButton of @p type
|
||||
**/
|
||||
bool hasButton(DecorationButtonType type) const;
|
||||
/**
|
||||
* @returns All DecorationButtons in this DecorationButtonGroup
|
||||
**/
|
||||
QList<DecorationButton *> buttons() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void spacingChanged(qreal);
|
||||
void geometryChanged(const QRectF &);
|
||||
void posChanged(const QPointF &);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
#include "decorationbuttongroup.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QRectF>
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the KDecoration3 API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class Decoration;
|
||||
|
||||
class Q_DECL_HIDDEN DecorationButtonGroup::Private
|
||||
{
|
||||
public:
|
||||
explicit Private(Decoration *decoration, DecorationButtonGroup *parent);
|
||||
~Private();
|
||||
|
||||
void setGeometry(const QRectF &geometry);
|
||||
void updateLayout();
|
||||
|
||||
Decoration *decoration;
|
||||
QRectF geometry;
|
||||
QList<DecorationButton *> buttons;
|
||||
qreal spacing;
|
||||
|
||||
private:
|
||||
DecorationButtonGroup *q;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
/**
|
||||
* The DecorationButtonType is a helper type for the DecorationButton.
|
||||
* A Decoration should provide a DecorationButton for each of the types,
|
||||
* if it wants to provide further buttons it should use the Custom type.
|
||||
* The DecorationButton gets configured depending on the type. E.g. the
|
||||
* Close button gets disabled if the DecoratedWindow is not closeable.
|
||||
**/
|
||||
enum class DecorationButtonType {
|
||||
/**
|
||||
* The Menu button requests showing the window menu on left or right click.
|
||||
**/
|
||||
Menu,
|
||||
/**
|
||||
* The ApplicationMenu button requests showing the application's menu on left or right click.
|
||||
*/
|
||||
ApplicationMenu,
|
||||
/**
|
||||
* The OnAllDesktops button requests toggling the DecoratedWindow's on all desktops state.
|
||||
* The DecoratedButton is only visible if multiple virtual desktops are available.
|
||||
**/
|
||||
OnAllDesktops,
|
||||
/**
|
||||
* The Minimize button requests minimizing the DecoratedWindow. The DecorationButton is only
|
||||
* enabled if the DecoratedWindow is minimizeable.
|
||||
**/
|
||||
Minimize,
|
||||
/**
|
||||
* The Maximize button requests maximizing the DecoratedWindow. The DecorationButton is checkable
|
||||
* and if the DecoratedWindow is maximized the DecorationButton is checked. The DecorationButton
|
||||
* supports multiple mouse buttons to change horizontal, vertical and overall maximized state.
|
||||
*
|
||||
* The DecorationButton is only enabled if the DecoratedWindow is maximizeable.
|
||||
**/
|
||||
Maximize,
|
||||
/**
|
||||
* The Close button requests closing the DecoratedWindow. The DecorationButton is only enabled
|
||||
* if the DecoratedWindow is closeable.
|
||||
**/
|
||||
Close,
|
||||
/**
|
||||
* The ContextHelp button requests entering the context help mode. The DecorationButton is only
|
||||
* visible if the DecoratedWindow provides context help.
|
||||
**/
|
||||
ContextHelp,
|
||||
/**
|
||||
* The Shade button requests toggling the DecoratedWindow's shaded state. The DecoratedButton
|
||||
* is only enabled if the DecoratedWindow is shadeable.
|
||||
**/
|
||||
Shade,
|
||||
/**
|
||||
* The KeepBelow button requests toggling the DecoratedWindow's keep below state.
|
||||
**/
|
||||
KeepBelow,
|
||||
/**
|
||||
* The KeepAbove button requests toggling the DecoratedWindow's keep above state.
|
||||
**/
|
||||
KeepAbove,
|
||||
/**
|
||||
* The Custom type allows a Decoration to provide custom DecorationButtons.
|
||||
**/
|
||||
Custom,
|
||||
/**
|
||||
* The Spacer button provides some space between buttons.
|
||||
*/
|
||||
Spacer,
|
||||
};
|
||||
|
||||
/**
|
||||
* Border sizes are a combination of visual and accessibility features.
|
||||
* Larger borders should be used to increase the non title bar borders to
|
||||
* make it easier to resize the decoration
|
||||
**/
|
||||
enum class BorderSize {
|
||||
/**
|
||||
* Border sizes of all non title bar sides should be set to 0.
|
||||
**/
|
||||
None,
|
||||
/**
|
||||
* Border sizes of the sides should be set to 0. Title bar and
|
||||
* the border on opposite side of the title bar should follow the
|
||||
* Normal settings.
|
||||
**/
|
||||
NoSides,
|
||||
/**
|
||||
* Borders should be smaller than Normal, e.g. a factor of 0.5.
|
||||
**/
|
||||
Tiny,
|
||||
/**
|
||||
* The default border size with borders on each side. This should
|
||||
* be the base for calculating other border sizes.
|
||||
**/
|
||||
Normal,
|
||||
/**
|
||||
* Increased border sizes, considered a factor of 1.5.
|
||||
**/
|
||||
Large,
|
||||
/**
|
||||
* Increased border sizes, considered a factor of 2.0.
|
||||
**/
|
||||
VeryLarge,
|
||||
/**
|
||||
* Increased border sizes, considered a factor of 2.5.
|
||||
**/
|
||||
Huge,
|
||||
/**
|
||||
* Increased border sizes, considered a factor of 3.0.
|
||||
**/
|
||||
VeryHuge,
|
||||
/**
|
||||
* Increased border sizes, considered a factor of 5.0.
|
||||
**/
|
||||
Oversized,
|
||||
};
|
||||
|
||||
/**
|
||||
* Color groups are used for DecoratedWindow::color().
|
||||
* @since 5.3
|
||||
**/
|
||||
enum class ColorGroup {
|
||||
/**
|
||||
* Inactive color, used for unfocused windows.
|
||||
**/
|
||||
Inactive,
|
||||
/**
|
||||
* Active color, used for focused windows.
|
||||
**/
|
||||
Active,
|
||||
/**
|
||||
* Warning color, can only be used with ColorRole::Foreground. If used with other roles,
|
||||
* a invalid QColor is returned. It can be used for close buttons and is typically red.
|
||||
**/
|
||||
Warning,
|
||||
};
|
||||
|
||||
/**
|
||||
* Color roles are used for DecoratedWindow::color().
|
||||
* @since 5.3
|
||||
**/
|
||||
enum class ColorRole {
|
||||
/**
|
||||
* The decoration's frame background color.
|
||||
**/
|
||||
Frame,
|
||||
/**
|
||||
* The decoration's title bar background color
|
||||
**/
|
||||
TitleBar,
|
||||
/**
|
||||
* The decoration's title bar forground color
|
||||
**/
|
||||
Foreground,
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "decorationsettings.h"
|
||||
#include "private/decorationbridge.h"
|
||||
#include "private/decorationsettingsprivate.h"
|
||||
|
||||
#include <QFontMetrics>
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
DecorationSettings::DecorationSettings(DecorationBridge *bridge, QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(bridge->settings(this))
|
||||
{
|
||||
auto updateUnits = [this] {
|
||||
int gridUnit = QFontMetrics(font()).boundingRect(QLatin1Char('M')).height();
|
||||
;
|
||||
if (gridUnit % 2 != 0) {
|
||||
gridUnit++;
|
||||
}
|
||||
if (gridUnit != d->gridUnit()) {
|
||||
d->setGridUnit(gridUnit);
|
||||
Q_EMIT gridUnitChanged(gridUnit);
|
||||
}
|
||||
if (gridUnit != d->largeSpacing()) {
|
||||
d->setSmallSpacing(qMax(2, (int)(gridUnit / 4))); // 1/4 of gridUnit, at least 2
|
||||
d->setLargeSpacing(gridUnit); // msize.height
|
||||
Q_EMIT spacingChanged();
|
||||
}
|
||||
};
|
||||
updateUnits();
|
||||
connect(this, &DecorationSettings::fontChanged, this, updateUnits);
|
||||
}
|
||||
|
||||
DecorationSettings::~DecorationSettings() = default;
|
||||
|
||||
bool DecorationSettings::isOnAllDesktopsAvailable() const
|
||||
{
|
||||
return d->isOnAllDesktopsAvailable();
|
||||
}
|
||||
|
||||
bool DecorationSettings::isAlphaChannelSupported() const
|
||||
{
|
||||
return d->isAlphaChannelSupported();
|
||||
}
|
||||
|
||||
bool DecorationSettings::isCloseOnDoubleClickOnMenu() const
|
||||
{
|
||||
return d->isCloseOnDoubleClickOnMenu();
|
||||
}
|
||||
|
||||
QList<DecorationButtonType> DecorationSettings::decorationButtonsLeft() const
|
||||
{
|
||||
return d->decorationButtonsLeft();
|
||||
}
|
||||
|
||||
QList<DecorationButtonType> DecorationSettings::decorationButtonsRight() const
|
||||
{
|
||||
return d->decorationButtonsRight();
|
||||
}
|
||||
|
||||
BorderSize DecorationSettings::borderSize() const
|
||||
{
|
||||
return d->borderSize();
|
||||
}
|
||||
|
||||
QFont DecorationSettings::font() const
|
||||
{
|
||||
return d->font();
|
||||
}
|
||||
|
||||
QFontMetricsF DecorationSettings::fontMetrics() const
|
||||
{
|
||||
return d->fontMetrics();
|
||||
}
|
||||
|
||||
int DecorationSettings::gridUnit() const
|
||||
{
|
||||
return d->gridUnit();
|
||||
}
|
||||
|
||||
int DecorationSettings::smallSpacing() const
|
||||
{
|
||||
return d->smallSpacing();
|
||||
}
|
||||
|
||||
int DecorationSettings::largeSpacing() const
|
||||
{
|
||||
return d->largeSpacing();
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_decorationsettings.cpp"
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "decorationbutton.h"
|
||||
#include <kdecoration3/kdecoration3_export.h>
|
||||
|
||||
#include <QFontMetricsF>
|
||||
#include <QObject>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class DecorationBridge;
|
||||
class DecorationSettingsPrivate;
|
||||
|
||||
/**
|
||||
* @brief Common settings for the Decoration.
|
||||
*
|
||||
* This class gets injected into the Decoration and provides recommendations for the
|
||||
* Decoration. The Decoration is suggested to honor the settings, but may decide that some
|
||||
* settings don't fit the design and ignore them.
|
||||
*
|
||||
* @see Decoration
|
||||
**/
|
||||
class KDECORATIONS3_EXPORT DecorationSettings : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
* Whether the feature to put a DecoratedWindow on all desktops is available.
|
||||
*
|
||||
* If this feature is not available a Decoration might decide to not show the
|
||||
* DecorationButtonType::OnAllDesktops.
|
||||
**/
|
||||
Q_PROPERTY(bool onAllDesktopsAvailable READ isOnAllDesktopsAvailable NOTIFY onAllDesktopsAvailableChanged)
|
||||
/**
|
||||
* Whether the Decoration will be rendered with an alpha channel.
|
||||
*
|
||||
* If no alpha channel is available a Decoration should not use round borders.
|
||||
**/
|
||||
Q_PROPERTY(bool alphaChannelSupported READ isAlphaChannelSupported NOTIFY alphaChannelSupportedChanged)
|
||||
/**
|
||||
* Whether the Decoration should close the DecoratedWindow when double clicking on the
|
||||
* DecorationButtonType::Menu.
|
||||
**/
|
||||
Q_PROPERTY(bool closeOnDoubleClickOnMenu READ isCloseOnDoubleClickOnMenu NOTIFY closeOnDoubleClickOnMenuChanged)
|
||||
/**
|
||||
* The suggested ordering of the decoration buttons on the left.
|
||||
**/
|
||||
Q_PROPERTY(QList<KDecoration3::DecorationButtonType> decorationButtonsLeft READ decorationButtonsLeft NOTIFY decorationButtonsLeftChanged)
|
||||
/**
|
||||
* The suggested ordering of the decoration buttons on the right.
|
||||
**/
|
||||
Q_PROPERTY(QList<KDecoration3::DecorationButtonType> decorationButtonsRight READ decorationButtonsRight NOTIFY decorationButtonsRightChanged)
|
||||
/**
|
||||
* The suggested border size.
|
||||
**/
|
||||
Q_PROPERTY(KDecoration3::BorderSize borderSize READ borderSize NOTIFY borderSizeChanged)
|
||||
/**
|
||||
* The fundamental unit of space that should be used for sizes, expressed in pixels.
|
||||
* Given the screen has an accurate DPI settings, it corresponds to a millimeter
|
||||
*/
|
||||
Q_PROPERTY(int gridUnit READ gridUnit NOTIFY gridUnitChanged)
|
||||
/**
|
||||
* The recommended font for the Decoration's caption.
|
||||
**/
|
||||
Q_PROPERTY(QFont font READ font NOTIFY fontChanged)
|
||||
/**
|
||||
* smallSpacing is the amount of spacing that should be used around smaller UI elements,
|
||||
* for example as spacing in Columns. Internally, this size depends on the size of
|
||||
* the default font as rendered on the screen, so it takes user-configured font size and DPI
|
||||
* into account.
|
||||
*/
|
||||
Q_PROPERTY(int smallSpacing READ smallSpacing NOTIFY spacingChanged)
|
||||
|
||||
/**
|
||||
* largeSpacing is the amount of spacing that should be used inside bigger UI elements,
|
||||
* for example between an icon and the corresponding text. Internally, this size depends on
|
||||
* the size of the default font as rendered on the screen, so it takes user-configured font
|
||||
* size and DPI into account.
|
||||
*/
|
||||
Q_PROPERTY(int largeSpacing READ largeSpacing NOTIFY spacingChanged)
|
||||
public:
|
||||
explicit DecorationSettings(DecorationBridge *bridge, QObject *parent = nullptr);
|
||||
~DecorationSettings() override;
|
||||
bool isOnAllDesktopsAvailable() const;
|
||||
bool isAlphaChannelSupported() const;
|
||||
bool isCloseOnDoubleClickOnMenu() const;
|
||||
QList<DecorationButtonType> decorationButtonsLeft() const;
|
||||
QList<DecorationButtonType> decorationButtonsRight() const;
|
||||
BorderSize borderSize() const;
|
||||
|
||||
QFont font() const;
|
||||
/**
|
||||
* The fontMetrics for the recommended font.
|
||||
* @see font
|
||||
**/
|
||||
QFontMetricsF fontMetrics() const;
|
||||
|
||||
int gridUnit() const;
|
||||
int smallSpacing() const;
|
||||
int largeSpacing() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void onAllDesktopsAvailableChanged(bool);
|
||||
void alphaChannelSupportedChanged(bool);
|
||||
void closeOnDoubleClickOnMenuChanged(bool);
|
||||
void decorationButtonsLeftChanged(const QList<KDecoration3::DecorationButtonType> &);
|
||||
void decorationButtonsRightChanged(const QList<KDecoration3::DecorationButtonType> &);
|
||||
void borderSizeChanged(KDecoration3::BorderSize size);
|
||||
void fontChanged(const QFont &font);
|
||||
void gridUnitChanged(int);
|
||||
void spacingChanged();
|
||||
|
||||
/**
|
||||
* This signal is emitted when the backend got reconfigured.
|
||||
* If the plugin uses custom settings, it is recommended to re-read
|
||||
* them after this signal got emitted.
|
||||
**/
|
||||
void reconfigured();
|
||||
|
||||
private:
|
||||
const std::unique_ptr<DecorationSettingsPrivate> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(KDecoration3::BorderSize)
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "decorationshadow.h"
|
||||
#include "decorationshadow_p.h"
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
DecorationShadow::Private::Private(DecorationShadow *parent)
|
||||
: q(parent)
|
||||
{
|
||||
}
|
||||
|
||||
DecorationShadow::Private::~Private() = default;
|
||||
|
||||
DecorationShadow::DecorationShadow()
|
||||
: QObject()
|
||||
, d(new Private(this))
|
||||
{
|
||||
}
|
||||
|
||||
DecorationShadow::~DecorationShadow() = default;
|
||||
|
||||
QRectF DecorationShadow::topLeftGeometry() const
|
||||
{
|
||||
if (d->innerShadowRect.isNull() || d->shadow.isNull()) {
|
||||
return QRectF();
|
||||
}
|
||||
return QRectF(0, 0, d->innerShadowRect.left(), d->innerShadowRect.top());
|
||||
}
|
||||
|
||||
QRectF DecorationShadow::topGeometry() const
|
||||
{
|
||||
if (d->innerShadowRect.isNull() || d->shadow.isNull()) {
|
||||
return QRectF();
|
||||
}
|
||||
return QRectF(d->innerShadowRect.left(), 0, d->innerShadowRect.width(), d->innerShadowRect.top());
|
||||
}
|
||||
|
||||
QRectF DecorationShadow::topRightGeometry() const
|
||||
{
|
||||
if (d->innerShadowRect.isNull() || d->shadow.isNull()) {
|
||||
return QRectF();
|
||||
}
|
||||
return QRectF(d->innerShadowRect.left() + d->innerShadowRect.width(),
|
||||
0,
|
||||
d->shadow.width() - d->innerShadowRect.width() - d->innerShadowRect.left(),
|
||||
d->innerShadowRect.top());
|
||||
}
|
||||
|
||||
QRectF DecorationShadow::rightGeometry() const
|
||||
{
|
||||
if (d->innerShadowRect.isNull() || d->shadow.isNull()) {
|
||||
return QRectF();
|
||||
}
|
||||
return QRectF(d->innerShadowRect.left() + d->innerShadowRect.width(),
|
||||
d->innerShadowRect.top(),
|
||||
d->shadow.width() - d->innerShadowRect.width() - d->innerShadowRect.left(),
|
||||
d->innerShadowRect.height());
|
||||
}
|
||||
|
||||
QRectF DecorationShadow::bottomRightGeometry() const
|
||||
{
|
||||
if (d->innerShadowRect.isNull() || d->shadow.isNull()) {
|
||||
return QRectF();
|
||||
}
|
||||
return QRectF(d->innerShadowRect.left() + d->innerShadowRect.width(),
|
||||
d->innerShadowRect.top() + d->innerShadowRect.height(),
|
||||
d->shadow.width() - d->innerShadowRect.width() - d->innerShadowRect.left(),
|
||||
d->shadow.height() - d->innerShadowRect.top() - d->innerShadowRect.height());
|
||||
}
|
||||
|
||||
QRectF DecorationShadow::bottomGeometry() const
|
||||
{
|
||||
if (d->innerShadowRect.isNull() || d->shadow.isNull()) {
|
||||
return QRectF();
|
||||
}
|
||||
return QRectF(d->innerShadowRect.left(),
|
||||
d->innerShadowRect.top() + d->innerShadowRect.height(),
|
||||
d->innerShadowRect.width(),
|
||||
d->shadow.height() - d->innerShadowRect.top() - d->innerShadowRect.height());
|
||||
}
|
||||
|
||||
QRectF DecorationShadow::bottomLeftGeometry() const
|
||||
{
|
||||
if (d->innerShadowRect.isNull() || d->shadow.isNull()) {
|
||||
return QRectF();
|
||||
}
|
||||
return QRectF(0,
|
||||
d->innerShadowRect.top() + d->innerShadowRect.height(),
|
||||
d->innerShadowRect.left(),
|
||||
d->shadow.height() - d->innerShadowRect.top() - d->innerShadowRect.height());
|
||||
}
|
||||
|
||||
QRectF DecorationShadow::leftGeometry() const
|
||||
{
|
||||
if (d->innerShadowRect.isNull() || d->shadow.isNull()) {
|
||||
return QRectF();
|
||||
}
|
||||
return QRectF(0, d->innerShadowRect.top(), d->innerShadowRect.left(), d->innerShadowRect.height());
|
||||
}
|
||||
|
||||
#ifndef K_DOXYGEN
|
||||
|
||||
QImage DecorationShadow::shadow() const
|
||||
{
|
||||
return d->shadow;
|
||||
}
|
||||
|
||||
QMarginsF DecorationShadow::padding() const
|
||||
{
|
||||
return d->padding;
|
||||
}
|
||||
|
||||
QRectF DecorationShadow::innerShadowRect() const
|
||||
{
|
||||
return d->innerShadowRect;
|
||||
}
|
||||
|
||||
qreal DecorationShadow::paddingTop() const
|
||||
{
|
||||
return d->padding.top();
|
||||
}
|
||||
|
||||
qreal DecorationShadow::paddingBottom() const
|
||||
{
|
||||
return d->padding.bottom();
|
||||
}
|
||||
|
||||
qreal DecorationShadow::paddingRight() const
|
||||
{
|
||||
return d->padding.right();
|
||||
}
|
||||
|
||||
qreal DecorationShadow::paddingLeft() const
|
||||
{
|
||||
return d->padding.left();
|
||||
}
|
||||
|
||||
void DecorationShadow::setShadow(const QImage &shadow)
|
||||
{
|
||||
if (d->shadow == shadow) {
|
||||
return;
|
||||
}
|
||||
d->shadow = shadow;
|
||||
Q_EMIT shadowChanged(d->shadow);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void DecorationShadow::setPadding(const QMarginsF &margins)
|
||||
{
|
||||
if (d->padding == margins) {
|
||||
return;
|
||||
}
|
||||
d->padding = margins;
|
||||
Q_EMIT paddingChanged();
|
||||
}
|
||||
|
||||
void DecorationShadow::setInnerShadowRect(const QRectF &rect)
|
||||
{
|
||||
if (d->innerShadowRect == rect) {
|
||||
return;
|
||||
}
|
||||
d->innerShadowRect = rect;
|
||||
Q_EMIT innerShadowRectChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "moc_decorationshadow.cpp"
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <kdecoration3/kdecoration3_export.h>
|
||||
|
||||
#include <QImage>
|
||||
#include <QMargins>
|
||||
#include <QObject>
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class DecorationShadowPrivate;
|
||||
|
||||
/**
|
||||
* @brief A wrapper to define the shadow around the Decoration.
|
||||
*
|
||||
* The shadow around the Decoration should not be rendered as part of the Decoration.
|
||||
* Instead a DecorationShadow should be used. That way a backend can optimize the
|
||||
* rendering of the shadow in a better way. If the shadow were part of the Decoration
|
||||
* directly it would need to be updated when the rendering changes. By using a dedicated
|
||||
* DecorationShadow the same shadow can be shared between multiple DecoratedWindows.
|
||||
*
|
||||
* The DecorationShadow consists of a shadow QImage which is composed of multiple parts:
|
||||
* @li topLeft: rendered as it is
|
||||
* @li top: stretched in x direction
|
||||
* @li topRight: rendered as it is
|
||||
* @li right: stretched in y direction
|
||||
* @li bottomRight: rendered as it is
|
||||
* @li bottom: stretched in x direction
|
||||
* @li bottomLeft: rendered as it is
|
||||
* @li left: stretched in y direction
|
||||
*
|
||||
* The sizes of these parts is denoted in the property innerShadowRect and the layout is the
|
||||
* following:
|
||||
* #######################################
|
||||
* # topLeft # top # topRight #
|
||||
* #######################################
|
||||
* # left # # right #
|
||||
* #######################################
|
||||
* # bottomLeft # bottom # bottomRight #
|
||||
* #######################################
|
||||
*
|
||||
* The innerShadowRect property is a QRect of the geometry of the areas not covered by any of the
|
||||
* elements. This means that:
|
||||
* @li x/y of the rect is the same as the size of the topLeft element
|
||||
* @li width of the rect is the same as the width of the top and bottom element
|
||||
* @li height of the rect is the same as the height of the left and the right element
|
||||
* By that the actual sizes of all elements can be derived out of the size of the shadow image
|
||||
* and the innerShadowRect.
|
||||
*
|
||||
* The position of the rendering depends on the values;
|
||||
* @li paddingTop
|
||||
* @li paddingRight
|
||||
* @li paddingBottom
|
||||
* @li paddingLeft
|
||||
*
|
||||
* The top left element is rendered with an offset of paddingLeft and paddingTop.
|
||||
* The non-stretched elements are rendered in the size as specified, the area
|
||||
* between two non-stretched elements (e.g. between topLeft and topRight) is filled
|
||||
* by the element with one direction stretched and the other direction fixed at the
|
||||
* corresponding padding value. E.g. the top element is stretched in x direction and
|
||||
* fixed at paddingTop value. If stretching the side elements is not wanted one needs
|
||||
* to provide a shadow image with those elements at a size that stretching is not
|
||||
* required.
|
||||
*
|
||||
* If the padding values are smaller than the sizes of the shadow elements the shadow
|
||||
* will overlap with the Decoration and be rendered behind the Decoration.
|
||||
*
|
||||
**/
|
||||
class KDECORATIONS3_EXPORT DecorationShadow : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QImage shadow READ shadow WRITE setShadow NOTIFY shadowChanged)
|
||||
Q_PROPERTY(QRectF innerShadowRect READ innerShadowRect WRITE setInnerShadowRect NOTIFY innerShadowRectChanged)
|
||||
Q_PROPERTY(QRectF topLeftGeometry READ topLeftGeometry NOTIFY innerShadowRectChanged)
|
||||
Q_PROPERTY(QRectF topGeometry READ topGeometry NOTIFY innerShadowRectChanged)
|
||||
Q_PROPERTY(QRectF topRightGeometry READ topRightGeometry NOTIFY innerShadowRectChanged)
|
||||
Q_PROPERTY(QRectF rightGeometry READ rightGeometry NOTIFY innerShadowRectChanged)
|
||||
Q_PROPERTY(QRectF bottomRightGeometry READ bottomRightGeometry NOTIFY innerShadowRectChanged)
|
||||
Q_PROPERTY(QRectF bottomGeometry READ bottomGeometry NOTIFY innerShadowRectChanged)
|
||||
Q_PROPERTY(QRectF bottomLeftGeometry READ bottomLeftGeometry NOTIFY innerShadowRectChanged)
|
||||
Q_PROPERTY(QRectF leftGeometry READ leftGeometry NOTIFY innerShadowRectChanged)
|
||||
Q_PROPERTY(qreal paddingTop READ paddingTop NOTIFY paddingChanged)
|
||||
Q_PROPERTY(qreal paddingRight READ paddingRight NOTIFY paddingChanged)
|
||||
Q_PROPERTY(qreal paddingBottom READ paddingBottom NOTIFY paddingChanged)
|
||||
Q_PROPERTY(qreal paddingLeft READ paddingLeft NOTIFY paddingChanged)
|
||||
Q_PROPERTY(QMarginsF padding READ padding WRITE setPadding NOTIFY paddingChanged)
|
||||
public:
|
||||
explicit DecorationShadow();
|
||||
~DecorationShadow() override;
|
||||
|
||||
QImage shadow() const;
|
||||
QRectF innerShadowRect() const;
|
||||
QRectF topLeftGeometry() const;
|
||||
QRectF topGeometry() const;
|
||||
QRectF topRightGeometry() const;
|
||||
QRectF rightGeometry() const;
|
||||
QRectF bottomRightGeometry() const;
|
||||
QRectF bottomGeometry() const;
|
||||
QRectF bottomLeftGeometry() const;
|
||||
QRectF leftGeometry() const;
|
||||
qreal paddingTop() const;
|
||||
qreal paddingRight() const;
|
||||
qreal paddingBottom() const;
|
||||
qreal paddingLeft() const;
|
||||
QMarginsF padding() const;
|
||||
|
||||
void setShadow(const QImage &image);
|
||||
void setInnerShadowRect(const QRectF &rect);
|
||||
void setPadding(const QMarginsF &margins);
|
||||
|
||||
Q_SIGNALS:
|
||||
void shadowChanged(const QImage &);
|
||||
void innerShadowRectChanged();
|
||||
void paddingChanged();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(KDecoration3::DecorationShadow *)
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the KDecoration3 API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "decorationshadow.h"
|
||||
|
||||
#include <QImage>
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class Q_DECL_HIDDEN DecorationShadow::Private
|
||||
{
|
||||
public:
|
||||
explicit Private(DecorationShadow *parent);
|
||||
~Private();
|
||||
QImage shadow;
|
||||
QRectF innerShadowRect;
|
||||
QMarginsF padding;
|
||||
|
||||
private:
|
||||
DecorationShadow *q;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "decorationthemeprovider.h"
|
||||
|
||||
class DecorationThemeMetaDataPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
QString visibleName;
|
||||
QString themeName;
|
||||
QString configurationName;
|
||||
QString pluginId;
|
||||
KDecoration3::BorderSize borderSize = KDecoration3::BorderSize::Normal;
|
||||
};
|
||||
|
||||
using namespace KDecoration3;
|
||||
|
||||
DecorationThemeMetaData::DecorationThemeMetaData()
|
||||
: d(new DecorationThemeMetaDataPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
DecorationThemeMetaData::~DecorationThemeMetaData() = default;
|
||||
|
||||
QString DecorationThemeMetaData::visibleName() const
|
||||
{
|
||||
return d->visibleName;
|
||||
}
|
||||
|
||||
void DecorationThemeMetaData::setVisibleName(const QString &name)
|
||||
{
|
||||
d->visibleName = name;
|
||||
}
|
||||
|
||||
QString DecorationThemeMetaData::themeName() const
|
||||
{
|
||||
return d->themeName;
|
||||
}
|
||||
|
||||
void DecorationThemeMetaData::setThemeName(const QString &name)
|
||||
{
|
||||
d->themeName = name;
|
||||
}
|
||||
|
||||
QString DecorationThemeMetaData::configurationName() const
|
||||
{
|
||||
return d->configurationName;
|
||||
}
|
||||
|
||||
void DecorationThemeMetaData::setConfigurationName(const QString &name)
|
||||
{
|
||||
d->configurationName = name;
|
||||
}
|
||||
|
||||
void DecorationThemeMetaData::setBorderSize(KDecoration3::BorderSize size)
|
||||
{
|
||||
d->borderSize = size;
|
||||
}
|
||||
|
||||
KDecoration3::BorderSize DecorationThemeMetaData::borderSize() const
|
||||
{
|
||||
return d->borderSize;
|
||||
}
|
||||
|
||||
QString DecorationThemeMetaData::pluginId() const
|
||||
{
|
||||
return d->pluginId;
|
||||
}
|
||||
|
||||
void DecorationThemeMetaData::setPluginId(const QString &id)
|
||||
{
|
||||
d->pluginId = id;
|
||||
}
|
||||
|
||||
DecorationThemeProvider::DecorationThemeProvider(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
DecorationThemeMetaData::DecorationThemeMetaData(const DecorationThemeMetaData &other) = default;
|
||||
|
||||
DecorationThemeMetaData &DecorationThemeMetaData::operator=(const DecorationThemeMetaData &other) = default;
|
||||
|
||||
#include "moc_decorationthemeprovider.cpp"
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "decorationdefines.h"
|
||||
#include <QObject>
|
||||
#include <QSharedDataPointer>
|
||||
#include <kdecoration3/kdecoration3_export.h>
|
||||
|
||||
class KPluginMetaData;
|
||||
class DecorationThemeMetaDataPrivate;
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
/**
|
||||
* Class providing type-safe access to data of themes
|
||||
*
|
||||
* @since 5.23
|
||||
* @author Alexander Lohnau
|
||||
*/
|
||||
class KDECORATIONS3_EXPORT DecorationThemeMetaData
|
||||
{
|
||||
public:
|
||||
explicit DecorationThemeMetaData();
|
||||
virtual ~DecorationThemeMetaData();
|
||||
DecorationThemeMetaData(const DecorationThemeMetaData &other);
|
||||
DecorationThemeMetaData &operator=(const DecorationThemeMetaData &other);
|
||||
|
||||
/// User-visible name of the theme
|
||||
QString visibleName() const;
|
||||
void setVisibleName(const QString &name);
|
||||
|
||||
/// Internal name of the theme
|
||||
QString themeName() const;
|
||||
void setThemeName(const QString &name);
|
||||
|
||||
/// Name of the kcm to configure the decoration theme
|
||||
QString configurationName() const;
|
||||
void setConfigurationName(const QString &name);
|
||||
|
||||
/// Border size of the decoration, this gets set based on the "recommendedBorderSize" key in the json metadata
|
||||
/// @internal
|
||||
KDecoration3::BorderSize borderSize() const;
|
||||
void setBorderSize(KDecoration3::BorderSize size);
|
||||
|
||||
/// plugin id of theme provider
|
||||
/// @see KPluginMetaData::pluginId
|
||||
QString pluginId() const;
|
||||
void setPluginId(const QString &id);
|
||||
|
||||
private:
|
||||
QSharedDataPointer<DecorationThemeMetaDataPrivate> d;
|
||||
};
|
||||
/**
|
||||
* Class to give the KWin decorationmodel access to the plugin's themes.
|
||||
*
|
||||
* @since 5.23
|
||||
* @author Alexander Lohnau
|
||||
*/
|
||||
class KDECORATIONS3_EXPORT DecorationThemeProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DecorationThemeProvider(QObject *parent);
|
||||
|
||||
/**
|
||||
* List containing information of supported themes
|
||||
*/
|
||||
virtual QList<DecorationThemeMetaData> themes() const = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
set(libkdecoration3Private_SRCS
|
||||
decoratedwindowprivate.cpp
|
||||
decoratedwindowprivate.h
|
||||
decorationbridge.cpp
|
||||
decorationbridge.h
|
||||
decorationsettingsprivate.cpp
|
||||
decorationsettingsprivate.h
|
||||
)
|
||||
|
||||
add_library(kdecorations3private SHARED ${libkdecoration3Private_SRCS})
|
||||
|
||||
generate_export_header(
|
||||
kdecorations3private
|
||||
BASE_NAME
|
||||
KDECORATIONS_PRIVATE
|
||||
EXPORT_FILE_NAME
|
||||
kdecoration3/private/kdecoration3_private_export.h
|
||||
)
|
||||
|
||||
add_library(KDecoration3::KDecorationPrivate ALIAS kdecorations3private)
|
||||
|
||||
target_link_libraries(kdecorations3private
|
||||
PUBLIC
|
||||
Qt::Core
|
||||
Qt::Gui
|
||||
)
|
||||
|
||||
target_include_directories(kdecorations3private INTERFACE "$<INSTALL_INTERFACE:${KDECORATION3_INCLUDEDIR}>" )
|
||||
|
||||
set_target_properties(kdecorations3private PROPERTIES VERSION ${KDECORATION3_VERSION}
|
||||
SOVERSION 2
|
||||
EXPORT_NAME KDecoration3Private
|
||||
)
|
||||
|
||||
ecm_generate_headers(KDecoration3Private_CamelCase_HEADERS
|
||||
HEADER_NAMES
|
||||
DecoratedWindowPrivate
|
||||
DecorationBridge
|
||||
DecorationSettingsPrivate
|
||||
PREFIX
|
||||
KDecoration3/Private
|
||||
REQUIRED_HEADERS KDecoration3Private_HEADERS
|
||||
)
|
||||
install(FILES ${KDecoration3Private_CamelCase_HEADERS}
|
||||
DESTINATION ${KDECORATION3_INCLUDEDIR}/KDecoration3/Private
|
||||
COMPONENT Devel)
|
||||
|
||||
install(TARGETS kdecorations3private EXPORT KDecoration3Targets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/kdecoration3/private/kdecoration3_private_export.h
|
||||
${KDecoration3Private_HEADERS}
|
||||
DESTINATION
|
||||
${KDECORATION3_INCLUDEDIR}/kdecoration3/private
|
||||
COMPONENT
|
||||
Devel
|
||||
)
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "decoratedwindowprivate.h"
|
||||
|
||||
#include <QColor>
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class Q_DECL_HIDDEN DecoratedWindowPrivate::Private
|
||||
{
|
||||
public:
|
||||
explicit Private(DecoratedWindow *client, Decoration *decoration);
|
||||
DecoratedWindow *client;
|
||||
Decoration *decoration;
|
||||
};
|
||||
|
||||
DecoratedWindowPrivate::Private::Private(DecoratedWindow *client, Decoration *decoration)
|
||||
: client(client)
|
||||
, decoration(decoration)
|
||||
{
|
||||
}
|
||||
|
||||
DecoratedWindowPrivate::DecoratedWindowPrivate(DecoratedWindow *client, Decoration *decoration)
|
||||
: d(new Private(client, decoration))
|
||||
{
|
||||
}
|
||||
|
||||
DecoratedWindowPrivate::~DecoratedWindowPrivate() = default;
|
||||
|
||||
Decoration *DecoratedWindowPrivate::decoration()
|
||||
{
|
||||
return d->decoration;
|
||||
}
|
||||
|
||||
Decoration *DecoratedWindowPrivate::decoration() const
|
||||
{
|
||||
return d->decoration;
|
||||
}
|
||||
|
||||
DecoratedWindow *DecoratedWindowPrivate::window()
|
||||
{
|
||||
return d->client;
|
||||
}
|
||||
|
||||
QColor DecoratedWindowPrivate::color(ColorGroup group, ColorRole role) const
|
||||
{
|
||||
Q_UNUSED(role)
|
||||
Q_UNUSED(group)
|
||||
|
||||
return QColor();
|
||||
}
|
||||
|
||||
DecoratedWindowPrivateV2::DecoratedWindowPrivateV2(DecoratedWindow *client, Decoration *decoration)
|
||||
: DecoratedWindowPrivate(client, decoration)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../decorationdefines.h"
|
||||
#include <kdecoration3/private/kdecoration3_private_export.h>
|
||||
|
||||
#include <QIcon>
|
||||
#include <QString>
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the KDecoration3 API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class Decoration;
|
||||
class DecoratedWindow;
|
||||
|
||||
class KDECORATIONS_PRIVATE_EXPORT DecoratedWindowPrivate
|
||||
{
|
||||
public:
|
||||
virtual ~DecoratedWindowPrivate();
|
||||
virtual bool isActive() const = 0;
|
||||
virtual QString caption() const = 0;
|
||||
virtual bool isOnAllDesktops() const = 0;
|
||||
virtual bool isShaded() const = 0;
|
||||
virtual QIcon icon() const = 0;
|
||||
virtual bool isMaximized() const = 0;
|
||||
virtual bool isMaximizedHorizontally() const = 0;
|
||||
virtual bool isMaximizedVertically() const = 0;
|
||||
virtual bool isKeepAbove() const = 0;
|
||||
virtual bool isKeepBelow() const = 0;
|
||||
|
||||
virtual bool isCloseable() const = 0;
|
||||
virtual bool isMaximizeable() const = 0;
|
||||
virtual bool isMinimizeable() const = 0;
|
||||
virtual bool providesContextHelp() const = 0;
|
||||
virtual bool isModal() const = 0;
|
||||
virtual bool isShadeable() const = 0;
|
||||
virtual bool isMoveable() const = 0;
|
||||
virtual bool isResizeable() const = 0;
|
||||
|
||||
virtual qreal width() const = 0;
|
||||
virtual qreal height() const = 0;
|
||||
virtual QSizeF size() const = 0;
|
||||
virtual QPalette palette() const = 0;
|
||||
virtual Qt::Edges adjacentScreenEdges() const = 0;
|
||||
virtual qreal scale() const = 0;
|
||||
virtual qreal nextScale() const = 0;
|
||||
|
||||
virtual void requestShowToolTip(const QString &text) = 0;
|
||||
virtual void requestHideToolTip() = 0;
|
||||
virtual void requestClose() = 0;
|
||||
virtual void requestToggleMaximization(Qt::MouseButtons buttons) = 0;
|
||||
virtual void requestMinimize() = 0;
|
||||
virtual void requestContextHelp() = 0;
|
||||
virtual void requestToggleOnAllDesktops() = 0;
|
||||
virtual void requestToggleShade() = 0;
|
||||
virtual void requestToggleKeepAbove() = 0;
|
||||
virtual void requestToggleKeepBelow() = 0;
|
||||
virtual void requestShowWindowMenu(const QRect &rect) = 0;
|
||||
|
||||
Decoration *decoration();
|
||||
Decoration *decoration() const;
|
||||
|
||||
virtual QColor color(ColorGroup group, ColorRole role) const;
|
||||
virtual QString windowClass() const = 0;
|
||||
|
||||
virtual bool hasApplicationMenu() const = 0;
|
||||
virtual bool isApplicationMenuActive() const = 0;
|
||||
|
||||
virtual void showApplicationMenu(int actionId) = 0;
|
||||
virtual void requestShowApplicationMenu(const QRect &rect, int actionId) = 0;
|
||||
|
||||
protected:
|
||||
explicit DecoratedWindowPrivate(DecoratedWindow *client, Decoration *decoration);
|
||||
DecoratedWindow *window();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
const std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
class KDECORATIONS_PRIVATE_EXPORT DecoratedWindowPrivateV2 : public DecoratedWindowPrivate
|
||||
{
|
||||
public:
|
||||
virtual QString applicationMenuServiceName() const = 0;
|
||||
virtual QString applicationMenuObjectPath() const = 0;
|
||||
|
||||
protected:
|
||||
explicit DecoratedWindowPrivateV2(DecoratedWindow *client, Decoration *decoration);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "decorationbridge.h"
|
||||
|
||||
Q_DECLARE_METATYPE(Qt::MouseButton)
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
DecorationBridge::DecorationBridge(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
qRegisterMetaType<Qt::MouseButton>();
|
||||
}
|
||||
|
||||
DecorationBridge::~DecorationBridge() = default;
|
||||
|
||||
}
|
||||
|
||||
#include "moc_decorationbridge.cpp"
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <kdecoration3/private/kdecoration3_private_export.h>
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the KDecoration3 API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
class QRect;
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class Decoration;
|
||||
class DecorationSettings;
|
||||
class DecorationSettingsPrivate;
|
||||
class DecoratedWindow;
|
||||
class DecoratedWindowPrivate;
|
||||
|
||||
class KDECORATIONS_PRIVATE_EXPORT DecorationBridge : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
~DecorationBridge() override;
|
||||
|
||||
virtual std::unique_ptr<DecoratedWindowPrivate> createClient(DecoratedWindow *client, Decoration *decoration) = 0;
|
||||
virtual std::unique_ptr<DecorationSettingsPrivate> settings(DecorationSettings *parent) = 0;
|
||||
|
||||
protected:
|
||||
explicit DecorationBridge(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
Q_DECLARE_METATYPE(KDecoration3::DecorationBridge *)
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "decorationsettingsprivate.h"
|
||||
#include <QFontDatabase>
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class Q_DECL_HIDDEN DecorationSettingsPrivate::Private
|
||||
{
|
||||
public:
|
||||
explicit Private(DecorationSettings *settings);
|
||||
DecorationSettings *settings;
|
||||
int gridUnit = -1;
|
||||
int smallSpacing = -1;
|
||||
int largeSpacing = -1;
|
||||
};
|
||||
|
||||
DecorationSettingsPrivate::Private::Private(DecorationSettings *settings)
|
||||
: settings(settings)
|
||||
{
|
||||
}
|
||||
|
||||
DecorationSettingsPrivate::DecorationSettingsPrivate(DecorationSettings *parent)
|
||||
: d(new Private(parent))
|
||||
{
|
||||
}
|
||||
|
||||
DecorationSettingsPrivate::~DecorationSettingsPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
DecorationSettings *DecorationSettingsPrivate::decorationSettings()
|
||||
{
|
||||
return d->settings;
|
||||
}
|
||||
|
||||
const DecorationSettings *DecorationSettingsPrivate::decorationSettings() const
|
||||
{
|
||||
return d->settings;
|
||||
}
|
||||
|
||||
QFont DecorationSettingsPrivate::font() const
|
||||
{
|
||||
return QFontDatabase::systemFont(QFontDatabase::TitleFont);
|
||||
}
|
||||
|
||||
QFontMetricsF DecorationSettingsPrivate::fontMetrics() const
|
||||
{
|
||||
return QFontMetricsF(font());
|
||||
}
|
||||
|
||||
int DecorationSettingsPrivate::gridUnit() const
|
||||
{
|
||||
return d->gridUnit;
|
||||
}
|
||||
|
||||
int DecorationSettingsPrivate::smallSpacing() const
|
||||
{
|
||||
return d->smallSpacing;
|
||||
}
|
||||
|
||||
int DecorationSettingsPrivate::largeSpacing() const
|
||||
{
|
||||
return d->largeSpacing;
|
||||
}
|
||||
|
||||
void DecorationSettingsPrivate::setGridUnit(int unit)
|
||||
{
|
||||
d->gridUnit = unit;
|
||||
}
|
||||
|
||||
void DecorationSettingsPrivate::setLargeSpacing(int spacing)
|
||||
{
|
||||
d->largeSpacing = spacing;
|
||||
}
|
||||
|
||||
void DecorationSettingsPrivate::setSmallSpacing(int spacing)
|
||||
{
|
||||
d->smallSpacing = spacing;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../decorationdefines.h"
|
||||
#include <QFont>
|
||||
#include <QFontMetricsF>
|
||||
#include <QList>
|
||||
#include <kdecoration3/private/kdecoration3_private_export.h>
|
||||
#include <memory>
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the KDecoration3 API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
class DecorationSettings;
|
||||
|
||||
class KDECORATIONS_PRIVATE_EXPORT DecorationSettingsPrivate
|
||||
{
|
||||
public:
|
||||
virtual ~DecorationSettingsPrivate();
|
||||
virtual bool isOnAllDesktopsAvailable() const = 0;
|
||||
virtual bool isAlphaChannelSupported() const = 0;
|
||||
virtual bool isCloseOnDoubleClickOnMenu() const = 0;
|
||||
virtual QList<DecorationButtonType> decorationButtonsLeft() const = 0;
|
||||
virtual QList<DecorationButtonType> decorationButtonsRight() const = 0;
|
||||
virtual BorderSize borderSize() const = 0;
|
||||
virtual QFont font() const;
|
||||
virtual QFontMetricsF fontMetrics() const;
|
||||
|
||||
DecorationSettings *decorationSettings();
|
||||
const DecorationSettings *decorationSettings() const;
|
||||
|
||||
int gridUnit() const;
|
||||
int smallSpacing() const;
|
||||
int largeSpacing() const;
|
||||
void setGridUnit(int unit);
|
||||
void setLargeSpacing(int spacing);
|
||||
void setSmallSpacing(int spacing);
|
||||
|
||||
protected:
|
||||
explicit DecorationSettingsPrivate(DecorationSettings *parent);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
const std::unique_ptr<Private> d;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Xaver Hugl <xaver.hugl@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QPointF>
|
||||
#include <QRectF>
|
||||
#include <QSizeF>
|
||||
|
||||
namespace KDecoration3
|
||||
{
|
||||
|
||||
/**
|
||||
* @returns the pixel size with the provided scale
|
||||
* @since 6.3
|
||||
*/
|
||||
inline qreal pixelSize(qreal scale)
|
||||
{
|
||||
return 1.0 / scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* snaps the logical geometry value to a fractional logical geometry value
|
||||
* that aligns to the pixel grid of the provided scale
|
||||
* @since 6.3
|
||||
*/
|
||||
inline qreal snapToPixelGrid(qreal value, qreal scale)
|
||||
{
|
||||
return std::round(value * scale) / scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* snaps the logical geometry value to a fractional logical geometry value
|
||||
* that aligns to the pixel grid of the provided scale
|
||||
* @since 6.3
|
||||
*/
|
||||
inline QPointF snapToPixelGrid(const QPointF &value, qreal scale)
|
||||
{
|
||||
return QPointF(snapToPixelGrid(value.x(), scale), snapToPixelGrid(value.y(), scale));
|
||||
}
|
||||
|
||||
/**
|
||||
* snaps the logical geometry value to a fractional logical geometry value
|
||||
* that aligns to the pixel grid of the provided scale
|
||||
* @since 6.3
|
||||
*/
|
||||
inline QSizeF snapToPixelGrid(const QSizeF &value, qreal scale)
|
||||
{
|
||||
return QSizeF(snapToPixelGrid(value.width(), scale), snapToPixelGrid(value.height(), scale));
|
||||
}
|
||||
|
||||
/**
|
||||
* snaps the logical geometry value to a fractional logical geometry value
|
||||
* that aligns to the pixel grid of the provided scale
|
||||
* @since 6.3
|
||||
*/
|
||||
inline QRectF snapToPixelGrid(const QRectF &value, qreal scale)
|
||||
{
|
||||
return QRectF(snapToPixelGrid(value.topLeft(), scale), snapToPixelGrid(value.bottomRight(), scale));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user