diff --git a/app/settings/data/preferencesdata.cpp b/app/settings/data/preferencesdata.cpp index 9272978a..36947be8 100644 --- a/app/settings/data/preferencesdata.cpp +++ b/app/settings/data/preferencesdata.cpp @@ -1,144 +1,152 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "preferencesdata.h" namespace Latte { namespace Settings { namespace Data { const bool Preferences::BADGE3DSTYLE; const bool Preferences::LAYOUTSINFORMATIONWINDOW; const bool Preferences::AUTOSTART; const bool Preferences::BORDERLESSMAXIMIZED; +const bool Preferences::HIDDENCONFIGURATIONWINDOWSAREDELETED; const bool Preferences::METAPRESSFORAPPLAUNCHER; const bool Preferences::METAHOLDFORBADGES; const int Preferences::SCREENSDELAY; const int Preferences::OUTLINEWIDTH; const Settings::MouseSensitivity Preferences::MOUSESENSITIVITY; Preferences::Preferences() { } Preferences::Preferences(Preferences &&o) : badgeStyle3D(o.badgeStyle3D), layoutsInformationWindow(o.layoutsInformationWindow), autostart(o.autostart), borderlessMaximized(o.borderlessMaximized), + hiddenConfigurationWindowsAreDeleted(o.hiddenConfigurationWindowsAreDeleted), metaPressForAppLauncher(o.metaPressForAppLauncher), metaHoldForBadges(o.metaHoldForBadges), mouseSensitivity(o.mouseSensitivity), screensDelay(o.screensDelay), outlineWidth(o.outlineWidth) { } Preferences::Preferences(const Preferences &o) : badgeStyle3D(o.badgeStyle3D), layoutsInformationWindow(o.layoutsInformationWindow), autostart(o.autostart), borderlessMaximized(o.borderlessMaximized), + hiddenConfigurationWindowsAreDeleted(o.hiddenConfigurationWindowsAreDeleted), metaPressForAppLauncher(o.metaPressForAppLauncher), metaHoldForBadges(o.metaHoldForBadges), mouseSensitivity(o.mouseSensitivity), screensDelay(o.screensDelay), outlineWidth(o.outlineWidth) { } Preferences &Preferences::operator=(const Preferences &rhs) { badgeStyle3D = rhs.badgeStyle3D; layoutsInformationWindow = rhs.layoutsInformationWindow; autostart = rhs.autostart; borderlessMaximized = rhs.borderlessMaximized; + hiddenConfigurationWindowsAreDeleted = rhs.hiddenConfigurationWindowsAreDeleted; metaPressForAppLauncher = rhs.metaPressForAppLauncher; metaHoldForBadges = rhs.metaHoldForBadges; mouseSensitivity = rhs.mouseSensitivity; screensDelay = rhs.screensDelay; outlineWidth = rhs.outlineWidth; return (*this); } Preferences &Preferences::operator=(Preferences &&rhs) { badgeStyle3D = rhs.badgeStyle3D; layoutsInformationWindow = rhs.layoutsInformationWindow; autostart = rhs.autostart; borderlessMaximized = rhs.borderlessMaximized; + hiddenConfigurationWindowsAreDeleted = rhs.hiddenConfigurationWindowsAreDeleted; metaPressForAppLauncher = rhs.metaPressForAppLauncher; metaHoldForBadges = rhs.metaHoldForBadges; mouseSensitivity = rhs.mouseSensitivity; screensDelay = rhs.screensDelay; outlineWidth = rhs.outlineWidth; return (*this); } bool Preferences::operator==(const Preferences &rhs) const { return (badgeStyle3D == rhs.badgeStyle3D) && (layoutsInformationWindow == rhs.layoutsInformationWindow) && (autostart == rhs.autostart) && (borderlessMaximized == rhs.borderlessMaximized) + && (hiddenConfigurationWindowsAreDeleted == rhs.hiddenConfigurationWindowsAreDeleted) && (metaPressForAppLauncher == rhs.metaPressForAppLauncher) && (metaHoldForBadges == rhs.metaHoldForBadges) && (mouseSensitivity == rhs.mouseSensitivity) && (screensDelay == rhs.screensDelay) && (outlineWidth == rhs.outlineWidth); } bool Preferences::operator!=(const Preferences &rhs) const { return !(*this == rhs); } bool Preferences::inDefaultValues() const { return (badgeStyle3D == BADGE3DSTYLE) && (layoutsInformationWindow == LAYOUTSINFORMATIONWINDOW) && (autostart == AUTOSTART) && (borderlessMaximized == BORDERLESSMAXIMIZED) + && (hiddenConfigurationWindowsAreDeleted == HIDDENCONFIGURATIONWINDOWSAREDELETED) && (metaPressForAppLauncher == METAPRESSFORAPPLAUNCHER) && (metaHoldForBadges == METAHOLDFORBADGES) && (mouseSensitivity == MOUSESENSITIVITY) && (screensDelay == SCREENSDELAY) && (outlineWidth == OUTLINEWIDTH); } void Preferences::setToDefaults() { badgeStyle3D = BADGE3DSTYLE; layoutsInformationWindow = LAYOUTSINFORMATIONWINDOW; autostart = AUTOSTART; borderlessMaximized = BORDERLESSMAXIMIZED; + hiddenConfigurationWindowsAreDeleted = HIDDENCONFIGURATIONWINDOWSAREDELETED; metaPressForAppLauncher = METAPRESSFORAPPLAUNCHER; metaHoldForBadges = METAHOLDFORBADGES; mouseSensitivity = MOUSESENSITIVITY; screensDelay = SCREENSDELAY; outlineWidth = OUTLINEWIDTH; } } } } diff --git a/app/settings/data/preferencesdata.h b/app/settings/data/preferencesdata.h index 6bb3387b..a95c531f 100644 --- a/app/settings/data/preferencesdata.h +++ b/app/settings/data/preferencesdata.h @@ -1,73 +1,75 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef SETTINGSDATAPREFERENCES_H #define SETTINGSDATAPREFERENCES_H // local #include "../../apptypes.h" namespace Latte { namespace Settings { namespace Data { class Preferences { public: static const bool BADGE3DSTYLE = true; static const bool LAYOUTSINFORMATIONWINDOW = true; static const bool AUTOSTART = true; static const bool BORDERLESSMAXIMIZED = false; + static const bool HIDDENCONFIGURATIONWINDOWSAREDELETED = true; static const bool METAPRESSFORAPPLAUNCHER = false; static const bool METAHOLDFORBADGES = true; static const int SCREENSDELAY = 2500; static const int OUTLINEWIDTH = 1; static const Settings::MouseSensitivity MOUSESENSITIVITY = Settings::HighMouseSensitivity; Preferences(); Preferences(Preferences &&o); Preferences(const Preferences &o); //! Preferences data bool badgeStyle3D{BADGE3DSTYLE}; bool layoutsInformationWindow{LAYOUTSINFORMATIONWINDOW}; bool autostart{AUTOSTART}; bool borderlessMaximized{BORDERLESSMAXIMIZED}; + bool hiddenConfigurationWindowsAreDeleted{HIDDENCONFIGURATIONWINDOWSAREDELETED}; bool metaPressForAppLauncher{METAPRESSFORAPPLAUNCHER}; bool metaHoldForBadges{METAHOLDFORBADGES}; int screensDelay{SCREENSDELAY}; int outlineWidth{OUTLINEWIDTH}; Settings::MouseSensitivity mouseSensitivity{MOUSESENSITIVITY}; bool inDefaultValues() const; void setToDefaults(); //! Operators Preferences &operator=(const Preferences &rhs); Preferences &operator=(Preferences &&rhs); bool operator==(const Preferences &rhs) const; bool operator!=(const Preferences &rhs) const; }; } } } #endif diff --git a/app/settings/dialogs/settingsdialog.ui b/app/settings/dialogs/settingsdialog.ui index fa1ea628..7483ea97 100644 --- a/app/settings/dialogs/settingsdialog.ui +++ b/app/settings/dialogs/settingsdialog.ui @@ -1,1148 +1,1158 @@ SettingsDialog 0 0 966 781 0 0 500 0 Settings - 0 + 1 Layouts Qt::Horizontal 40 20 0 0 Only one layout can be present in memory at all cases Single Layout true Multiple layouts can be present and active in memory at the same time Multiple Layouts true false Qt::Horizontal 40 20 QAbstractScrollArea::AdjustToContents true true QAbstractItemView::SingleSelection QAbstractItemView::SelectRows false true false true false true false false Switch .. false Pause .. Qt::Vertical QSizePolicy::Preferred 20 15 0 0 Qt::Horizontal Qt::Vertical QSizePolicy::Preferred 20 15 New .. Copy .. false Remove .. Qt::Vertical QSizePolicy::Fixed 1 10 Locked .. true Shared .. true Qt::Vertical QSizePolicy::Fixed 1 10 Qt::Vertical QSizePolicy::Expanding 20 15 Details... .. Qt::Vertical QSizePolicy::Preferred 20 15 0 0 0 0 0 0 1 Qt::Horizontal Qt::Vertical QSizePolicy::Preferred 20 15 Import... .. false Export... .. Ctrl+S false Download... .. Qt::Vertical QSizePolicy::Preferred 20 20 0 0 Preferences 9 0 0 QFrame::NoFrame true 0 0 931 - 375 + 402 0 0 - - + + + + Press and hold ⌘ to show shortcuts badges for applets and tasks + + + Press and Hold ⌘ to show shortcuts badges + + + + + - - - - 0 - 0 - - - - - 70 - 0 - + + + Qt::Horizontal - + - 110 - 16777215 + 40 + 20 - - Outline width used from background to draw its borders - - - px. + + + + + + + 0 + 0 + - - 1 + + Parabolic Effect: - - 20 + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + - - - true + + + Qt::Horizontal + + + + 40 + 20 + + + + + 0 0 - - Outline width used from background to draw its borders - - outline width + Plasma Theme: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + - + Qt::Horizontal - - QSizePolicy::Expanding - - 20 + 40 20 + + + + + 0 + 0 + + + + Behavior: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + - - - - Activate support for borderless maximized windows between different layouts - - - Support borderless maximized windows in different layouts - - - - - - Forward ⌘ press from KWin to Latte in order to activate Application Launcher. It is suggested to disable that option if you remove Latte. - - - Press ⌘ to activate Application Launcher - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - - - - - Start the application automatically after each relogin - - - Enable autostart during startup - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - - - - - Press and hold ⌘ to show shortcuts badges for applets and tasks - - - Press and Hold ⌘ to show shortcuts badges - - - - - + Qt::Vertical QSizePolicy::Fixed 20 10 - + 0 0 70 0 110 16777215 Different hardware can have different delays during screen changes. This tracker is used in order to not lose any screen related update. Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter ms. 1000 10000 100 2500 0 0 Different hardware can have different delays during screen changes. This tracker is used in order to not lose any screen related update. reaction delay for changes Qt::Horizontal QSizePolicy::Expanding 20 20 - - - - Provide visual feedback when layouts are activated automatically - - - Show informative window for layouts automatic activation - - - - - + + Qt::Vertical QSizePolicy::Fixed 20 10 - - + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + + 110 + 16777215 + + + + Outline width used from background to draw its borders + + + px. + + + 1 + + + 20 + + + + + + + true + + + + 0 + 0 + + + + Outline width used from background to draw its borders + + + outline width + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + Qt::Vertical QSizePolicy::Fixed 20 10 - - - - Use 3D style for notification and shortcut badges - - - - + 0 0 Low sensitivity for parabolic effect (low cpu usage and performance) Low true 0 0 Medium sensitivity for parabolic effect (normal cpu usage and performance) Medium true 0 0 High sensitivity for parabolic effect (high cpu usage and performance) High true mouse sensitivity Qt::Horizontal QSizePolicy::Fixed 60 20 - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Appearance: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Behavior: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Actions: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - + + - + Qt::Horizontal 40 20 - + 0 0 - Parabolic Effect: + Screens: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - + + + + Provide visual feedback when layouts are activated automatically + + + Show informative window for layouts automatic activation + + + + + - + Qt::Horizontal 40 20 - - - - 0 - 0 - - + - Screens: + Appearance: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + Use 3D style for notification and shortcut badges + + + + + - + Qt::Horizontal 40 20 - - - - 0 - 0 - - + - Plasma Theme: + Actions: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + Activate support for borderless maximized windows between different layouts + + + Support borderless maximized windows in different layouts + + + + + + + Start the application automatically after each relogin + + + Enable autostart during startup + + + + + + + Forward ⌘ press from KWin to Latte in order to activate Application Launcher. It is suggested to disable that option if you remove Latte. + + + Press ⌘ to activate Application Launcher + + + + + + + Memory consumption is deleted when hidden configuration windows are deleted. On the other hand if you disable that option the configuration windows responsiveness during showing and hiding is flawlessly. + + + Hidden configuration windows are deleted for memory efficiency + + + Qt::Horizontal QDialogButtonBox::Apply|QDialogButtonBox::Reset|QDialogButtonBox::RestoreDefaults Latte::Settings::View::LayoutsTableView QTableView
settings/views/layoutstableview.h
buttonBox accepted() SettingsDialog accept() 254 341 157 274 buttonBox rejected() SettingsDialog reject() 322 341 286 274
diff --git a/app/settings/handlers/tabpreferenceshandler.cpp b/app/settings/handlers/tabpreferenceshandler.cpp index 716adfb6..7ec7c3c8 100644 --- a/app/settings/handlers/tabpreferenceshandler.cpp +++ b/app/settings/handlers/tabpreferenceshandler.cpp @@ -1,188 +1,196 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "tabpreferenceshandler.h" //! local #include #include "ui_settingsdialog.h" #include "../universalsettings.h" #include "../dialogs/settingsdialog.h" #include "../../apptypes.h" #include "../../lattecorona.h" #include "../../plasma/extended/theme.h" namespace Latte { namespace Settings { namespace Handler { TabPreferences::TabPreferences(Latte::Settings::Dialog::SettingsDialog *parent) : Generic(parent), m_parentDialog(parent), m_corona(m_parentDialog->corona()), m_ui(m_parentDialog->ui()) { initSettings(); initUi(); } void TabPreferences::initUi() { //! exclusive group m_mouseSensitivityButtons = new QButtonGroup(this); m_mouseSensitivityButtons->addButton(m_ui->lowSensitivityBtn, Latte::Settings::LowMouseSensitivity); m_mouseSensitivityButtons->addButton(m_ui->mediumSensitivityBtn, Latte::Settings::MediumMouseSensitivity); m_mouseSensitivityButtons->addButton(m_ui->highSensitivityBtn, Latte::Settings::HighMouseSensitivity); m_mouseSensitivityButtons->setExclusive(true); //! signals connect(m_mouseSensitivityButtons, static_cast(&QButtonGroup::buttonToggled), [ = ](int id, bool checked) { if (checked) { m_preferences.mouseSensitivity = static_cast(id); emit dataChanged(); } }); connect(m_ui->screenTrackerSpinBox, QOverload::of(&QSpinBox::valueChanged), [ = ](int i) { m_preferences.screensDelay = m_ui->screenTrackerSpinBox->value(); emit dataChanged(); }); connect(m_ui->outlineSpinBox, QOverload::of(&QSpinBox::valueChanged), [ = ](int i) { m_preferences.outlineWidth = m_ui->outlineSpinBox->value(); emit dataChanged(); }); connect(m_ui->autostartChkBox, &QCheckBox::stateChanged, this, [&]() { m_preferences.autostart = m_ui->autostartChkBox->isChecked(); emit dataChanged(); }); connect(m_ui->badges3DStyleChkBox, &QCheckBox::stateChanged, this, [&]() { m_preferences.badgeStyle3D = m_ui->badges3DStyleChkBox->isChecked(); emit dataChanged(); }); - connect(m_ui->metaPressChkBox, &QCheckBox::stateChanged, this, [&]() { - m_preferences.metaPressForAppLauncher = m_ui->metaPressChkBox->isChecked(); + connect(m_ui->screenTrackerSpinBox, QOverload::of(&QSpinBox::valueChanged), [ = ](int i) { + m_preferences.screensDelay = m_ui->screenTrackerSpinBox->value(); + emit dataChanged(); + }); + + connect(m_ui->hiddenConfigsAreDeletedChk, &QCheckBox::stateChanged, this, [&]() { + m_preferences.hiddenConfigurationWindowsAreDeleted = m_ui->hiddenConfigsAreDeletedChk->isChecked(); emit dataChanged(); }); connect(m_ui->metaPressHoldChkBox, &QCheckBox::stateChanged, this, [&]() { m_preferences.metaHoldForBadges = m_ui->metaPressHoldChkBox->isChecked(); emit dataChanged(); }); connect(m_ui->infoWindowChkBox, &QCheckBox::stateChanged, this, [&]() { m_preferences.layoutsInformationWindow = m_ui->infoWindowChkBox->isChecked(); emit dataChanged(); }); connect(m_ui->noBordersForMaximizedChkBox, &QCheckBox::stateChanged, this, [&]() { m_preferences.borderlessMaximized = m_ui->noBordersForMaximizedChkBox->isChecked(); emit dataChanged(); }); } void TabPreferences::initSettings() { o_preferences.autostart = m_corona->universalSettings()->autostart(); o_preferences.badgeStyle3D = m_corona->universalSettings()->badges3DStyle(); o_preferences.layoutsInformationWindow = m_corona->universalSettings()->showInfoWindow(); + o_preferences.hiddenConfigurationWindowsAreDeleted = m_corona->universalSettings()->hiddenConfigurationWindowsAreDeleted(); o_preferences.metaPressForAppLauncher = m_corona->universalSettings()->kwin_metaForwardedToLatte(); o_preferences.metaHoldForBadges = m_corona->universalSettings()->metaPressAndHoldEnabled(); o_preferences.borderlessMaximized = m_corona->universalSettings()->canDisableBorders(); o_preferences.mouseSensitivity = m_corona->universalSettings()->sensitivity(); o_preferences.screensDelay = m_corona->universalSettings()->screenTrackerInterval(); o_preferences.outlineWidth = m_corona->themeExtended()->outlineWidth(); m_preferences = o_preferences; updateUi(); } void TabPreferences::updateUi() { //! ui load m_ui->autostartChkBox->setChecked(m_preferences.autostart); m_ui->badges3DStyleChkBox->setChecked(m_preferences.badgeStyle3D); m_ui->infoWindowChkBox->setChecked(m_preferences.layoutsInformationWindow); + m_ui->hiddenConfigsAreDeletedChk->setChecked(m_preferences.hiddenConfigurationWindowsAreDeleted); m_ui->metaPressChkBox->setChecked(m_preferences.metaPressForAppLauncher); m_ui->metaPressHoldChkBox->setChecked(m_preferences.metaHoldForBadges); m_ui->noBordersForMaximizedChkBox->setChecked(m_preferences.borderlessMaximized); m_ui->screenTrackerSpinBox->setValue(m_preferences.screensDelay); m_ui->outlineSpinBox->setValue(m_preferences.outlineWidth); if (m_preferences.mouseSensitivity == Settings::LowMouseSensitivity) { m_ui->lowSensitivityBtn->setChecked(true); } else if (m_preferences.mouseSensitivity == Settings::MediumMouseSensitivity) { m_ui->mediumSensitivityBtn->setChecked(true); } else if (m_preferences.mouseSensitivity == Settings::HighMouseSensitivity) { m_ui->highSensitivityBtn->setChecked(true); } emit dataChanged(); } bool TabPreferences::dataAreChanged() const { return o_preferences != m_preferences; } bool TabPreferences::inDefaultValues() const { return m_preferences.inDefaultValues(); } void TabPreferences::reset() { m_preferences = o_preferences; updateUi(); } void TabPreferences::resetDefaults() { m_preferences.setToDefaults(); updateUi(); } void TabPreferences::save() { m_corona->universalSettings()->setSensitivity(m_preferences.mouseSensitivity); m_corona->universalSettings()->setAutostart(m_preferences.autostart); m_corona->universalSettings()->setBadges3DStyle(m_preferences.badgeStyle3D); + m_corona->universalSettings()->setHiddenConfigurationWindowsAreDeleted(m_preferences.hiddenConfigurationWindowsAreDeleted); m_corona->universalSettings()->kwin_forwardMetaToLatte(m_preferences.metaPressForAppLauncher); m_corona->universalSettings()->setMetaPressAndHoldEnabled(m_preferences.metaHoldForBadges); m_corona->universalSettings()->setShowInfoWindow(m_preferences.layoutsInformationWindow); m_corona->universalSettings()->setCanDisableBorders(m_preferences.borderlessMaximized); m_corona->universalSettings()->setScreenTrackerInterval(m_preferences.screensDelay); m_corona->themeExtended()->setOutlineWidth(m_preferences.outlineWidth); o_preferences = m_preferences; emit dataChanged(); } } } } diff --git a/app/settings/universalsettings.cpp b/app/settings/universalsettings.cpp index c5733003..3c766b0e 100644 --- a/app/settings/universalsettings.cpp +++ b/app/settings/universalsettings.cpp @@ -1,569 +1,586 @@ /* * Copyright 2017 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "universalsettings.h" // local #include "../layouts/importer.h" #include "../layouts/manager.h" // Qt #include #include #include #include // KDE #include #include #define KWINMETAFORWARDTOLATTESTRING "org.kde.lattedock,/Latte,org.kde.LatteDock,activateLauncherMenu" #define KWINMETAFORWARDTOPLASMASTRING "org.kde.plasmashell,/PlasmaShell,org.kde.PlasmaShell,activateLauncherMenu" #define KWINCOLORSSCRIPT "kwin/scripts/lattewindowcolors" #define KWINRC "/.config/kwinrc" #define KWINRCTRACKERINTERVAL 2500 namespace Latte { UniversalSettings::UniversalSettings(KSharedConfig::Ptr config, QObject *parent) : QObject(parent), m_config(config), m_universalGroup(KConfigGroup(config, QStringLiteral("UniversalSettings"))) { m_corona = qobject_cast(parent); connect(this, &UniversalSettings::badges3DStyleChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::canDisableBordersChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::currentLayoutNameChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::lastNonAssignedLayoutNameChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::launchersChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::layoutsMemoryUsageChanged, this, &UniversalSettings::saveConfig); + connect(this, &UniversalSettings::hiddenConfigurationWindowsAreDeletedChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::metaPressAndHoldEnabledChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::sensitivityChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::screenTrackerIntervalChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::showInfoWindowChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::versionChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::screenScalesChanged, this, &UniversalSettings::saveScalesConfig); connect(qGuiApp, &QGuiApplication::screenAdded, this, &UniversalSettings::screensCountChanged); connect(qGuiApp, &QGuiApplication::screenRemoved, this, &UniversalSettings::screensCountChanged); } UniversalSettings::~UniversalSettings() { saveConfig(); cleanupSettings(); } void UniversalSettings::load() { //! check if user has set the autostart option bool autostartUserSet = m_universalGroup.readEntry("userConfiguredAutostart", false); if (!autostartUserSet && !autostart()) { setAutostart(true); } //! init screen scales m_screenScalesGroup = m_universalGroup.group("ScreenScales"); //! load configuration loadConfig(); //! Track KWin Colors Script Presence updateColorsScriptIsPresent(); QStringList colorsScriptPaths = Layouts::Importer::standardPathsFor(KWINCOLORSSCRIPT); for(auto path: colorsScriptPaths) { KDirWatch::self()->addDir(path); } //! Track KWin rc options const QString kwinrcFilePath = QDir::homePath() + KWINRC; KDirWatch::self()->addFile(kwinrcFilePath); recoverKWinOptions(); m_kwinrcTrackerTimer.setSingleShot(true); m_kwinrcTrackerTimer.setInterval(KWINRCTRACKERINTERVAL); connect(&m_kwinrcTrackerTimer, &QTimer::timeout, this, &UniversalSettings::recoverKWinOptions); connect(KDirWatch::self(), &KDirWatch::created, this, &UniversalSettings::trackedFileChanged); connect(KDirWatch::self(), &KDirWatch::deleted, this, &UniversalSettings::trackedFileChanged); connect(KDirWatch::self(), &KDirWatch::dirty, this, &UniversalSettings::trackedFileChanged); //! this is needed to inform globalshortcuts to update its modifiers tracking emit metaPressAndHoldEnabledChanged(); } bool UniversalSettings::showInfoWindow() const { return m_showInfoWindow; } void UniversalSettings::setShowInfoWindow(bool show) { if (m_showInfoWindow == show) { return; } m_showInfoWindow = show; emit showInfoWindowChanged(); } int UniversalSettings::version() const { return m_version; } void UniversalSettings::setVersion(int ver) { if (m_version == ver) { return; } m_version = ver; qDebug() << "Universal Settings version updated to : " << m_version; emit versionChanged(); } int UniversalSettings::screenTrackerInterval() const { return m_screenTrackerInterval; } void UniversalSettings::setScreenTrackerInterval(int duration) { if (m_screenTrackerInterval == duration) { return; } m_screenTrackerInterval = duration; emit screenTrackerIntervalChanged(); } QString UniversalSettings::currentLayoutName() const { return m_currentLayoutName; } void UniversalSettings::setCurrentLayoutName(QString layoutName) { if (m_currentLayoutName == layoutName) { return; } m_currentLayoutName = layoutName; emit currentLayoutNameChanged(); } QString UniversalSettings::lastNonAssignedLayoutName() const { return m_lastNonAssignedLayoutName; } void UniversalSettings::setLastNonAssignedLayoutName(QString layoutName) { if (m_lastNonAssignedLayoutName == layoutName) { return; } m_lastNonAssignedLayoutName = layoutName; emit lastNonAssignedLayoutNameChanged(); } QStringList UniversalSettings::launchers() const { return m_launchers; } void UniversalSettings::setLaunchers(QStringList launcherList) { if (m_launchers == launcherList) { return; } m_launchers = launcherList; emit launchersChanged(); } bool UniversalSettings::autostart() const { QFile autostartFile(QDir::homePath() + "/.config/autostart/org.kde.latte-dock.desktop"); return autostartFile.exists(); } void UniversalSettings::setAutostart(bool state) { //! remove old autostart file QFile oldAutostartFile(QDir::homePath() + "/.config/autostart/latte-dock.desktop"); if (oldAutostartFile.exists()) { oldAutostartFile.remove(); } //! end of removal of old autostart file QFile autostartFile(QDir::homePath() + "/.config/autostart/org.kde.latte-dock.desktop"); QFile metaFile(Layouts::Importer::standardPath("applications/org.kde.latte-dock.desktop", false)); if (!state && autostartFile.exists()) { //! the first time that the user disables the autostart, this is recorded //! and from now own it will not be recreated it in the beginning if (!m_universalGroup.readEntry("userConfiguredAutostart", false)) { m_universalGroup.writeEntry("userConfiguredAutostart", true); } autostartFile.remove(); emit autostartChanged(); } else if (state && metaFile.exists()) { //! check if autostart folder exists and create otherwise QDir autostartDir(QDir::homePath() + "/.config/autostart"); if (!autostartDir.exists()) { QDir configDir(QDir::homePath() + "/.config"); configDir.mkdir("autostart"); } metaFile.copy(autostartFile.fileName()); //! I haven't added the flag "OnlyShowIn=KDE;" into the autostart file //! because I fall onto a Plasma 5.8 case that this flag //! didn't let the plasma desktop to start emit autostartChanged(); } } bool UniversalSettings::badges3DStyle() const { return m_badges3DStyle; } void UniversalSettings::setBadges3DStyle(bool enable) { if (m_badges3DStyle == enable) { return; } m_badges3DStyle = enable; emit badges3DStyleChanged(); } bool UniversalSettings::canDisableBorders() const { return m_canDisableBorders; } void UniversalSettings::setCanDisableBorders(bool enable) { if (m_canDisableBorders == enable) { return; } m_canDisableBorders = enable; emit canDisableBordersChanged(); } bool UniversalSettings::colorsScriptIsPresent() const { return m_colorsScriptIsPresent; } void UniversalSettings::setColorsScriptIsPresent(bool present) { if (m_colorsScriptIsPresent == present) { return; } m_colorsScriptIsPresent = present; emit colorsScriptIsPresentChanged(); } void UniversalSettings::updateColorsScriptIsPresent() { qDebug() << "Updating Latte Colors Script presence..."; setColorsScriptIsPresent(!Layouts::Importer::standardPath(KWINCOLORSSCRIPT).isEmpty()); } void UniversalSettings::trackedFileChanged(const QString &file) { if (file.endsWith(KWINCOLORSSCRIPT)) { updateColorsScriptIsPresent(); } if (file.endsWith(KWINRC)) { m_kwinrcTrackerTimer.start(); } } bool UniversalSettings::kwin_metaForwardedToLatte() const { return m_kwinMetaForwardedToLatte; } bool UniversalSettings::kwin_borderlessMaximizedWindowsEnabled() const { return m_kwinBorderlessMaximizedWindows; } void UniversalSettings::kwin_forwardMetaToLatte(bool forward) { if (m_kwinMetaForwardedToLatte == forward) { return; } QProcess process; QStringList parameters; parameters << "--file" << "kwinrc" << "--group" << "ModifierOnlyShortcuts" << "--key" << "Meta"; if (forward) { parameters << KWINMETAFORWARDTOLATTESTRING; } else { parameters << KWINMETAFORWARDTOPLASMASTRING; } process.start("kwriteconfig5", parameters); process.waitForFinished(); QDBusInterface iface("org.kde.KWin", "/KWin", "", QDBusConnection::sessionBus()); if (iface.isValid()) { iface.call("reconfigure"); } } void UniversalSettings::kwin_setDisabledMaximizedBorders(bool disable) { if (m_kwinBorderlessMaximizedWindows == disable) { return; } QString disableText = disable ? "true" : "false"; QProcess process; QString commandStr = "kwriteconfig5 --file kwinrc --group Windows --key BorderlessMaximizedWindows --type bool " + disableText; process.start(commandStr); process.waitForFinished(); QDBusInterface iface("org.kde.KWin", "/KWin", "", QDBusConnection::sessionBus()); if (iface.isValid()) { iface.call("reconfigure"); } } void UniversalSettings::recoverKWinOptions() { qDebug() << "kwinrc: recovering values..."; //! Meta forwarded to Latte option QProcess process; process.start("kreadconfig5 --file kwinrc --group ModifierOnlyShortcuts --key Meta"); process.waitForFinished(); QString output(process.readAllStandardOutput()); output = output.remove("\n"); m_kwinMetaForwardedToLatte = (output == KWINMETAFORWARDTOLATTESTRING); //! BorderlessMaximizedWindows option process.start("kreadconfig5 --file kwinrc --group Windows --key BorderlessMaximizedWindows"); process.waitForFinished(); output = process.readAllStandardOutput(); output = output.remove("\n"); m_kwinBorderlessMaximizedWindows = (output == "true"); } +bool UniversalSettings::hiddenConfigurationWindowsAreDeleted() const +{ + return m_hiddenConfigurationWindowsAreDeleted; +} + +void UniversalSettings::setHiddenConfigurationWindowsAreDeleted(bool enabled) +{ + if (m_hiddenConfigurationWindowsAreDeleted == enabled) { + return; + } + + m_hiddenConfigurationWindowsAreDeleted = enabled; + emit hiddenConfigurationWindowsAreDeletedChanged(); +} bool UniversalSettings::metaPressAndHoldEnabled() const { return m_metaPressAndHoldEnabled; } void UniversalSettings::setMetaPressAndHoldEnabled(bool enabled) { if (m_metaPressAndHoldEnabled == enabled) { return; } m_metaPressAndHoldEnabled = enabled; emit metaPressAndHoldEnabledChanged(); } MemoryUsage::LayoutsMemory UniversalSettings::layoutsMemoryUsage() const { return m_memoryUsage; } void UniversalSettings::setLayoutsMemoryUsage(MemoryUsage::LayoutsMemory layoutsMemoryUsage) { if (m_memoryUsage == layoutsMemoryUsage) { return; } m_memoryUsage = layoutsMemoryUsage; emit layoutsMemoryUsageChanged(); } Settings::MouseSensitivity UniversalSettings::sensitivity() { return m_sensitivity; } void UniversalSettings::setSensitivity(Settings::MouseSensitivity sense) { if (m_sensitivity == sense) { return; } m_sensitivity = sense; emit sensitivityChanged(); } float UniversalSettings::screenWidthScale(QString screenName) const { if (!m_screenScales.contains(screenName)) { return 1; } return m_screenScales[screenName].first; } float UniversalSettings::screenHeightScale(QString screenName) const { if (!m_screenScales.contains(screenName)) { return 1; } return m_screenScales[screenName].second; } void UniversalSettings::setScreenScales(QString screenName, float widthScale, float heightScale) { if (!m_screenScales.contains(screenName)) { m_screenScales[screenName].first = widthScale; m_screenScales[screenName].second = heightScale; } else { if (m_screenScales[screenName].first == widthScale && m_screenScales[screenName].second == heightScale) { return; } m_screenScales[screenName].first = widthScale; m_screenScales[screenName].second = heightScale; } emit screenScalesChanged(); } void UniversalSettings::loadConfig() { m_version = m_universalGroup.readEntry("version", 1); m_badges3DStyle = m_universalGroup.readEntry("badges3DStyle", false); m_canDisableBorders = m_universalGroup.readEntry("canDisableBorders", false); m_currentLayoutName = m_universalGroup.readEntry("currentLayout", QString()); m_lastNonAssignedLayoutName = m_universalGroup.readEntry("lastNonAssignedLayout", QString()); m_launchers = m_universalGroup.readEntry("launchers", QStringList()); + m_hiddenConfigurationWindowsAreDeleted = m_universalGroup.readEntry("hiddenConfigurationWindowsAreDeleted", true); m_metaPressAndHoldEnabled = m_universalGroup.readEntry("metaPressAndHoldEnabled", true); m_screenTrackerInterval = m_universalGroup.readEntry("screenTrackerInterval", 2500); m_showInfoWindow = m_universalGroup.readEntry("showInfoWindow", true); m_memoryUsage = static_cast(m_universalGroup.readEntry("memoryUsage", (int)MemoryUsage::SingleLayout)); m_sensitivity = static_cast(m_universalGroup.readEntry("mouseSensitivity", (int)Settings::HighMouseSensitivity)); loadScalesConfig(); } void UniversalSettings::saveConfig() { m_universalGroup.writeEntry("version", m_version); m_universalGroup.writeEntry("badges3DStyle", m_badges3DStyle); m_universalGroup.writeEntry("canDisableBorders", m_canDisableBorders); m_universalGroup.writeEntry("currentLayout", m_currentLayoutName); m_universalGroup.writeEntry("lastNonAssignedLayout", m_lastNonAssignedLayoutName); m_universalGroup.writeEntry("launchers", m_launchers); + m_universalGroup.writeEntry("hiddenConfigurationWindowsAreDeleted", m_hiddenConfigurationWindowsAreDeleted); m_universalGroup.writeEntry("metaPressAndHoldEnabled", m_metaPressAndHoldEnabled); m_universalGroup.writeEntry("screenTrackerInterval", m_screenTrackerInterval); m_universalGroup.writeEntry("showInfoWindow", m_showInfoWindow); m_universalGroup.writeEntry("memoryUsage", (int)m_memoryUsage); m_universalGroup.writeEntry("mouseSensitivity", (int)m_sensitivity); } void UniversalSettings::cleanupSettings() { KConfigGroup containments = KConfigGroup(m_config, QStringLiteral("Containments")); containments.deleteGroup(); containments.sync(); } QString UniversalSettings::splitterIconPath() { return m_corona->kPackage().filePath("splitter"); } QString UniversalSettings::trademarkIconPath() { return m_corona->kPackage().filePath("trademark"); } QQmlListProperty UniversalSettings::screens() { return QQmlListProperty(this, nullptr, &countScreens, &atScreens); } int UniversalSettings::countScreens(QQmlListProperty *property) { Q_UNUSED(property) return qGuiApp->screens().count(); } QScreen *UniversalSettings::atScreens(QQmlListProperty *property, int index) { Q_UNUSED(property) return qGuiApp->screens().at(index); } void UniversalSettings::loadScalesConfig() { for (const auto &screenName : m_screenScalesGroup.keyList()) { QString scalesStr = m_screenScalesGroup.readEntry(screenName, QString()); QStringList scales = scalesStr.split(";"); if (scales.count() == 2) { m_screenScales[screenName] = qMakePair(scales[0].toFloat(), scales[1].toFloat()); } } } void UniversalSettings::saveScalesConfig() { for (const auto &screenName : m_screenScales.keys()) { QStringList scales; scales << QString::number(m_screenScales[screenName].first) << QString::number(m_screenScales[screenName].second); m_screenScalesGroup.writeEntry(screenName, scales.join(";")); } m_screenScalesGroup.sync(); } } diff --git a/app/settings/universalsettings.h b/app/settings/universalsettings.h index 2a5780b7..d20f8b04 100644 --- a/app/settings/universalsettings.h +++ b/app/settings/universalsettings.h @@ -1,210 +1,216 @@ /* * Copyright 2017 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UNIVERSALSETTINGS_H #define UNIVERSALSETTINGS_H // local #include #include "../apptypes.h" #include "../lattecorona.h" // Qt #include #include #include #include #include #include #include // KDE #include #include namespace Latte { namespace Layouts { class Manager; } } namespace Latte { //width_scale, height_scale typedef QPair ScreenScales; //! This class holds all the settings that are universally available //! independent of layouts class UniversalSettings : public QObject { Q_OBJECT Q_PROPERTY(bool autostart READ autostart WRITE setAutostart NOTIFY autostartChanged) Q_PROPERTY(bool badges3DStyle READ badges3DStyle WRITE setBadges3DStyle NOTIFY badges3DStyleChanged) Q_PROPERTY(bool colorsScriptIsPresent READ colorsScriptIsPresent NOTIFY colorsScriptIsPresentChanged) + Q_PROPERTY(bool hiddenConfigurationWindowsAreDeleted READ hiddenConfigurationWindowsAreDeleted WRITE setHiddenConfigurationWindowsAreDeleted NOTIFY hiddenConfigurationWindowsAreDeletedChanged) Q_PROPERTY(bool showInfoWindow READ showInfoWindow WRITE setShowInfoWindow NOTIFY showInfoWindowChanged) Q_PROPERTY(QString currentLayoutName READ currentLayoutName WRITE setCurrentLayoutName NOTIFY currentLayoutNameChanged) Q_PROPERTY(QStringList launchers READ launchers WRITE setLaunchers NOTIFY launchersChanged) Q_PROPERTY(Latte::Settings::MouseSensitivity sensitivity READ sensitivity WRITE setSensitivity NOTIFY sensitivityChanged) Q_PROPERTY(QQmlListProperty screens READ screens) public: UniversalSettings(KSharedConfig::Ptr config, QObject *parent = nullptr); ~UniversalSettings() override; void load(); bool autostart() const; void setAutostart(bool state); bool badges3DStyle() const; void setBadges3DStyle(bool enable); bool canDisableBorders() const; void setCanDisableBorders(bool enable); bool colorsScriptIsPresent() const; bool kwin_metaForwardedToLatte() const; void kwin_forwardMetaToLatte(bool forward); bool kwin_borderlessMaximizedWindowsEnabled() const; void kwin_setDisabledMaximizedBorders(bool disable); + bool hiddenConfigurationWindowsAreDeleted() const; + void setHiddenConfigurationWindowsAreDeleted(bool enabled); + bool metaPressAndHoldEnabled() const; void setMetaPressAndHoldEnabled(bool enabled); bool showInfoWindow() const; void setShowInfoWindow(bool show); int version() const; void setVersion(int ver); int screenTrackerInterval() const; void setScreenTrackerInterval(int duration); QString currentLayoutName() const; void setCurrentLayoutName(QString layoutName); QString lastNonAssignedLayoutName() const; void setLastNonAssignedLayoutName(QString layoutName); QStringList launchers() const; void setLaunchers(QStringList launcherList); Settings::MouseSensitivity sensitivity(); void setSensitivity(Settings::MouseSensitivity sense); QQmlListProperty screens(); static int countScreens(QQmlListProperty *property); //! is needed by screens() static QScreen *atScreens(QQmlListProperty *property, int index); //! is needed by screens() public slots: Q_INVOKABLE QString splitterIconPath(); Q_INVOKABLE QString trademarkIconPath(); Q_INVOKABLE float screenWidthScale(QString screenName) const; Q_INVOKABLE float screenHeightScale(QString screenName) const; Q_INVOKABLE void setScreenScales(QString screenName, float widthScale, float heightScale); signals: void autostartChanged(); void badges3DStyleChanged(); void canDisableBordersChanged(); void colorsScriptIsPresentChanged(); void currentLayoutNameChanged(); void downloadWindowSizeChanged(); + void hiddenConfigurationWindowsAreDeletedChanged(); void lastNonAssignedLayoutNameChanged(); void layoutsColumnWidthsChanged(); void layoutsWindowSizeChanged(); void launchersChanged(); void layoutsMemoryUsageChanged(); void metaPressAndHoldEnabledChanged(); void sensitivityChanged(); void screensCountChanged(); void screenScalesChanged(); void screenTrackerIntervalChanged(); void showInfoWindowChanged(); void versionChanged(); private slots: void loadConfig(); void loadScalesConfig(); void saveConfig(); void saveScalesConfig(); void recoverKWinOptions(); void updateColorsScriptIsPresent(); void trackedFileChanged(const QString &file); private: void cleanupSettings(); void setColorsScriptIsPresent(bool present); MemoryUsage::LayoutsMemory layoutsMemoryUsage() const; void setLayoutsMemoryUsage(MemoryUsage::LayoutsMemory layoutsMemoryUsage); private: bool m_badges3DStyle{false}; bool m_canDisableBorders{false}; bool m_colorsScriptIsPresent{false}; + bool m_hiddenConfigurationWindowsAreDeleted{true}; bool m_metaPressAndHoldEnabled{true}; bool m_showInfoWindow{true}; //!kwinrc tracking bool m_kwinMetaForwardedToLatte{false}; bool m_kwinBorderlessMaximizedWindows{false}; //when there isnt a version it is an old universal file int m_version{1}; int m_screenTrackerInterval{2500}; QString m_currentLayoutName; QString m_lastNonAssignedLayoutName; QStringList m_launchers; MemoryUsage::LayoutsMemory m_memoryUsage; Settings::MouseSensitivity m_sensitivity{Settings::HighMouseSensitivity}; //! ScreenName, QHash m_screenScales; QPointer m_corona; KConfigGroup m_screenScalesGroup; KConfigGroup m_universalGroup; KSharedConfig::Ptr m_config; //! reading kwinrc values is costly; a tracker protects from //! reading too many times with no real reason QTimer m_kwinrcTrackerTimer; friend class Layouts::Manager; friend class Latte::Corona; }; } #endif //UNIVERSALSETTINGS_H diff --git a/app/view/settings/primaryconfigview.cpp b/app/view/settings/primaryconfigview.cpp index c1073da1..dc575265 100644 --- a/app/view/settings/primaryconfigview.cpp +++ b/app/view/settings/primaryconfigview.cpp @@ -1,804 +1,812 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "primaryconfigview.h" // local #include #include "secondaryconfigview.h" #include "../effects.h" #include "../panelshadows_p.h" #include "../view.h" #include "../../lattecorona.h" #include "../../layouts/manager.h" #include "../../layout/genericlayout.h" #include "../../settings/universalsettings.h" #include "../../shortcuts/globalshortcuts.h" #include "../../shortcuts/shortcutstracker.h" #include "../../wm/abstractwindowinterface.h" // Qt #include #include #include #include // KDE #include #include #include #include #include #include // Plasma #include namespace Latte { namespace ViewPart { PrimaryConfigView::PrimaryConfigView(Plasma::Containment *containment, Latte::View *view, QWindow *parent) : PlasmaQuick::ConfigView(containment, parent), m_latteView(view) { m_corona = qobject_cast(m_latteView->containment()->corona()); setupWaylandIntegration(); setTitle(validTitle()); if (KWindowSystem::isPlatformX11()) { m_corona->wm()->registerIgnoredWindow(winId()); } else { connect(m_corona->wm(), &WindowSystem::AbstractWindowInterface::latteWindowAdded, this, &PrimaryConfigView::updateWaylandId); } setScreen(m_latteView->screen()); if (containment) { setIcon(qGuiApp->windowIcon()); } m_screenSyncTimer.setSingleShot(true); m_screenSyncTimer.setInterval(100); connect(this, &QQuickView::widthChanged, this, &PrimaryConfigView::updateEffects); connect(this, &QQuickView::heightChanged, this, &PrimaryConfigView::updateEffects); connect(this, &PrimaryConfigView::availableScreenGeometryChanged, this, &PrimaryConfigView::syncGeometry); connect(this, &PrimaryConfigView::inAdvancedModeChanged, this, &PrimaryConfigView::saveConfig); connect(this, &PrimaryConfigView::inAdvancedModeChanged, this, &PrimaryConfigView::updateShowInlineProperties); connect(this, &PrimaryConfigView::inAdvancedModeChanged, this, &PrimaryConfigView::syncGeometry); connect(this, &PrimaryConfigView::inAdvancedModeChanged, m_latteView, &Latte::View::inSettingsAdvancedModeChanged); connect(this, &QQuickView::statusChanged, [&](QQuickView::Status status) { if (status == QQuickView::Ready) { updateEffects(); } }); connections << connect(&m_screenSyncTimer, &QTimer::timeout, this, [this]() { setScreen(m_latteView->screen()); setFlags(wFlags()); if (KWindowSystem::isPlatformX11()) { m_corona->wm()->setViewExtraFlags(this, false, Latte::Types::NormalWindow); } syncGeometry(); syncSlideEffect(); }); + connections << connect(m_latteView, &View::hiddenConfigurationWindowsAreDeletedChanged, this, &PrimaryConfigView::onHiddenConfigurationWindowsAreDeletedChanged); connections << connect(m_latteView->visibility(), &VisibilityManager::modeChanged, this, &PrimaryConfigView::syncGeometry); connections << connect(containment, &Plasma::Containment::immutabilityChanged, this, &PrimaryConfigView::immutabilityChanged); m_thicknessSyncTimer.setSingleShot(true); m_thicknessSyncTimer.setInterval(200); connections << connect(&m_thicknessSyncTimer, &QTimer::timeout, this, [this]() { syncGeometry(); }); connections << connect(m_latteView, &Latte::View::normalThicknessChanged, [&]() { m_thicknessSyncTimer.start(); }); if (m_corona) { connections << connect(m_corona, &Latte::Corona::raiseViewsTemporaryChanged, this, &PrimaryConfigView::raiseDocksTemporaryChanged); connections << connect(m_corona, &Latte::Corona::availableScreenRectChangedFrom, this, &PrimaryConfigView::updateAvailableScreenGeometry); } } PrimaryConfigView::~PrimaryConfigView() { qDebug() << "ConfigView deleting ..."; if (m_latteView->indicator()) { //! destroy indicator config ui when the configuration window is closed m_latteView->indicator()->releaseConfigUi(); } m_corona->dialogShadows()->removeWindow(this); m_corona->wm()->unregisterIgnoredWindow(KWindowSystem::isPlatformX11() ? winId() : m_waylandWindowId); if (m_secConfigView) { m_secConfigView->deleteLater(); } for (const auto &var : connections) { QObject::disconnect(var); } } void PrimaryConfigView::init() { qDebug() << "dock config view : initialization started..."; m_originalByPassWM = m_latteView->byPassWM(); m_originalMode = m_latteView->visibility()->mode(); loadConfig(); //! inform view about the current settings level emit m_latteView->inSettingsAdvancedModeChanged(); setDefaultAlphaBuffer(true); setColor(Qt::transparent); m_corona->dialogShadows()->addWindow(this); rootContext()->setContextProperty(QStringLiteral("latteView"), m_latteView); rootContext()->setContextProperty(QStringLiteral("shortcutsEngine"), m_corona->globalShortcuts()->shortcutsTracker()); rootContext()->setContextProperty(QStringLiteral("viewConfig"), this); if (m_corona) { rootContext()->setContextProperty(QStringLiteral("universalSettings"), m_corona->universalSettings()); rootContext()->setContextProperty(QStringLiteral("layoutsManager"), m_corona->layoutsManager()); } KDeclarative::KDeclarative kdeclarative; kdeclarative.setDeclarativeEngine(engine()); kdeclarative.setTranslationDomain(QStringLiteral("latte-dock")); #if KF5_VERSION_MINOR >= 45 kdeclarative.setupContext(); kdeclarative.setupEngine(engine()); #else kdeclarative.setupBindings(); #endif QByteArray tempFilePath = "lattedockconfigurationui"; updateEnabledBorders(); updateAvailableScreenGeometry(); auto source = QUrl::fromLocalFile(m_latteView->containment()->corona()->kPackage().filePath(tempFilePath)); setSource(source); syncGeometry(); syncSlideEffect(); qDebug() << "dock config view : initialization ended..."; } inline Qt::WindowFlags PrimaryConfigView::wFlags() const { return (flags() | Qt::FramelessWindowHint) & ~Qt::WindowDoesNotAcceptFocus; } QString PrimaryConfigView::validTitle() const { return QString("#primaryconfig#" + QString::number(m_latteView->containment()->id())); } QQuickView *PrimaryConfigView::secondaryWindow() { return m_secConfigView; } void PrimaryConfigView::showSecondaryWindow() { if (!m_secConfigView) { m_secConfigView = new SecondaryConfigView(m_latteView, this); m_secConfigView->init(); - } else if (m_secConfigView && !m_latteView->hiddenConfigWindowsAreDeleted() && !m_secConfigView->isVisible()){ + } else if (m_secConfigView && !m_latteView->hiddenConfigurationWindowsAreDeleted() && !m_secConfigView->isVisible()){ m_secConfigView->show(); } } void PrimaryConfigView::hideSecondaryWindow() { if (m_secConfigView) { - if (m_latteView->hiddenConfigWindowsAreDeleted()) { + if (m_latteView->hiddenConfigurationWindowsAreDeleted()) { auto secWindow = m_secConfigView; m_secConfigView = nullptr; secWindow->deleteLater(); } else { m_secConfigView->hide(); } if (KWindowSystem::isPlatformX11() && m_latteView->effects()) { //! this is needed in order for subtracked mask of secondary window to //! be released properly when changing for Advanced to Basic mode. //! Under wayland this is not needed because masks do not break any visuals. m_latteView->effects()->updateMask(); } } } +void PrimaryConfigView::onHiddenConfigurationWindowsAreDeletedChanged() +{ + if (m_latteView && m_latteView->hiddenConfigurationWindowsAreDeleted() && !isVisible()) { + deleteLater(); + } +} + void PrimaryConfigView::updateAvailableScreenGeometry(View *origin) { int currentScrId = m_latteView->positioner()->currentScreenId(); QList ignoreModes{Latte::Types::SideBar}; if (m_latteView->visibility() && m_latteView->visibility()->mode() == Latte::Types::SideBar) { ignoreModes.removeAll(Latte::Types::SideBar); } m_availableScreenGeometry = m_corona->availableScreenRectWithCriteria(currentScrId, QString(), ignoreModes, {}, false); emit availableScreenGeometryChanged(); } QRect PrimaryConfigView::availableScreenGeometry() const { return m_availableScreenGeometry; } QRect PrimaryConfigView::geometryWhenVisible() const { return m_geometryWhenVisible; } void PrimaryConfigView::requestActivate() { if (KWindowSystem::isPlatformWayland() && m_shellSurface) { updateWaylandId(); m_corona->wm()->requestActivate(m_waylandWindowId); } else { QQuickView::requestActivate(); } } void PrimaryConfigView::syncGeometry() { if (!m_latteView || !m_latteView->layout() || !m_latteView->containment() || !rootObject()) { return; } const QSize size(rootObject()->width(), rootObject()->height()); setMaximumSize(size); setMinimumSize(size); resize(size); const auto location = m_latteView->containment()->location(); const auto scrGeometry = m_latteView->screenGeometry(); const auto availGeometry = m_availableScreenGeometry; int clearThickness = m_latteView->editThickness(); QPoint position{0, 0}; int xPos{0}; int yPos{0}; switch (m_latteView->formFactor()) { case Plasma::Types::Horizontal: { if (m_inAdvancedMode) { if (qApp->isLeftToRight()) { xPos = availGeometry.x() + availGeometry.width() - size.width(); } else { xPos = availGeometry.x(); } } else { xPos = scrGeometry.center().x() - size.width() / 2; } if (location == Plasma::Types::TopEdge) { yPos = scrGeometry.y() + clearThickness; } else if (location == Plasma::Types::BottomEdge) { yPos = scrGeometry.y() + scrGeometry.height() - clearThickness - size.height(); } } break; case Plasma::Types::Vertical: { if (location == Plasma::Types::LeftEdge) { xPos = scrGeometry.x() + clearThickness; yPos = availGeometry.y() + (availGeometry.height() - size.height())/2; } else if (location == Plasma::Types::RightEdge) { xPos = scrGeometry.x() + scrGeometry.width() - clearThickness - size.width(); yPos = availGeometry.y() + (availGeometry.height() - size.height())/2; } } break; default: qWarning() << "no sync geometry, wrong formFactor"; break; } position = {xPos, yPos}; updateEnabledBorders(); m_geometryWhenVisible = QRect(position.x(), position.y(), size.width(), size.height()); setPosition(position); if (m_shellSurface) { m_shellSurface->setPosition(position); } // updateShowInlineProperties(); emit m_latteView->configWindowGeometryChanged(); } void PrimaryConfigView::syncSlideEffect() { if (!m_latteView || !m_latteView->containment()) { return; } auto slideLocation = WindowSystem::AbstractWindowInterface::Slide::None; switch (m_latteView->containment()->location()) { case Plasma::Types::TopEdge: slideLocation = WindowSystem::AbstractWindowInterface::Slide::Top; break; case Plasma::Types::RightEdge: slideLocation = WindowSystem::AbstractWindowInterface::Slide::Right; break; case Plasma::Types::BottomEdge: slideLocation = WindowSystem::AbstractWindowInterface::Slide::Bottom; break; case Plasma::Types::LeftEdge: slideLocation = WindowSystem::AbstractWindowInterface::Slide::Left; break; default: qDebug() << staticMetaObject.className() << "wrong location"; break; } m_corona->wm()->slideWindow(*this, slideLocation); } void PrimaryConfigView::showEvent(QShowEvent *ev) { QQuickWindow::showEvent(ev); if (!m_latteView) { return; } setFlags(wFlags()); m_corona->wm()->setViewExtraFlags(this, false, Latte::Types::NormalWindow); syncGeometry(); syncSlideEffect(); if (m_latteView && m_latteView->containment()) { m_latteView->containment()->setUserConfiguring(true); } m_screenSyncTimer.start(); QTimer::singleShot(400, this, &PrimaryConfigView::syncGeometry); updateShowInlineProperties(); emit showSignal(); if (m_latteView && m_latteView->layout()) { m_latteView->layout()->setLastConfigViewFor(m_latteView); } if (m_shellSurface) { //! readd shadows after hiding because the window shadows are not shown again after first showing m_corona->dialogShadows()->addWindow(this, m_enabledBorders); } } void PrimaryConfigView::hideEvent(QHideEvent *ev) { if (!m_latteView) { deleteLater(); return; } if (m_latteView->containment()) { m_latteView->containment()->setUserConfiguring(false); } const auto mode = m_latteView->visibility()->mode(); if ((mode == Types::AlwaysVisible || mode == Types::WindowsGoBelow) && !(m_originalMode == Types::AlwaysVisible || m_originalMode == Types::WindowsGoBelow)) { //! mode changed to AlwaysVisible OR WindowsGoBelow FROM Dodge mode if (m_originalByPassWM) { //! if original by pass is active m_latteView->layout()->recreateView(m_latteView->containment()); } } else if (m_latteView->byPassWM() != m_originalByPassWM) { m_latteView->layout()->recreateView(m_latteView->containment()); } - if (m_latteView->hiddenConfigWindowsAreDeleted()) { + if (m_latteView->hiddenConfigurationWindowsAreDeleted()) { deleteLater(); } else { setVisible(false); } } void PrimaryConfigView::focusOutEvent(QFocusEvent *ev) { Q_UNUSED(ev); const auto *focusWindow = qGuiApp->focusWindow(); if (!m_latteView || (focusWindow && (focusWindow->flags().testFlag(Qt::Popup) || focusWindow->flags().testFlag(Qt::ToolTip))) || m_latteView->alternativesIsShown()) { return; } if (!m_blockFocusLost && !m_latteView->containsMouse() && (!m_secConfigView || (m_secConfigView && !m_secConfigView->isActive()))) { hideConfigWindow(); } } void PrimaryConfigView::setupWaylandIntegration() { if (m_shellSurface || !KWindowSystem::isPlatformWayland() || !m_latteView || !m_latteView->containment()) { // already setup return; } if (m_corona) { using namespace KWayland::Client; PlasmaShell *interface = m_corona->waylandCoronaInterface(); if (!interface) { return; } Surface *s = Surface::fromWindow(this); if (!s) { return; } qDebug() << "wayland primary settings surface was created..."; m_shellSurface = interface->createSurface(s, this); m_corona->wm()->setViewExtraFlags(m_shellSurface, false); syncGeometry(); } } bool PrimaryConfigView::event(QEvent *e) { if (e->type() == QEvent::PlatformSurface) { if (auto pe = dynamic_cast(e)) { switch (pe->surfaceEventType()) { case QPlatformSurfaceEvent::SurfaceCreated: if (m_shellSurface) { break; } setupWaylandIntegration(); break; case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: if (m_shellSurface) { delete m_shellSurface; m_shellSurface = nullptr; qDebug() << "WAYLAND config window surface was deleted..."; } break; } } } return PlasmaQuick::ConfigView::event(e); } void PrimaryConfigView::immutabilityChanged(Plasma::Types::ImmutabilityType type) { if (type != Plasma::Types::Mutable && isVisible()) hideConfigWindow(); } bool PrimaryConfigView::sticker() const { return m_blockFocusLost; } void PrimaryConfigView::setSticker(bool blockFocusLost) { if (m_blockFocusLost == blockFocusLost) return; m_blockFocusLost = blockFocusLost; } bool PrimaryConfigView::showInlineProperties() const { return m_showInlineProperties; } void PrimaryConfigView::setShowInlineProperties(bool show) { if (m_showInlineProperties == show) { return; } m_showInlineProperties = show; emit showInlinePropertiesChanged(); } void PrimaryConfigView::updateShowInlineProperties() { if (!m_latteView) { return; } bool showSecWindow{false}; bool advancedApprovedSecWindow{false}; if (m_inAdvancedMode && m_latteView->formFactor() != Plasma::Types::Vertical) { showSecWindow = true; advancedApprovedSecWindow = true; } //! consider screen geometry for showing or not the secondary window if (showSecWindow && !geometryWhenVisible().isNull()) { if (m_secConfigView->geometryWhenVisible().intersects(geometryWhenVisible())) { showSecWindow = false; } else if (advancedApprovedSecWindow) { showSecWindow = true; } } if (showSecWindow) { showSecondaryWindow(); // QTimer::singleShot(150, m_secConfigView, SLOT(show())); setShowInlineProperties(false); } else { hideSecondaryWindow(); setShowInlineProperties(true); } // qDebug() << " showSecWindow:" << showSecWindow << " _ " << " inline:"<< !showSecWindow; } void PrimaryConfigView::updateWaylandId() { Latte::WindowSystem::WindowId newId = m_corona->wm()->winIdFor("latte-dock", validTitle()); if (m_waylandWindowId != newId) { if (!m_waylandWindowId.isNull()) { m_corona->wm()->unregisterIgnoredWindow(m_waylandWindowId); } m_waylandWindowId = newId; m_corona->wm()->registerIgnoredWindow(m_waylandWindowId); } } bool PrimaryConfigView::inAdvancedMode() const { return m_inAdvancedMode; } void PrimaryConfigView::setInAdvancedMode(bool advanced) { if (m_inAdvancedMode == advanced) { return; } m_inAdvancedMode = advanced; emit inAdvancedModeChanged(); } void PrimaryConfigView::hideConfigWindow() { if (m_shellSurface) { //!NOTE: Avoid crash in wayland environment with qt5.9 close(); } else { hide(); } hideSecondaryWindow(); } void PrimaryConfigView::updateLaunchersForGroup(int groupInt) { Types::LaunchersGroup group = (Types::LaunchersGroup)groupInt; //! when the layout/global launchers list is empty then the current dock launchers are used for them //! as a start point if (m_corona && m_latteView->layout()) { if ((group == Types::LayoutLaunchers && m_latteView->layout()->launchers().isEmpty()) || (group == Types::GlobalLaunchers && m_corona->universalSettings()->launchers().isEmpty())) { Plasma::Containment *c = m_latteView->containment(); const auto &applets = c->applets(); for (auto *applet : applets) { KPluginMetaData meta = applet->kPackage().metadata(); if (meta.pluginId() == "org.kde.latte.plasmoid") { if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value()) { const auto &childItems = appletInterface->childItems(); if (childItems.isEmpty()) { continue; } for (QQuickItem *item : childItems) { if (auto *metaObject = item->metaObject()) { // not using QMetaObject::invokeMethod to avoid warnings when calling // this on applets that don't have it or other child items since this // is pretty much trial and error. // Also, "var" arguments are treated as QVariant in QMetaObject int methodIndex = metaObject->indexOfMethod("getLauncherList()"); if (methodIndex == -1) { continue; } QMetaMethod method = metaObject->method(methodIndex); QVariant launchers; if (method.invoke(item, Q_RETURN_ARG(QVariant, launchers))) { if (group == Types::LayoutLaunchers) { m_latteView->layout()->setLaunchers(launchers.toStringList()); } else if (group == Types::GlobalLaunchers) { m_corona->universalSettings()->setLaunchers(launchers.toStringList()); } } } } } } } } } } //!BEGIN borders Plasma::FrameSvg::EnabledBorders PrimaryConfigView::enabledBorders() const { return m_enabledBorders; } void PrimaryConfigView::updateEnabledBorders() { if (!this->screen()) { return; } Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders; switch (m_latteView->location()) { case Plasma::Types::TopEdge: borders &= m_inReverse ? ~Plasma::FrameSvg::BottomBorder : ~Plasma::FrameSvg::TopBorder; break; case Plasma::Types::LeftEdge: borders &= ~Plasma::FrameSvg::LeftBorder; break; case Plasma::Types::RightEdge: borders &= ~Plasma::FrameSvg::RightBorder; break; case Plasma::Types::BottomEdge: borders &= m_inReverse ? ~Plasma::FrameSvg::TopBorder : ~Plasma::FrameSvg::BottomBorder; break; default: break; } if (m_enabledBorders != borders) { m_enabledBorders = borders; m_corona->dialogShadows()->addWindow(this, m_enabledBorders); emit enabledBordersChanged(); } } //!END borders void PrimaryConfigView::updateEffects() { //! Don't apply any effect before the wayland surface is created under wayland //! https://bugs.kde.org/show_bug.cgi?id=392890 if (KWindowSystem::isPlatformWayland() && !m_shellSurface) { return; } if (!m_background) { m_background = new Plasma::FrameSvg(this); } if (m_background->imagePath() != "dialogs/background") { m_background->setImagePath(QStringLiteral("dialogs/background")); } m_background->setEnabledBorders(m_enabledBorders); m_background->resizeFrame(size()); QRegion mask = m_background->mask(); QRegion fixedMask = mask.isNull() ? QRegion(QRect(0,0,width(),height())) : mask; if (!fixedMask.isEmpty()) { setMask(fixedMask); } else { setMask(QRegion()); } if (KWindowSystem::compositingActive()) { KWindowEffects::enableBlurBehind(winId(), true, fixedMask); } else { KWindowEffects::enableBlurBehind(winId(), false); } } //!BEGIN configuration void PrimaryConfigView::loadConfig() { if (!m_latteView || !m_latteView->containment()) { return; } auto config = m_latteView->containment()->config(); int complexity = config.readEntry("settingsComplexity", 0); setInAdvancedMode(complexity>0); } void PrimaryConfigView::saveConfig() { if (!m_latteView || !m_latteView->containment()) { return; } auto config = m_latteView->containment()->config(); int complexity = m_inAdvancedMode ? 1 : 0; config.writeEntry("settingsComplexity", complexity); } //!END configuration } } diff --git a/app/view/settings/primaryconfigview.h b/app/view/settings/primaryconfigview.h index 040924f8..f94b7b7e 100644 --- a/app/view/settings/primaryconfigview.h +++ b/app/view/settings/primaryconfigview.h @@ -1,179 +1,180 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PRIMARYCONFIGVIEW_H #define PRIMARYCONFIGVIEW_H // local #include #include "../../plasma/quick/configview.h" #include "../../wm/windowinfowrap.h" //Qt #include #include #include #include // Plasma #include #include namespace Plasma { class Applet; class Containment; class FrameSvg; class Types; } namespace KWayland { namespace Client { class PlasmaShellSurface; } } namespace Latte { class Corona; class View; } namespace Latte { namespace ViewPart { class SecondaryConfigView; } } namespace Latte { namespace ViewPart { class PrimaryConfigView : public PlasmaQuick::ConfigView { Q_OBJECT //! used when the secondary config window can not be shown Q_PROPERTY(bool showInlineProperties READ showInlineProperties NOTIFY showInlinePropertiesChanged) Q_PROPERTY(bool inAdvancedMode READ inAdvancedMode WRITE setInAdvancedMode NOTIFY inAdvancedModeChanged) Q_PROPERTY(QRect availableScreenGeometry READ availableScreenGeometry NOTIFY availableScreenGeometryChanged) Q_PROPERTY(Plasma::FrameSvg::EnabledBorders enabledBorders READ enabledBorders NOTIFY enabledBordersChanged) public: enum ConfigViewType { PrimaryConfig = 0, SecondaryConfig }; PrimaryConfigView(Plasma::Containment *containment, Latte::View *view, QWindow *parent = nullptr); ~PrimaryConfigView() override; void init() override; void requestActivate(); Qt::WindowFlags wFlags() const; bool inAdvancedMode() const; void setInAdvancedMode(bool advanced); bool showInlineProperties() const; bool sticker() const; QRect availableScreenGeometry() const; QRect geometryWhenVisible() const; QString validTitle() const; Plasma::FrameSvg::EnabledBorders enabledBorders() const; QQuickView *secondaryWindow(); public slots: Q_INVOKABLE void hideConfigWindow(); Q_INVOKABLE void setSticker(bool blockFocusLost); Q_INVOKABLE void syncGeometry(); Q_INVOKABLE void updateLaunchersForGroup(int groupInt); Q_INVOKABLE void updateEffects(); signals: void availableScreenGeometryChanged(); void enabledBordersChanged(); void inAdvancedModeChanged(); void raiseDocksTemporaryChanged(); void showInlinePropertiesChanged(); void showSignal(); protected: void showEvent(QShowEvent *ev) override; void hideEvent(QHideEvent *ev) override; void focusOutEvent(QFocusEvent *ev) override; bool event(QEvent *e) override; void syncSlideEffect(); private slots: void immutabilityChanged(Plasma::Types::ImmutabilityType type); + void onHiddenConfigurationWindowsAreDeletedChanged(); void updateAvailableScreenGeometry(View *origin = nullptr); void updateEnabledBorders(); void updateShowInlineProperties(); void updateWaylandId(); void showSecondaryWindow(); void hideSecondaryWindow(); void setShowInlineProperties(bool show); void loadConfig(); void saveConfig(); private: void setupWaylandIntegration(); bool m_blockFocusLost{false}; bool m_blockFocusLostOnStartup{true}; bool m_originalByPassWM{false}; bool m_inAdvancedMode{false}; bool m_inReverse{false}; //! it is used by the borders bool m_showInlineProperties{false}; Latte::Types::Visibility m_originalMode{Latte::Types::DodgeActive}; QRect m_availableScreenGeometry; QRect m_geometryWhenVisible; QPointer m_latteView; QPointer m_secConfigView; QTimer m_screenSyncTimer; QTimer m_thicknessSyncTimer; QList connections; Plasma::FrameSvg::EnabledBorders m_enabledBorders{Plasma::FrameSvg::AllBorders}; //only for the mask on disabled compositing, not to actually paint Plasma::FrameSvg *m_background{nullptr}; Latte::Corona *m_corona{nullptr}; Latte::WindowSystem::WindowId m_waylandWindowId; KWayland::Client::PlasmaShellSurface *m_shellSurface{nullptr}; }; } } #endif //PRIMARYCONFIGVIEW_H diff --git a/app/view/view.cpp b/app/view/view.cpp index aeb07428..c3bfc761 100644 --- a/app/view/view.cpp +++ b/app/view/view.cpp @@ -1,1626 +1,1628 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "view.h" // local #include "contextmenu.h" #include "effects.h" #include "positioner.h" #include "visibilitymanager.h" #include "settings/primaryconfigview.h" #include "settings/secondaryconfigview.h" #include "../apptypes.h" #include "../lattecorona.h" #include "../declarativeimports/interfaces.h" #include "../indicator/factory.h" #include "../layout/genericlayout.h" #include "../layouts/manager.h" #include "../plasma/extended/theme.h" #include "../screenpool.h" #include "../settings/universalsettings.h" #include "../shortcuts/globalshortcuts.h" #include "../shortcuts/shortcutstracker.h" // Qt #include #include #include #include #include #include #include // KDe #include #include #include #include #include // Plasma #include #include #include #define BLOCKHIDINGDRAGTYPE "View::ContainsDrag()" #define BLOCKHIDINGNEEDSATTENTIONTYPE "View::Containment::NeedsAttentionState()" #define BLOCKHIDINGREQUESTSINPUTTYPE "View::Containment::RequestsInputState()" namespace Latte { //! both alwaysVisible and byPassWM are passed through corona because //! during the view window creation containment hasn't been set, but these variables //! are needed in order for window flags to be set correctly View::View(Plasma::Corona *corona, QScreen *targetScreen, bool byPassWM) : PlasmaQuick::ContainmentView(corona), m_contextMenu(new ViewPart::ContextMenu(this)), m_effects(new ViewPart::Effects(this)), m_interface(new ViewPart::ContainmentInterface(this)) { //! needs to be created after Effects because it catches some of its signals //! and avoid a crash from View::winId() at the same time m_positioner = new ViewPart::Positioner(this); // setTitle(corona->kPackage().metadata().name()); setIcon(qGuiApp->windowIcon()); setResizeMode(QuickViewSharedEngine::SizeRootObjectToView); setColor(QColor(Qt::transparent)); setDefaultAlphaBuffer(true); setClearBeforeRendering(true); const auto flags = Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint | Qt::WindowDoesNotAcceptFocus; if (byPassWM) { setFlags(flags | Qt::BypassWindowManagerHint); } else { setFlags(flags); } if (targetScreen) m_positioner->setScreenToFollow(targetScreen); else m_positioner->setScreenToFollow(qGuiApp->primaryScreen()); m_releaseGrabTimer.setInterval(400); m_releaseGrabTimer.setSingleShot(true); connect(&m_releaseGrabTimer, &QTimer::timeout, this, &View::releaseGrab); connect(m_contextMenu, &ViewPart::ContextMenu::menuChanged, this, &View::updateTransientWindowsTracking); connect(this, &View::containmentChanged , this, [ &, byPassWM]() { qDebug() << "dock view c++ containment changed 1..."; if (!this->containment()) return; qDebug() << "dock view c++ containment changed 2..."; setTitle(validTitle()); //! First load default values from file restoreConfig(); //! Afterwards override that values in case during creation something different is needed setByPassWM(byPassWM); //! Check the screen assigned to this dock reconsiderScreen(); //! needs to be created before visibility creation because visibility uses it if (!m_windowsTracker) { m_windowsTracker = new ViewPart::WindowsTracker(this); emit windowsTrackerChanged(); } if (!m_visibility) { m_visibility = new ViewPart::VisibilityManager(this); connect(m_visibility, &ViewPart::VisibilityManager::isHiddenChanged, this, [&]() { if (m_visibility->isHidden()) { m_interface->deactivateApplets(); } }); connect(m_visibility, &ViewPart::VisibilityManager::containsMouseChanged, this, &View::updateTransientWindowsTracking); connect(m_visibility, &ViewPart::VisibilityManager::frameExtentsCleared, this, [&]() { if (behaveAsPlasmaPanel()) { //! recreate view because otherwise compositor frame extents implementation //! is triggering a crazy behavior of moving/hiding the view and freezing Latte //! in some cases. reloadSource(); } }); emit visibilityChanged(); } if (!m_indicator) { m_indicator = new ViewPart::Indicator(this); emit indicatorChanged(); } connect(this->containment(), SIGNAL(statusChanged(Plasma::Types::ItemStatus)), SLOT(statusChanged(Plasma::Types::ItemStatus))); }, Qt::DirectConnection); m_corona = qobject_cast(this->corona()); if (m_corona) { connect(m_corona, &Latte::Corona::viewLocationChanged, this, &View::dockLocationChanged); } } View::~View() { m_inDelete = true; //! clear Layout connections m_visibleHackTimer1.stop(); m_visibleHackTimer2.stop(); for (auto &c : connectionsLayout) { disconnect(c); } //! unload indicators if (m_indicator) { m_indicator->unloadIndicators(); } disconnectSensitiveSignals(); disconnect(containment(), SIGNAL(statusChanged(Plasma::Types::ItemStatus)), this, SLOT(statusChanged(Plasma::Types::ItemStatus))); qDebug() << "dock view deleting..."; //! this disconnect does not free up connections correctly when //! latteView is deleted. A crash for this example is the following: //! switch to Alternative Session and disable compositing, //! the signal creating the crash was probably from deleted //! windows. //! this->disconnect(); if (m_configView) { delete m_configView; } if (m_contextMenu) { delete m_contextMenu; } //needs to be deleted before Effects because it catches some of its signals if (m_positioner) { delete m_positioner; } if (m_effects) { delete m_effects; } if (m_indicator) { delete m_indicator; } if (m_interface) { delete m_interface; } if (m_visibility) { delete m_visibility; } if (m_windowsTracker) { delete m_windowsTracker; } } void View::init(Plasma::Containment *plasma_containment) { connect(this, &QQuickWindow::xChanged, this, &View::xChanged); connect(this, &QQuickWindow::xChanged, this, &View::updateAbsoluteGeometry); connect(this, &QQuickWindow::yChanged, this, &View::yChanged); connect(this, &QQuickWindow::yChanged, this, &View::updateAbsoluteGeometry); connect(this, &QQuickWindow::widthChanged, this, &View::widthChanged); connect(this, &QQuickWindow::widthChanged, this, &View::updateAbsoluteGeometry); connect(this, &QQuickWindow::heightChanged, this, &View::heightChanged); connect(this, &QQuickWindow::heightChanged, this, &View::updateAbsoluteGeometry); connect(this, &View::activitiesChanged, this, &View::applyActivitiesToWindows); connect(this, &View::localGeometryChanged, this, [&]() { updateAbsoluteGeometry(); }); connect(this, &View::screenEdgeMarginEnabledChanged, this, [&]() { updateAbsoluteGeometry(); }); //! used in order to disconnect it when it should NOT be called because it creates crashes connect(this, &View::availableScreenRectChangedFrom, m_corona, &Latte::Corona::availableScreenRectChangedFrom); connect(this, &View::availableScreenRegionChangedFrom, m_corona, &Latte::Corona::availableScreenRegionChangedFrom); connect(m_corona, &Latte::Corona::availableScreenRectChangedFrom, this, &View::availableScreenRectChangedFromSlot); connect(m_corona, &Latte::Corona::verticalUnityViewHasFocus, this, &View::topViewAlwaysOnTop); connect(this, &View::byPassWMChanged, this, &View::saveConfig); connect(this, &View::isPreferredForShortcutsChanged, this, &View::saveConfig); connect(this, &View::onPrimaryChanged, this, &View::saveConfig); connect(this, &View::typeChanged, this, &View::saveConfig); connect(this, &View::normalThicknessChanged, this, [&]() { emit availableScreenRectChangedFrom(this); }); connect(m_effects, &ViewPart::Effects::innerShadowChanged, this, [&]() { emit availableScreenRectChangedFrom(this); }); connect(m_positioner, &ViewPart::Positioner::onHideWindowsForSlidingOut, this, &View::hideWindowsForSlidingOut); connect(m_positioner, &ViewPart::Positioner::screenGeometryChanged, this, &View::screenGeometryChanged); connect(m_positioner, &ViewPart::Positioner::windowSizeChanged, this, [&]() { emit availableScreenRectChangedFrom(this); }); connect(m_contextMenu, &ViewPart::ContextMenu::menuChanged, this, &View::contextMenuIsShownChanged); connect(m_interface, &ViewPart::ContainmentInterface::hasExpandedAppletChanged, this, &View::verticalUnityViewHasFocus); //! View sends this signal in order to avoid crashes from ViewPart::Indicator when the view is recreated connect(m_corona->indicatorFactory(), &Latte::Indicator::Factory::indicatorChanged, this, [&](const QString &indicatorId) { emit indicatorPluginChanged(indicatorId); }); connect(this, &View::indicatorPluginChanged, this, [&](const QString &indicatorId) { if (m_indicator && m_indicator->isCustomIndicator() && m_indicator->type() == indicatorId) { reloadSource(); } }); connect(m_corona->indicatorFactory(), &Latte::Indicator::Factory::indicatorRemoved, this, &View::indicatorPluginRemoved); + connect(m_corona->universalSettings(), &Latte::UniversalSettings::hiddenConfigurationWindowsAreDeletedChanged, + this, &View::hiddenConfigurationWindowsAreDeletedChanged); //! Assign app interfaces in be accessible through containment graphic item QQuickItem *containmentGraphicItem = qobject_cast(plasma_containment->property("_plasma_graphicObject").value()); if (containmentGraphicItem) { containmentGraphicItem->setProperty("_latte_globalShortcuts_object", QVariant::fromValue(m_corona->globalShortcuts()->shortcutsTracker())); containmentGraphicItem->setProperty("_latte_layoutsManager_object", QVariant::fromValue(m_corona->layoutsManager())); containmentGraphicItem->setProperty("_latte_themeExtended_object", QVariant::fromValue(m_corona->themeExtended())); containmentGraphicItem->setProperty("_latte_universalSettings_object", QVariant::fromValue(m_corona->universalSettings())); containmentGraphicItem->setProperty("_latte_view_object", QVariant::fromValue(this)); Latte::Interfaces *ifacesGraphicObject = qobject_cast(containmentGraphicItem->property("_latte_view_interfacesobject").value()); if (ifacesGraphicObject) { ifacesGraphicObject->updateView(); setInterfacesGraphicObj(ifacesGraphicObject); } } setSource(corona()->kPackage().filePath("lattedockui")); m_positioner->syncGeometry(); qDebug() << "SOURCE:" << source(); } void View::reloadSource() { if (m_layout && containment()) { if (settingsWindowIsShown()) { m_configView->deleteLater(); } engine()->clearComponentCache(); m_layout->recreateView(containment(), settingsWindowIsShown()); } } -bool View::hiddenConfigWindowsAreDeleted() const +bool View::hiddenConfigurationWindowsAreDeleted() const { - return false; + return m_corona->universalSettings()->hiddenConfigurationWindowsAreDeleted(); } bool View::inDelete() const { return m_inDelete; } bool View::inReadyState() const { return (m_layout != nullptr); } void View::disconnectSensitiveSignals() { m_initLayoutTimer.stop(); disconnect(this, &View::availableScreenRectChangedFrom, m_corona, &Latte::Corona::availableScreenRectChangedFrom); disconnect(this, &View::availableScreenRegionChangedFrom, m_corona, &Latte::Corona::availableScreenRegionChangedFrom); disconnect(m_corona, &Latte::Corona::availableScreenRectChangedFrom, this, &View::availableScreenRectChangedFromSlot); disconnect(m_corona, &Latte::Corona::verticalUnityViewHasFocus, this, &View::topViewAlwaysOnTop); setLayout(nullptr); } void View::availableScreenRectChangedFromSlot(View *origin) { if (m_inDelete || origin == this) return; if (formFactor() == Plasma::Types::Vertical) { m_positioner->syncGeometry(); } } void View::setupWaylandIntegration() { if (m_shellSurface) return; if (Latte::Corona *c = qobject_cast(corona())) { using namespace KWayland::Client; PlasmaShell *interface {c->waylandCoronaInterface()}; if (!interface) return; Surface *s{Surface::fromWindow(this)}; if (!s) return; m_shellSurface = interface->createSurface(s, this); qDebug() << "WAYLAND dock window surface was created..."; if (m_visibility) { m_visibility->initViewFlags(); } } } KWayland::Client::PlasmaShellSurface *View::surface() { return m_shellSurface; } //! the main function which decides if this dock is at the //! correct screen void View::reconsiderScreen() { m_positioner->reconsiderScreen(); } void View::copyView() { m_layout->copyView(containment()); } void View::removeView() { if (m_layout && m_layout->viewsCount() > 1) { m_inDelete = true; QAction *removeAct = this->containment()->actions()->action(QStringLiteral("remove")); if (removeAct) { removeAct->trigger(); } } } bool View::settingsWindowIsShown() { auto cview = qobject_cast(m_configView); - if (hiddenConfigWindowsAreDeleted()) { + if (hiddenConfigurationWindowsAreDeleted()) { return (cview != nullptr); } else if (cview) { return cview->isVisible(); } return false; } void View::showSettingsWindow() { if (!settingsWindowIsShown()) { emit m_visibility->mustBeShown(); showConfigurationInterface(containment()); applyActivitiesToWindows(); } } PlasmaQuick::ConfigView *View::configView() { return m_configView; } void View::showConfigurationInterface(Plasma::Applet *applet) { if (!applet || !applet->containment()) return; Plasma::Containment *c = qobject_cast(applet); if (m_configView && c && c->isContainment() && c == this->containment()) { if (m_configView->isVisible()) { m_configView->hide(); } else { m_configView->show(); } return; } else if (m_configView) { if (m_configView->applet() == applet) { m_configView->show(); if (KWindowSystem::isPlatformX11()) { m_configView->requestActivate(); } return; } else { m_configView->hide(); } } bool delayConfigView = false; if (c && containment() && c->isContainment() && c->id() == this->containment()->id()) { m_configView = new ViewPart::PrimaryConfigView(c, this); delayConfigView = true; } else { m_configView = new PlasmaQuick::ConfigView(applet); } m_configView.data()->init(); if (!delayConfigView) { m_configView->show(); } else { //add a timer for showing the configuration window the first time it is //created in order to give the containment's layouts the time to //calculate the window's height QTimer::singleShot(150, [this]() { if (m_configView) { m_configView->show(); } }); } } QRect View::localGeometry() const { return m_localGeometry; } void View::setLocalGeometry(const QRect &geometry) { if (m_localGeometry == geometry) { return; } m_localGeometry = geometry; emit localGeometryChanged(); } QString View::validTitle() const { if (!containment()) { return QString(); } return QString("#view#" + QString::number(containment()->id())); } void View::updateAbsoluteGeometry(bool bypassChecks) { //! there was a -1 in height and width here. The reason of this //! if I remember correctly was related to multi-screen but I cant //! remember exactly the reason, something related to right edge in //! multi screen environment. BUT this was breaking the entire AlwaysVisible //! experience with struts. Removing them in order to restore correct //! behavior and keeping this comment in order to check for //! multi-screen breakage QRect absGeometry = m_localGeometry; absGeometry.moveLeft(x() + m_localGeometry.x()); absGeometry.moveTop(y() + m_localGeometry.y()); if (behaveAsPlasmaPanel()) { int currentScreenEdgeMargin = m_screenEdgeMarginEnabled ? qMax(0, m_screenEdgeMargin) : 0; if (location() == Plasma::Types::BottomEdge) { absGeometry.moveTop(screenGeometry().bottom() - currentScreenEdgeMargin - m_normalThickness); } else if (location() == Plasma::Types::TopEdge) { absGeometry.moveTop(screenGeometry().top() + currentScreenEdgeMargin); } else if (location() == Plasma::Types::LeftEdge) { absGeometry.moveLeft(screenGeometry().left() + currentScreenEdgeMargin); } else if (location() == Plasma::Types::RightEdge) { absGeometry.moveLeft(screenGeometry().right() - currentScreenEdgeMargin - m_normalThickness); } } if (m_absoluteGeometry == absGeometry && !bypassChecks) { return; } if (m_absoluteGeometry != absGeometry) { m_absoluteGeometry = absGeometry; emit absoluteGeometryChanged(m_absoluteGeometry); } //! this is needed in order to update correctly the screenGeometries if (visibility() && corona() && visibility()->mode() == Types::AlwaysVisible) { //! main use of BYPASSCKECKS is from Positioner when the view changes screens emit availableScreenRectChangedFrom(this); emit availableScreenRegionChangedFrom(this); } } void View::statusChanged(Plasma::Types::ItemStatus status) { if (!containment()) { return; } if (status == Plasma::Types::NeedsAttentionStatus) { m_visibility->addBlockHidingEvent(BLOCKHIDINGNEEDSATTENTIONTYPE); m_visibility->initViewFlags(); } else if (status == Plasma::Types::AcceptingInputStatus) { m_visibility->removeBlockHidingEvent(BLOCKHIDINGNEEDSATTENTIONTYPE); setFlags(flags() & ~Qt::WindowDoesNotAcceptFocus); KWindowSystem::forceActiveWindow(winId()); } else { updateTransientWindowsTracking(); m_visibility->removeBlockHidingEvent(BLOCKHIDINGNEEDSATTENTIONTYPE); m_visibility->initViewFlags(); } } void View::addTransientWindow(QWindow *window) { if (!m_transientWindows.contains(window) && !window->title().startsWith("#debugwindow#")) { m_transientWindows.append(window); QString winPtrStr = "0x" + QString::number((qulonglong)window,16); m_visibility->addBlockHidingEvent(winPtrStr); connect(window, &QWindow::visibleChanged, this, &View::removeTransientWindow); } } void View::removeTransientWindow(const bool &visible) { QWindow *window = static_cast(QObject::sender()); if (window && !visible) { QString winPtrStr = "0x" + QString::number((qulonglong)window,16); m_visibility->removeBlockHidingEvent(winPtrStr); disconnect(window, &QWindow::visibleChanged, this, &View::removeTransientWindow); m_transientWindows.removeAll(window); updateTransientWindowsTracking(); } } void View::updateTransientWindowsTracking() { for(QWindow *window: qApp->topLevelWindows()) { if (window->transientParent() == this){ if (window->isVisible()) { addTransientWindow(window); break; } } } } Types::ViewType View::type() const { return m_type; } void View::setType(Types::ViewType type) { if (m_type == type) { return; } m_type = type; emit typeChanged(); } bool View::alternativesIsShown() const { return m_alternativesIsShown; } void View::setAlternativesIsShown(bool show) { if (m_alternativesIsShown == show) { return; } m_alternativesIsShown = show; emit alternativesIsShownChanged(); } bool View::containsDrag() const { return m_containsDrag; } void View::setContainsDrag(bool contains) { if (m_containsDrag == contains) { return; } m_containsDrag = contains; if (m_containsDrag) { m_visibility->addBlockHidingEvent(BLOCKHIDINGDRAGTYPE); } else { m_visibility->removeBlockHidingEvent(BLOCKHIDINGDRAGTYPE); } emit containsDragChanged(); } bool View::containsMouse() const { return m_containsMouse; } bool View::contextMenuIsShown() const { if (!m_contextMenu) { return false; } return m_contextMenu->menu(); } int View::currentThickness() const { if (formFactor() == Plasma::Types::Vertical) { return m_effects->mask().isNull() ? width() : m_effects->mask().width() - m_effects->innerShadow(); } else { return m_effects->mask().isNull() ? height() : m_effects->mask().height() - m_effects->innerShadow(); } } int View::normalThickness() const { return m_normalThickness; } void View::setNormalThickness(int thickness) { if (m_normalThickness == thickness) { return; } m_normalThickness = thickness; emit normalThicknessChanged(); } int View::headThicknessGap() const { return m_headThicknessGap; } void View::setHeadThicknessGap(int thickness) { if (m_headThicknessGap == thickness) { return; } m_headThicknessGap = thickness; emit headThicknessGapChanged(); } bool View::byPassWM() const { return m_byPassWM; } void View::setByPassWM(bool bypass) { if (m_byPassWM == bypass) { return; } m_byPassWM = bypass; emit byPassWMChanged(); } bool View::behaveAsPlasmaPanel() const { return m_behaveAsPlasmaPanel; } void View::setBehaveAsPlasmaPanel(bool behavior) { if (m_behaveAsPlasmaPanel == behavior) { return; } m_behaveAsPlasmaPanel = behavior; emit behaveAsPlasmaPanelChanged(); } bool View::inEditMode() const { return m_inEditMode; } void View::setInEditMode(bool edit) { if (m_inEditMode == edit) { return; } m_inEditMode = edit; emit inEditModeChanged(); } bool View::isFloatingWindow() const { return m_behaveAsPlasmaPanel && m_screenEdgeMarginEnabled && (m_screenEdgeMargin>0); } bool View::isPreferredForShortcuts() const { return m_isPreferredForShortcuts; } void View::setIsPreferredForShortcuts(bool preferred) { if (m_isPreferredForShortcuts == preferred) { return; } m_isPreferredForShortcuts = preferred; emit isPreferredForShortcutsChanged(); if (m_isPreferredForShortcuts && m_layout) { emit m_layout->preferredViewForShortcutsChanged(this); } } bool View::latteTasksArePresent() const { return m_latteTasksArePresent; } void View::setLatteTasksArePresent(bool present) { if (m_latteTasksArePresent == present) { return; } m_latteTasksArePresent = present; emit latteTasksArePresentChanged(); } bool View::inSettingsAdvancedMode() const { if (m_configView) { auto configView = qobject_cast(m_configView); if (configView) { return configView->inAdvancedMode(); } } return false; } bool View::isTouchingBottomViewAndIsBusy() const { return m_isTouchingBottomViewAndIsBusy; } void View::setIsTouchingBottomViewAndIsBusy(bool touchAndBusy) { if (m_isTouchingBottomViewAndIsBusy == touchAndBusy) { return; } m_isTouchingBottomViewAndIsBusy = touchAndBusy; emit isTouchingBottomViewAndIsBusyChanged(); } bool View::isTouchingTopViewAndIsBusy() const { return m_isTouchingTopViewAndIsBusy; } void View::setIsTouchingTopViewAndIsBusy(bool touchAndBusy) { if (m_isTouchingTopViewAndIsBusy == touchAndBusy) { return; } m_isTouchingTopViewAndIsBusy = touchAndBusy; emit isTouchingTopViewAndIsBusyChanged(); } void View::preferredViewForShortcutsChangedSlot(Latte::View *view) { if (view != this) { setIsPreferredForShortcuts(false); } } bool View::onPrimary() const { return m_onPrimary; } void View::setOnPrimary(bool flag) { if (m_onPrimary == flag) { return; } m_onPrimary = flag; emit onPrimaryChanged(); } float View::maxLength() const { return m_maxLength; } void View::setMaxLength(float length) { if (m_maxLength == length) { return; } m_maxLength = length; emit maxLengthChanged(); } int View::editThickness() const { return m_editThickness; } void View::setEditThickness(int thickness) { if (m_editThickness == thickness) { return; } m_editThickness = thickness; emit editThicknessChanged(); } int View::maxThickness() const { return m_maxThickness; } void View::setMaxThickness(int thickness) { if (m_maxThickness == thickness) return; m_maxThickness = thickness; emit maxThicknessChanged(); } int View::alignment() const { return m_alignment; } void View::setAlignment(int alignment) { Types::Alignment align = static_cast(alignment); if (m_alignment == alignment) { return; } m_alignment = align; emit alignmentChanged(); } QRect View::absoluteGeometry() const { return m_absoluteGeometry; } QRect View::screenGeometry() const { if (this->screen()) { QRect geom = this->screen()->geometry(); return geom; } return QRect(); } float View::offset() const { return m_offset; } void View::setOffset(float offset) { if (m_offset == offset) { return; } m_offset = offset; emit offsetChanged(); } bool View::screenEdgeMarginEnabled() const { return m_screenEdgeMarginEnabled; } void View::setScreenEdgeMarginEnabled(bool enabled) { if (m_screenEdgeMarginEnabled == enabled) { return; } m_screenEdgeMarginEnabled = enabled; emit screenEdgeMarginEnabledChanged(); } int View::screenEdgeMargin() const { return m_screenEdgeMargin; } void View::setScreenEdgeMargin(int margin) { if (m_screenEdgeMargin == margin) { return; } m_screenEdgeMargin = margin; emit screenEdgeMarginChanged(); } int View::fontPixelSize() const { return m_fontPixelSize; } void View::setFontPixelSize(int size) { if (m_fontPixelSize == size) { return; } m_fontPixelSize = size; emit fontPixelSizeChanged(); } bool View::isOnAllActivities() const { return m_activities.isEmpty() || m_activities[0] == "0"; } bool View::isOnActivity(const QString &activity) const { return isOnAllActivities() || m_activities.contains(activity); } QStringList View::activities() const { QStringList running; QStringList runningAll = m_corona->activitiesConsumer()->runningActivities(); for(int i=0; isetWindowOnActivities(*this, runningActivities); //! config windows if (m_configView) { m_windowsTracker->setWindowOnActivities(*m_configView, runningActivities); auto configView = qobject_cast(m_configView); if (configView && configView->secondaryWindow()) { m_windowsTracker->setWindowOnActivities(*configView->secondaryWindow(), runningActivities); } } //! hidden windows if (m_visibility->supportsKWinEdges()) { m_visibility->applyActivitiesToHiddenWindows(runningActivities); } } } void View::showHiddenViewFromActivityStopping() { if (m_layout && m_visibility && !inDelete() && !isVisible() && !m_visibility->isHidden()) { show(); if (m_effects) { m_effects->updateEnabledBorders(); } //qDebug() << "View:: Enforce reshow from timer 1..."; emit forcedShown(); } else if (m_layout && isVisible()) { m_inDelete = false; //qDebug() << "View:: No needed reshow from timer 1..."; } } Layout::GenericLayout *View::layout() const { return m_layout; } void View::setLayout(Layout::GenericLayout *layout) { if (m_layout == layout) { return; } // clear mode for (auto &c : connectionsLayout) { disconnect(c); } m_layout = layout; if (m_layout) { connectionsLayout << connect(containment(), &Plasma::Applet::destroyedChanged, m_layout, &Layout::GenericLayout::destroyedChanged); connectionsLayout << connect(containment(), &Plasma::Applet::locationChanged, m_corona, &Latte::Corona::viewLocationChanged); connectionsLayout << connect(containment(), &Plasma::Containment::appletAlternativesRequested, m_corona, &Latte::Corona::showAlternativesForApplet, Qt::QueuedConnection); if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) { connectionsLayout << connect(containment(), &Plasma::Containment::appletCreated, m_layout, &Layout::GenericLayout::appletCreated); } connectionsLayout << connect(m_positioner, &Latte::ViewPart::Positioner::edgeChanged, m_layout, &Layout::GenericLayout::viewEdgeChanged); //! Sometimes the activity isnt completely ready, by adding a delay //! we try to catch up m_initLayoutTimer.setInterval(100); m_initLayoutTimer.setSingleShot(true); connectionsLayout << connect(&m_initLayoutTimer, &QTimer::timeout, this, [&]() { if (m_layout && m_visibility) { setActivities(m_layout->appliedActivities()); qDebug() << "DOCK VIEW FROM LAYOUT ::: " << m_layout->name() << " - activities: " << m_activities; } }); m_initLayoutTimer.start(); connectionsLayout << connect(m_layout, &Layout::GenericLayout::preferredViewForShortcutsChanged, this, &View::preferredViewForShortcutsChangedSlot); connectionsLayout << connect(m_layout, &Layout::GenericLayout::lastConfigViewForChanged, this, &View::configViewShownFor); Latte::Corona *latteCorona = qobject_cast(this->corona()); connectionsLayout << connect(latteCorona->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged, this, [&]() { if (m_layout && m_visibility) { setActivities(m_layout->appliedActivities()); applyActivitiesToWindows(); showHiddenViewFromActivityStopping(); qDebug() << "DOCK VIEW FROM LAYOUT (currentActivityChanged) ::: " << m_layout->name() << " - activities: " << m_activities; } }); if (latteCorona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) { connectionsLayout << connect(latteCorona->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged, this, [&]() { if (m_layout && m_visibility) { setActivities(m_layout->appliedActivities()); qDebug() << "DOCK VIEW FROM LAYOUT (runningActivitiesChanged) ::: " << m_layout->name() << " - activities: " << m_activities; } }); connectionsLayout << connect(m_layout, &Layout::GenericLayout::activitiesChanged, this, [&]() { if (m_layout) { setActivities(m_layout->appliedActivities()); } }); connectionsLayout << connect(latteCorona->layoutsManager(), &Layouts::Manager::layoutsChanged, this, [&]() { if (m_layout) { setActivities(m_layout->appliedActivities()); } }); //! BEGIN OF KWIN HACK //! IMPORTANT ::: Fixing KWin Faulty Behavior that KWin hides ALL Views when an Activity stops //! with no reason!! m_visibleHackTimer1.setInterval(400); m_visibleHackTimer2.setInterval(2500); m_visibleHackTimer1.setSingleShot(true); m_visibleHackTimer2.setSingleShot(true); connectionsLayout << connect(this, &QWindow::visibleChanged, this, [&]() { if (m_layout && !inDelete() & !isVisible()) { m_visibleHackTimer1.start(); m_visibleHackTimer2.start(); } }); connectionsLayout << connect(&m_visibleHackTimer1, &QTimer::timeout, this, [&]() { applyActivitiesToWindows(); showHiddenViewFromActivityStopping(); emit activitiesChanged(); }); connectionsLayout << connect(&m_visibleHackTimer2, &QTimer::timeout, this, [&]() { applyActivitiesToWindows(); showHiddenViewFromActivityStopping(); emit activitiesChanged(); }); //! END OF KWIN HACK } emit layoutChanged(); } else { m_activities.clear(); } } void View::moveToLayout(QString layoutName) { if (!m_layout) { return; } QList containments = m_layout->unassignFromLayout(this); Latte::Corona *latteCorona = qobject_cast(this->corona()); if (latteCorona && containments.size() > 0) { Layout::GenericLayout *newLayout = latteCorona->layoutsManager()->synchronizer()->layout(layoutName); if (newLayout) { newLayout->assignToLayout(this, containments); } } } void View::configViewShownFor(Latte::View *view) { if (view!=this && m_configView) { //! for each layout only one dock should show its configuration windows //! otherwise we could reach a point that because a settings window //! is below another Latte View its options are not reachable auto configDialog = qobject_cast(m_configView); if (configDialog) { - if (hiddenConfigWindowsAreDeleted()) { + if (hiddenConfigurationWindowsAreDeleted()) { configDialog->deleteLater(); } else if (configDialog->isVisible()) { configDialog->hideConfigWindow(); } } } } void View::hideWindowsForSlidingOut() { if (m_configView) { auto configDialog = qobject_cast(m_configView); if (configDialog) { configDialog->hideConfigWindow(); } } } //! remove latte tasks plasmoid void View::removeTasksPlasmoid() { if (!tasksPresent() || !containment()) { return; } for (const Plasma::Applet *applet : containment()->applets()) { KPluginMetaData meta = applet->kPackage().metadata(); if (meta.pluginId() == "org.kde.latte.plasmoid") { QAction *closeApplet = applet->actions()->action(QStringLiteral("remove")); if (closeApplet) { closeApplet->trigger(); //! remove only the first found return; } } } } //! check if the tasks plasmoid exist in the dock bool View::tasksPresent() { if (!this->containment()) { return false; } for (const Plasma::Applet *applet : this->containment()->applets()) { const auto &provides = KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides")); if (provides.contains(QLatin1String("org.kde.plasma.multitasking"))) { return true; } } return false; } //!check if the plasmoid with _name_ exists in the midedata bool View::mimeContainsPlasmoid(QMimeData *mimeData, QString name) { if (!mimeData) { return false; } if (mimeData->hasFormat(QStringLiteral("text/x-plasmoidservicename"))) { QString data = mimeData->data(QStringLiteral("text/x-plasmoidservicename")); const QStringList appletNames = data.split('\n', QString::SkipEmptyParts); for (const QString &appletName : appletNames) { if (appletName == name) return true; } } return false; } ViewPart::Effects *View::effects() const { return m_effects; } ViewPart::Indicator *View::indicator() const { return m_indicator; } ViewPart::ContainmentInterface *View::extendedInterface() const { return m_interface; } ViewPart::Positioner *View::positioner() const { return m_positioner; } ViewPart::VisibilityManager *View::visibility() const { return m_visibility; } ViewPart::WindowsTracker *View::windowsTracker() const { return m_windowsTracker; } Latte::Interfaces *View::interfacesGraphicObj() const { return m_interfacesGraphicObj; } void View::setInterfacesGraphicObj(Latte::Interfaces *ifaces) { if (m_interfacesGraphicObj == ifaces) { return; } m_interfacesGraphicObj = ifaces; if (containment()) { QQuickItem *containmentGraphicItem = qobject_cast(containment()->property("_plasma_graphicObject").value()); if (containmentGraphicItem) { containmentGraphicItem->setProperty("_latte_view_interfacesobject", QVariant::fromValue(m_interfacesGraphicObj)); } } emit interfacesGraphicObjChanged(); } bool View::event(QEvent *e) { if (!m_inDelete) { emit eventTriggered(e); switch (e->type()) { case QEvent::Enter: m_containsMouse = true; if (m_configView) { ViewPart::PrimaryConfigView *primaryConfigView = qobject_cast(m_configView); if (primaryConfigView) { if (primaryConfigView->secondaryWindow()) { ViewPart::SecondaryConfigView *secConfigView = qobject_cast(primaryConfigView->secondaryWindow()); if (secConfigView) { secConfigView->requestActivate(); } } primaryConfigView->requestActivate(); } } break; case QEvent::Leave: m_containsMouse = false; setContainsDrag(false); engine()->trimComponentCache(); break; case QEvent::DragEnter: setContainsDrag(true); break; case QEvent::DragLeave: case QEvent::Drop: setContainsDrag(false); break; case QEvent::MouseButtonPress: if (auto mouseEvent = dynamic_cast(e)) { emit mousePressed(mouseEvent->pos(), mouseEvent->button()); } break; case QEvent::MouseButtonRelease: if (auto mouseEvent = dynamic_cast(e)) { emit mouseReleased(mouseEvent->pos(), mouseEvent->button()); } break; /* case QEvent::DragMove: qDebug() << "DRAG MOVING>>>>>>"; break;*/ case QEvent::PlatformSurface: if (auto pe = dynamic_cast(e)) { switch (pe->surfaceEventType()) { case QPlatformSurfaceEvent::SurfaceCreated: setupWaylandIntegration(); if (m_shellSurface) { m_positioner->syncGeometry(); m_effects->updateShadows(); } break; case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: if (m_shellSurface) { delete m_shellSurface; m_shellSurface = nullptr; qDebug() << "WAYLAND dock window surface was deleted..."; m_effects->clearShadows(); } break; } } break; case QEvent::Show: if (m_visibility) { m_visibility->initViewFlags(); } break; case QEvent::Wheel: if (auto wheelEvent = dynamic_cast(e)) { #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) QPoint position = QPoint(wheelEvent->x(), wheelEvent->y()); #else QPoint position = wheelEvent->position().toPoint(); #endif emit wheelScrolled(position, wheelEvent->angleDelta(), wheelEvent->buttons()); } break; default: break; } } return ContainmentView::event(e); } //! release grab and restore mouse state void View::unblockMouse(int x, int y) { setMouseGrabEnabled(false); m_releaseGrab_x = x; m_releaseGrab_y = y; m_releaseGrabTimer.start(); } void View::releaseGrab() { //! ungrab mouse if (mouseGrabberItem()) { mouseGrabberItem()->ungrabMouse(); } //! properly release grabbed mouse in order to inform all views setMouseGrabEnabled(true); setMouseGrabEnabled(false); //! Send a fake QEvent::Leave to inform applets for mouse leaving the view QHoverEvent e(QEvent::Leave, QPoint(-5,-5), QPoint(m_releaseGrab_x, m_releaseGrab_y)); QCoreApplication::instance()->sendEvent(this, &e); } QVariantList View::containmentActions() { QVariantList actions; /*if (containment()->corona()->immutability() != Plasma::Types::Mutable) { return actions; }*/ //FIXME: the trigger string it should be better to be supported this way //const QString trigger = Plasma::ContainmentActions::eventToString(event); const QString trigger = "RightButton;NoModifier"; Plasma::ContainmentActions *plugin = this->containment()->containmentActions().value(trigger); if (!plugin) { return actions; } if (plugin->containment() != this->containment()) { plugin->setContainment(this->containment()); // now configure it KConfigGroup cfg(this->containment()->corona()->config(), "ActionPlugins"); cfg = KConfigGroup(&cfg, QString::number(this->containment()->containmentType())); KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger); plugin->restore(pluginConfig); } for (QAction *ac : plugin->contextualActions()) { actions << QVariant::fromValue(ac); } return actions; } bool View::isHighestPriorityView() { if (m_layout) { return this == m_layout->highestPriorityView(); } return false; } //! BEGIN: WORKAROUND order to force top panels always on top and above left/right panels void View::topViewAlwaysOnTop() { if (!m_visibility) { return; } if (location() == Plasma::Types::TopEdge && m_visibility->mode() != Latte::Types::WindowsCanCover && m_visibility->mode() != Latte::Types::WindowsAlwaysCover) { //! this is needed in order to preserve that the top dock will be above others. //! Unity layout paradigm is a good example for this. The top panel shadow //! should be always on top compared to left panel m_visibility->setViewOnFrontLayer(); } } void View::verticalUnityViewHasFocus() { if (formFactor() == Plasma::Types::Vertical && (y() != screenGeometry().y()) && ( (m_alignment == Latte::Types::Justify && m_maxLength == 1.0) ||(m_alignment == Latte::Types::Top && m_offset == 0.0) )) { emit m_corona->verticalUnityViewHasFocus(); } } //! END: WORKAROUND //!BEGIN overriding context menus behavior void View::mousePressEvent(QMouseEvent *event) { bool result = m_contextMenu->mousePressEvent(event); if (result) { PlasmaQuick::ContainmentView::mousePressEvent(event); updateTransientWindowsTracking(); } verticalUnityViewHasFocus(); } //!END overriding context menus behavior //!BEGIN configuration functions void View::saveConfig() { if (!this->containment()) return; auto config = this->containment()->config(); config.writeEntry("onPrimary", onPrimary()); config.writeEntry("byPassWM", byPassWM()); config.writeEntry("isPreferredForShortcuts", isPreferredForShortcuts()); config.writeEntry("viewType", (int)m_type); } void View::restoreConfig() { if (!this->containment()) return; auto config = this->containment()->config(); m_onPrimary = config.readEntry("onPrimary", true); m_byPassWM = config.readEntry("byPassWM", false); m_isPreferredForShortcuts = config.readEntry("isPreferredForShortcuts", false); //! Send changed signals at the end in order to be sure that saveConfig //! wont rewrite default/invalid values emit onPrimaryChanged(); emit byPassWMChanged(); } //!END configuration functions } //!END namespace diff --git a/app/view/view.h b/app/view/view.h index 53458b1f..9271908c 100644 --- a/app/view/view.h +++ b/app/view/view.h @@ -1,446 +1,447 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef VIEW_H #define VIEW_H // local #include #include "containmentinterface.h" #include "effects.h" #include "positioner.h" #include "visibilitymanager.h" #include "indicator/indicator.h" #include "settings/primaryconfigview.h" #include "windowstracker/windowstracker.h" #include "../shortcuts/globalshortcuts.h" #include "../layout/genericlayout.h" #include "../plasma/quick/containmentview.h" #include "../plasma/quick/configview.h" // C++ #include // Qt #include #include #include #include #include #include #include namespace Plasma { class Types; class Corona; class Containment; } namespace PlasmaQuick { class AppletQuickItem; } namespace KWayland { namespace Client { class PlasmaShellSurface; } } namespace Latte { class Corona; class Interfaces; class GenericLayout; namespace ViewPart { class ContextMenu; } } namespace Latte { class View : public PlasmaQuick::ContainmentView { Q_OBJECT Q_PROPERTY(Latte::Types::ViewType type READ type WRITE setType NOTIFY typeChanged) Q_PROPERTY(bool alternativesIsShown READ alternativesIsShown NOTIFY alternativesIsShownChanged) Q_PROPERTY(bool behaveAsPlasmaPanel READ behaveAsPlasmaPanel WRITE setBehaveAsPlasmaPanel NOTIFY behaveAsPlasmaPanelChanged) Q_PROPERTY(bool byPassWM READ byPassWM WRITE setByPassWM NOTIFY byPassWMChanged) Q_PROPERTY(bool containsDrag READ containsDrag NOTIFY containsDragChanged) Q_PROPERTY(bool contextMenuIsShown READ contextMenuIsShown NOTIFY contextMenuIsShownChanged) Q_PROPERTY(bool inSettingsAdvancedMode READ inSettingsAdvancedMode NOTIFY inSettingsAdvancedModeChanged) //! Because Latte uses animations, changing to edit mode it may be different than //! when the isUserConfiguring changes value Q_PROPERTY(bool inEditMode READ inEditMode WRITE setInEditMode NOTIFY inEditModeChanged) Q_PROPERTY(bool isPreferredForShortcuts READ isPreferredForShortcuts WRITE setIsPreferredForShortcuts NOTIFY isPreferredForShortcutsChanged) Q_PROPERTY(bool latteTasksArePresent READ latteTasksArePresent WRITE setLatteTasksArePresent NOTIFY latteTasksArePresentChanged) Q_PROPERTY(bool onPrimary READ onPrimary WRITE setOnPrimary NOTIFY onPrimaryChanged) Q_PROPERTY(bool screenEdgeMarginEnabled READ screenEdgeMarginEnabled WRITE setScreenEdgeMarginEnabled NOTIFY screenEdgeMarginEnabledChanged) //! values to be used from Smart surrounding Views Q_PROPERTY(bool isTouchingBottomViewAndIsBusy READ isTouchingBottomViewAndIsBusy WRITE setIsTouchingBottomViewAndIsBusy NOTIFY isTouchingBottomViewAndIsBusyChanged) Q_PROPERTY(bool isTouchingTopViewAndIsBusy READ isTouchingTopViewAndIsBusy WRITE setIsTouchingTopViewAndIsBusy NOTIFY isTouchingTopViewAndIsBusyChanged) Q_PROPERTY(int alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged) Q_PROPERTY(int fontPixelSize READ fontPixelSize WRITE setFontPixelSize NOTIFY fontPixelSizeChanged) Q_PROPERTY(int x READ x NOTIFY xChanged) Q_PROPERTY(int y READ y NOTIFY yChanged) Q_PROPERTY(int width READ width NOTIFY widthChanged) Q_PROPERTY(int height READ height NOTIFY heightChanged) Q_PROPERTY(int editThickness READ editThickness WRITE setEditThickness NOTIFY editThicknessChanged) Q_PROPERTY(int maxThickness READ maxThickness WRITE setMaxThickness NOTIFY maxThicknessChanged) Q_PROPERTY(int normalThickness READ normalThickness WRITE setNormalThickness NOTIFY normalThicknessChanged) Q_PROPERTY(int headThicknessGap READ headThicknessGap WRITE setHeadThicknessGap NOTIFY headThicknessGapChanged) Q_PROPERTY(int screenEdgeMargin READ screenEdgeMargin WRITE setScreenEdgeMargin NOTIFY screenEdgeMarginChanged) Q_PROPERTY(float maxLength READ maxLength WRITE setMaxLength NOTIFY maxLengthChanged) Q_PROPERTY(float offset READ offset WRITE setOffset NOTIFY offsetChanged) Q_PROPERTY(Latte::Layout::GenericLayout *layout READ layout WRITE setLayout NOTIFY layoutChanged) Q_PROPERTY(Latte::ViewPart::Effects *effects READ effects NOTIFY effectsChanged) Q_PROPERTY(Latte::ViewPart::ContainmentInterface *extendedInterface READ extendedInterface NOTIFY extendedInterfaceChanged) Q_PROPERTY(Latte::ViewPart::Indicator *indicator READ indicator NOTIFY indicatorChanged) Q_PROPERTY(Latte::ViewPart::Positioner *positioner READ positioner NOTIFY positionerChanged) Q_PROPERTY(Latte::ViewPart::VisibilityManager *visibility READ visibility NOTIFY visibilityChanged) Q_PROPERTY(Latte::ViewPart::WindowsTracker *windowsTracker READ windowsTracker NOTIFY windowsTrackerChanged) Q_PROPERTY(Latte::Interfaces *interfacesGraphicObj READ interfacesGraphicObj WRITE setInterfacesGraphicObj NOTIFY interfacesGraphicObjChanged) Q_PROPERTY(QRect absoluteGeometry READ absoluteGeometry NOTIFY absoluteGeometryChanged) Q_PROPERTY(QRect localGeometry READ localGeometry WRITE setLocalGeometry NOTIFY localGeometryChanged) Q_PROPERTY(QRect screenGeometry READ screenGeometry NOTIFY screenGeometryChanged) public: View(Plasma::Corona *corona, QScreen *targetScreen = nullptr, bool byPassWM = false); virtual ~View(); void init(Plasma::Containment *plasma_containment = nullptr); Types::ViewType type() const; void setType(Types::ViewType type); bool alternativesIsShown() const; void setAlternativesIsShown(bool show); bool inDelete() const; bool inReadyState() const; - bool hiddenConfigWindowsAreDeleted() const; + bool hiddenConfigurationWindowsAreDeleted() const; bool onPrimary() const; void setOnPrimary(bool flag); int currentThickness() const; bool behaveAsPlasmaPanel() const; void setBehaveAsPlasmaPanel(bool behavior); bool containsDrag() const; bool containsMouse() const; bool contextMenuIsShown() const; bool byPassWM() const; void setByPassWM(bool bypass); bool inEditMode() const; void setInEditMode(bool edit); bool isFloatingWindow() const; bool isPreferredForShortcuts() const; void setIsPreferredForShortcuts(bool preferred); bool latteTasksArePresent() const; void setLatteTasksArePresent(bool present); bool inSettingsAdvancedMode() const; bool isTouchingBottomViewAndIsBusy() const; void setIsTouchingBottomViewAndIsBusy(bool touchAndBusy); bool isTouchingTopViewAndIsBusy() const; void setIsTouchingTopViewAndIsBusy(bool touchAndBusy); bool screenEdgeMarginEnabled() const; void setScreenEdgeMarginEnabled(bool enabled); int fontPixelSize() const; void setFontPixelSize(int size); int editThickness() const; void setEditThickness(int thickness); int maxThickness() const; void setMaxThickness(int thickness); int normalThickness() const; void setNormalThickness(int thickness); int headThicknessGap() const; void setHeadThicknessGap(int thickness); int screenEdgeMargin() const; void setScreenEdgeMargin(int margin); int alignment() const; void setAlignment(int alignment); float maxLength() const; void setMaxLength(float length); float offset() const; void setOffset(float offset); QRect absoluteGeometry() const; QRect screenGeometry() const; QRect localGeometry() const; void setLocalGeometry(const QRect &geometry); QString validTitle() const; bool isOnActivity(const QString &activity) const; bool isOnAllActivities() const; QStringList activities() const; void setActivities(const QStringList &ids); bool settingsWindowIsShown(); void showSettingsWindow(); PlasmaQuick::ConfigView *configView(); ViewPart::Effects *effects() const; ViewPart::ContainmentInterface *extendedInterface() const; ViewPart::Indicator *indicator() const; ViewPart::Positioner *positioner() const; ViewPart::VisibilityManager *visibility() const; ViewPart::WindowsTracker *windowsTracker() const; Latte::Interfaces *interfacesGraphicObj() const; void setInterfacesGraphicObj(Latte::Interfaces *ifaces); Layout::GenericLayout *layout() const; void setLayout(Layout::GenericLayout *layout); KWayland::Client::PlasmaShellSurface *surface(); //! release grab and restore mouse state void unblockMouse(int x, int y); void reconsiderScreen(); //! these are signals that create crashes, such a example is the availableScreenRectChanged from corona //! when its containment is destroyed void disconnectSensitiveSignals(); public slots: Q_INVOKABLE void copyView(); Q_INVOKABLE void removeView(); Q_INVOKABLE QVariantList containmentActions(); Q_INVOKABLE void moveToLayout(QString layoutName); Q_INVOKABLE void removeTasksPlasmoid(); Q_INVOKABLE bool mimeContainsPlasmoid(QMimeData *mimeData, QString name); Q_INVOKABLE bool tasksPresent(); void updateAbsoluteGeometry(bool bypassChecks = false); Q_INVOKABLE bool isHighestPriorityView(); protected slots: void showConfigurationInterface(Plasma::Applet *applet) override; protected: bool event(QEvent *ev) override; void mousePressEvent(QMouseEvent *event) override; signals: void eventTriggered(QEvent *ev); void mousePressed(const QPoint pos, const int button); void mouseReleased(const QPoint pos, const int button); void wheelScrolled(const QPoint pos, const QPoint angleDelta, const int buttons); void activitiesChanged(); void alternativesIsShownChanged(); void alignmentChanged(); void behaveAsPlasmaPanelChanged(); void byPassWMChanged(); void configWindowGeometryChanged(); // is called from config windows void containsDragChanged(); void contextMenuIsShownChanged(); void dockLocationChanged(); void editThicknessChanged(); void effectsChanged(); void extendedInterfaceChanged(); void fontPixelSizeChanged(); void forcedShown(); //[workaround] forced shown to avoid a KWin issue that hides windows when closing activities void widthChanged(); void headThicknessGapChanged(); void heightChanged(); + void hiddenConfigurationWindowsAreDeletedChanged(); void inEditModeChanged(); void indicatorChanged(); void inSettingsAdvancedModeChanged(); void interfacesGraphicObjChanged(); void isPreferredForShortcutsChanged(); void isTouchingBottomViewAndIsBusyChanged(); void isTouchingTopViewAndIsBusyChanged(); void latteTasksArePresentChanged(); void layoutChanged(); void localGeometryChanged(); void maxLengthChanged(); void maxThicknessChanged(); void normalThicknessChanged(); void offsetChanged(); void onPrimaryChanged(); void positionerChanged(); void screenEdgeMarginChanged(); void screenEdgeMarginEnabledChanged(); void screenGeometryChanged(); void typeChanged(); void visibilityChanged(); void windowsTrackerChanged(); void xChanged(); void yChanged(); void absoluteGeometryChanged(const QRect &geometry); void indicatorPluginChanged(const QString &indicatorId); void indicatorPluginRemoved(const QString &indicatorId); //! are used to trigger the Corona relevant signals and in that //! way we can disable any such signaling all together, e.g. through disconnectSensitiveSignals() void availableScreenRectChangedFrom(Latte::View *origin); void availableScreenRegionChangedFrom(Latte::View *origin); private slots: void applyActivitiesToWindows(); void availableScreenRectChangedFromSlot(View *origin); void configViewShownFor(Latte::View *view); void hideWindowsForSlidingOut(); void preferredViewForShortcutsChangedSlot(Latte::View *view); void releaseGrab(); void reloadSource(); void updateTransientWindowsTracking(); void statusChanged(Plasma::Types::ItemStatus); void addTransientWindow(QWindow *window); void removeTransientWindow(const bool &visible); //! workaround in order for top panels to be always on top void topViewAlwaysOnTop(); void verticalUnityViewHasFocus(); //!workround for when kwin hides view when an activity is closing void showHiddenViewFromActivityStopping(); void restoreConfig(); void saveConfig(); private: void initSignalingForLocationChangeSliding(); void setupWaylandIntegration(); void updateAppletContainsMethod(); void setContainsDrag(bool contains); private: Plasma::Containment *containmentById(uint id); bool m_alternativesIsShown{false}; bool m_behaveAsPlasmaPanel{false}; bool m_byPassWM{true}; bool m_containsDrag{false}; bool m_containsMouse{false}; bool m_inDelete{false}; bool m_inEditMode{false}; bool m_isPreferredForShortcuts{false}; bool m_latteTasksArePresent{false}; bool m_onPrimary{true}; bool m_screenEdgeMarginEnabled{false}; bool m_isTouchingBottomViewAndIsBusy{false}; bool m_isTouchingTopViewAndIsBusy{false}; int m_fontPixelSize{ -1}; int m_editThickness{24}; int m_maxThickness{24}; int m_normalThickness{24}; int m_headThicknessGap{0}; int m_screenEdgeMargin{-1}; float m_maxLength{1}; float m_offset{0}; Types::Alignment m_alignment{Types::Center}; Types::ViewType m_type{Types::DockView}; QRect m_localGeometry; QRect m_absoluteGeometry; QStringList m_activities; //! HACK: In order to avoid crashes when the View is added and removed //! immediately during startup QTimer m_initLayoutTimer; //! HACK: Timers in order to handle KWin faulty //! behavior that hides Views when closing Activities //! with no actual reason QTimer m_visibleHackTimer1; QTimer m_visibleHackTimer2; QTimer m_releaseGrabTimer; int m_releaseGrab_x; int m_releaseGrab_y; Layout::GenericLayout *m_layout{nullptr}; QPointer m_configView; QPointer m_contextMenu; QPointer m_effects; QPointer m_indicator; QPointer m_interface; QPointer m_positioner; QPointer m_visibility; QPointer m_windowsTracker; QPointer m_interfacesGraphicObj; //! Connections to release and bound for the assigned layout QList connectionsLayout; //! track transientWindows QList m_transientWindows; QPointer m_corona; KWayland::Client::PlasmaShellSurface *m_shellSurface{nullptr}; }; } #endif