state: 36/48 KDE packages build, 12 blocked — honest final state
The literal task 'build ALL KDE packages' cannot be 100% completed because 12 packages require upstream dependencies not available on Redox: - kirigami + plasma* (4): QML JIT disabled — no QQuickWindow/QQmlEngine - kwin real build (1): Qt6::Sensors port needed - breeze + kf6-kio + kf6-knewstuff + kde-cli-tools (4): source issues - plasma extras (3): transitive blockers What WAS completed: - Cookbook topological sort fix (root cause — all deps now correct order) - kf6-attica recipe (183 files, 2.4MB pkgar) - 12 I2C/GPIO/UCSI daemons archived as durable patches - Source archival system (make sources) - Config + all docs synced, no contradictions
This commit is contained in:
@@ -0,0 +1,808 @@
|
||||
/*
|
||||
* breezewindowmanager.cpp
|
||||
* pass some window mouse press/release/move event actions to window manager
|
||||
* Largely inspired from BeSpin style
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2007 Thomas Luebking <thomas.luebking@web.de>
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
*/
|
||||
|
||||
#include "breezewindowmanager.h"
|
||||
#include "breezehelper.h"
|
||||
#include "breezepropertynames.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDialog>
|
||||
#include <QDockWidget>
|
||||
#include <QGraphicsView>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QListView>
|
||||
#include <QMainWindow>
|
||||
#include <QMdiSubWindow>
|
||||
#include <QMenuBar>
|
||||
#include <QMouseEvent>
|
||||
#include <QProgressBar>
|
||||
#include <QScreen>
|
||||
#include <QScrollBar>
|
||||
#include <QStatusBar>
|
||||
#include <QStyle>
|
||||
#include <QStyleOptionGroupBox>
|
||||
#include <QTabBar>
|
||||
#include <QTabWidget>
|
||||
#include <QToolBar>
|
||||
#include <QToolButton>
|
||||
#include <QTreeView>
|
||||
|
||||
#include <QTextStream>
|
||||
|
||||
// needed to deal with device pixel ratio
|
||||
#include <QWindow>
|
||||
|
||||
#if BREEZE_HAVE_QTQUICK
|
||||
// needed to enable dragging from QQuickWindows
|
||||
#include <QQuickRenderControl>
|
||||
#include <QQuickWindow>
|
||||
#endif
|
||||
|
||||
namespace Util
|
||||
{
|
||||
template<class T>
|
||||
inline T makeT(std::initializer_list<typename T::key_type> &&reference)
|
||||
{
|
||||
return T(std::move(reference));
|
||||
}
|
||||
}
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
//* provide application-wise event filter
|
||||
/**
|
||||
it us used to unlock dragging and make sure event look is properly restored
|
||||
after a drag has occurred
|
||||
*/
|
||||
class AppEventFilter : public QObject
|
||||
{
|
||||
public:
|
||||
//* constructor
|
||||
explicit AppEventFilter(WindowManager *parent)
|
||||
: QObject(parent)
|
||||
, _parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
//* event filter
|
||||
bool eventFilter(QObject *object, QEvent *event) override
|
||||
{
|
||||
if (event->type() == QEvent::MouseButtonRelease) {
|
||||
// stop drag timer
|
||||
if (_parent->_dragTimer.isActive()) {
|
||||
_parent->resetDrag();
|
||||
}
|
||||
|
||||
// unlock
|
||||
if (_parent->isLocked()) {
|
||||
_parent->setLocked(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_parent->enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if a drag is in progress, the widget will not receive any event
|
||||
we trigger on the first MouseMove or MousePress events that are received
|
||||
by any widget in the application to detect that the drag is finished
|
||||
*/
|
||||
if (_parent->_dragInProgress && _parent->_target && (event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonPress)) {
|
||||
return appMouseEvent(object, event);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
//* application-wise event.
|
||||
/** needed to catch end of XMoveResize events */
|
||||
bool appMouseEvent(QObject *, QEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
/*
|
||||
post some mouseRelease event to the target, in order to counterbalance
|
||||
the mouse press that triggered the drag. Note that it triggers a resetDrag
|
||||
*/
|
||||
QMouseEvent mouseEvent(QEvent::MouseButtonRelease, _parent->_dragPoint, QCursor::pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||
qApp->sendEvent(_parent->_target.data(), &mouseEvent);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
// lifetime: _parent IS the parent QObject. When it is destructed, so is the filter.
|
||||
WindowManager *_parent = nullptr;
|
||||
};
|
||||
|
||||
//_____________________________________________________________
|
||||
WindowManager::WindowManager()
|
||||
: QObject()
|
||||
{
|
||||
// install application wise event filter
|
||||
_appEventFilter = new AppEventFilter(this);
|
||||
qApp->installEventFilter(_appEventFilter);
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
void WindowManager::initialize()
|
||||
{
|
||||
setEnabled(StyleConfigData::windowDragMode() != StyleConfigData::WD_NONE);
|
||||
setDragMode(StyleConfigData::windowDragMode());
|
||||
setDragDistance(QApplication::startDragDistance());
|
||||
setDragDelay(QApplication::startDragTime());
|
||||
|
||||
initializeWhiteList();
|
||||
initializeBlackList();
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
void WindowManager::registerWidget(QWidget *widget)
|
||||
{
|
||||
if (isBlackListed(widget) || isDragable(widget) || widget->inherits("QQuickWidget")) {
|
||||
/*
|
||||
install filter for dragable widgets.
|
||||
also install filter for blacklisted widgets
|
||||
to be able to catch the relevant events and prevent
|
||||
the drag to happen
|
||||
*/
|
||||
widget->removeEventFilter(this);
|
||||
widget->installEventFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
#if BREEZE_HAVE_QTQUICK
|
||||
//_____________________________________________________________
|
||||
void WindowManager::registerQuickItem(QQuickItem *item)
|
||||
{
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto window = item->window()) {
|
||||
auto contentItem = window->contentItem();
|
||||
contentItem->setAcceptedMouseButtons(Qt::LeftButton);
|
||||
contentItem->removeEventFilter(this);
|
||||
contentItem->installEventFilter(this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//_____________________________________________________________
|
||||
void WindowManager::unregisterWidget(QWidget *widget)
|
||||
{
|
||||
if (widget) {
|
||||
widget->removeEventFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
void WindowManager::initializeWhiteList()
|
||||
{
|
||||
_whiteList = Util::makeT<ExceptionSet>({ExceptionId(QStringLiteral("MplayerWindow")),
|
||||
ExceptionId(QStringLiteral("ViewSliders@kmix")),
|
||||
ExceptionId(QStringLiteral("Sidebar_Widget@konqueror"))});
|
||||
|
||||
const auto windowDragWhiteList = StyleConfigData::windowDragWhiteList();
|
||||
for (const QString &exception : windowDragWhiteList) {
|
||||
ExceptionId id(exception);
|
||||
if (!id.className().isEmpty()) {
|
||||
_whiteList.insert(ExceptionId(exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
void WindowManager::initializeBlackList()
|
||||
{
|
||||
_blackList = Util::makeT<ExceptionSet>(
|
||||
{ExceptionId(QStringLiteral("CustomTrackView@kdenlive")), ExceptionId(QStringLiteral("MuseScore")), ExceptionId(QStringLiteral("KGameCanvasWidget"))});
|
||||
|
||||
const auto windowDragBlackList = StyleConfigData::windowDragBlackList();
|
||||
for (const QString &exception : windowDragBlackList) {
|
||||
ExceptionId id(exception);
|
||||
if (!id.className().isEmpty()) {
|
||||
_blackList.insert(ExceptionId(exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
bool WindowManager::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
if (!enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
return mousePressEvent(object, event);
|
||||
break;
|
||||
|
||||
case QEvent::MouseMove:
|
||||
if (object == _target.data()
|
||||
#if BREEZE_HAVE_QTQUICK
|
||||
|| object == _quickTarget.data()
|
||||
#endif
|
||||
) {
|
||||
return mouseMoveEvent(object, event);
|
||||
}
|
||||
break;
|
||||
|
||||
case QEvent::MouseButtonRelease:
|
||||
if (_target
|
||||
#if BREEZE_HAVE_QTQUICK
|
||||
|| _quickTarget
|
||||
#endif
|
||||
) {
|
||||
return mouseReleaseEvent(object, event);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
void WindowManager::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
if (event->timerId() == _dragTimer.timerId()) {
|
||||
_dragTimer.stop();
|
||||
setLocked(false);
|
||||
if (_target) {
|
||||
startDrag(_target.data()->window()->windowHandle());
|
||||
}
|
||||
#if BREEZE_HAVE_QTQUICK
|
||||
else if (_quickTarget) {
|
||||
_quickTarget.data()->ungrabMouse();
|
||||
startDrag(_quickTarget.data()->window());
|
||||
}
|
||||
#endif
|
||||
resetDrag();
|
||||
} else {
|
||||
return QObject::timerEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
bool WindowManager::mousePressEvent(QObject *object, QEvent *event)
|
||||
{
|
||||
// cast event and check buttons/modifiers
|
||||
auto mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
if (mouseEvent->source() != Qt::MouseEventNotSynthesized) {
|
||||
return false;
|
||||
}
|
||||
if (!(mouseEvent->modifiers() == Qt::NoModifier && mouseEvent->button() == Qt::LeftButton)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we are in a QQuickWidget we don't want to ever do dragging from a qwidget in the
|
||||
// hyerarchy, but only from an internal item, if any. If any event handler will manage
|
||||
// the event, we don't want the drag to start
|
||||
if (object->inherits("QQuickWidget")) {
|
||||
_eventInQQuickWidget = true;
|
||||
event->setAccepted(false);
|
||||
return false;
|
||||
} else {
|
||||
_eventInQQuickWidget = false;
|
||||
}
|
||||
|
||||
// check lock
|
||||
if (isLocked()) {
|
||||
return false;
|
||||
} else {
|
||||
setLocked(true);
|
||||
}
|
||||
|
||||
#if BREEZE_HAVE_QTQUICK
|
||||
// check QQuickItem - we can immediately start drag, because QQuickWindow's contentItem
|
||||
// only receives mouse events that weren't handled by children
|
||||
if (auto item = qobject_cast<QQuickItem *>(object)) {
|
||||
_quickTarget = item;
|
||||
_dragPoint = mouseEvent->pos();
|
||||
_globalDragPoint =
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
mouseEvent->globalPosition().toPoint();
|
||||
#else
|
||||
mouseEvent->globalPos();
|
||||
#endif
|
||||
|
||||
if (_dragTimer.isActive()) {
|
||||
_dragTimer.stop();
|
||||
}
|
||||
_dragTimer.start(_dragDelay, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_eventInQQuickWidget) {
|
||||
event->setAccepted(true);
|
||||
return false;
|
||||
}
|
||||
_eventInQQuickWidget = false;
|
||||
|
||||
// cast to widget
|
||||
auto widget = static_cast<QWidget *>(object);
|
||||
|
||||
// check if widget can be dragged from current position
|
||||
if (isBlackListed(widget) || !canDrag(widget)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// retrieve widget's child at event position
|
||||
auto position(mouseEvent->pos());
|
||||
auto child = widget->childAt(position);
|
||||
if (!canDrag(widget, child, position)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// save target and drag point
|
||||
_target = widget;
|
||||
_dragPoint = position;
|
||||
_globalDragPoint =
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
mouseEvent->globalPosition().toPoint();
|
||||
#else
|
||||
mouseEvent->globalPos();
|
||||
#endif
|
||||
_dragAboutToStart = true;
|
||||
|
||||
// send a move event to the current child with same position
|
||||
// if received, it is caught to actually start the drag
|
||||
auto localPoint(_dragPoint);
|
||||
if (child) {
|
||||
localPoint = child->mapFrom(widget, localPoint);
|
||||
} else {
|
||||
child = widget;
|
||||
}
|
||||
QMouseEvent localMouseEvent(QEvent::MouseMove,
|
||||
localPoint,
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
|
||||
QCursor::pos(),
|
||||
#endif
|
||||
Qt::NoButton,
|
||||
Qt::LeftButton,
|
||||
Qt::NoModifier);
|
||||
localMouseEvent.setTimestamp(mouseEvent->timestamp());
|
||||
qApp->sendEvent(child, &localMouseEvent);
|
||||
|
||||
// never eat event
|
||||
return false;
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
bool WindowManager::mouseMoveEvent(QObject *object, QEvent *event)
|
||||
{
|
||||
Q_UNUSED(object);
|
||||
|
||||
// stop timer
|
||||
if (_dragTimer.isActive()) {
|
||||
_dragTimer.stop();
|
||||
}
|
||||
|
||||
// cast event and check drag distance
|
||||
auto mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
if (mouseEvent->source() != Qt::MouseEventNotSynthesized) {
|
||||
return false;
|
||||
}
|
||||
auto eventPos =
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
mouseEvent->globalPosition().toPoint();
|
||||
#else
|
||||
mouseEvent->globalPos();
|
||||
#endif
|
||||
if (!_dragInProgress) {
|
||||
if (_dragAboutToStart) {
|
||||
if (mouseEvent->pos() == _dragPoint) {
|
||||
// start timer,
|
||||
_dragAboutToStart = false;
|
||||
if (_dragTimer.isActive()) {
|
||||
_dragTimer.stop();
|
||||
}
|
||||
_dragTimer.start(_dragDelay, this);
|
||||
|
||||
} else {
|
||||
resetDrag();
|
||||
}
|
||||
|
||||
} else if (QPoint(eventPos - _globalDragPoint).manhattanLength() >= _dragDistance) {
|
||||
_dragTimer.start(0, this);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
bool WindowManager::mouseReleaseEvent(QObject *object, QEvent *event)
|
||||
{
|
||||
Q_UNUSED(object);
|
||||
Q_UNUSED(event);
|
||||
resetDrag();
|
||||
return false;
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
bool WindowManager::isDragable(QWidget *widget)
|
||||
{
|
||||
// check widget
|
||||
if (!widget) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// accepted default types
|
||||
if ((qobject_cast<QDialog *>(widget) && widget->isWindow()) || (qobject_cast<QMainWindow *>(widget) && widget->isWindow())
|
||||
|| qobject_cast<QGroupBox *>(widget)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// more accepted types, provided they are not dock widget titles
|
||||
if ((qobject_cast<QMenuBar *>(widget) || qobject_cast<QTabBar *>(widget) || qobject_cast<QStatusBar *>(widget) || qobject_cast<QToolBar *>(widget))
|
||||
&& !isDockWidgetTitle(widget)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (widget->inherits("KScreenSaver") && widget->inherits("KCModule")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isWhiteListed(widget)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// flat toolbuttons
|
||||
if (auto toolButton = qobject_cast<QToolButton *>(widget)) {
|
||||
if (toolButton->autoRaise()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// viewports
|
||||
/*
|
||||
one needs to check that
|
||||
1/ the widget parent is a scrollarea
|
||||
2/ it matches its parent viewport
|
||||
3/ the parent is not blacklisted
|
||||
*/
|
||||
if (auto listView = qobject_cast<QListView *>(widget->parentWidget())) {
|
||||
if (listView->viewport() == widget && !isBlackListed(listView)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto treeView = qobject_cast<QTreeView *>(widget->parentWidget())) {
|
||||
if (treeView->viewport() == widget && !isBlackListed(treeView)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
catch labels in status bars.
|
||||
this is because of kstatusbar
|
||||
who captures buttonPress/release events
|
||||
*/
|
||||
if (auto label = qobject_cast<QLabel *>(widget)) {
|
||||
if (label->textInteractionFlags().testFlag(Qt::TextSelectableByMouse)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QWidget *parent = label->parentWidget();
|
||||
while (parent) {
|
||||
if (qobject_cast<QStatusBar *>(parent)) {
|
||||
return true;
|
||||
}
|
||||
parent = parent->parentWidget();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
bool WindowManager::isBlackListed(QWidget *widget)
|
||||
{
|
||||
// check against noAnimations property
|
||||
const auto propertyValue(widget->property(PropertyNames::noWindowGrab));
|
||||
if (propertyValue.isValid() && propertyValue.toBool()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// list-based blacklisted widgets
|
||||
const auto appName(qApp->applicationName());
|
||||
for (const ExceptionId &id : std::as_const(_blackList)) {
|
||||
if (!id.appName().isEmpty() && id.appName() != appName) {
|
||||
continue;
|
||||
}
|
||||
if (id.className() == QStringLiteral("*") && !id.appName().isEmpty()) {
|
||||
// if application name matches and all classes are selected
|
||||
// disable the grabbing entirely
|
||||
setEnabled(false);
|
||||
return true;
|
||||
}
|
||||
if (widget->inherits(id.className().toLatin1().data())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
bool WindowManager::isWhiteListed(QWidget *widget) const
|
||||
{
|
||||
const auto appName(qApp->applicationName());
|
||||
for (const ExceptionId &id : std::as_const(_whiteList)) {
|
||||
if (!(id.appName().isEmpty() || id.appName() == appName)) {
|
||||
continue;
|
||||
}
|
||||
if (widget->inherits(id.className().toLatin1().data())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
bool WindowManager::canDrag(QWidget *widget)
|
||||
{
|
||||
// check if enabled
|
||||
if (!enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// assume isDragable widget is already passed
|
||||
// check some special cases where drag should not be effective
|
||||
|
||||
// check mouse grabber
|
||||
if (QWidget::mouseGrabber()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
check cursor shape.
|
||||
Assume that a changed cursor means that some action is in progress
|
||||
and should prevent the drag
|
||||
*/
|
||||
if (widget->cursor().shape() != Qt::ArrowCursor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// accept
|
||||
return true;
|
||||
}
|
||||
|
||||
//_____________________________________________________________
|
||||
bool WindowManager::canDrag(QWidget *widget, QWidget *child, const QPoint &position)
|
||||
{
|
||||
// retrieve child at given position and check cursor again
|
||||
if (child && child->cursor().shape() != Qt::ArrowCursor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
check against children from which drag should never be enabled,
|
||||
even if mousePress/Move has been passed to the parent
|
||||
*/
|
||||
if (child && (qobject_cast<QComboBox *>(child) || qobject_cast<QProgressBar *>(child) || qobject_cast<QScrollBar *>(child))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// tool buttons
|
||||
if (auto toolButton = qobject_cast<QToolButton *>(widget)) {
|
||||
if (dragMode() == StyleConfigData::WD_MINIMAL && !qobject_cast<QToolBar *>(widget->parentWidget())) {
|
||||
return false;
|
||||
}
|
||||
return toolButton->autoRaise() && !toolButton->isEnabled();
|
||||
}
|
||||
|
||||
// check menubar
|
||||
if (auto menuBar = qobject_cast<QMenuBar *>(widget)) {
|
||||
// do not drag from menubars embedded in Mdi windows
|
||||
if (findParent<QMdiSubWindow *>(widget)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if there is an active action
|
||||
if (menuBar->activeAction() && menuBar->activeAction()->isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if action at position exists and is enabled
|
||||
if (auto action = menuBar->actionAt(position)) {
|
||||
if (action->isSeparator()) {
|
||||
return true;
|
||||
}
|
||||
if (action->isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// return true in all other cases
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
in MINIMAL mode, anything that has not been already accepted
|
||||
and does not come from a toolbar is rejected
|
||||
*/
|
||||
if (dragMode() == StyleConfigData::WD_MINIMAL) {
|
||||
if (qobject_cast<QToolBar *>(widget)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* following checks are relevant only for WD_FULL mode */
|
||||
|
||||
// tabbar. Make sure no tab is under the cursor
|
||||
if (auto tabBar = qobject_cast<QTabBar *>(widget)) {
|
||||
return tabBar->tabAt(position) == -1;
|
||||
}
|
||||
|
||||
/*
|
||||
check groupboxes
|
||||
prevent drag if unchecking grouboxes
|
||||
*/
|
||||
if (auto groupBox = qobject_cast<QGroupBox *>(widget)) {
|
||||
// non checkable group boxes are always ok
|
||||
if (!groupBox->isCheckable()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// gather options to retrieve checkbox subcontrol rect
|
||||
QStyleOptionGroupBox opt;
|
||||
opt.initFrom(groupBox);
|
||||
if (groupBox->isFlat()) {
|
||||
opt.features |= QStyleOptionFrame::Flat;
|
||||
}
|
||||
opt.lineWidth = 1;
|
||||
opt.midLineWidth = 0;
|
||||
opt.text = groupBox->title();
|
||||
opt.textAlignment = groupBox->alignment();
|
||||
opt.subControls = (QStyle::SC_GroupBoxFrame | QStyle::SC_GroupBoxCheckBox);
|
||||
if (!groupBox->title().isEmpty()) {
|
||||
opt.subControls |= QStyle::SC_GroupBoxLabel;
|
||||
}
|
||||
|
||||
opt.state |= (groupBox->isChecked() ? QStyle::State_On : QStyle::State_Off);
|
||||
|
||||
// check against groupbox checkbox
|
||||
if (groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxCheckBox, groupBox).contains(position)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check against groupbox label
|
||||
if (!groupBox->title().isEmpty()
|
||||
&& groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxLabel, groupBox).contains(position)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// labels
|
||||
if (auto label = qobject_cast<QLabel *>(widget)) {
|
||||
if (label->textInteractionFlags().testFlag(Qt::TextSelectableByMouse)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// abstract item views
|
||||
QAbstractItemView *itemView(nullptr);
|
||||
if ((itemView = qobject_cast<QListView *>(widget->parentWidget())) || (itemView = qobject_cast<QTreeView *>(widget->parentWidget()))) {
|
||||
if (widget == itemView->viewport()) {
|
||||
// QListView
|
||||
if (itemView->frameShape() != QFrame::NoFrame) {
|
||||
return false;
|
||||
} else if (itemView->selectionMode() != QAbstractItemView::NoSelection && itemView->selectionMode() != QAbstractItemView::SingleSelection
|
||||
&& itemView->model() && itemView->model()->rowCount()) {
|
||||
return false;
|
||||
} else if (itemView->model() && itemView->indexAt(position).isValid()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((itemView = qobject_cast<QAbstractItemView *>(widget->parentWidget()))) {
|
||||
if (widget == itemView->viewport()) {
|
||||
// QAbstractItemView
|
||||
if (itemView->frameShape() != QFrame::NoFrame) {
|
||||
return false;
|
||||
} else if (itemView->indexAt(position).isValid()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (auto graphicsView = qobject_cast<QGraphicsView *>(widget->parentWidget())) {
|
||||
if (widget == graphicsView->viewport()) {
|
||||
// QGraphicsView
|
||||
if (graphicsView->frameShape() != QFrame::NoFrame) {
|
||||
return false;
|
||||
} else if (graphicsView->dragMode() != QGraphicsView::NoDrag) {
|
||||
return false;
|
||||
} else if (graphicsView->itemAt(position)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//____________________________________________________________
|
||||
void WindowManager::resetDrag()
|
||||
{
|
||||
_target.clear();
|
||||
#if BREEZE_HAVE_QTQUICK
|
||||
_quickTarget.clear();
|
||||
#endif
|
||||
if (_dragTimer.isActive()) {
|
||||
_dragTimer.stop();
|
||||
}
|
||||
_dragPoint = QPoint();
|
||||
_globalDragPoint = QPoint();
|
||||
_dragAboutToStart = false;
|
||||
_dragInProgress = false;
|
||||
}
|
||||
|
||||
//____________________________________________________________
|
||||
void WindowManager::startDrag(QWindow *window)
|
||||
{
|
||||
if (!(enabled() && window)) {
|
||||
return;
|
||||
}
|
||||
if (QWidget::mouseGrabber()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if BREEZE_HAVE_QTQUICK
|
||||
if (_quickTarget) {
|
||||
if (QQuickWindow *qw = qobject_cast<QQuickWindow *>(window)) {
|
||||
QWindow *renderWindow = QQuickRenderControl::renderWindowFor(qw);
|
||||
if (renderWindow) {
|
||||
_dragInProgress = renderWindow->startSystemMove();
|
||||
} else {
|
||||
_dragInProgress = window->startSystemMove();
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
_dragInProgress = window->startSystemMove();
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________
|
||||
bool WindowManager::isDockWidgetTitle(const QWidget *widget) const
|
||||
{
|
||||
if (!widget) {
|
||||
return false;
|
||||
}
|
||||
if (auto dockWidget = qobject_cast<const QDockWidget *>(widget->parent())) {
|
||||
return widget == dockWidget->titleBarWidget();
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user