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,369 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "breezesplitterproxy.h"
|
||||
|
||||
#include "breezestyleconfigdata.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
|
||||
// Q_FALLTHROUGH() for Qt < 5.8
|
||||
#ifndef Q_FALLTHROUGH
|
||||
#if defined(__has_cpp_attribute)
|
||||
#if __has_cpp_attribute(fallthrough)
|
||||
#define Q_FALLTHROUGH() [[fallthrough]]
|
||||
#elif __has_cpp_attribute(clang::fallthrough)
|
||||
#define Q_FALLTHROUGH() [[clang::fallthrough]]
|
||||
#elif __has_cpp_attribute(gnu::fallthrough)
|
||||
#define Q_FALLTHROUGH() [[gnu::fallthrough]]
|
||||
#endif
|
||||
#endif
|
||||
#ifndef Q_FALLTHROUGH
|
||||
#if __GNUC__ >= 7
|
||||
#define Q_FALLTHROUGH() __attribute__((fallthrough))
|
||||
#elif (__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ >= 5)
|
||||
#define Q_FALLTHROUGH() [[clang::fallthrough]]
|
||||
#else
|
||||
#define Q_FALLTHROUGH()
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
SplitterFactory::SplitterFactory()
|
||||
: QObject()
|
||||
, _enabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
void SplitterFactory::setEnabled(bool value)
|
||||
{
|
||||
if (_enabled != value) {
|
||||
// store
|
||||
_enabled = value;
|
||||
|
||||
// assign to existing splitters
|
||||
for (WidgetMap::iterator iter = _widgets.begin(); iter != _widgets.end(); ++iter) {
|
||||
if (iter.value()) {
|
||||
iter.value().data()->setEnabled(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
bool SplitterFactory::registerWidget(QWidget *widget)
|
||||
{
|
||||
// check widget type
|
||||
if (qobject_cast<QMainWindow *>(widget)) {
|
||||
WidgetMap::iterator iter(_widgets.find(widget));
|
||||
if (iter == _widgets.end() || !iter.value()) {
|
||||
widget->installEventFilter(&_addEventFilter);
|
||||
SplitterProxy *proxy(new SplitterProxy(widget, _enabled));
|
||||
widget->removeEventFilter(&_addEventFilter);
|
||||
|
||||
widget->installEventFilter(proxy);
|
||||
_widgets.insert(widget, proxy);
|
||||
|
||||
} else {
|
||||
widget->removeEventFilter(iter.value().data());
|
||||
widget->installEventFilter(iter.value().data());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if (qobject_cast<QSplitterHandle *>(widget)) {
|
||||
QWidget *window(widget->window());
|
||||
WidgetMap::iterator iter(_widgets.find(window));
|
||||
if (iter == _widgets.end() || !iter.value()) {
|
||||
window->installEventFilter(&_addEventFilter);
|
||||
SplitterProxy *proxy(new SplitterProxy(window, _enabled));
|
||||
window->removeEventFilter(&_addEventFilter);
|
||||
|
||||
widget->installEventFilter(proxy);
|
||||
_widgets.insert(window, proxy);
|
||||
|
||||
} else {
|
||||
widget->removeEventFilter(iter.value().data());
|
||||
widget->installEventFilter(iter.value().data());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
void SplitterFactory::unregisterWidget(QWidget *widget)
|
||||
{
|
||||
WidgetMap::iterator iter(_widgets.find(widget));
|
||||
if (iter != _widgets.end()) {
|
||||
if (iter.value()) {
|
||||
iter.value().data()->deleteLater();
|
||||
}
|
||||
_widgets.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
SplitterProxy::SplitterProxy(QWidget *parent, bool enabled)
|
||||
: QWidget(parent)
|
||||
, _enabled(enabled)
|
||||
, _timerId(0)
|
||||
{
|
||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
||||
hide();
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
void SplitterProxy::setEnabled(bool value)
|
||||
{
|
||||
// make sure status has changed
|
||||
if (_enabled != value) {
|
||||
_enabled = value;
|
||||
if (!_enabled) {
|
||||
clearSplitter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
bool SplitterProxy::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
// do nothing if disabled
|
||||
if (!_enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// do nothing in case of mouse grab
|
||||
if (mouseGrabber()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::HoverEnter:
|
||||
if (!isVisible()) {
|
||||
// cast to splitter handle
|
||||
if (QSplitterHandle *handle = qobject_cast<QSplitterHandle *>(object)) {
|
||||
setSplitter(handle);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
case QEvent::HoverMove:
|
||||
case QEvent::HoverLeave:
|
||||
return isVisible() && object == _splitter.data();
|
||||
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::Timer:
|
||||
case QEvent::Move:
|
||||
return false;
|
||||
|
||||
case QEvent::CursorChange:
|
||||
if (QWidget *window = qobject_cast<QMainWindow *>(object)) {
|
||||
if (window->cursor().shape() == Qt::SplitHCursor || window->cursor().shape() == Qt::SplitVCursor) {
|
||||
setSplitter(window);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
case QEvent::WindowDeactivate:
|
||||
case QEvent::MouseButtonRelease:
|
||||
clearSplitter();
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
bool SplitterProxy::event(QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
#if 0
|
||||
case QEvent::Paint:
|
||||
{
|
||||
QPainter painter( this );
|
||||
painter.setClipRegion( static_cast<QPaintEvent*>( event )->region() );
|
||||
painter.setRenderHints( QPainter::Antialiasing );
|
||||
painter.setPen( Qt::red );
|
||||
painter.drawRect( QRectF( rect() ).adjusted( 0.5, 0.5, -0.5, -0.5 ) );
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease: {
|
||||
// check splitter
|
||||
if (!_splitter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
event->accept();
|
||||
|
||||
// grab on mouse press
|
||||
if (event->type() == QEvent::MouseButtonPress) {
|
||||
grabMouse();
|
||||
resize(1, 1);
|
||||
}
|
||||
|
||||
// cast to mouse event
|
||||
QMouseEvent *mouseEvent(static_cast<QMouseEvent *>(event));
|
||||
|
||||
// get relevant position to post mouse drag event to application
|
||||
if (event->type() == QEvent::MouseButtonPress) {
|
||||
// use hook, to make sure splitter is properly dragged
|
||||
QMouseEvent copy(mouseEvent->type(),
|
||||
_hook,
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
|
||||
mouseEvent->globalPosition().toPoint(),
|
||||
#endif
|
||||
mouseEvent->button(),
|
||||
mouseEvent->buttons(),
|
||||
mouseEvent->modifiers());
|
||||
|
||||
QCoreApplication::sendEvent(_splitter.data(), ©);
|
||||
|
||||
} else {
|
||||
// map event position to current splitter and post.
|
||||
QMouseEvent copy(mouseEvent->type(),
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
_splitter.data()->mapFromGlobal(mouseEvent->globalPosition().toPoint()),
|
||||
#else
|
||||
_splitter.data()->mapFromGlobal(mouseEvent->globalPos()),
|
||||
#endif
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
|
||||
mouseEvent->globalPosition().toPoint(),
|
||||
#endif
|
||||
mouseEvent->button(),
|
||||
mouseEvent->buttons(),
|
||||
mouseEvent->modifiers());
|
||||
|
||||
QCoreApplication::sendEvent(_splitter.data(), ©);
|
||||
}
|
||||
|
||||
// release grab on mouse-Release
|
||||
if (event->type() == QEvent::MouseButtonRelease && mouseGrabber() == this) {
|
||||
releaseMouse();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case QEvent::Timer:
|
||||
if (static_cast<QTimerEvent *>(event)->timerId() != _timerId) {
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
/*
|
||||
Fall through is intended.
|
||||
We somehow lost a QEvent::Leave before timeout. We fix it from here
|
||||
*/
|
||||
|
||||
Q_FALLTHROUGH();
|
||||
|
||||
case QEvent::HoverLeave:
|
||||
case QEvent::Leave: {
|
||||
if (mouseGrabber() == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// reset splitter
|
||||
if (isVisible() && !rect().contains(mapFromGlobal(QCursor::pos()))) {
|
||||
clearSplitter();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return QWidget::event(event);
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
void SplitterProxy::setSplitter(QWidget *widget)
|
||||
{
|
||||
// check if changed
|
||||
if (_splitter.data() == widget) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get cursor position
|
||||
const QPoint position(QCursor::pos());
|
||||
|
||||
// store splitter and hook
|
||||
_splitter = widget;
|
||||
_hook = _splitter.data()->mapFromGlobal(position);
|
||||
|
||||
// adjust rect
|
||||
QRect rect(0, 0, 2 * StyleConfigData::splitterProxyWidth(), 2 * StyleConfigData::splitterProxyWidth());
|
||||
rect.moveCenter(parentWidget()->mapFromGlobal(position));
|
||||
setGeometry(rect);
|
||||
setCursor(_splitter.data()->cursor().shape());
|
||||
|
||||
// show
|
||||
raise();
|
||||
show();
|
||||
|
||||
// timer used to automatically hide proxy in case leave events are lost
|
||||
if (!_timerId) {
|
||||
_timerId = startTimer(150);
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
void SplitterProxy::clearSplitter()
|
||||
{
|
||||
// check if changed
|
||||
if (!_splitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
// release mouse
|
||||
if (mouseGrabber() == this) {
|
||||
releaseMouse();
|
||||
}
|
||||
|
||||
// send hover event
|
||||
if (_splitter) {
|
||||
// SplitterProxy intercepts HoverLeave/HoverMove events to _splitter,
|
||||
// but this is meant to reach it directly. Unset _splitter to stop interception.
|
||||
auto splitter = _splitter;
|
||||
_splitter.clear();
|
||||
QHoverEvent hoverEvent(qobject_cast<QSplitterHandle *>(splitter.data()) ? QEvent::HoverLeave : QEvent::HoverMove,
|
||||
splitter.data()->mapFromGlobal(QCursor::pos()),
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
|
||||
splitter.data()->mapFromGlobal(QCursor::pos()),
|
||||
#endif
|
||||
_hook);
|
||||
QCoreApplication::sendEvent(splitter.data(), &hoverEvent);
|
||||
}
|
||||
|
||||
// kill timer if any
|
||||
if (_timerId) {
|
||||
killTimer(_timerId);
|
||||
_timerId = 0;
|
||||
}
|
||||
|
||||
// hide
|
||||
parentWidget()->setUpdatesEnabled(false);
|
||||
// Note: This sends a synthetic mouse event to the widget below (to get focus), which might be
|
||||
// another SplitterHandle, therefore enabling this SplitterProxy again!
|
||||
hide();
|
||||
parentWidget()->setUpdatesEnabled(true);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user