/* This file is part of KDDockWidgets. SPDX-FileCopyrightText: 2020-2022 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Sérgio Martins SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only Contact KDAB at for commercial licensing options. */ #include "Platform_qtwidgets.h" #include "kddockwidgets/KDDockWidgets.h" #include "Window_qtwidgets.h" #include "DebugWindow.h" #include "views/ViewWrapper_qtwidgets.h" #include "views/View_qtwidgets.h" #include "private/Platform_p.h" #include "ViewFactory_qtwidgets.h" #include #include #include #include #include #include #if defined(KDDOCKWIDGETS_STATICLIB) || defined(QT_STATIC) static void initResources() { Q_INIT_RESOURCE(kddockwidgets_resources); } #endif using namespace KDDockWidgets; static_assert(SizePolicy::Fixed == SizePolicy(QSizePolicy::Fixed), "Enums dont match"); static_assert(SizePolicy::Minimum == SizePolicy(QSizePolicy::Minimum), "Enums dont match"); static_assert(SizePolicy::Maximum == SizePolicy(QSizePolicy::Maximum), "Enums dont match"); static_assert(SizePolicy::Preferred == SizePolicy(QSizePolicy::Preferred), "Enums dont match"); static_assert(SizePolicy::Expanding == SizePolicy(QSizePolicy::Expanding), "Enums dont match"); class Platform_qtwidgets::GlobalEventFilter : public QObject { public: GlobalEventFilter() { if (qGuiApp) qGuiApp->installEventFilter(this); } bool eventFilter(QObject *o, QEvent *ev) override { if (!o->isWidgetType()) // QWindow is not receiving it return false; if (auto w = qobject_cast(o)) { if (w->isWindow()) { if (ev->type() == QEvent::WindowActivate) { Platform::instance()->d->windowActivated.emit(Views::ViewWrapper_qtwidgets::create(w)); } if (ev->type() == QEvent::WindowDeactivate) { Platform::instance()->d->windowDeactivated.emit(Views::ViewWrapper_qtwidgets::create(w)); } } } return false; } ~GlobalEventFilter() override; }; Platform_qtwidgets::GlobalEventFilter::~GlobalEventFilter() = default; Platform_qtwidgets::Platform_qtwidgets() : m_globalEventFilter(new GlobalEventFilter()) { init(); } void Platform_qtwidgets::init() { #if defined(KDDOCKWIDGETS_STATICLIB) || defined(QT_STATIC) initResources(); #endif #ifdef DOCKS_DEVELOPER_MODE if (qEnvironmentVariableIntValue("KDDOCKWIDGETS_SHOW_DEBUG_WINDOW") == 1) { auto dv = new Debug::DebugWindow(); dv->show(); } #endif qGuiApp->connect(qApp, &QGuiApplication::focusObjectChanged, qApp, [this](QObject *obj) { d->focusedViewChanged.emit(Views::ViewWrapper_qtwidgets::create(obj)); }); } Platform_qtwidgets::~Platform_qtwidgets() { delete m_globalEventFilter; } const char *Platform_qtwidgets::name() const { return "qtwidgets"; } bool Platform_qtwidgets::hasActivePopup() const { return qApp->activePopupWidget() != nullptr; } std::shared_ptr Platform_qtwidgets::qobjectAsView(QObject *obj) const { return Views::ViewWrapper_qtwidgets::create(obj); } std::shared_ptr Platform_qtwidgets::windowFromQWindow(QWindow *qwindow) const { return std::shared_ptr(new Window_qtwidgets(qwindow)); } ViewFactory *Platform_qtwidgets::createDefaultViewFactory() { return new ViewFactory_qtwidgets(); } Window::Ptr Platform_qtwidgets::windowAt(QPoint globalPos) const { if (auto qwindow = qGuiApp->QGuiApplication::topLevelAt(globalPos)) { auto window = new Window_qtwidgets(qwindow); return Window::Ptr(window); } return {}; } int Platform_qtwidgets::screenNumberFor(View *view) const { if (auto widget = Views::View_qt::asQWidget(view)) { if (QWindow *qtwindow = widget->window()->windowHandle()) return screenNumberForQWindow(qtwindow); } return -1; } QSize Platform_qtwidgets::screenSizeFor(View *view) const { if (auto widget = Views::View_qt::asQWidget(view)) { if (QScreen *screen = widget->screen()) { return screen->size(); } } return {}; } int Platform_qtwidgets::startDragDistance_impl() const { return QApplication::startDragDistance(); } View *Platform_qtwidgets::createView(Controller *controller, View *parent) const { return new Views::View_qtwidgets(controller, Type::None, Views::View_qt::asQWidget(parent)); } bool Platform_qtwidgets::usesFallbackMouseGrabber() const { // For QtWidgets we just use QWidget::grabMouse() return false; } bool Platform_qtwidgets::inDisallowedDragView(QPoint globalPos) const { QWidget *widget = qApp->widgetAt(globalPos); if (!widget) return false; // User might have a line edit on the toolbar. // Not so elegant fix, we should make the user's tabbar implement some virtual method... return qobject_cast(widget) || qobject_cast(widget); } void Platform_qtwidgets::ungrabMouse() { if (QWidget *grabber = QWidget::mouseGrabber()) grabber->releaseMouse(); } #ifdef DOCKS_DEVELOPER_MODE inline QCoreApplication *createCoreApplication(int &argc, char **argv) { Platform_qt::maybeSetOffscreenQPA(argc, argv); return new QApplication(argc, argv); } Platform_qtwidgets::Platform_qtwidgets(int &argc, char **argv) : Platform_qt(createCoreApplication(argc, argv)) , m_globalEventFilter(new Platform_qtwidgets::GlobalEventFilter()) { qputenv("KDDOCKWIDGETS_SHOW_DEBUG_WINDOW", ""); qApp->setStyle(QStyleFactory::create(QStringLiteral("fusion"))); init(); } #endif