From 04aecb369304afa7b9a5dc2e0bb3d0b106472670 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 31 Aug 2020 08:32:56 +0200 Subject: [PATCH] Some code cleanup, adjustments to match ADS coding style --- src/DockFocusController.cpp | 3 +- src/DockManager.cpp | 47 +++++++---- src/FloatingDockContainer.cpp | 119 ++++++++++++++++++--------- src/FloatingDockContainer.h | 4 + src/ads_globals.cpp | 116 ++++++++++++++++++-------- src/ads_globals.h | 46 +++++------ src/linux/FloatingWidgetTitleBar.cpp | 8 +- 7 files changed, 231 insertions(+), 112 deletions(-) diff --git a/src/DockFocusController.cpp b/src/DockFocusController.cpp index 702a00a..c488288 100644 --- a/src/DockFocusController.cpp +++ b/src/DockFocusController.cpp @@ -83,7 +83,8 @@ static void updateDockAreaFocusStyle(CDockAreaWidget* DockArea, bool Focused) #ifdef Q_OS_LINUX static void updateFloatingWidgetFocusStyle(CFloatingDockContainer* FloatingWidget, bool Focused) { - if(FloatingWidget->hasNativeTitleBar()){ + if (FloatingWidget->hasNativeTitleBar()) + { return; } auto TitleBar = qobject_cast(FloatingWidget->titleBarWidget()); diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 3fcac69..d322dfe 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -493,45 +493,62 @@ CDockManager::~CDockManager() //============================================================================ #ifdef Q_OS_LINUX -bool CDockManager::eventFilter(QObject *obj, QEvent *e){ +bool CDockManager::eventFilter(QObject *obj, QEvent *e) +{ // Emulate Qt:Tool behaviour. // Required because on some WMs Tool windows can't be maximized. // Window always on top of the MainWindow. - if(e->type() == QEvent::WindowActivate){ - for(auto _window : floatingWidgets()){ - if(!_window->isVisible() || window()->isMinimized()){ + if (e->type() == QEvent::WindowActivate) + { + for (auto _window : floatingWidgets()) + { + if (!_window->isVisible() || window()->isMinimized()) + { continue; } // setWindowFlags(Qt::WindowStaysOnTopHint) will hide the window and thus requires a show call. // This then leads to flickering and a nasty endless loop (also buggy behaviour on Ubuntu). // So we just do it ourself. - internal::xcb_update_prop(true, _window->window()->winId(), "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP"); + internal::xcb_update_prop(true, _window->window()->winId(), + "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP"); } } - else if(e->type() == QEvent::WindowDeactivate){ - for(auto _window : floatingWidgets()){ - if(!_window->isVisible() || window()->isMinimized()){ + else if (e->type() == QEvent::WindowDeactivate) + { + for (auto _window : floatingWidgets()) + { + if (!_window->isVisible() || window()->isMinimized()) + { continue; } - internal::xcb_update_prop(false, _window->window()->winId(), "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP"); + internal::xcb_update_prop(false, _window->window()->winId(), + "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP"); _window->raise(); } } // Sync minimize with MainWindow - if(e->type() == QEvent::WindowStateChange){ - for(auto _window : floatingWidgets()){ - if(! _window->isVisible()){ + if (e->type() == QEvent::WindowStateChange) + { + for (auto _window : floatingWidgets()) + { + if (! _window->isVisible()) + { continue; } - if(window()->isMinimized()){ + + if (window()->isMinimized()) + { _window->showMinimized(); - } else { + } + else + { _window->setWindowState(_window->windowState() & (~Qt::WindowMinimized)); } } - if(!window()->isMinimized()){ + if (!window()->isMinimized()) + { QApplication::setActiveWindow(window()); } } diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index cfe66fd..8da5626 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -411,7 +411,8 @@ struct FloatingDockContainerPrivate void setWindowTitle(const QString &Text) { #ifdef Q_OS_LINUX - if(TitleBar){ + if (TitleBar) + { TitleBar->setTitle(Text); } #endif @@ -610,24 +611,40 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) : QDockWidget::setFloating(true); QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures); - // KDE doesn't seem to fire MoveEvents while moving windows, so for now no native titlebar for everything using KWin. - QString window_manager = internal::windowManager().toUpper().split(" ")[0]; - bool native_window = window_manager != "KWIN"; + bool native_window = true; + // FloatingContainerForce*TitleBar is overwritten by the "ADS_UseNativeTitle" environment variable if set. auto env = qgetenv("ADS_UseNativeTitle").toUpper(); - if (env == "1"){ + if (env == "1") + { native_window = true; - } else if (env == "0"){ - native_window = false; - } else if ( DockManager->testConfigFlag( CDockManager::FloatingContainerForceNativeTitleBar )){ - native_window = true; - } else if ( DockManager->testConfigFlag( CDockManager::FloatingContainerForceCustomTitleBar )){ + } + else if (env == "0") + { native_window = false; } - if(native_window){ + else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceNativeTitleBar)) + { + native_window = true; + } + else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceCustomTitleBar)) + { + native_window = false; + } + else + { + // KDE doesn't seem to fire MoveEvents while moving windows, so for now no native titlebar for everything using KWin. + QString window_manager = internal::windowManager().toUpper().split(" ")[0]; + bool native_window = window_manager != "KWIN"; + } + + if (native_window) + { setTitleBarWidget(new QWidget()); setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint); - } else { + } + else + { d->TitleBar = new CFloatingWidgetTitleBar(this); setTitleBarWidget(d->TitleBar); setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint); @@ -705,7 +722,8 @@ void CFloatingDockContainer::changeEvent(QEvent *event) d->zOrderIndex = ++zOrderCounter; #ifdef Q_OS_LINUX - if(d->DraggingState == DraggingFloatingWidget){ + if (d->DraggingState == DraggingFloatingWidget) + { d->titleMouseReleaseEvent(); d->DraggingState = DraggingInactive; } @@ -848,20 +866,13 @@ void CFloatingDockContainer::showEvent(QShowEvent *event) void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos, const QSize &Size, eDragState DragState, QWidget *MouseEventHandler) { -#ifndef Q_OS_LINUX - Q_UNUSED(MouseEventHandler) -#endif #ifdef Q_OS_LINUX - if (!isMaximized()) { + if (!isMaximized()) + { resize(Size); d->DragStartMousePosition = DragStartMousePos; } -#else - resize(Size); - d->DragStartMousePosition = DragStartMousePos; -#endif d->setState(DragState); -#ifdef Q_OS_LINUX if (DraggingFloatingWidget == DragState) { d->MouseEventHandler = MouseEventHandler; @@ -870,15 +881,20 @@ void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos, d->MouseEventHandler->grabMouse(); } } -#endif -#ifdef Q_OS_LINUX - if (!isMaximized()) { + + if (!isMaximized()) + { moveFloating(); } -#else - moveFloating(); -#endif show(); +#else + Q_UNUSED(MouseEventHandler) + resize(Size); + d->DragStartMousePosition = DragStartMousePos; + d->setState(DragState); + moveFloating(); + show(); +#endif } //============================================================================ @@ -988,7 +1004,8 @@ bool CFloatingDockContainer::restoreState(CDockingStateReader &Stream, } onDockAreasAddedOrRemoved(); #ifdef Q_OS_LINUX - if(d->TitleBar){ + if(d->TitleBar) + { d->TitleBar->setMaximizedIcon(windowState() == Qt::WindowMaximized); } #endif @@ -1134,15 +1151,21 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event) #ifdef Q_OS_LINUX +//============================================================================ void CFloatingDockContainer::onMaximizeRequest() { - if(windowState() == Qt::WindowMaximized){ + if (windowState() == Qt::WindowMaximized) + { showNormal(); - }else{ + } + else + { showMaximized(); } } + +//============================================================================ void CFloatingDockContainer::showNormal(bool fixGeometry) { if (windowState() == Qt::WindowMaximized) @@ -1154,45 +1177,65 @@ void CFloatingDockContainer::showNormal(bool fixGeometry) setGeometry(oldNormal); } } - if(d->TitleBar){ + if(d->TitleBar) + { d->TitleBar->setMaximizedIcon(false); } } + +//============================================================================ void CFloatingDockContainer::showMaximized() { Super::showMaximized(); - if(d->TitleBar){ + if (d->TitleBar) + { d->TitleBar->setMaximizedIcon(true); } } + +//============================================================================ bool CFloatingDockContainer::isMaximized() const { return windowState() == Qt::WindowMaximized; } -void CFloatingDockContainer::show(){ + +//============================================================================ +void CFloatingDockContainer::show() +{ // Prevent this window from showing in the taskbar and pager (alt+tab) internal::xcb_add_prop(true, winId(), "_NET_WM_STATE", "_NET_WM_STATE_SKIP_TASKBAR"); internal::xcb_add_prop(true, winId(), "_NET_WM_STATE", "_NET_WM_STATE_SKIP_PAGER"); Super::show(); } -void CFloatingDockContainer::resizeEvent(QResizeEvent *event){ + + +//============================================================================ +void CFloatingDockContainer::resizeEvent(QResizeEvent *event) +{ d->IsResizing = true; Super::resizeEvent(event); } -void CFloatingDockContainer::moveEvent(QMoveEvent *event){ + +//============================================================================ +void CFloatingDockContainer::moveEvent(QMoveEvent *event) +{ Super::moveEvent(event); - if(!d->IsResizing && event->spontaneous()){ + if (!d->IsResizing && event->spontaneous()) + { d->DraggingState = DraggingFloatingWidget; d->updateDropOverlays(QCursor::pos()); } d->IsResizing = false; } -bool CFloatingDockContainer::hasNativeTitleBar(){ + +//============================================================================ +bool CFloatingDockContainer::hasNativeTitleBar() +{ return d->TitleBar == nullptr; } #endif diff --git a/src/FloatingDockContainer.h b/src/FloatingDockContainer.h index 6062315..a22d394 100644 --- a/src/FloatingDockContainer.h +++ b/src/FloatingDockContainer.h @@ -284,6 +284,10 @@ public: */ void show(); + /** + * Returns true if the floating widget has a native titlebar or false if + * the floating widget has a QWidget based title bar + */ bool hasNativeTitleBar(); #endif diff --git a/src/ads_globals.cpp b/src/ads_globals.cpp index ee72d4e..322046e 100644 --- a/src/ads_globals.cpp +++ b/src/ads_globals.cpp @@ -53,33 +53,44 @@ namespace ads namespace internal { #ifdef Q_OS_LINUX - static QString _window_manager; - static QHash _xcb_atom_cache; +static QString _window_manager; +static QHash _xcb_atom_cache; -xcb_atom_t xcb_get_atom(const char *name){ - if (!QX11Info::isPlatformX11()){ + +//============================================================================ +xcb_atom_t xcb_get_atom(const char *name) +{ + if (!QX11Info::isPlatformX11()) + { return XCB_ATOM_NONE; } auto key = QString(name); - if(_xcb_atom_cache.contains(key)){ + if(_xcb_atom_cache.contains(key)) + { return _xcb_atom_cache[key]; } xcb_connection_t *connection = QX11Info::connection(); xcb_intern_atom_cookie_t request = xcb_intern_atom(connection, 1, strlen(name), name); xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, request, NULL); - if(!reply){ + if (!reply) + { return XCB_ATOM_NONE; } xcb_atom_t atom = reply->atom; - if(atom == XCB_ATOM_NONE){ + if(atom == XCB_ATOM_NONE) + { ADS_PRINT("Unknown Atom response from XServer: " << name); - } else { + } + else + { _xcb_atom_cache.insert(key, atom); } free(reply); return atom; } + +//============================================================================ void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2) { auto connection = QX11Info::connection(); @@ -103,18 +114,24 @@ void xcb_update_prop(bool set, WId window, const char *type, const char *prop, c xcb_flush(connection); } -xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned int atom_type){ - if (!QX11Info::isPlatformX11()){ + +//============================================================================ +xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned int atom_type) +{ + if (!QX11Info::isPlatformX11()) + { return nullptr; } xcb_connection_t *connection = QX11Info::connection(); xcb_atom_t type_atom = xcb_get_atom(type); - if (type_atom == XCB_ATOM_NONE){ + if (type_atom == XCB_ATOM_NONE) + { return nullptr; } xcb_get_property_cookie_t request = xcb_get_property_unchecked(connection, 0, window, type_atom, atom_type, 0, 1024); xcb_get_property_reply_t *reply = xcb_get_property_reply(connection, request, nullptr); - if(reply && reply->type != atom_type){ + if(reply && reply->type != atom_type) + { ADS_PRINT("ATOM TYPE MISMATCH (" << type <<"). Expected: " << atom_type << " but got " << reply->type); free(reply); return nullptr; @@ -122,10 +139,14 @@ xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned return reply; } + +//============================================================================ template -void xcb_get_prop_list(WId window, const char *type, QVector &ret, unsigned int atom_type){ +void xcb_get_prop_list(WId window, const char *type, QVector &ret, unsigned int atom_type) +{ xcb_get_property_reply_t *reply = _xcb_get_props(window, type, atom_type); - if (reply && reply->format == 32 && reply->type == atom_type && reply->value_len > 0) { + if (reply && reply->format == 32 && reply->type == atom_type && reply->value_len > 0) + { const xcb_atom_t *data = static_cast(xcb_get_property_value(reply)); ret.resize(reply->value_len); memcpy((void *)&ret.first(), (void *)data, reply->value_len * sizeof(T)); @@ -133,13 +154,18 @@ void xcb_get_prop_list(WId window, const char *type, QVector &ret, unsigned i free(reply); } -QString xcb_get_prop_string(WId window, const char *type){ + +//============================================================================ +QString xcb_get_prop_string(WId window, const char *type) +{ QString ret; // try utf8 first xcb_atom_t utf_atom = xcb_get_atom("UTF8_STRING"); - if(utf_atom != XCB_ATOM_NONE){ + if(utf_atom != XCB_ATOM_NONE) + { xcb_get_property_reply_t *reply = _xcb_get_props(window, type, utf_atom); - if (reply && reply->format == 8 && reply->type == utf_atom) { + if (reply && reply->format == 8 && reply->type == utf_atom) + { const char *value = reinterpret_cast(xcb_get_property_value(reply)); ret = QString::fromUtf8(value, xcb_get_property_value_length(reply)); free(reply); @@ -149,7 +175,8 @@ QString xcb_get_prop_string(WId window, const char *type){ } // Fall back to XCB_ATOM_STRING xcb_get_property_reply_t *reply = _xcb_get_props(window, type, XCB_ATOM_STRING); - if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) { + if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) + { const char *value = reinterpret_cast(xcb_get_property_value(reply)); ret = QString::fromLatin1(value, xcb_get_property_value_length(reply)); } @@ -157,12 +184,16 @@ QString xcb_get_prop_string(WId window, const char *type){ return ret; } -bool xcb_dump_props(WId window, const char *type){ + +//============================================================================ +bool xcb_dump_props(WId window, const char *type) +{ QVector atoms; xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM); qDebug() << "\n\n!!!" << type << " - " << atoms.length(); xcb_connection_t *connection = QX11Info::connection(); - for(auto atom : atoms){ + for (auto atom : atoms) + { auto foo = xcb_get_atom_name(connection, atom); auto bar = xcb_get_atom_name_reply(connection, foo, nullptr); qDebug() << "\t" << xcb_get_atom_name_name(bar); @@ -171,21 +202,29 @@ bool xcb_dump_props(WId window, const char *type){ return true; } -void xcb_add_prop(bool state, WId window, const char *type, const char *prop){ - if (!QX11Info::isPlatformX11()){ + +//============================================================================ +void xcb_add_prop(bool state, WId window, const char *type, const char *prop) +{ + if (!QX11Info::isPlatformX11()) + { return; } xcb_atom_t prop_atom = xcb_get_atom(prop); xcb_atom_t type_atom = xcb_get_atom(type); - if(prop_atom == XCB_ATOM_NONE || type_atom == XCB_ATOM_NONE){ + if (prop_atom == XCB_ATOM_NONE || type_atom == XCB_ATOM_NONE) + { return; } QVector atoms; xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM); int index = atoms.indexOf(prop_atom); - if(state && index == -1){ + if (state && index == -1) + { atoms.push_back(prop_atom); - } else if(!state && index >= 0){ + } + else if (!state && index >= 0) + { atoms.remove(index); } xcb_connection_t *connection = QX11Info::connection(); @@ -193,15 +232,20 @@ void xcb_add_prop(bool state, WId window, const char *type, const char *prop){ xcb_flush(connection); } -QString detectWindowManagerX11(){ + +//============================================================================ +QString detectWindowManagerX11() +{ // Tries to detect the windowmanager via X11. // See: https://specifications.freedesktop.org/wm-spec/1.3/ar01s03.html#idm46018259946000 - if (!QX11Info::isPlatformX11()){ + if (!QX11Info::isPlatformX11()) + { return "UNKNOWN"; } xcb_connection_t *connection = QX11Info::connection(); xcb_screen_t *first_screen = xcb_setup_roots_iterator (xcb_get_setup (connection)).data; - if(!first_screen){ + if(!first_screen) + { ADS_PRINT("No screen found via XCB."); return "UNKNOWN"; } @@ -210,26 +254,32 @@ QString detectWindowManagerX11(){ xcb_window_t support_win = 0; QVector sup_windows; xcb_get_prop_list(root, "_NET_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_WINDOW); - if(sup_windows.length() == 0){ + if(sup_windows.length() == 0) + { // This doesn't seem to be in use anymore, but wmctrl does the same so lets play safe. // Both XCB_ATOM_CARDINAL and XCB_ATOM_WINDOW break down to a uint32_t, so reusing sup_windows should be fine. xcb_get_prop_list(root, "_WIN_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_CARDINAL); } - if(sup_windows.length() == 0){ + if(sup_windows.length() == 0) + { ADS_PRINT("Failed to get the supporting window on non EWMH comform WM."); return "UNKNOWN"; } support_win = sup_windows[0]; QString ret = xcb_get_prop_string(support_win, "_NET_WM_NAME"); - if(ret.length() == 0){ + if(ret.length() == 0) + { ADS_PRINT("Empty WM name occured."); return "UNKNOWN"; } return ret; } -QString windowManager(){ - if(_window_manager.length() == 0){ +//============================================================================ +QString windowManager() +{ + if(_window_manager.length() == 0) + { _window_manager = detectWindowManagerX11(); } return _window_manager; diff --git a/src/ads_globals.h b/src/ads_globals.h index dc278bf..c5fe28d 100644 --- a/src/ads_globals.h +++ b/src/ads_globals.h @@ -135,30 +135,30 @@ static const char* const ClosedProperty = "close"; static const char* const DirtyProperty = "dirty"; #ifdef Q_OS_LINUX - // Utils to directly communicate with the X server - /** - * Get atom from cache or request it from the XServer. - */ - xcb_atom_t xcb_get_atom(const char *name); +// Utils to directly communicate with the X server +/** + * Get atom from cache or request it from the XServer. + */ +xcb_atom_t xcb_get_atom(const char *name); - /** - * Add a property to a window. Only works on "hidden" windows. - */ - void xcb_add_prop(bool state, WId window, const char *type, const char *prop); - /** - * Updates up to two window properties. Can be set on a visible window. - */ - void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2 = nullptr); - /** - * Only for debugging purposes. - */ - bool xcb_dump_props(WId window, const char *type); - /** - * Gets the active window manager from the X11 Server. - * Requires a EWMH conform window manager (Allmost all common used ones are). - * Returns "UNKNOWN" otherwise. - */ - QString windowManager(); +/** + * Add a property to a window. Only works on "hidden" windows. + */ +void xcb_add_prop(bool state, WId window, const char *type, const char *prop); +/** + * Updates up to two window properties. Can be set on a visible window. + */ +void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2 = nullptr); +/** + * Only for debugging purposes. + */ +bool xcb_dump_props(WId window, const char *type); +/** + * Gets the active window manager from the X11 Server. + * Requires a EWMH conform window manager (Allmost all common used ones are). + * Returns "UNKNOWN" otherwise. + */ +QString windowManager(); #endif /** diff --git a/src/linux/FloatingWidgetTitleBar.cpp b/src/linux/FloatingWidgetTitleBar.cpp index 63f88ef..fa1ae5b 100644 --- a/src/linux/FloatingWidgetTitleBar.cpp +++ b/src/linux/FloatingWidgetTitleBar.cpp @@ -154,6 +154,7 @@ void CFloatingWidgetTitleBar::mousePressEvent(QMouseEvent *ev) Super::mousePressEvent(ev); } + //============================================================================ void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev) { @@ -165,6 +166,7 @@ void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev) Super::mouseReleaseEvent(ev); } + //============================================================================ void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev) { @@ -178,12 +180,10 @@ void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev) // move floating window if (DraggingFloatingWidget == d->DragState) { -#ifdef Q_OS_LINUX if(d->FloatingWidget->isMaximized()) { d->FloatingWidget->showNormal(true); } -#endif d->FloatingWidget->moveFloating(); Super::mouseMoveEvent(ev); return; @@ -211,6 +211,8 @@ void CFloatingWidgetTitleBar::updateStyle() internal::repolishStyle(this, internal::RepolishDirectChildren); } + +//============================================================================ void CFloatingWidgetTitleBar::mouseDoubleClickEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) @@ -224,6 +226,8 @@ void CFloatingWidgetTitleBar::mouseDoubleClickEvent(QMouseEvent *event) } } + +//============================================================================ void CFloatingWidgetTitleBar::setMaximizedIcon(bool maximized) { if (maximized)