Merge desktop grid and overview together with a new three-state design
Merges the desktop grid and overview effects together in a new three-state one; you can switch between them with a certain shortcut or gesture, and you can also still access either the desktop grid or overview directly. Default shortcuts are also updated to be Meta+G for Grid, Meta+W for Overview, Meta+Tab to switch between the three states and Meta+Shift+Tab to cycle in the opposite direction. BUG: 474044 BUG: 460661 BUG: 460774 BUG: 456572 BUG: 449601 BUG: 450262 BUG: 449801 BUG: 461510 BUG: 463886 BUG: 459754 BUG: 459749 BUG: 459748 BUG: 459467 FIXED-IN: 6.0
This commit is contained in:
parent
1d6ac05a8c
commit
028dd552cf
29 changed files with 987 additions and 1872 deletions
|
@ -51,6 +51,7 @@ option(KWIN_BUILD_TABBOX "Enable building of KWin Tabbox functionality" ON)
|
|||
find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
|
||||
Concurrent
|
||||
Core
|
||||
Core5Compat
|
||||
DBus
|
||||
Quick
|
||||
UiTools
|
||||
|
@ -455,6 +456,7 @@ if (KF6DocTools_FOUND)
|
|||
endif()
|
||||
|
||||
add_subdirectory(data)
|
||||
add_subdirectory(kconf_update)
|
||||
add_subdirectory(src)
|
||||
|
||||
if (BUILD_TESTING)
|
||||
|
|
7
kconf_update/CMakeLists.txt
Normal file
7
kconf_update/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
# SPDX-FileCopyrightText: 2023 Niccolò Venerandi <niccolo.venerandi@kde.org>
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
install(FILES kwin.upd
|
||||
DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR})
|
||||
install(PROGRAMS kwin-6.0-overview-activities-shortcuts.py
|
||||
DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR})
|
20
kconf_update/kwin-6.0-overview-activities-shortcuts.py
Normal file
20
kconf_update/kwin-6.0-overview-activities-shortcuts.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-FileCopyrightText: 2023 Niccolò Venerandi <niccolo.venerandi@kde.org>
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import fileinput
|
||||
|
||||
for line in fileinput.input():
|
||||
if line.startswith('next activity'):
|
||||
print(line.replace('Meta+Tab', 'Meta+A'))
|
||||
elif line.startswith('previous activity'):
|
||||
print(line.replace('Meta+Shift+Tab', 'Meta+Shift+A'))
|
||||
elif line.startswith('ShowDesktopGrid'):
|
||||
pass
|
||||
elif line.startswith('Overview'):
|
||||
print('Overview=Meta+W,Meta+W,Toggle Overview')
|
||||
print('Cycle Overview=Meta+Tab,Meta+Tab,Cycle through Overview and Grid View')
|
||||
print('Cycle Overview Opposite=Meta+Shift+Tab,Meta+Shift+Tab,Cycle through Grid View and Overview')
|
||||
print('Grid View=Meta+G,Meta+G,Toggle Grid View')
|
||||
else:
|
||||
print(line)
|
11
kconf_update/kwin.upd
Normal file
11
kconf_update/kwin.upd
Normal file
|
@ -0,0 +1,11 @@
|
|||
# SPDX-FileCopyrightText: 2023 Niccolò Venerandi <niccolo.venerandi@kde.org>
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
Version=5
|
||||
|
||||
# Changes the default Activities shortcut from Meta+Tab to Meta+A,
|
||||
# so that the Overview can take its place
|
||||
Id=change-activities-overview-shortcuts
|
||||
File=kglobalshortcutsrc
|
||||
Group=plasmashell,kwin
|
||||
Script=kwin-6.0-overview-activities-shortcuts.py,python3
|
|
@ -43,9 +43,9 @@ EffectTogglableState::EffectTogglableState(Effect *effect)
|
|||
|
||||
void EffectTogglableState::activate()
|
||||
{
|
||||
setStatus(Status::Active);
|
||||
setInProgress(false);
|
||||
setPartialActivationFactor(0.0);
|
||||
setPartialActivationFactor(1.0);
|
||||
setStatus(Status::Active);
|
||||
}
|
||||
|
||||
void EffectTogglableState::setPartialActivationFactor(qreal factor)
|
||||
|
@ -60,6 +60,13 @@ void EffectTogglableState::deactivate()
|
|||
{
|
||||
setInProgress(false);
|
||||
setPartialActivationFactor(0.0);
|
||||
setStatus(Status::Inactive);
|
||||
}
|
||||
|
||||
void EffectTogglableState::stop()
|
||||
{
|
||||
setInProgress(false);
|
||||
setStatus(Status::Stopped);
|
||||
}
|
||||
|
||||
bool EffectTogglableState::inProgress() const
|
||||
|
@ -103,7 +110,7 @@ void EffectTogglableState::partialDeactivate(qreal factor)
|
|||
|
||||
void EffectTogglableState::toggle()
|
||||
{
|
||||
if (m_status == Status::Inactive || m_partialActivationFactor > 0.5) {
|
||||
if (m_status == Status::Inactive) {
|
||||
activate();
|
||||
Q_EMIT activated();
|
||||
} else {
|
||||
|
@ -114,6 +121,9 @@ void EffectTogglableState::toggle()
|
|||
|
||||
void EffectTogglableState::setProgress(qreal progress)
|
||||
{
|
||||
if (m_status == Status::Stopped) {
|
||||
return;
|
||||
}
|
||||
if (!effects->hasActiveFullScreenEffect() || effects->activeFullScreenEffect() == parent()) {
|
||||
switch (m_status) {
|
||||
case Status::Inactive:
|
||||
|
@ -128,6 +138,9 @@ void EffectTogglableState::setProgress(qreal progress)
|
|||
|
||||
void EffectTogglableState::setRegress(qreal regress)
|
||||
{
|
||||
if (m_status == Status::Stopped) {
|
||||
return;
|
||||
}
|
||||
if (!effects->hasActiveFullScreenEffect() || effects->activeFullScreenEffect() == parent()) {
|
||||
switch (m_status) {
|
||||
case Status::Active:
|
||||
|
|
|
@ -29,7 +29,8 @@ public:
|
|||
Inactive,
|
||||
Activating,
|
||||
Deactivating,
|
||||
Active
|
||||
Active,
|
||||
Stopped
|
||||
};
|
||||
Q_ENUM(Status)
|
||||
|
||||
|
@ -61,6 +62,7 @@ public:
|
|||
void activate();
|
||||
void deactivate();
|
||||
void toggle();
|
||||
void stop();
|
||||
void setStatus(Status status);
|
||||
Status status() const
|
||||
{
|
||||
|
|
|
@ -54,7 +54,6 @@ add_subdirectory(buttonrebinds)
|
|||
add_subdirectory(colord-integration)
|
||||
add_subdirectory(colorpicker)
|
||||
add_subdirectory(desktopchangeosd)
|
||||
add_subdirectory(desktopgrid)
|
||||
add_subdirectory(dialogparent)
|
||||
add_subdirectory(diminactive)
|
||||
add_subdirectory(dimscreen)
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
set(desktopgrid_SOURCES
|
||||
main.cpp
|
||||
desktopgrideffect.cpp
|
||||
)
|
||||
|
||||
kconfig_add_kcfg_files(desktopgrid_SOURCES
|
||||
desktopgridconfig.kcfgc
|
||||
)
|
||||
|
||||
|
||||
kwin_add_builtin_effect(desktopgrid ${desktopgrid_SOURCES})
|
||||
|
||||
target_link_libraries(desktopgrid PRIVATE
|
||||
kwineffects
|
||||
|
||||
KF6::ConfigGui
|
||||
KF6::GlobalAccel
|
||||
KF6::I18n
|
||||
|
||||
Qt::Quick
|
||||
)
|
||||
|
||||
#######################################
|
||||
# Config
|
||||
if (KWIN_BUILD_KCMS)
|
||||
set(kwin_desktopgrid_config_SRCS desktopgrid_config.cpp)
|
||||
ki18n_wrap_ui(kwin_desktopgrid_config_SRCS desktopgrid_config.ui)
|
||||
kconfig_add_kcfg_files(kwin_desktopgrid_config_SRCS desktopgridconfig.kcfgc)
|
||||
|
||||
kwin_add_effect_config(kwin_desktopgrid_config ${kwin_desktopgrid_config_SRCS})
|
||||
|
||||
target_link_libraries(kwin_desktopgrid_config
|
||||
KF6::KCMUtils
|
||||
KF6::CoreAddons
|
||||
KF6::GlobalAccel
|
||||
KF6::I18n
|
||||
KF6::XmlGui
|
||||
Qt::Quick
|
||||
kwineffects
|
||||
KWinEffectsInterface
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
install(DIRECTORY qml DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/desktopgrid)
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2007 Rivo Laks <rivolaks@hot.ee>
|
||||
SPDX-FileCopyrightText: 2008 Lucas Murray <lmurray@undefinedfire.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "desktopgrid_config.h"
|
||||
|
||||
#include <config-kwin.h>
|
||||
|
||||
// KConfigSkeleton
|
||||
#include "desktopgridconfig.h"
|
||||
#include <kwineffects_interface.h>
|
||||
|
||||
#include <QAction>
|
||||
|
||||
#include <KActionCollection>
|
||||
#include <KGlobalAccel>
|
||||
#include <KLocalizedString>
|
||||
#include <KPluginFactory>
|
||||
#include <kconfiggroup.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
|
||||
K_PLUGIN_CLASS(KWin::DesktopGridEffectConfig)
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
DesktopGridEffectConfigForm::DesktopGridEffectConfigForm(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
}
|
||||
|
||||
DesktopGridEffectConfig::DesktopGridEffectConfig(QObject *parent, const KPluginMetaData &data)
|
||||
: KCModule(parent, data)
|
||||
, m_ui(widget())
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(widget());
|
||||
layout->addWidget(&m_ui);
|
||||
|
||||
// Shortcut config. The shortcut belongs to the component "kwin"!
|
||||
m_actionCollection = new KActionCollection(widget(), QStringLiteral("kwin"));
|
||||
|
||||
m_actionCollection->setComponentDisplayName(i18n("KWin"));
|
||||
m_actionCollection->setConfigGroup(QStringLiteral("DesktopGrid"));
|
||||
m_actionCollection->setConfigGlobal(true);
|
||||
|
||||
QAction *a = m_actionCollection->addAction(QStringLiteral("ShowDesktopGrid"));
|
||||
a->setText(i18n("Show Desktop Grid"));
|
||||
a->setProperty("isConfigurationAction", true);
|
||||
KGlobalAccel::self()->setDefaultShortcut(a, QList<QKeySequence>() << (Qt::CTRL | Qt::Key_F8));
|
||||
KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>() << (Qt::CTRL | Qt::Key_F8));
|
||||
|
||||
m_ui.shortcutEditor->addCollection(m_actionCollection);
|
||||
|
||||
m_ui.desktopNameAlignmentCombo->addItem(i18nc("Desktop name alignment:", "Disabled"), QVariant(Qt::Alignment()));
|
||||
m_ui.desktopNameAlignmentCombo->addItem(i18n("Top"), QVariant(Qt::AlignHCenter | Qt::AlignTop));
|
||||
m_ui.desktopNameAlignmentCombo->addItem(i18n("Top-Right"), QVariant(Qt::AlignRight | Qt::AlignTop));
|
||||
m_ui.desktopNameAlignmentCombo->addItem(i18n("Right"), QVariant(Qt::AlignRight | Qt::AlignVCenter));
|
||||
m_ui.desktopNameAlignmentCombo->addItem(i18n("Bottom-Right"), QVariant(Qt::AlignRight | Qt::AlignBottom));
|
||||
m_ui.desktopNameAlignmentCombo->addItem(i18n("Bottom"), QVariant(Qt::AlignHCenter | Qt::AlignBottom));
|
||||
m_ui.desktopNameAlignmentCombo->addItem(i18n("Bottom-Left"), QVariant(Qt::AlignLeft | Qt::AlignBottom));
|
||||
m_ui.desktopNameAlignmentCombo->addItem(i18n("Left"), QVariant(Qt::AlignLeft | Qt::AlignVCenter));
|
||||
m_ui.desktopNameAlignmentCombo->addItem(i18n("Top-Left"), QVariant(Qt::AlignLeft | Qt::AlignTop));
|
||||
m_ui.desktopNameAlignmentCombo->addItem(i18n("Center"), QVariant(Qt::AlignCenter));
|
||||
|
||||
DesktopGridConfig::instance(KWIN_CONFIG);
|
||||
addConfig(DesktopGridConfig::self(), &m_ui);
|
||||
connect(m_ui.kcfg_DesktopLayoutMode, qOverload<int>(&QComboBox::currentIndexChanged), this, &DesktopGridEffectConfig::desktopLayoutSelectionChanged);
|
||||
connect(m_ui.desktopNameAlignmentCombo, qOverload<int>(&QComboBox::currentIndexChanged), this, &KCModule::markAsChanged);
|
||||
connect(m_ui.shortcutEditor, &KShortcutsEditor::keyChange, this, &KCModule::markAsChanged);
|
||||
}
|
||||
|
||||
DesktopGridEffectConfig::~DesktopGridEffectConfig()
|
||||
{
|
||||
// If save() is called undo() has no effect
|
||||
m_ui.shortcutEditor->undo();
|
||||
}
|
||||
|
||||
void DesktopGridEffectConfig::save()
|
||||
{
|
||||
m_ui.shortcutEditor->save();
|
||||
DesktopGridConfig::setDesktopNameAlignment(m_ui.desktopNameAlignmentCombo->itemData(m_ui.desktopNameAlignmentCombo->currentIndex()).toInt());
|
||||
KCModule::save();
|
||||
DesktopGridConfig::self()->save();
|
||||
|
||||
OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"),
|
||||
QStringLiteral("/Effects"),
|
||||
QDBusConnection::sessionBus());
|
||||
interface.reconfigureEffect(QStringLiteral("desktopgrid"));
|
||||
}
|
||||
|
||||
void DesktopGridEffectConfig::load()
|
||||
{
|
||||
KCModule::load();
|
||||
m_ui.desktopNameAlignmentCombo->setCurrentIndex(m_ui.desktopNameAlignmentCombo->findData(QVariant(DesktopGridConfig::desktopNameAlignment())));
|
||||
|
||||
desktopLayoutSelectionChanged();
|
||||
}
|
||||
|
||||
void DesktopGridEffectConfig::desktopLayoutSelectionChanged()
|
||||
{
|
||||
if (m_ui.kcfg_DesktopLayoutMode->currentIndex() == int(DesktopGridEffect::DesktopLayoutMode::LayoutCustom)) {
|
||||
m_ui.layoutRowsLabel->setEnabled(true);
|
||||
m_ui.kcfg_CustomLayoutRows->setEnabled(true);
|
||||
} else {
|
||||
m_ui.layoutRowsLabel->setEnabled(false);
|
||||
m_ui.kcfg_CustomLayoutRows->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DesktopGridEffectConfig::defaults()
|
||||
{
|
||||
KCModule::defaults();
|
||||
m_ui.desktopNameAlignmentCombo->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "desktopgrid_config.moc"
|
||||
|
||||
#include "moc_desktopgrid_config.cpp"
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2007 Rivo Laks <rivolaks@hot.ee>
|
||||
SPDX-FileCopyrightText: 2008 Lucas Murray <lmurray@undefinedfire.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <kcmodule.h>
|
||||
|
||||
#include "desktopgrideffect.h"
|
||||
#include "ui_desktopgrid_config.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class DesktopGridEffectConfigForm : public QWidget, public Ui::DesktopGridEffectConfigForm
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DesktopGridEffectConfigForm(QWidget *parent);
|
||||
};
|
||||
|
||||
class DesktopGridEffectConfig : public KCModule
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DesktopGridEffectConfig(QObject *parent, const KPluginMetaData &data);
|
||||
~DesktopGridEffectConfig() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void save() override;
|
||||
void load() override;
|
||||
void defaults() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void desktopLayoutSelectionChanged();
|
||||
|
||||
private:
|
||||
DesktopGridEffectConfigForm m_ui;
|
||||
KActionCollection *m_actionCollection;
|
||||
};
|
||||
|
||||
} // namespace
|
|
@ -1,206 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>KWin::DesktopGridEffectConfigForm</class>
|
||||
<widget class="QWidget" name="KWin::DesktopGridEffectConfigForm">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>574</width>
|
||||
<height>312</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Appearance</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="kcfg_DesktopLayoutMode">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Pager</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Automatic</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="layoutRowsLabel">
|
||||
<property name="text">
|
||||
<string>N&umber of rows:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>kcfg_CustomLayoutRows</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="kcfg_CustomLayoutRows">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="desktopNameAlignmentCombo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Desktop &name alignment:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>desktopNameAlignmentCombo</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="kcfg_ShowAddRemove">
|
||||
<property name="text">
|
||||
<string>Show buttons to alter count of virtual desktops</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>&Grid layout mode:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>kcfg_DesktopLayoutMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="kcfg_LayoutMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Closest</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Natural</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Windows layout:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>kcfg_LayoutMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Activation</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="KShortcutsEditor" name="shortcutEditor">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KShortcutsEditor</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>kshortcutseditor.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>desktopNameAlignmentCombo</tabstop>
|
||||
<tabstop>kcfg_DesktopLayoutMode</tabstop>
|
||||
<tabstop>kcfg_LayoutMode</tabstop>
|
||||
<tabstop>kcfg_CustomLayoutRows</tabstop>
|
||||
<tabstop>kcfg_ShowAddRemove</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1,32 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
-->
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile arg="true"/>
|
||||
<group name="Effect-desktopgrid">
|
||||
<entry name="BorderActivate" type="IntList" />
|
||||
<entry name="TouchBorderActivate" type="IntList" />
|
||||
|
||||
<entry name="DesktopNameAlignment" type="Int">
|
||||
<default>0</default>
|
||||
</entry>
|
||||
<entry name="LayoutMode" type="Int">
|
||||
<default>1</default>
|
||||
</entry>
|
||||
<entry name="DesktopLayoutMode" type="Int">
|
||||
<default code="true">0</default>
|
||||
</entry>
|
||||
<entry name="CustomLayoutRows" type="Int">
|
||||
<default>2</default>
|
||||
</entry>
|
||||
<entry name="ShowAddRemove" type="Bool">
|
||||
<default>true</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
|
@ -1,9 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
File=desktopgridconfig.kcfg
|
||||
ClassName=DesktopGridConfig
|
||||
NameSpace=KWin
|
||||
Singleton=true
|
||||
Mutators=true
|
|
@ -1,250 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "desktopgrideffect.h"
|
||||
#include "desktopgridconfig.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QQuickItem>
|
||||
#include <QTimer>
|
||||
#include <cmath>
|
||||
|
||||
#include <KGlobalAccel>
|
||||
#include <KLocalizedString>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
DesktopGridEffect::DesktopGridEffect()
|
||||
: m_shutdownTimer(new QTimer(this))
|
||||
, m_state(new EffectTogglableState(this))
|
||||
, m_border(new EffectTogglableTouchBorder(m_state))
|
||||
{
|
||||
qmlRegisterUncreatableType<DesktopGridEffect>("org.kde.kwin.private.desktopgrid", 1, 0, "DesktopGridEffect", QStringLiteral("Cannot create elements of type DesktopGridEffect"));
|
||||
|
||||
m_shutdownTimer->setSingleShot(true);
|
||||
connect(m_shutdownTimer, &QTimer::timeout, this, &DesktopGridEffect::realDeactivate);
|
||||
connect(effects, &EffectsHandler::screenAboutToLock, this, &DesktopGridEffect::realDeactivate);
|
||||
connect(effects, &EffectsHandler::desktopGridWidthChanged, this, &DesktopGridEffect::gridColumnsChanged);
|
||||
connect(effects, &EffectsHandler::desktopGridHeightChanged, this, &DesktopGridEffect::gridRowsChanged);
|
||||
connect(m_state, &EffectTogglableState::activated, this, &DesktopGridEffect::activate);
|
||||
connect(m_state, &EffectTogglableState::deactivated, this, &DesktopGridEffect::deactivate);
|
||||
connect(m_state, &EffectTogglableState::inProgressChanged, this, &DesktopGridEffect::gestureInProgressChanged);
|
||||
connect(m_state, &EffectTogglableState::partialActivationFactorChanged, this, &DesktopGridEffect::partialActivationFactorChanged);
|
||||
connect(m_state, &EffectTogglableState::statusChanged, this, [this](EffectTogglableState::Status status) {
|
||||
setRunning(status != EffectTogglableState::Status::Inactive);
|
||||
});
|
||||
|
||||
auto toggleAction = m_state->toggleAction();
|
||||
toggleAction->setObjectName(QStringLiteral("ShowDesktopGrid"));
|
||||
toggleAction->setText(i18n("Show Desktop Grid"));
|
||||
KGlobalAccel::self()->setDefaultShortcut(toggleAction, QList<QKeySequence>() << (Qt::META | Qt::Key_F8));
|
||||
KGlobalAccel::self()->setShortcut(toggleAction, QList<QKeySequence>() << (Qt::META | Qt::Key_F8));
|
||||
m_toggleShortcut = KGlobalAccel::self()->shortcut(toggleAction);
|
||||
|
||||
auto gesture = new EffectTogglableGesture(m_state);
|
||||
gesture->addTouchpadSwipeGesture(SwipeDirection::Up, 4);
|
||||
|
||||
initConfig<DesktopGridConfig>();
|
||||
reconfigure(ReconfigureAll);
|
||||
|
||||
setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/effects/desktopgrid/qml/main.qml"))));
|
||||
}
|
||||
|
||||
DesktopGridEffect::~DesktopGridEffect()
|
||||
{
|
||||
}
|
||||
|
||||
void DesktopGridEffect::reconfigure(ReconfigureFlags)
|
||||
{
|
||||
DesktopGridConfig::self()->read();
|
||||
setLayout(DesktopGridConfig::layoutMode());
|
||||
setAnimationDuration(animationTime(300));
|
||||
|
||||
for (const ElectricBorder &border : std::as_const(m_borderActivate)) {
|
||||
effects->unreserveElectricBorder(border, this);
|
||||
}
|
||||
|
||||
m_borderActivate.clear();
|
||||
|
||||
const QList<int> activateBorders = DesktopGridConfig::borderActivate();
|
||||
for (const int &border : activateBorders) {
|
||||
m_borderActivate.append(ElectricBorder(border));
|
||||
effects->reserveElectricBorder(ElectricBorder(border), this);
|
||||
}
|
||||
|
||||
m_border->setBorders(DesktopGridConfig::touchBorderActivate());
|
||||
|
||||
Q_EMIT showAddRemoveChanged();
|
||||
Q_EMIT desktopNameAlignmentChanged();
|
||||
Q_EMIT desktopLayoutModeChanged();
|
||||
Q_EMIT customLayoutRowsChanged();
|
||||
}
|
||||
|
||||
int DesktopGridEffect::requestedEffectChainPosition() const
|
||||
{
|
||||
return 70;
|
||||
}
|
||||
|
||||
bool DesktopGridEffect::borderActivated(ElectricBorder border)
|
||||
{
|
||||
if (m_borderActivate.contains(border)) {
|
||||
m_state->toggle();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DesktopGridEffect::grabbedKeyboardEvent(QKeyEvent *keyEvent)
|
||||
{
|
||||
if (m_toggleShortcut.contains(keyEvent->key() | keyEvent->modifiers())) {
|
||||
if (keyEvent->type() == QEvent::KeyPress) {
|
||||
m_state->toggle();
|
||||
}
|
||||
return;
|
||||
}
|
||||
QuickSceneEffect::grabbedKeyboardEvent(keyEvent);
|
||||
}
|
||||
|
||||
Qt::AlignmentFlag DesktopGridEffect::desktopNameAlignment() const
|
||||
{
|
||||
return Qt::AlignmentFlag(DesktopGridConfig::desktopNameAlignment());
|
||||
}
|
||||
|
||||
DesktopGridEffect::DesktopLayoutMode DesktopGridEffect::desktopLayoutMode() const
|
||||
{
|
||||
return DesktopGridEffect::DesktopLayoutMode(DesktopGridConfig::desktopLayoutMode());
|
||||
}
|
||||
|
||||
int DesktopGridEffect::customLayoutRows() const
|
||||
{
|
||||
return DesktopGridConfig::customLayoutRows();
|
||||
}
|
||||
|
||||
void DesktopGridEffect::addDesktop() const
|
||||
{
|
||||
effects->setNumberOfDesktops(effects->numberOfDesktops() + 1);
|
||||
}
|
||||
|
||||
void DesktopGridEffect::removeDesktop() const
|
||||
{
|
||||
effects->setNumberOfDesktops(effects->numberOfDesktops() - 1);
|
||||
}
|
||||
|
||||
void DesktopGridEffect::swapDesktops(int from, int to)
|
||||
{
|
||||
QList<EffectWindow *> fromList;
|
||||
QList<EffectWindow *> toList;
|
||||
for (auto *w : effects->stackingOrder()) {
|
||||
if (!w->isNormalWindow() || !w->isOnCurrentActivity() ) {
|
||||
continue;
|
||||
}
|
||||
if (w->isOnDesktop(from)) {
|
||||
fromList << w;
|
||||
} else if (w->isOnDesktop(to)) {
|
||||
toList << w;
|
||||
}
|
||||
}
|
||||
for (auto *w : fromList) {
|
||||
effects->windowToDesktop(w, to);
|
||||
}
|
||||
for (auto *w : toList) {
|
||||
effects->windowToDesktop(w, from);
|
||||
}
|
||||
}
|
||||
|
||||
int DesktopGridEffect::gridRows() const
|
||||
{
|
||||
switch (desktopLayoutMode()) {
|
||||
case DesktopLayoutMode::LayoutAutomatic:
|
||||
return ceil(sqrt(effects->numberOfDesktops()));
|
||||
case DesktopLayoutMode::LayoutCustom:
|
||||
return std::clamp(customLayoutRows(), 1, effects->numberOfDesktops());
|
||||
case DesktopLayoutMode::LayoutPager:
|
||||
default:
|
||||
return effects->desktopGridSize().height();
|
||||
}
|
||||
}
|
||||
|
||||
int DesktopGridEffect::gridColumns() const
|
||||
{
|
||||
switch (desktopLayoutMode()) {
|
||||
case DesktopLayoutMode::LayoutAutomatic:
|
||||
return ceil(sqrt(effects->numberOfDesktops()));
|
||||
case DesktopLayoutMode::LayoutCustom:
|
||||
return std::max(1.0, ceil(qreal(effects->numberOfDesktops()) / customLayoutRows()));
|
||||
case DesktopLayoutMode::LayoutPager:
|
||||
default:
|
||||
return effects->desktopGridSize().width();
|
||||
}
|
||||
}
|
||||
|
||||
int DesktopGridEffect::animationDuration() const
|
||||
{
|
||||
return m_animationDuration;
|
||||
}
|
||||
|
||||
void DesktopGridEffect::setAnimationDuration(int duration)
|
||||
{
|
||||
if (m_animationDuration != duration) {
|
||||
m_animationDuration = duration;
|
||||
Q_EMIT animationDurationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool DesktopGridEffect::showAddRemove() const
|
||||
{
|
||||
return DesktopGridConfig::showAddRemove();
|
||||
}
|
||||
|
||||
int DesktopGridEffect::layout() const
|
||||
{
|
||||
return m_layout;
|
||||
}
|
||||
|
||||
void DesktopGridEffect::setLayout(int layout)
|
||||
{
|
||||
if (m_layout != layout) {
|
||||
m_layout = layout;
|
||||
Q_EMIT layoutChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool DesktopGridEffect::gestureInProgress() const
|
||||
{
|
||||
return m_state->inProgress();
|
||||
}
|
||||
|
||||
void DesktopGridEffect::activate()
|
||||
{
|
||||
if (effects->isScreenLocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_state->activate();
|
||||
}
|
||||
|
||||
void DesktopGridEffect::deactivate()
|
||||
{
|
||||
const auto screens = effects->screens();
|
||||
for (const auto screen : screens) {
|
||||
if (QuickSceneView *view = viewForScreen(screen)) {
|
||||
QMetaObject::invokeMethod(view->rootItem(), "stop");
|
||||
}
|
||||
}
|
||||
m_shutdownTimer->start(animationDuration());
|
||||
|
||||
m_state->deactivate();
|
||||
}
|
||||
|
||||
void DesktopGridEffect::realDeactivate()
|
||||
{
|
||||
m_state->setStatus(EffectTogglableState::Status::Inactive);
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
||||
#include "moc_desktopgrideffect.cpp"
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "libkwineffects/effecttogglablestate.h"
|
||||
#include "libkwineffects/kwinquickeffect.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class DesktopGridEffect : public QuickSceneEffect
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int gridRows READ gridRows NOTIFY gridRowsChanged)
|
||||
Q_PROPERTY(int gridColumns READ gridColumns NOTIFY gridColumnsChanged)
|
||||
Q_PROPERTY(int animationDuration READ animationDuration NOTIFY animationDurationChanged)
|
||||
Q_PROPERTY(int layout READ layout NOTIFY layoutChanged)
|
||||
Q_PROPERTY(qreal partialActivationFactor READ partialActivationFactor NOTIFY partialActivationFactorChanged)
|
||||
Q_PROPERTY(bool gestureInProgress READ gestureInProgress NOTIFY gestureInProgressChanged)
|
||||
Q_PROPERTY(bool showAddRemove READ showAddRemove NOTIFY showAddRemoveChanged)
|
||||
Q_PROPERTY(Qt::AlignmentFlag desktopNameAlignment READ desktopNameAlignment NOTIFY desktopNameAlignmentChanged)
|
||||
Q_PROPERTY(DesktopLayoutMode desktopLayoutMode READ desktopLayoutMode NOTIFY desktopLayoutModeChanged)
|
||||
Q_PROPERTY(int customLayoutRows READ customLayoutRows NOTIFY customLayoutRowsChanged)
|
||||
|
||||
public:
|
||||
enum class DesktopLayoutMode {
|
||||
LayoutPager,
|
||||
LayoutAutomatic,
|
||||
LayoutCustom
|
||||
};
|
||||
Q_ENUM(DesktopLayoutMode)
|
||||
|
||||
DesktopGridEffect();
|
||||
~DesktopGridEffect() override;
|
||||
|
||||
int layout() const;
|
||||
void setLayout(int layout);
|
||||
|
||||
int animationDuration() const;
|
||||
void setAnimationDuration(int duration);
|
||||
|
||||
bool showAddRemove() const;
|
||||
|
||||
qreal partialActivationFactor() const
|
||||
{
|
||||
return m_state->partialActivationFactor();
|
||||
}
|
||||
|
||||
bool gestureInProgress() const;
|
||||
|
||||
int gridRows() const;
|
||||
int gridColumns() const;
|
||||
|
||||
int requestedEffectChainPosition() const override;
|
||||
bool borderActivated(ElectricBorder border) override;
|
||||
void reconfigure(ReconfigureFlags flags) override;
|
||||
void grabbedKeyboardEvent(QKeyEvent *keyEvent) override;
|
||||
|
||||
Qt::AlignmentFlag desktopNameAlignment() const;
|
||||
DesktopLayoutMode desktopLayoutMode() const;
|
||||
int customLayoutRows() const;
|
||||
|
||||
Q_INVOKABLE void addDesktop() const;
|
||||
Q_INVOKABLE void removeDesktop() const;
|
||||
Q_INVOKABLE void swapDesktops(int from, int to);
|
||||
|
||||
public Q_SLOTS:
|
||||
void activate();
|
||||
void deactivate();
|
||||
|
||||
Q_SIGNALS:
|
||||
void gridRowsChanged();
|
||||
void gridColumnsChanged();
|
||||
void animationDurationChanged();
|
||||
void layoutChanged();
|
||||
void partialActivationFactorChanged();
|
||||
void gestureInProgressChanged();
|
||||
void showAddRemoveChanged();
|
||||
void desktopNameAlignmentChanged();
|
||||
void desktopLayoutModeChanged();
|
||||
void customLayoutRowsChanged();
|
||||
|
||||
private:
|
||||
void realDeactivate();
|
||||
|
||||
QTimer *m_shutdownTimer;
|
||||
QList<QKeySequence> m_toggleShortcut;
|
||||
QList<ElectricBorder> m_borderActivate;
|
||||
EffectTogglableState *const m_state;
|
||||
EffectTogglableTouchBorder *const m_border;
|
||||
int m_animationDuration = 400;
|
||||
int m_layout = 1;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
|
@ -1,18 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2022 Marco Martin <mart@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "desktopgrideffect.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
KWIN_EFFECT_FACTORY_SUPPORTED(DesktopGridEffect,
|
||||
"metadata.json.stripped",
|
||||
return DesktopGridEffect::supported();)
|
||||
|
||||
} // namespace KWin
|
||||
|
||||
#include "main.moc"
|
|
@ -1,92 +0,0 @@
|
|||
{
|
||||
"KPlugin": {
|
||||
"Category": "Window Management",
|
||||
"Description": "Zoom out so all desktops are displayed side-by-side in a grid",
|
||||
"Description[ar]": "بعّد لتُعرَض كلّ أسطح المكتب واحدة بجانب الأخرى في شبكة",
|
||||
"Description[az]": "Bütün İş Masaların bir ekranda yan yana göstərmək",
|
||||
"Description[be]": "Маштаб памяншаецца, і ўсе працоўныя сталы паказваюцца побач адзін з адным у сетцы",
|
||||
"Description[bg]": "Намаляване на мащаба, докато всички работни плотове се представят като плочки един до друг",
|
||||
"Description[ca@valencia]": "Reduïx tots els escriptoris per a visualitzar-los un al costat de l'altre en una quadrícula",
|
||||
"Description[ca]": "Redueix tots els escriptoris per a visualitzar-los un al costat de l'altre en una quadrícula",
|
||||
"Description[cs]": "Oddálí plochy a zobrazí je v mřížce",
|
||||
"Description[de]": "Verkleinert die Arbeitsflächen, sodass sie in einem Raster nebeneinander zu sehen sind",
|
||||
"Description[en_GB]": "Zoom out so all desktops are displayed side-by-side in a grid",
|
||||
"Description[eo]": "Malzomi por ke ĉiuj labortabloj estu montrataj flank-al-flanke en krado",
|
||||
"Description[es]": "Reduce la ampliación para que todos los escritorios se muestren uno al lado del otro en una cuadrícula",
|
||||
"Description[et]": "Vähendamine, et kõik töölauad oleksid üksteise kõrval võrgustikus näha",
|
||||
"Description[eu]": "Zooma urrundu mahaigain guztiak sareta batean bata bestearen ondoan ager daitezen",
|
||||
"Description[fi]": "Loitontaa työpöytiä niin, että ne näytetään rinnakkain ruudukkona",
|
||||
"Description[fr]": "Faire un zoom arrière de manière à afficher tous les bureaux côte à côte dans une grille",
|
||||
"Description[hu]": "Kinagyítja az asztalt oly módon, hogy a virtuális asztalok rácsban elrendezve jelennek meg",
|
||||
"Description[ia]": "Face zoom retro assi que omne scriptorios es monstrate flanco a flanco in un grillia",
|
||||
"Description[id]": "Zoom keluar sehingga semua desktop ditampilkan sisi demi sisi di dalam kisi",
|
||||
"Description[it]": "Arretra per mostrare tutti i desktop virtuali affiancati in una griglia",
|
||||
"Description[ja]": "ズームアウトしてすべてのデスクトップを並べて表示します",
|
||||
"Description[ka]": "დაპატარავება ისე, რომ ყველა სამუშაო მაგიდა გვერდიგვერდ, ბადეში იქნება ნაჩვენები",
|
||||
"Description[ko]": "모든 바탕 화면을 한 화면에 볼 수 있도록 격자형으로 축소합니다",
|
||||
"Description[nl]": "Verkleint alle bureaubladen zodat ze zij-aan-zij in een raster getoond kunnen worden",
|
||||
"Description[nn]": "Forminsk skjermflata slik at alle skriveborda vert viste side om side",
|
||||
"Description[pl]": "Pomniejsza do chwili, aż wszystkie pulpity będą widoczne obok siebie na siatce",
|
||||
"Description[pt]": "Reduz o ecrã de forma a mostrar todos os ecrãs lado-a-lado numa grelha",
|
||||
"Description[pt_BR]": "Reduz para que todas as áreas de trabalho sejam mostradas lado a lado em uma grade",
|
||||
"Description[ro]": "Îndepărtează astfel încât toate birourile sunt afișate alăturat într-o grilă",
|
||||
"Description[ru]": "Просмотр всех рабочих столов на одном экране",
|
||||
"Description[sk]": "Oddiali všetky plochy a zobrazí ich vedľa seba v mriežke",
|
||||
"Description[sl]": "Oddalji pogled tako, da so vsa namizja prikazana drugo ob drugem v mreži",
|
||||
"Description[sv]": "Zooma ut så att alla skrivbord visas sida vid sida i ett rutnät",
|
||||
"Description[ta]": "அனைத்து பணிமேடைகளை வரிசைகளிலும் நெடுவரிசைகளிலும் காட்டும்",
|
||||
"Description[tr]": "Uzaklaştır, böylece tüm masaüstleri bir ızgarada yan yana görüntülenirler",
|
||||
"Description[uk]": "Зменшення стільниць так, щоб всі стільниці було показано поруч у форматі таблиці",
|
||||
"Description[vi]": "Thu nhỏ để tất cả các bàn làm việc được hiển thị cạnh nhau trong một lưới",
|
||||
"Description[x-test]": "xxZoom out so all desktops are displayed side-by-side in a gridxx",
|
||||
"Description[zh_CN]": "所有虚拟桌面缩小后显示在一套网格中",
|
||||
"Description[zh_TW]": "縮小顯示讓所有桌面都同時顯示在格線內",
|
||||
"EnabledByDefault": true,
|
||||
"License": "GPL",
|
||||
"Name": "Desktop Grid",
|
||||
"Name[ar]": "شبكة سطح المكتب",
|
||||
"Name[az]": "İş masası toru",
|
||||
"Name[be]": "Сетка для працоўных сталоў",
|
||||
"Name[bg]": "Плочки",
|
||||
"Name[ca@valencia]": "Quadrícula de l'escriptori",
|
||||
"Name[ca]": "Quadrícula de l'escriptori",
|
||||
"Name[cs]": "Mřížka plochy",
|
||||
"Name[de]": "Arbeitsflächen-Umschalter (Raster)",
|
||||
"Name[en_GB]": "Desktop Grid",
|
||||
"Name[eo]": "Labortabla Krado",
|
||||
"Name[es]": "Rejilla del escritorio",
|
||||
"Name[et]": "Töölauavõrgustik",
|
||||
"Name[eu]": "Mahaigain sareta",
|
||||
"Name[fi]": "Työpöydän ruudukko",
|
||||
"Name[fr]": "Grille de bureaux",
|
||||
"Name[hu]": "Asztalrács",
|
||||
"Name[ia]": "Grillia de scriptorio",
|
||||
"Name[id]": "Kisi Desktop",
|
||||
"Name[it]": "Griglia dei Desktop",
|
||||
"Name[ja]": "デスクトップグリッド",
|
||||
"Name[ka]": "სამუშაო მაგიდის ბადე",
|
||||
"Name[ko]": "바탕 화면 격자",
|
||||
"Name[nl]": "Bureaubladraster",
|
||||
"Name[nn]": "Skrivebordsoversikt",
|
||||
"Name[pl]": "Siatka pulpitu",
|
||||
"Name[pt]": "Grelha de Ecrãs",
|
||||
"Name[pt_BR]": "Grade de áreas de trabalho",
|
||||
"Name[ro]": "Grilă de birou",
|
||||
"Name[ru]": "Все рабочие столы",
|
||||
"Name[sk]": "Plochy v mriežke",
|
||||
"Name[sl]": "Mreža namizja",
|
||||
"Name[sv]": "Skrivbordsrutnät",
|
||||
"Name[ta]": "பணிமேடை கிரிட்",
|
||||
"Name[tr]": "Masaüstü Izgarası",
|
||||
"Name[uk]": "Таблиця стільниць",
|
||||
"Name[vi]": "Lưới bàn làm việc",
|
||||
"Name[x-test]": "xxDesktop Gridxx",
|
||||
"Name[zh_CN]": "虚拟桌面平铺网格",
|
||||
"Name[zh_TW]": "桌面格線"
|
||||
},
|
||||
"X-KDE-ConfigModule": "kwin_desktopgrid_config",
|
||||
"X-KWin-Border-Activate": true,
|
||||
"org.kde.kwin.effect": {
|
||||
"video": "https://files.kde.org/plasma/kwin/effect-videos/desktop_grid.mp4"
|
||||
}
|
||||
}
|
|
@ -1,306 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
SPDX-FileCopyrightText: 2022 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2022 ivan tkachenko <me@ratijas.tk>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick
|
||||
import org.kde.kwin as KWinComponents
|
||||
import org.kde.kwin.private.effects
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
import org.kde.kwin.private.desktopgrid
|
||||
|
||||
FocusScope {
|
||||
id: desktopView
|
||||
|
||||
required property QtObject windowModel
|
||||
required property QtObject desktop
|
||||
required property var dndManagerStore
|
||||
readonly property bool dragActive: heap.dragActive || dragHandler.active || xAnim.running || yAnim.running
|
||||
property real panelOpacity: 1
|
||||
focus: true
|
||||
|
||||
function selectLastItem(direction) {
|
||||
heap.selectLastItem(direction);
|
||||
}
|
||||
|
||||
DropArea {
|
||||
anchors.fill: parent
|
||||
onEntered: {
|
||||
drag.accepted = true;
|
||||
}
|
||||
onDropped: drop => {
|
||||
drop.accepted = true;
|
||||
if (drag.source instanceof DesktopView) {
|
||||
// dragging a desktop as a whole
|
||||
if (drag.source === desktopView) {
|
||||
drop.action = Qt.IgnoreAction;
|
||||
return;
|
||||
}
|
||||
effect.swapDesktops(drag.source.desktop.x11DesktopNumber, desktop.x11DesktopNumber);
|
||||
} else {
|
||||
// dragging a KWin::Window
|
||||
if (drag.source.desktops.length === 0 || drag.source.desktops.indexOf(desktopView.desktop) !== -1) {
|
||||
drop.action = Qt.IgnoreAction;
|
||||
return;
|
||||
}
|
||||
drag.source.desktops = [desktopView.desktop];
|
||||
}
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: effect
|
||||
function onItemDroppedOutOfScreen(globalPos, item, screen) {
|
||||
if (screen !== targetScreen) {
|
||||
return;
|
||||
}
|
||||
const pos = screen.mapFromGlobal(globalPos);
|
||||
if (!desktopView.contains(desktopView.mapFromItem(null, pos.x, pos.y))) {
|
||||
return;
|
||||
}
|
||||
item.client.desktops = [desktopView.desktop];
|
||||
}
|
||||
}
|
||||
Repeater {
|
||||
model: KWinComponents.WindowFilterModel {
|
||||
activity: KWinComponents.Workspace.currentActivity
|
||||
desktop: desktopView.desktop
|
||||
screenName: targetScreen.name
|
||||
windowModel: desktopView.windowModel
|
||||
windowType: KWinComponents.WindowFilterModel.Dock | KWinComponents.WindowFilterModel.Desktop
|
||||
}
|
||||
|
||||
KWinComponents.WindowThumbnail {
|
||||
wId: model.window.internalId
|
||||
x: model.window.x - targetScreen.geometry.x
|
||||
y: model.window.y - targetScreen.geometry.y
|
||||
z: model.window.stackingOrder
|
||||
width: model.window.width
|
||||
height: model.window.height
|
||||
opacity: model.window.dock ? desktopView.panelOpacity : 1
|
||||
}
|
||||
}
|
||||
|
||||
DragHandler {
|
||||
id: dragHandler
|
||||
target: heap
|
||||
grabPermissions: PointerHandler.ApprovesTakeOverByHandlersOfSameType
|
||||
onActiveChanged: {
|
||||
if (!active) {
|
||||
heap.Drag.drop();
|
||||
Qt.callLater(heap.resetPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WindowHeap {
|
||||
id: heap
|
||||
function resetPosition() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
Drag.active: dragHandler.active
|
||||
Drag.proposedAction: Qt.MoveAction
|
||||
Drag.supportedActions: Qt.MoveAction
|
||||
Drag.source: desktopView
|
||||
Drag.hotSpot: Qt.point(width * 0.5, height * 0.5)
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
focus: true
|
||||
z: 9999
|
||||
animationDuration: container.effect.animationDuration
|
||||
absolutePositioning: false
|
||||
animationEnabled: container.animationEnabled
|
||||
organized: container.organized
|
||||
layout.mode: effect.layout
|
||||
dndManagerStore: desktopView.dndManagerStore
|
||||
model: KWinComponents.WindowFilterModel {
|
||||
activity: KWinComponents.Workspace.currentActivity
|
||||
desktop: desktopView.desktop
|
||||
screenName: targetScreen.name
|
||||
windowModel: desktopView.windowModel
|
||||
windowType: ~KWinComponents.WindowFilterModel.Dock &
|
||||
~KWinComponents.WindowFilterModel.Desktop &
|
||||
~KWinComponents.WindowFilterModel.Notification &
|
||||
~KWinComponents.WindowFilterModel.CriticalNotification
|
||||
}
|
||||
delegate: WindowHeapDelegate {
|
||||
windowHeap: heap
|
||||
closeButtonVisible: false
|
||||
windowTitleVisible: false
|
||||
|
||||
TapHandler {
|
||||
acceptedPointerTypes: PointerDevice.GenericPointer | PointerDevice.Pen
|
||||
acceptedButtons: Qt.MiddleButton | Qt.RightButton
|
||||
onTapped: (eventPoint, button) => {
|
||||
if (button === Qt.MiddleButton) {
|
||||
window.closeWindow();
|
||||
} else if (button === Qt.RightButton) {
|
||||
if (window.desktops.length > 0) {
|
||||
window.desktops = [];
|
||||
} else {
|
||||
window.desktops = [desktopView.desktop];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onActivated: effect.deactivate(effect.animationDuration);
|
||||
Behavior on x {
|
||||
enabled: !dragHandler.active
|
||||
NumberAnimation {
|
||||
id: xAnim
|
||||
duration: container.effect.animationDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
Behavior on y {
|
||||
enabled: !dragHandler.active
|
||||
NumberAnimation {
|
||||
id: yAnim
|
||||
duration: container.effect.animationDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: heap
|
||||
acceptedButtons: Qt.NoButton
|
||||
cursorShape: dragHandler.active ? Qt.ClosedHandCursor : Qt.ArrowCursor
|
||||
}
|
||||
|
||||
PC3.Control {
|
||||
id: desktopLabel
|
||||
anchors.margins: Kirigami.Units.gridUnit
|
||||
z: 9999
|
||||
visible: effect.desktopNameAlignment !== 0
|
||||
|
||||
states: [
|
||||
State {
|
||||
when: container.effect.desktopNameAlignment === (Qt.AlignTop | Qt.AlignLeft)
|
||||
AnchorChanges {
|
||||
target: desktopLabel
|
||||
anchors.left: desktopView.left
|
||||
anchors.top: desktopView.top
|
||||
}
|
||||
PropertyChanges {
|
||||
target: desktopLabel
|
||||
transformOrigin: Item.TopLeft
|
||||
}
|
||||
},
|
||||
State {
|
||||
when: container.effect.desktopNameAlignment === (Qt.AlignTop | Qt.AlignHCenter)
|
||||
AnchorChanges {
|
||||
target: desktopLabel
|
||||
anchors.top: desktopView.top
|
||||
anchors.horizontalCenter: desktopView.horizontalCenter
|
||||
}
|
||||
PropertyChanges {
|
||||
target: desktopLabel
|
||||
transformOrigin: Item.Top
|
||||
}
|
||||
},
|
||||
State {
|
||||
when: container.effect.desktopNameAlignment === (Qt.AlignTop | Qt.AlignRight)
|
||||
AnchorChanges {
|
||||
target: desktopLabel
|
||||
anchors.top: desktopView.top
|
||||
anchors.right: desktopView.right
|
||||
}
|
||||
PropertyChanges {
|
||||
target: desktopLabel
|
||||
transformOrigin: Item.TopRight
|
||||
}
|
||||
},
|
||||
State {
|
||||
when: container.effect.desktopNameAlignment === (Qt.AlignVCenter | Qt.AlignLeft)
|
||||
AnchorChanges {
|
||||
target: desktopLabel
|
||||
anchors.left: desktopView.left
|
||||
anchors.verticalCenter: desktopView.verticalCenter
|
||||
}
|
||||
PropertyChanges {
|
||||
target: desktopLabel
|
||||
transformOrigin: Item.Left
|
||||
}
|
||||
},
|
||||
State {
|
||||
when: container.effect.desktopNameAlignment === Qt.AlignCenter
|
||||
AnchorChanges {
|
||||
target: desktopLabel
|
||||
anchors.horizontalCenter: desktopView.horizontalCenter
|
||||
anchors.verticalCenter: desktopView.verticalCenter
|
||||
}
|
||||
PropertyChanges {
|
||||
target: desktopLabel
|
||||
transformOrigin: Item.Center
|
||||
}
|
||||
},
|
||||
State {
|
||||
when: container.effect.desktopNameAlignment === (Qt.AlignVCenter | Qt.AlignRight)
|
||||
AnchorChanges {
|
||||
target: desktopLabel
|
||||
anchors.verticalCenter: desktopView.verticalCenter
|
||||
anchors.right: desktopView.right
|
||||
}
|
||||
PropertyChanges {
|
||||
target: desktopLabel
|
||||
transformOrigin: Item.Right
|
||||
}
|
||||
},
|
||||
State {
|
||||
when: container.effect.desktopNameAlignment === (Qt.AlignBottom | Qt.AlignLeft)
|
||||
AnchorChanges {
|
||||
target: desktopLabel
|
||||
anchors.left: desktopView.left
|
||||
anchors.bottom: desktopView.bottom
|
||||
}
|
||||
PropertyChanges {
|
||||
target: desktopLabel
|
||||
transformOrigin: Item.BottomLeft
|
||||
}
|
||||
},
|
||||
State {
|
||||
when: container.effect.desktopNameAlignment === (Qt.AlignBottom | Qt.AlignHCenter)
|
||||
AnchorChanges {
|
||||
target: desktopLabel
|
||||
anchors.bottom: desktopView.bottom
|
||||
anchors.horizontalCenter: desktopView.horizontalCenter
|
||||
}
|
||||
PropertyChanges {
|
||||
target: desktopLabel
|
||||
transformOrigin: Item.Bottom
|
||||
}
|
||||
},
|
||||
State {
|
||||
when: container.effect.desktopNameAlignment === (Qt.AlignBottom | Qt.AlignRight)
|
||||
AnchorChanges {
|
||||
target: desktopLabel
|
||||
anchors.bottom: desktopView.bottom
|
||||
anchors.right: desktopView.right
|
||||
}
|
||||
PropertyChanges {
|
||||
target: desktopLabel
|
||||
transformOrigin: Item.BottomRight
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
scale: 1 / desktopView.parent.scale
|
||||
leftPadding: Kirigami.Units.smallSpacing
|
||||
rightPadding: Kirigami.Units.smallSpacing
|
||||
contentItem: PC3.Label {
|
||||
text: desktopView.desktop.name
|
||||
textFormat: Text.PlainText
|
||||
}
|
||||
background: Rectangle {
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
radius: height
|
||||
opacity: 0.6
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,328 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
SPDX-FileCopyrightText: 2022 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2022 ivan tkachenko <me@ratijas.tk>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Window
|
||||
import org.kde.kwin as KWinComponents
|
||||
import org.kde.kwin.private.effects
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
|
||||
Rectangle {
|
||||
id: container
|
||||
|
||||
readonly property QtObject effect: KWinComponents.SceneView.effect
|
||||
readonly property QtObject targetScreen: KWinComponents.SceneView.screen
|
||||
|
||||
property bool animationEnabled: false
|
||||
property bool organized: false
|
||||
|
||||
/** Shared Drag&Drop store to keep track of DND state across desktops. */
|
||||
property var dndManagerStore: ({})
|
||||
|
||||
color: "black"
|
||||
|
||||
function start() {
|
||||
animationEnabled = true;
|
||||
organized = true;
|
||||
}
|
||||
|
||||
function stop() {
|
||||
organized = false;
|
||||
}
|
||||
|
||||
function switchTo(desktop) {
|
||||
KWinComponents.Workspace.currentDesktop = desktop;
|
||||
effect.deactivate();
|
||||
}
|
||||
|
||||
function selectNext(direction) {
|
||||
let currentIndex = 0
|
||||
for (let i = 0; i < gridRepeater.count; i++) {
|
||||
if (gridRepeater.itemAt(i).focus) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let x = currentIndex % grid.columns;
|
||||
let y = Math.floor(currentIndex / grid.columns);
|
||||
|
||||
// the direction we move in is the opposite of the window to select
|
||||
// i.e pressing left should select the rightmost window on the desktop
|
||||
// to the left
|
||||
let invertedDirection;
|
||||
switch(direction) {
|
||||
case WindowHeap.Direction.Up:
|
||||
y--;
|
||||
invertedDirection = WindowHeap.Direction.Down;
|
||||
break;
|
||||
case WindowHeap.Direction.Down:
|
||||
y++
|
||||
invertedDirection = WindowHeap.Direction.Up;
|
||||
break;
|
||||
case WindowHeap.Direction.Left:
|
||||
x--;
|
||||
invertedDirection = WindowHeap.Direction.Right;
|
||||
break;
|
||||
case WindowHeap.Direction.Right:
|
||||
x++;
|
||||
invertedDirection = WindowHeap.Direction.Left;
|
||||
break;
|
||||
}
|
||||
|
||||
if (x < 0 || x >= grid.columns) {
|
||||
return false;
|
||||
}
|
||||
if (y < 0 || y >= grid.rows) {
|
||||
return false;
|
||||
}
|
||||
let newIndex = y * grid.columns + x;
|
||||
|
||||
gridRepeater.itemAt(newIndex).focus = true;
|
||||
gridRepeater.itemAt(newIndex).selectLastItem(invertedDirection);
|
||||
return true;
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
effect.deactivate();
|
||||
} else if (event.key === Qt.Key_Plus || event.key === Qt.Key_Equal) {
|
||||
addButton.clicked();
|
||||
} else if (event.key === Qt.Key_Minus) {
|
||||
removeButton.clicked();
|
||||
} else if (event.key >= Qt.Key_F1 && event.key <= Qt.Key_F12) {
|
||||
const desktopId = event.key - Qt.Key_F1;
|
||||
if (desktopId < gridRepeater.count) {
|
||||
switchTo(gridRepeater.itemAt(desktopId).desktop);
|
||||
}
|
||||
} else if (event.key >= Qt.Key_0 && event.key <= Qt.Key_9) {
|
||||
const desktopId = event.key === Qt.Key_0 ? 9 : (event.key - Qt.Key_1);
|
||||
if (desktopId < gridRepeater.count) {
|
||||
switchTo(gridRepeater.itemAt(desktopId).desktop);
|
||||
}
|
||||
} else if (event.key === Qt.Key_Up) {
|
||||
event.accepted = selectNext(WindowHeap.Direction.Up);
|
||||
if (!event.accepted) {
|
||||
let view = effect.getView(Qt.TopEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
}
|
||||
}
|
||||
} else if (event.key === Qt.Key_Down) {
|
||||
event.accepted = selectNext(WindowHeap.Direction.Down);
|
||||
if (!event.accepted) {
|
||||
let view = effect.getView(Qt.BottomEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
}
|
||||
}
|
||||
} else if (event.key === Qt.Key_Left) {
|
||||
event.accepted = selectNext(WindowHeap.Direction.Left);
|
||||
if (!event.accepted) {
|
||||
let view = effect.getView(Qt.LeftEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
}
|
||||
}
|
||||
} else if (event.key === Qt.Key_Right) {
|
||||
event.accepted = selectNext(WindowHeap.Direction.Right);
|
||||
if (!event.accepted) {
|
||||
let view = effect.getView(Qt.RightEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
}
|
||||
}
|
||||
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Space) {
|
||||
for (let i = 0; i < gridRepeater.count; i++) {
|
||||
if (gridRepeater.itemAt(i).focus) {
|
||||
switchTo(gridRepeater.itemAt(i).desktop)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Keys.priority: Keys.AfterItem
|
||||
|
||||
KWinComponents.VirtualDesktopModel {
|
||||
id: desktopModel
|
||||
}
|
||||
KWinComponents.WindowModel {
|
||||
id: stackModel
|
||||
}
|
||||
|
||||
// A grid, not a gridlayout as a gridlayout positions its elements too late
|
||||
Grid {
|
||||
id: grid
|
||||
|
||||
property Item currentItem
|
||||
readonly property real targetScale: Math.min(parent.width / width, parent.height / height)
|
||||
property real panelOpacity: 1
|
||||
|
||||
Behavior on x {
|
||||
enabled: !container.effect.gestureInProgress
|
||||
NumberAnimation {
|
||||
duration: container.effect.animationDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
Behavior on y {
|
||||
enabled: !container.effect.gestureInProgress
|
||||
NumberAnimation {
|
||||
duration: container.effect.animationDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
Behavior on scale {
|
||||
enabled: !container.effect.gestureInProgress
|
||||
NumberAnimation {
|
||||
duration: container.effect.animationDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
Behavior on panelOpacity {
|
||||
enabled: !container.effect.gestureInProgress
|
||||
NumberAnimation {
|
||||
duration: container.effect.animationDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
width: (parent.width + columnSpacing) * columns - columnSpacing
|
||||
height: (parent.height + rowSpacing) * rows - rowSpacing
|
||||
rowSpacing: Kirigami.Units.gridUnit
|
||||
columnSpacing: Kirigami.Units.gridUnit
|
||||
rows: container.effect.gridRows
|
||||
columns: container.effect.gridColumns
|
||||
transformOrigin: Item.TopLeft
|
||||
|
||||
states: [
|
||||
State {
|
||||
when: container.effect.gestureInProgress
|
||||
PropertyChanges {
|
||||
target: grid
|
||||
x: Math.max(0, container.width / 2 - (grid.width * grid.targetScale) / 2) * container.effect.partialActivationFactor - grid.currentItem.x * (1 - container.effect.partialActivationFactor)
|
||||
y: Math.max(0, container.height / 2 - (grid.height * grid.targetScale) / 2) * container.effect.partialActivationFactor - grid.currentItem.y * (1 - container.effect.partialActivationFactor)
|
||||
scale: 1 - (1 - grid.targetScale) * container.effect.partialActivationFactor
|
||||
panelOpacity: 1 - container.effect.partialActivationFactor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: buttonsLayout
|
||||
opacity: container.effect.partialActivationFactor
|
||||
}
|
||||
},
|
||||
State {
|
||||
when: container.organized
|
||||
PropertyChanges {
|
||||
target: grid
|
||||
x: Math.max(0, container.width / 2 - (grid.width * grid.targetScale) / 2)
|
||||
y: Math.max(0, container.height / 2 - (grid.height * grid.targetScale) / 2)
|
||||
scale: grid.targetScale
|
||||
panelOpacity: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: buttonsLayout
|
||||
opacity: 1
|
||||
}
|
||||
},
|
||||
State {
|
||||
when: !container.organized
|
||||
PropertyChanges {
|
||||
target: grid
|
||||
x: -grid.currentItem.x
|
||||
y: -grid.currentItem.y
|
||||
scale: 1
|
||||
panelOpacity: 1
|
||||
}
|
||||
PropertyChanges {
|
||||
target: buttonsLayout
|
||||
opacity: 0
|
||||
}
|
||||
}
|
||||
]
|
||||
Repeater {
|
||||
id: gridRepeater
|
||||
model: desktopModel
|
||||
DesktopView {
|
||||
id: thumbnail
|
||||
|
||||
panelOpacity: grid.panelOpacity
|
||||
readonly property bool current: KWinComponents.Workspace.currentDesktop === desktop
|
||||
z: dragActive ? 1 : 0
|
||||
onCurrentChanged: {
|
||||
if (current) {
|
||||
grid.currentItem = thumbnail;
|
||||
}
|
||||
}
|
||||
Component.onCompleted: {
|
||||
if (current) {
|
||||
grid.currentItem = thumbnail;
|
||||
}
|
||||
}
|
||||
width: container.width
|
||||
height: container.height
|
||||
|
||||
windowModel: stackModel
|
||||
dndManagerStore: container.dndManagerStore
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
border {
|
||||
color: Kirigami.Theme.highlightColor
|
||||
width: 1 / grid.scale
|
||||
}
|
||||
visible: parent.activeFocus
|
||||
}
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onTapped: {
|
||||
KWinComponents.Workspace.currentDesktop = thumbnail.desktop;
|
||||
container.effect.deactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: buttonsLayout
|
||||
anchors {
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
margins: Kirigami.Units.smallSpacing
|
||||
}
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
visible: container.effect.showAddRemove
|
||||
PC3.Button {
|
||||
id: addButton
|
||||
icon.name: "list-add"
|
||||
onClicked: container.effect.addDesktop()
|
||||
}
|
||||
PC3.Button {
|
||||
id: removeButton
|
||||
icon.name: "list-remove"
|
||||
onClicked: container.effect.removeDesktop()
|
||||
}
|
||||
Behavior on opacity {
|
||||
enabled: !container.effect.gestureInProgress
|
||||
NumberAnimation {
|
||||
duration: container.effect.animationDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onTapped: {
|
||||
container.effect.deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: start()
|
||||
}
|
|
@ -36,12 +36,33 @@ OverviewEffectConfig::OverviewEffectConfig(QObject *parent, const KPluginMetaDat
|
|||
actionCollection->setConfigGroup(QStringLiteral("Overview"));
|
||||
actionCollection->setConfigGlobal(true);
|
||||
|
||||
const QKeySequence defaultToggleShortcut = Qt::META | Qt::Key_W;
|
||||
QAction *toggleAction = actionCollection->addAction(QStringLiteral("Overview"));
|
||||
toggleAction->setText(i18n("Toggle Overview"));
|
||||
toggleAction->setProperty("isConfigurationAction", true);
|
||||
KGlobalAccel::self()->setDefaultShortcut(toggleAction, {defaultToggleShortcut});
|
||||
KGlobalAccel::self()->setShortcut(toggleAction, {defaultToggleShortcut});
|
||||
const QKeySequence defaultCycleShortcut = Qt::META | Qt::Key_Tab;
|
||||
QAction *cycleAction = actionCollection->addAction(QStringLiteral("Cycle Overview"));
|
||||
cycleAction->setText(i18nc("@action Overview and Grid View are the name of KWin effects", "Cycle through Overview and Grid View"));
|
||||
cycleAction->setProperty("isConfigurationAction", true);
|
||||
KGlobalAccel::self()->setDefaultShortcut(cycleAction, {defaultCycleShortcut});
|
||||
KGlobalAccel::self()->setShortcut(cycleAction, {defaultCycleShortcut});
|
||||
|
||||
const QKeySequence defaultUncycleShortcut = Qt::META | Qt::SHIFT | Qt::Key_Tab;
|
||||
QAction *reverseCycleAction = actionCollection->addAction(QStringLiteral("Cycle Overview Opposite"));
|
||||
reverseCycleAction->setText(i18nc("@action Grid View and Overview are the name of KWin effects", "Cycle through Grid View and Overview"));
|
||||
reverseCycleAction->setProperty("isConfigurationAction", true);
|
||||
KGlobalAccel::self()->setDefaultShortcut(reverseCycleAction, {defaultUncycleShortcut});
|
||||
KGlobalAccel::self()->setShortcut(reverseCycleAction, {defaultUncycleShortcut});
|
||||
|
||||
const QKeySequence defaultOverviewShortcut = Qt::META | Qt::Key_W;
|
||||
QAction *overviewAction = actionCollection->addAction(QStringLiteral("Overview"));
|
||||
overviewAction->setText(i18nc("@action Overview is the name of a KWin effect", "Toggle Overview"));
|
||||
overviewAction->setProperty("isConfigurationAction", true);
|
||||
KGlobalAccel::self()->setDefaultShortcut(overviewAction, {defaultOverviewShortcut});
|
||||
KGlobalAccel::self()->setShortcut(overviewAction, {defaultOverviewShortcut});
|
||||
|
||||
const QKeySequence defaultGridShortcut = Qt::META | Qt::Key_G;
|
||||
QAction *gridAction = actionCollection->addAction(QStringLiteral("Grid View"));
|
||||
gridAction->setText(i18nc("@action Grid View is the name of a KWin effect", "Toggle Grid View"));
|
||||
gridAction->setProperty("isConfigurationAction", true);
|
||||
KGlobalAccel::self()->setDefaultShortcut(gridAction, {defaultGridShortcut});
|
||||
KGlobalAccel::self()->setShortcut(gridAction, {defaultGridShortcut});
|
||||
|
||||
ui.shortcutsEditor->addCollection(actionCollection);
|
||||
connect(ui.shortcutsEditor, &KShortcutsEditor::keyChange, this, &KCModule::markAsChanged);
|
||||
|
|
|
@ -51,7 +51,21 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Organize windows in the Grid View:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="kcfg_OrganizedGrid">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="KShortcutsEditor" name="shortcutsEditor">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
<entry name="IgnoreMinimized" type="bool">
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="OrganizedGrid" type="bool">
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="BorderActivate" type="IntList" />
|
||||
<entry name="TouchBorderActivate" type="IntList" />
|
||||
|
|
|
@ -19,35 +19,137 @@ namespace KWin
|
|||
{
|
||||
|
||||
OverviewEffect::OverviewEffect()
|
||||
: m_state(new EffectTogglableState(this))
|
||||
, m_border(new EffectTogglableTouchBorder(m_state))
|
||||
// manages the transition between inactive -> overview
|
||||
: m_overviewState(new EffectTogglableState(this))
|
||||
// manages the transition between overview -> grid
|
||||
, m_transitionState(new EffectTogglableState(this))
|
||||
// manages the transition betwee inactive -> overview
|
||||
, m_gridState(new EffectTogglableState(this))
|
||||
, m_border(new EffectTogglableTouchBorder(m_overviewState))
|
||||
, m_shutdownTimer(new QTimer(this))
|
||||
{
|
||||
auto gesture = new EffectTogglableGesture(m_state);
|
||||
gesture->addTouchpadPinchGesture(PinchDirection::Contracting, 4);
|
||||
auto gesture = new EffectTogglableGesture(m_overviewState);
|
||||
gesture->addTouchpadSwipeGesture(SwipeDirection::Up, 4);
|
||||
gesture->addTouchscreenSwipeGesture(SwipeDirection::Up, 3);
|
||||
|
||||
connect(m_state, &EffectTogglableState::activated, this, &OverviewEffect::activate);
|
||||
connect(m_state, &EffectTogglableState::deactivated, this, &OverviewEffect::deactivate);
|
||||
connect(m_state, &EffectTogglableState::inProgressChanged, this, &OverviewEffect::gestureInProgressChanged);
|
||||
connect(m_state, &EffectTogglableState::partialActivationFactorChanged, this, &OverviewEffect::partialActivationFactorChanged);
|
||||
connect(m_state, &EffectTogglableState::statusChanged, this, [this](EffectTogglableState::Status status) {
|
||||
auto transitionGesture = new EffectTogglableGesture(m_transitionState);
|
||||
transitionGesture->addTouchpadSwipeGesture(SwipeDirection::Up, 4);
|
||||
transitionGesture->addTouchscreenSwipeGesture(SwipeDirection::Up, 3);
|
||||
m_transitionState->stop();
|
||||
|
||||
auto gridGesture = new EffectTogglableGesture(m_gridState);
|
||||
gridGesture->addTouchpadSwipeGesture(SwipeDirection::Down, 4);
|
||||
gridGesture->addTouchscreenSwipeGesture(SwipeDirection::Down, 3);
|
||||
|
||||
connect(m_overviewState, &EffectTogglableState::inProgressChanged, this, &OverviewEffect::overviewGestureInProgressChanged);
|
||||
connect(m_overviewState, &EffectTogglableState::partialActivationFactorChanged, this, &OverviewEffect::overviewPartialActivationFactorChanged);
|
||||
|
||||
connect(m_overviewState, &EffectTogglableState::statusChanged, this, [this](EffectTogglableState::Status status) {
|
||||
if (status == EffectTogglableState::Status::Activating || status == EffectTogglableState::Status::Active) {
|
||||
m_searchText = QString();
|
||||
setRunning(true);
|
||||
m_gridState->stop();
|
||||
}
|
||||
setRunning(status != EffectTogglableState::Status::Inactive);
|
||||
if (status == EffectTogglableState::Status::Active) {
|
||||
m_transitionState->deactivate();
|
||||
}
|
||||
if (status == EffectTogglableState::Status::Inactive || status == EffectTogglableState::Status::Deactivating) {
|
||||
m_transitionState->stop();
|
||||
}
|
||||
if (status == EffectTogglableState::Status::Inactive) {
|
||||
m_gridState->deactivate();
|
||||
deactivate();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_transitionState, &EffectTogglableState::statusChanged, this, [this](EffectTogglableState::Status status) {
|
||||
if (status == EffectTogglableState::Status::Activating || status == EffectTogglableState::Status::Active) {
|
||||
m_overviewState->stop();
|
||||
}
|
||||
if (status == EffectTogglableState::Status::Inactive) {
|
||||
m_overviewState->activate();
|
||||
}
|
||||
if (status == EffectTogglableState::Status::Active) {
|
||||
m_gridState->activate();
|
||||
}
|
||||
if (status == EffectTogglableState::Status::Inactive || status == EffectTogglableState::Status::Deactivating) {
|
||||
m_gridState->stop();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_gridState, &EffectTogglableState::statusChanged, this, [this](EffectTogglableState::Status status) {
|
||||
if (status == EffectTogglableState::Status::Activating || status == EffectTogglableState::Status::Active) {
|
||||
m_searchText = QString();
|
||||
setRunning(true);
|
||||
m_overviewState->stop();
|
||||
}
|
||||
if (status == EffectTogglableState::Status::Inactive) {
|
||||
m_overviewState->deactivate();
|
||||
deactivate();
|
||||
}
|
||||
if (status == EffectTogglableState::Status::Active) {
|
||||
m_transitionState->activate();
|
||||
}
|
||||
if (status == EffectTogglableState::Status::Inactive || status == EffectTogglableState::Status::Deactivating) {
|
||||
m_transitionState->stop();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_transitionState, &EffectTogglableState::inProgressChanged, this, &OverviewEffect::transitionGestureInProgressChanged);
|
||||
connect(m_transitionState, &EffectTogglableState::partialActivationFactorChanged, this, &OverviewEffect::transitionPartialActivationFactorChanged);
|
||||
|
||||
connect(m_gridState, &EffectTogglableState::inProgressChanged, this, &OverviewEffect::gridGestureInProgressChanged);
|
||||
connect(m_gridState, &EffectTogglableState::partialActivationFactorChanged, this, &OverviewEffect::gridPartialActivationFactorChanged);
|
||||
|
||||
connect(effects, &EffectsHandler::desktopChanging, this, [this](uint old, QPointF desktopOffset, EffectWindow *with) {
|
||||
m_desktopOffset = desktopOffset;
|
||||
Q_EMIT desktopOffsetChanged();
|
||||
});
|
||||
connect(effects, &EffectsHandler::desktopChanged, this, [this](int old, int current, EffectWindow *with) {
|
||||
m_desktopOffset = QPointF(0, 0);
|
||||
Q_EMIT desktopOffsetChanged();
|
||||
});
|
||||
connect(effects, &EffectsHandler::desktopChangingCancelled, this, [this]() {
|
||||
m_desktopOffset = QPointF(0, 0);
|
||||
Q_EMIT desktopOffsetChanged();
|
||||
});
|
||||
|
||||
m_shutdownTimer->setSingleShot(true);
|
||||
connect(m_shutdownTimer, &QTimer::timeout, this, &OverviewEffect::realDeactivate);
|
||||
|
||||
const QKeySequence defaultToggleShortcut = Qt::META | Qt::Key_W;
|
||||
auto toggleAction = m_state->toggleAction();
|
||||
toggleAction->setObjectName(QStringLiteral("Overview"));
|
||||
toggleAction->setText(i18n("Toggle Overview"));
|
||||
KGlobalAccel::self()->setDefaultShortcut(toggleAction, {defaultToggleShortcut});
|
||||
KGlobalAccel::self()->setShortcut(toggleAction, {defaultToggleShortcut});
|
||||
m_toggleShortcut = KGlobalAccel::self()->shortcut(toggleAction);
|
||||
const QKeySequence defaultCycleShortcut = Qt::META | Qt::Key_Tab;
|
||||
auto cycleAction = new QAction(this);
|
||||
connect(cycleAction, &QAction::triggered, this, &OverviewEffect::cycle);
|
||||
cycleAction->setObjectName(QStringLiteral("Cycle Overview"));
|
||||
cycleAction->setText(i18nc("@action Grid View and Overview are the name of KWin effects", "Cycle through Overview and Grid View"));
|
||||
KGlobalAccel::self()->setDefaultShortcut(cycleAction, {defaultCycleShortcut});
|
||||
KGlobalAccel::self()->setShortcut(cycleAction, {defaultCycleShortcut});
|
||||
m_cycleShortcut = KGlobalAccel::self()->shortcut(cycleAction);
|
||||
|
||||
const QKeySequence defaultUncycleShortcut = Qt::META | Qt::SHIFT | Qt::Key_Tab;
|
||||
auto reverseCycleAction = new QAction(this);
|
||||
connect(reverseCycleAction, &QAction::triggered, this, &OverviewEffect::reverseCycle);
|
||||
reverseCycleAction->setObjectName(QStringLiteral("Cycle Overview Opposite"));
|
||||
reverseCycleAction->setText(i18nc("@action Grid View and Overview are the name of KWin effects", "Cycle through Grid View and Overview"));
|
||||
KGlobalAccel::self()->setDefaultShortcut(reverseCycleAction, {defaultUncycleShortcut});
|
||||
KGlobalAccel::self()->setShortcut(reverseCycleAction, {defaultUncycleShortcut});
|
||||
m_reverseCycleShortcut = KGlobalAccel::self()->shortcut(reverseCycleAction);
|
||||
|
||||
const QKeySequence defaultOverviewShortcut = Qt::META | Qt::Key_W;
|
||||
auto overviewAction = m_overviewState->toggleAction();
|
||||
overviewAction->setObjectName(QStringLiteral("Overview"));
|
||||
overviewAction->setText(i18nc("@action Overview is the name of a Kwin effect", "Toggle Overview"));
|
||||
KGlobalAccel::self()->setDefaultShortcut(overviewAction, {defaultOverviewShortcut});
|
||||
KGlobalAccel::self()->setShortcut(overviewAction, {defaultOverviewShortcut});
|
||||
m_overviewShortcut = KGlobalAccel::self()->shortcut(overviewAction);
|
||||
|
||||
const QKeySequence defaultGridShortcut = Qt::META | Qt::Key_G;
|
||||
auto gridAction = m_gridState->toggleAction();
|
||||
gridAction->setObjectName(QStringLiteral("Grid View"));
|
||||
gridAction->setText(i18nc("@action Grid view is the name of a Kwin effect", "Toggle Grid View"));
|
||||
KGlobalAccel::self()->setDefaultShortcut(gridAction, {defaultGridShortcut});
|
||||
KGlobalAccel::self()->setShortcut(gridAction, {defaultGridShortcut});
|
||||
m_overviewShortcut = KGlobalAccel::self()->shortcut(gridAction);
|
||||
|
||||
connect(effects, &EffectsHandler::screenAboutToLock, this, &OverviewEffect::realDeactivate);
|
||||
|
||||
|
@ -95,6 +197,41 @@ void OverviewEffect::setAnimationDuration(int duration)
|
|||
}
|
||||
}
|
||||
|
||||
qreal OverviewEffect::overviewPartialActivationFactor() const
|
||||
{
|
||||
return m_overviewState->partialActivationFactor();
|
||||
}
|
||||
|
||||
bool OverviewEffect::overviewGestureInProgress() const
|
||||
{
|
||||
return m_overviewState->inProgress();
|
||||
}
|
||||
|
||||
qreal OverviewEffect::transitionPartialActivationFactor() const
|
||||
{
|
||||
return m_transitionState->partialActivationFactor();
|
||||
}
|
||||
|
||||
bool OverviewEffect::transitionGestureInProgress() const
|
||||
{
|
||||
return m_transitionState->inProgress();
|
||||
}
|
||||
|
||||
qreal OverviewEffect::gridPartialActivationFactor() const
|
||||
{
|
||||
return m_gridState->partialActivationFactor();
|
||||
}
|
||||
|
||||
bool OverviewEffect::gridGestureInProgress() const
|
||||
{
|
||||
return m_gridState->inProgress();
|
||||
}
|
||||
|
||||
QPointF OverviewEffect::desktopOffset() const
|
||||
{
|
||||
return m_desktopOffset;
|
||||
}
|
||||
|
||||
int OverviewEffect::layout() const
|
||||
{
|
||||
return m_layout;
|
||||
|
@ -105,6 +242,11 @@ bool OverviewEffect::ignoreMinimized() const
|
|||
return OverviewConfig::ignoreMinimized();
|
||||
}
|
||||
|
||||
bool OverviewEffect::organizedGrid() const
|
||||
{
|
||||
return OverviewConfig::organizedGrid();
|
||||
}
|
||||
|
||||
void OverviewEffect::setLayout(int layout)
|
||||
{
|
||||
if (m_layout != layout) {
|
||||
|
@ -121,7 +263,7 @@ int OverviewEffect::requestedEffectChainPosition() const
|
|||
bool OverviewEffect::borderActivated(ElectricBorder border)
|
||||
{
|
||||
if (m_borderActivate.contains(border)) {
|
||||
m_state->toggle();
|
||||
cycle();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -133,7 +275,7 @@ void OverviewEffect::activate()
|
|||
return;
|
||||
}
|
||||
|
||||
m_state->activate();
|
||||
m_overviewState->activate();
|
||||
}
|
||||
|
||||
void OverviewEffect::deactivate()
|
||||
|
@ -145,26 +287,89 @@ void OverviewEffect::deactivate()
|
|||
}
|
||||
}
|
||||
m_shutdownTimer->start(animationDuration());
|
||||
|
||||
m_state->deactivate();
|
||||
m_overviewState->deactivate();
|
||||
}
|
||||
|
||||
void OverviewEffect::realDeactivate()
|
||||
{
|
||||
m_state->setStatus(EffectTogglableState::Status::Inactive);
|
||||
if (m_overviewState->status() == EffectTogglableState::Status::Inactive) {
|
||||
setRunning(false);
|
||||
}
|
||||
}
|
||||
|
||||
void OverviewEffect::cycle()
|
||||
{
|
||||
if (m_overviewState->status() == EffectTogglableState::Status::Inactive) {
|
||||
m_overviewState->activate();
|
||||
} else if (m_transitionState->status() == EffectTogglableState::Status::Inactive) {
|
||||
m_transitionState->activate();
|
||||
} else if (m_gridState->status() == EffectTogglableState::Status::Active) {
|
||||
m_overviewState->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void OverviewEffect::reverseCycle()
|
||||
{
|
||||
if (m_overviewState->status() == EffectTogglableState::Status::Active) {
|
||||
m_overviewState->deactivate();
|
||||
} else if (m_transitionState->status() == EffectTogglableState::Status::Active) {
|
||||
m_transitionState->deactivate();
|
||||
} else if (m_gridState->status() == EffectTogglableState::Status::Inactive) {
|
||||
m_gridState->activate();
|
||||
}
|
||||
}
|
||||
|
||||
void OverviewEffect::grabbedKeyboardEvent(QKeyEvent *keyEvent)
|
||||
{
|
||||
if (m_toggleShortcut.contains(keyEvent->key() | keyEvent->modifiers())) {
|
||||
if (m_cycleShortcut.contains(keyEvent->key() | keyEvent->modifiers())) {
|
||||
if (keyEvent->type() == QEvent::KeyPress) {
|
||||
m_state->toggle();
|
||||
cycle();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (m_reverseCycleShortcut.contains(keyEvent->key() | keyEvent->modifiers())) {
|
||||
if (keyEvent->type() == QEvent::KeyPress) {
|
||||
reverseCycle();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (m_overviewShortcut.contains(keyEvent->key() | keyEvent->modifiers())) {
|
||||
if (keyEvent->type() == QEvent::KeyPress) {
|
||||
m_overviewState->toggleAction();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (m_gridShortcut.contains(keyEvent->key() | keyEvent->modifiers())) {
|
||||
if (keyEvent->type() == QEvent::KeyPress) {
|
||||
m_gridState->toggleAction();
|
||||
}
|
||||
return;
|
||||
}
|
||||
QuickSceneEffect::grabbedKeyboardEvent(keyEvent);
|
||||
}
|
||||
|
||||
void OverviewEffect::swapDesktops(int from, int to)
|
||||
{
|
||||
QList<EffectWindow *> fromList;
|
||||
QList<EffectWindow *> toList;
|
||||
for (auto *w : effects->stackingOrder()) {
|
||||
if (!w->isNormalWindow() || !w->isOnCurrentActivity()) {
|
||||
continue;
|
||||
}
|
||||
if (w->isOnDesktop(from)) {
|
||||
fromList << w;
|
||||
} else if (w->isOnDesktop(to)) {
|
||||
toList << w;
|
||||
}
|
||||
}
|
||||
for (auto *w : fromList) {
|
||||
effects->windowToDesktop(w, to);
|
||||
}
|
||||
for (auto *w : toList) {
|
||||
effects->windowToDesktop(w, from);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
||||
#include "moc_overvieweffect.cpp"
|
||||
|
|
|
@ -18,9 +18,15 @@ class OverviewEffect : public QuickSceneEffect
|
|||
Q_PROPERTY(int animationDuration READ animationDuration NOTIFY animationDurationChanged)
|
||||
Q_PROPERTY(int layout READ layout NOTIFY layoutChanged)
|
||||
Q_PROPERTY(bool ignoreMinimized READ ignoreMinimized NOTIFY ignoreMinimizedChanged)
|
||||
Q_PROPERTY(qreal partialActivationFactor READ partialActivationFactor NOTIFY partialActivationFactorChanged)
|
||||
// More efficient from a property binding pov rather than binding to partialActivationFactor !== 0
|
||||
Q_PROPERTY(bool gestureInProgress READ gestureInProgress NOTIFY gestureInProgressChanged)
|
||||
Q_PROPERTY(bool organizedGrid READ organizedGrid NOTIFY organizedGridChanged)
|
||||
Q_PROPERTY(qreal overviewPartialActivationFactor READ overviewPartialActivationFactor NOTIFY overviewPartialActivationFactorChanged)
|
||||
// More efficient from a property binding pov rather than checking if partialActivationFactor is strictly between 0 and 1
|
||||
Q_PROPERTY(bool overviewGestureInProgress READ overviewGestureInProgress NOTIFY overviewGestureInProgressChanged)
|
||||
Q_PROPERTY(qreal transitionPartialActivationFactor READ transitionPartialActivationFactor NOTIFY transitionPartialActivationFactorChanged)
|
||||
Q_PROPERTY(bool transitionGestureInProgress READ transitionGestureInProgress NOTIFY transitionGestureInProgressChanged)
|
||||
Q_PROPERTY(qreal gridPartialActivationFactor READ gridPartialActivationFactor NOTIFY gridPartialActivationFactorChanged)
|
||||
Q_PROPERTY(bool gridGestureInProgress READ gridGestureInProgress NOTIFY gridGestureInProgressChanged)
|
||||
Q_PROPERTY(QPointF desktopOffset READ desktopOffset NOTIFY desktopOffsetChanged)
|
||||
Q_PROPERTY(QString searchText MEMBER m_searchText NOTIFY searchTextChanged)
|
||||
|
||||
public:
|
||||
|
@ -31,31 +37,38 @@ public:
|
|||
void setLayout(int layout);
|
||||
|
||||
bool ignoreMinimized() const;
|
||||
bool organizedGrid() const;
|
||||
|
||||
int animationDuration() const;
|
||||
void setAnimationDuration(int duration);
|
||||
|
||||
qreal partialActivationFactor() const
|
||||
{
|
||||
return m_state->partialActivationFactor();
|
||||
}
|
||||
|
||||
bool gestureInProgress() const
|
||||
{
|
||||
return m_state->inProgress();
|
||||
}
|
||||
qreal overviewPartialActivationFactor() const;
|
||||
bool overviewGestureInProgress() const;
|
||||
qreal transitionPartialActivationFactor() const;
|
||||
bool transitionGestureInProgress() const;
|
||||
qreal gridPartialActivationFactor() const;
|
||||
bool gridGestureInProgress() const;
|
||||
QPointF desktopOffset() const;
|
||||
|
||||
int requestedEffectChainPosition() const override;
|
||||
bool borderActivated(ElectricBorder border) override;
|
||||
void reconfigure(ReconfigureFlags flags) override;
|
||||
void grabbedKeyboardEvent(QKeyEvent *keyEvent) override;
|
||||
|
||||
Q_INVOKABLE void swapDesktops(int from, int to);
|
||||
|
||||
Q_SIGNALS:
|
||||
void animationDurationChanged();
|
||||
void layoutChanged();
|
||||
void partialActivationFactorChanged();
|
||||
void gestureInProgressChanged();
|
||||
void overviewPartialActivationFactorChanged();
|
||||
void overviewGestureInProgressChanged();
|
||||
void transitionPartialActivationFactorChanged();
|
||||
void transitionGestureInProgressChanged();
|
||||
void gridPartialActivationFactorChanged();
|
||||
void gridGestureInProgressChanged();
|
||||
void ignoreMinimizedChanged();
|
||||
void organizedGridChanged();
|
||||
void desktopOffsetChanged();
|
||||
void searchTextChanged();
|
||||
|
||||
public Q_SLOTS:
|
||||
|
@ -64,14 +77,22 @@ public Q_SLOTS:
|
|||
|
||||
private:
|
||||
void realDeactivate();
|
||||
void cycle();
|
||||
void reverseCycle();
|
||||
|
||||
EffectTogglableState *const m_state;
|
||||
EffectTogglableState *const m_overviewState;
|
||||
EffectTogglableState *const m_transitionState;
|
||||
EffectTogglableState *const m_gridState;
|
||||
EffectTogglableTouchBorder *const m_border;
|
||||
|
||||
QTimer *m_shutdownTimer;
|
||||
QList<QKeySequence> m_toggleShortcut;
|
||||
QList<QKeySequence> m_cycleShortcut;
|
||||
QList<QKeySequence> m_reverseCycleShortcut;
|
||||
QList<QKeySequence> m_overviewShortcut;
|
||||
QList<QKeySequence> m_gridShortcut;
|
||||
QList<ElectricBorder> m_borderActivate;
|
||||
QString m_searchText;
|
||||
QPointF m_desktopOffset;
|
||||
int m_animationDuration = 400;
|
||||
int m_layout = 1;
|
||||
};
|
||||
|
|
|
@ -6,28 +6,31 @@
|
|||
*/
|
||||
|
||||
import QtQuick
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.kwin as KWinComponents
|
||||
import org.kde.kwin.private.effects
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.kwin.private.effects 1.0
|
||||
import org.kde.plasma.components as PC3
|
||||
|
||||
Item {
|
||||
id: bar
|
||||
|
||||
readonly property real desktopHeight: Kirigami.Units.gridUnit * 4
|
||||
readonly property real desktopHeight: Kirigami.Units.gridUnit * 5
|
||||
readonly property real desktopWidth: desktopHeight * targetScreen.geometry.width / targetScreen.geometry.height
|
||||
readonly property real columnHeight: desktopHeight + Kirigami.Units.gridUnit
|
||||
readonly property real columnWidth: desktopWidth + Kirigami.Units.gridUnit
|
||||
readonly property int desktopCount: desktopRepeater.count
|
||||
|
||||
property bool verticalDesktopBar
|
||||
property QtObject windowModel
|
||||
property alias desktopModel: desktopRepeater.model
|
||||
property QtObject selectedDesktop: null
|
||||
property WindowHeap heap
|
||||
property var heap
|
||||
|
||||
implicitHeight: columnHeight + 2 * Kirigami.Units.smallSpacing
|
||||
implicitWidth: columnWidth + 2 * Kirigami.Units.smallSpacing
|
||||
|
||||
Flickable {
|
||||
anchors.fill: parent
|
||||
|
@ -39,8 +42,9 @@ Item {
|
|||
clip: true
|
||||
flickableDirection: Flickable.HorizontalFlick
|
||||
|
||||
Row {
|
||||
spacing: Kirigami.Units.gridUnit
|
||||
Grid {
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
columns: verticalDesktopBar ? 1 : desktopCount + 1
|
||||
|
||||
Repeater {
|
||||
id: desktopRepeater
|
||||
|
@ -71,7 +75,11 @@ Item {
|
|||
Keys.onRightPressed: nextItemInFocusChain(!LayoutMirroring.enabled).forceActiveFocus(Qt.TabFocusReason);
|
||||
|
||||
function activate() {
|
||||
KWinComponents.Workspace.currentDesktop = delegate.desktop;
|
||||
if (KWinComponents.Workspace.currentDesktop === delegate.desktop) {
|
||||
effect.deactivate()
|
||||
} else {
|
||||
KWinComponents.Workspace.currentDesktop = delegate.desktop;
|
||||
}
|
||||
}
|
||||
|
||||
function remove() {
|
||||
|
@ -92,40 +100,48 @@ Item {
|
|||
width: bar.desktopWidth
|
||||
height: bar.desktopHeight
|
||||
|
||||
scale: thumbnailHover.hovered ? 1.03 : 1
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Kirigami.Units.Kirigami.Units.shortDuration
|
||||
}
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
id: thumbnailHover
|
||||
}
|
||||
|
||||
DesktopView {
|
||||
id: thumbnail
|
||||
|
||||
width: targetScreen.geometry.width
|
||||
height: targetScreen.geometry.height
|
||||
visible: false
|
||||
windowModel: bar.windowModel
|
||||
desktop: delegate.desktop
|
||||
scale: bar.desktopHeight / targetScreen.geometry.height
|
||||
transformOrigin: Item.TopLeft
|
||||
|
||||
// Disable the item layer while being scaled.
|
||||
layer.enabled: true
|
||||
layer.textureSize: Qt.size(bar.desktopWidth, bar.desktopHeight)
|
||||
}
|
||||
|
||||
OpacityMask {
|
||||
anchors.fill: parent
|
||||
cached: true
|
||||
source: thumbnail
|
||||
maskSource: Rectangle {
|
||||
width: bar.desktopWidth
|
||||
height: bar.desktopHeight
|
||||
radius: 3
|
||||
layer.textureSize: Qt.size(bar.desktopWidth, bar.desktopHeight)
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: thumbnail.width
|
||||
height: thumbnail.height
|
||||
// Using 5% of width since that's constant even under scaling:
|
||||
radius: width / 20
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
readonly property bool active: delegate.activeFocus || dropArea.containsDrag || mouseArea.containsPress || bar.selectedDesktop === delegate.desktop
|
||||
readonly property bool active: (delegate.activeFocus || dropArea.containsDrag || mouseArea.containsPress || bar.selectedDesktop === delegate.desktop)
|
||||
anchors.fill: parent
|
||||
anchors.margins: -border.width
|
||||
radius: 3
|
||||
radius: width / 20
|
||||
color: "transparent"
|
||||
border.width: 2
|
||||
border.width: active ? 2 : 1
|
||||
border.color: active ? Kirigami.Theme.highlightColor : Kirigami.Theme.textColor
|
||||
opacity: dropArea.containsDrag || !active ? 0.5 : 1.0
|
||||
}
|
||||
|
@ -145,18 +161,11 @@ Item {
|
|||
break;
|
||||
}
|
||||
}
|
||||
onDoubleClicked: {
|
||||
if (mouse.button == Qt.LeftButton) {
|
||||
mouse.accepted = true;
|
||||
delegate.activate();
|
||||
effect.deactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
|
||||
active: !heap.dragActive && (hoverHandler.hovered || Kirigami.Settings.tabletMode || Kirigami.Settings.hasTransientTouchInput) && desktopRepeater.count > 1
|
||||
active: !bar.heap.dragActive && (hoverHandler.hovered || Kirigami.Settings.tabletMode || Kirigami.Settings.hasTransientTouchInput) && desktopCount > 1
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
sourceComponent: PC3.Button {
|
||||
|
@ -281,8 +290,7 @@ Item {
|
|||
drag.accepted = desktopModel.rowCount() < 20
|
||||
}
|
||||
onDropped: {
|
||||
const desktop = desktopModel.create(desktopModel.rowCount());
|
||||
drag.source.desktops = [desktop];
|
||||
drag.source.desktops = [desktopModel.create(desktopModel.rowCount())];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
SPDX-FileCopyrightText: 2022 ivan tkachenko <me@ratijas.tk>
|
||||
SPDX-FileCopyrightText: 2023 Niccolò Venerandi <niccolo@venerandi.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import QtQuick.Layouts
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.kwin as KWinComponents
|
||||
import org.kde.kwin.private.effects
|
||||
import org.kde.milou as Milou
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.plasma.components as PC3
|
||||
import org.kde.plasma.extras as PlasmaExtras
|
||||
import org.kde.kcmutils as KCM
|
||||
|
||||
FocusScope {
|
||||
id: container
|
||||
|
@ -29,135 +31,176 @@ FocusScope {
|
|||
property bool animationEnabled: false
|
||||
property bool organized: false
|
||||
|
||||
property alias currentHeap: heapView.currentItem
|
||||
property bool verticalDesktopBar: KWinComponents.Workspace.desktopGridHeight >= bar.desktopCount && KWinComponents.Workspace.desktopGridHeight != 1
|
||||
property bool anyDesktopBar: verticalDesktopBar || KWinComponents.Workspace.desktopGridHeight == 1
|
||||
|
||||
// The values of overviewVal and gridVal might not be 0 on startup,
|
||||
// but we always want to animate from 0 to those values. So, we initially
|
||||
// always set them to 0 and bind their full values when the effect starts.
|
||||
// See start()
|
||||
property real overviewVal: 0
|
||||
property real gridVal: 0
|
||||
|
||||
Behavior on overviewVal {
|
||||
NumberAnimation {
|
||||
duration: Kirigami.Units.shortDuration
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on gridVal {
|
||||
NumberAnimation {
|
||||
duration: Kirigami.Units.shortDuration
|
||||
}
|
||||
}
|
||||
|
||||
function start() {
|
||||
animationEnabled = true;
|
||||
organized = true;
|
||||
|
||||
overviewVal = Qt.binding(() => effect.overviewGestureInProgress ? effect.overviewPartialActivationFactor :
|
||||
effect.transitionGestureInProgress ? 1 - effect.transitionPartialActivationFactor :
|
||||
effect.overviewPartialActivationFactor == 1 && effect.transitionPartialActivationFactor == 0)
|
||||
gridVal = Qt.binding(() => effect.transitionGestureInProgress ? effect.transitionPartialActivationFactor :
|
||||
effect.gridGestureInProgress ? effect.gridPartialActivationFactor :
|
||||
effect.transitionPartialActivationFactor == 1 && effect.gridPartialActivationFactor == 1)
|
||||
}
|
||||
|
||||
function stop() {
|
||||
organized = false;
|
||||
}
|
||||
|
||||
Keys.onEscapePressed: effect.deactivate();
|
||||
|
||||
Keys.forwardTo: searchField
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
currentHeap.forceActiveFocus();
|
||||
if (currentHeap.count === 1) {
|
||||
currentHeap.activateCurrentClient();
|
||||
}
|
||||
function switchTo(desktop) {
|
||||
KWinComponents.Workspace.currentDesktop = desktop;
|
||||
effect.deactivate();
|
||||
}
|
||||
|
||||
Keys.onLeftPressed: {
|
||||
let view = effect.getView(Qt.LeftEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
}
|
||||
}
|
||||
Keys.onRightPressed: {
|
||||
let view = effect.getView(Qt.RightEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
}
|
||||
}
|
||||
Keys.onUpPressed: {
|
||||
let view = effect.getView(Qt.TopEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
}
|
||||
}
|
||||
Keys.onDownPressed: {
|
||||
let view = effect.getView(Qt.BottomEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
function selectNext(direction) {
|
||||
if (effect.searchText !== "") return false;
|
||||
let currentIndex = 0
|
||||
for (let i = 0; i < allDesktopHeaps.count; i++) {
|
||||
if (allDesktopHeaps.itemAt(i).current) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let x = currentIndex % container.columns;
|
||||
let y = Math.floor(currentIndex / container.columns);
|
||||
|
||||
// the direction we move in is the opposite of the window to select
|
||||
// i.e pressing left should select the rightmost window on the desktop
|
||||
// to the left
|
||||
let invertedDirection;
|
||||
switch(direction) {
|
||||
case WindowHeap.Direction.Up:
|
||||
y--;
|
||||
invertedDirection = WindowHeap.Direction.Down;
|
||||
break;
|
||||
case WindowHeap.Direction.Down:
|
||||
y++
|
||||
invertedDirection = WindowHeap.Direction.Up;
|
||||
break;
|
||||
case WindowHeap.Direction.Left:
|
||||
x--;
|
||||
invertedDirection = WindowHeap.Direction.Right;
|
||||
break;
|
||||
case WindowHeap.Direction.Right:
|
||||
x++;
|
||||
invertedDirection = WindowHeap.Direction.Left;
|
||||
break;
|
||||
}
|
||||
|
||||
if (x < 0 || x >= container.columns) {
|
||||
return false;
|
||||
}
|
||||
if (y < 0 || y >= container.rows) {
|
||||
return false;
|
||||
}
|
||||
let newIndex = y * container.columns + x;
|
||||
|
||||
KWinComponents.Workspace.currentDesktop = allDesktopHeaps.itemAt(newIndex).desktop
|
||||
allDesktopHeaps.itemAt(newIndex).nestedHeap.focus = true
|
||||
allDesktopHeaps.itemAt(newIndex).selectLastItem(invertedDirection);
|
||||
return true;
|
||||
}
|
||||
|
||||
Keys.onPressed: (event) => {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
if (effect.searchText !== "") {
|
||||
effect.searchText = ""
|
||||
} else {
|
||||
effect.deactivate();
|
||||
}
|
||||
} else if (event.key === Qt.Key_Plus || event.key === Qt.Key_Equal) {
|
||||
desktopModel.create(desktopModel.rowCount());
|
||||
} else if (event.key === Qt.Key_Minus) {
|
||||
desktopModel.remove(desktopModel.rowCount() - 1);
|
||||
} else if (event.key >= Qt.Key_F1 && event.key <= Qt.Key_F12) {
|
||||
const desktopId = event.key - Qt.Key_F1;
|
||||
if (desktopId < allDesktopHeaps.count) {
|
||||
switchTo(allDesktopHeaps.itemAt(desktopId).desktop);
|
||||
}
|
||||
} else if (event.key >= Qt.Key_0 && event.key <= Qt.Key_9) {
|
||||
const desktopId = event.key === Qt.Key_0 ? 9 : (event.key - Qt.Key_1);
|
||||
if (desktopId < allDesktopHeaps.count) {
|
||||
switchTo(allDesktopHeaps.itemAt(desktopId).desktop);
|
||||
}
|
||||
} else if (event.key === Qt.Key_Up) {
|
||||
event.accepted = selectNext(WindowHeap.Direction.Up);
|
||||
if (!event.accepted) {
|
||||
let view = effect.getView(Qt.TopEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
}
|
||||
}
|
||||
} else if (event.key === Qt.Key_Down) {
|
||||
event.accepted = selectNext(WindowHeap.Direction.Down);
|
||||
if (!event.accepted) {
|
||||
let view = effect.getView(Qt.BottomEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
}
|
||||
}
|
||||
} else if (event.key === Qt.Key_Left) {
|
||||
event.accepted = selectNext(WindowHeap.Direction.Left);
|
||||
if (!event.accepted) {
|
||||
let view = effect.getView(Qt.LeftEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
}
|
||||
}
|
||||
} else if (event.key === Qt.Key_Right) {
|
||||
event.accepted = selectNext(WindowHeap.Direction.Right);
|
||||
if (!event.accepted) {
|
||||
let view = effect.getView(Qt.RightEdge)
|
||||
if (view) {
|
||||
effect.activateView(view)
|
||||
}
|
||||
}
|
||||
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Space) {
|
||||
for (let i = 0; i < allDesktopHeaps.count; i++) {
|
||||
if (allDesktopHeaps.itemAt(i).current) {
|
||||
switchTo(allDesktopHeaps.itemAt(i).desktop)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Keys.priority: Keys.AfterItem
|
||||
|
||||
KWinComponents.DesktopBackground {
|
||||
id: backgroundItem
|
||||
activity: KWinComponents.Workspace.currentActivity
|
||||
desktop: KWinComponents.Workspace.currentDesktop
|
||||
outputName: targetScreen.name
|
||||
property real blurRadius: 0
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: FastBlur {
|
||||
radius: backgroundItem.blurRadius
|
||||
}
|
||||
}
|
||||
|
||||
state: {
|
||||
if (effect.gestureInProgress) {
|
||||
return "partial";
|
||||
} else if (organized) {
|
||||
return "active";
|
||||
} else {
|
||||
return "initial";
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "initial"
|
||||
PropertyChanges {
|
||||
target: underlay
|
||||
opacity: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: topBar
|
||||
opacity: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: backgroundItem
|
||||
blurRadius: 0
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "partial"
|
||||
PropertyChanges {
|
||||
target: underlay
|
||||
opacity: 0.75 * effect.partialActivationFactor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: topBar
|
||||
opacity: effect.partialActivationFactor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: backgroundItem
|
||||
blurRadius: 64 * effect.partialActivationFactor
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "active"
|
||||
PropertyChanges {
|
||||
target: underlay
|
||||
opacity: 0.75
|
||||
}
|
||||
PropertyChanges {
|
||||
target: topBar
|
||||
opacity: 1
|
||||
}
|
||||
PropertyChanges {
|
||||
target: backgroundItem
|
||||
blurRadius: 64
|
||||
}
|
||||
}
|
||||
]
|
||||
transitions: Transition {
|
||||
to: "initial, active"
|
||||
NumberAnimation {
|
||||
duration: effect.animationDuration
|
||||
properties: "opacity, blurRadius"
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
layer.effect: FastBlur {radius: 64}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: underlay
|
||||
anchors.fill: parent
|
||||
opacity: 0.7
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
|
||||
TapHandler {
|
||||
|
@ -165,112 +208,355 @@ FocusScope {
|
|||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
Item {
|
||||
id: desktopBar
|
||||
visible: container.anyDesktopBar
|
||||
|
||||
Item {
|
||||
id: topBar
|
||||
width: parent.width
|
||||
height: searchBar.height + desktopBar.height
|
||||
// (overviewVal, gridVal) represents the state of the overview
|
||||
// in a 2D coordinate plane. Math.atan2 returns the angle between
|
||||
// the x axis and that point. By using this to set the opacity,
|
||||
// we can have an opaque desktopBar when the point moves from
|
||||
// the origin to the "overviewVal" direction, which has angle pi/2,
|
||||
// and a transparent desktopBar when the point moves from
|
||||
// the origin to the "gridVal" direction, which has angle 0,
|
||||
// whilst still animating when the point moves from overviewVal to
|
||||
// gridVal too.
|
||||
opacity: Math.atan2(overviewVal, gridVal) / Math.PI * 2
|
||||
|
||||
Rectangle {
|
||||
id: desktopBar
|
||||
width: parent.width
|
||||
implicitHeight: bar.implicitHeight + 2 * Kirigami.Units.smallSpacing
|
||||
color: container.lightBackground ? Qt.rgba(Kirigami.Theme.backgroundColor.r,
|
||||
Kirigami.Theme.backgroundColor.g,
|
||||
Kirigami.Theme.backgroundColor.b, 0.75)
|
||||
: Qt.rgba(0, 0, 0, 0.25)
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: container.verticalDesktopBar ? undefined : parent.right
|
||||
anchors.bottom: container.verticalDesktopBar ? parent.bottom : undefined
|
||||
height: bar.implicitHeight + 2 * Kirigami.Units.smallSpacing
|
||||
width: bar.implicitWidth + 2 * Kirigami.Units.smallSpacing
|
||||
|
||||
DesktopBar {
|
||||
id: bar
|
||||
anchors.fill: parent
|
||||
windowModel: stackModel
|
||||
desktopModel: desktopModel
|
||||
selectedDesktop: KWinComponents.Workspace.currentDesktop
|
||||
heap: currentHeap
|
||||
}
|
||||
DesktopBar {
|
||||
id: bar
|
||||
anchors.fill: parent
|
||||
windowModel: stackModel
|
||||
desktopModel: desktopModel
|
||||
verticalDesktopBar: container.verticalDesktopBar
|
||||
selectedDesktop: KWinComponents.Workspace.currentDesktop
|
||||
heap: allDesktopHeaps.currentHeap
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: topBar
|
||||
opacity: desktopBar.opacity
|
||||
anchors.left: container.verticalDesktopBar ? desktopBar.right : parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: container.verticalDesktopBar || !container.anyDesktopBar ? parent.top : desktopBar.bottom
|
||||
anchors.topMargin: Kirigami.Units.largeSpacing
|
||||
height: searchField.height + 1 * Kirigami.Units.largeSpacing
|
||||
|
||||
PlasmaExtras.SearchField {
|
||||
id: searchField
|
||||
anchors.centerIn: parent
|
||||
width: Math.min(parent.width, 20 * Kirigami.Units.gridUnit)
|
||||
focus: enabled
|
||||
readOnly: gridVal == 1
|
||||
onReadOnlyChanged: {
|
||||
text = ""
|
||||
effect.searchText = ""
|
||||
effect.searchTextChanged()
|
||||
}
|
||||
|
||||
Item {
|
||||
id: searchBar
|
||||
anchors.top: desktopBar.bottom
|
||||
width: parent.width
|
||||
height: searchField.height + 2 * Kirigami.Units.gridUnit
|
||||
|
||||
PlasmaExtras.SearchField {
|
||||
id: searchField
|
||||
anchors.centerIn: parent
|
||||
width: Math.min(parent.width, 20 * Kirigami.Units.gridUnit)
|
||||
focus: true
|
||||
Keys.priority: Keys.BeforeItem
|
||||
Keys.forwardTo: text && currentHeap.count === 0 ? searchResults : currentHeap
|
||||
text: effect.searchText
|
||||
onTextEdited: {
|
||||
effect.searchText = text;
|
||||
currentHeap.resetSelected();
|
||||
currentHeap.selectNextItem(WindowHeap.Direction.Down);
|
||||
searchField.focus = true;
|
||||
}
|
||||
}
|
||||
Keys.priority: Keys.BeforeItem
|
||||
Keys.forwardTo: text && allDesktopHeaps.currentHeap.count === 0 ? searchResults : allDesktopHeaps.currentHeap
|
||||
text: effect.searchText
|
||||
onTextEdited: {
|
||||
effect.searchText = text;
|
||||
allDesktopHeaps.currentHeap.resetSelected();
|
||||
allDesktopHeaps.currentHeap.selectNextItem(WindowHeap.Direction.Down);
|
||||
searchField.focus = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: parent.height - topBar.height
|
||||
property var currentGeometry: targetScreen.geometry
|
||||
|
||||
PlasmaExtras.PlaceholderMessage {
|
||||
id: placeholderMessage
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: container.organized && effect.searchText.length > 0 && currentHeap.count === 0
|
||||
text: i18nd("kwin", "No matching windows")
|
||||
// These are the minimum position of maximum size of the desktop preview in the overview
|
||||
property int minX: Kirigami.Units.largeSpacing + (container.verticalDesktopBar ? desktopBar.width : 0)
|
||||
property int minY: Kirigami.Units.largeSpacing + topBar.height + (container.verticalDesktopBar || !container.anyDesktopBar ? 0 : desktopBar.height)
|
||||
property int maxWidth: currentGeometry.width - minX - Kirigami.Units.gridUnit * 2
|
||||
property int maxHeight: currentGeometry.height - minY - Kirigami.Units.gridUnit * 2
|
||||
|
||||
property int desktops: Math.max(bar.desktopCount, 2)
|
||||
property int columns: Math.ceil(desktops / rows)
|
||||
property int rows: KWinComponents.Workspace.desktopGridHeight
|
||||
|
||||
// The desktop might shuffle around as soon as it's
|
||||
// created since the rows/columns are updated after
|
||||
// the desktop is added. We don't want to see that.
|
||||
property bool desktopJustCreated: false
|
||||
onDesktopsChanged: {
|
||||
desktopJustCreated = true
|
||||
startTimer.running = true
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: startTimer
|
||||
interval: effect.animationDuration
|
||||
running: false
|
||||
onTriggered: desktopJustCreated = false
|
||||
}
|
||||
|
||||
Item {
|
||||
id: desktopGrid
|
||||
anchors.fill: parent
|
||||
property var dndManagerStore: ({})
|
||||
|
||||
ColumnLayout {
|
||||
x: Math.round(parent.width / 2) + Math.round(parent.width / 8)
|
||||
width: Math.round(parent.width / 2) - Math.round(parent.width / 8) * 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: bar.desktopCount === 1
|
||||
opacity: gridVal
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
Kirigami.PlaceholderMessage {
|
||||
text: i18ndc("kwin", "@info:placeholder", "No other Virtual Desktops to show")
|
||||
icon.name: "virtual-desktops-symbolic"
|
||||
}
|
||||
|
||||
StackView {
|
||||
id: heapView
|
||||
PC3.Button {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: i18ndc("kwin", "@action:button", "Add Virtual Desktop")
|
||||
icon.name: "list-add-symbolic"
|
||||
onClicked: desktopModel.create(desktopModel.rowCount())
|
||||
}
|
||||
|
||||
PC3.Button {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: i18ndc("kwin", "@action:button", "Configure Virtual Desktops…")
|
||||
icon.name: "preferences-virtual-desktops"
|
||||
onClicked: {
|
||||
KCM.KCMLauncher.openSystemSettings("kcm_kwin_virtualdesktops")
|
||||
effect.deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Repeater {
|
||||
id: allDesktopHeaps
|
||||
model: desktopModel
|
||||
|
||||
property Item currentHeap
|
||||
property Item currentBackgroundItem
|
||||
|
||||
Kirigami.ShadowedRectangle {
|
||||
id: mainBackground
|
||||
color: Kirigami.Theme.highlightColor
|
||||
visible: gridVal > 0 || nearCurrent
|
||||
anchors.fill: parent
|
||||
property bool shouldBeVisibleInOverview: !(container.organized && effect.searchText.length > 0 && current) || heap.count !== 0
|
||||
opacity: 1 - overviewVal * (shouldBeVisibleInOverview ? 0 : 1)
|
||||
|
||||
function switchTo(desktop) {
|
||||
container.animationEnabled = false;
|
||||
heapView.replace(heapTemplate, { desktop: desktop });
|
||||
currentItem.layout.forceLayout();
|
||||
container.animationEnabled = true;
|
||||
function selectLastItem(direction) {
|
||||
heap.selectLastItem(direction);
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
push(heapTemplate, { desktop: KWinComponents.Workspace.currentDesktop });
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: KWinComponents.Workspace
|
||||
function onCurrentDesktopChanged() {
|
||||
heapView.switchTo(KWinComponents.Workspace.currentDesktop);
|
||||
}
|
||||
}
|
||||
required property QtObject desktop
|
||||
required property int index
|
||||
readonly property bool current: KWinComponents.Workspace.currentDesktop === desktop
|
||||
readonly property bool nearCurrent: Math.abs(deltaColumn) <= 1 && Math.abs(deltaRow) <= 1
|
||||
readonly property var nestedHeap: heap
|
||||
|
||||
Component {
|
||||
id: heapTemplate
|
||||
z: dragActive ? 1 : 0
|
||||
readonly property bool dragActive: heap.dragActive || dragHandler.active
|
||||
|
||||
shadow {
|
||||
size: Kirigami.Units.gridUnit * 2
|
||||
color: Qt.rgba(0, 0, 0, 0.3)
|
||||
yOffset: 3
|
||||
}
|
||||
radius: Kirigami.Units.largeSpacing * 2 * (overviewVal + gridVal * 2)
|
||||
|
||||
property int gridSize: Math.max(rows, columns)
|
||||
property real row: (index - column) / columns
|
||||
property real column: index % columns
|
||||
// deltaX and deltaY are used to move all the desktops together to 1:1 animate the
|
||||
// switching between different desktops
|
||||
property real deltaX: (!current ? effect.desktopOffset.x :
|
||||
column == 0 ? Math.max(0, effect.desktopOffset.x) :
|
||||
column == columns - 1 ? Math.min(0, effect.desktopOffset.x) :
|
||||
effect.desktopOffset.x)
|
||||
property real deltaY: (!current ? effect.desktopOffset.y :
|
||||
row == 0 ? Math.max(0, effect.desktopOffset.y) :
|
||||
row == rows - 1 ? Math.min(0, effect.desktopOffset.y) :
|
||||
effect.desktopOffset.y)
|
||||
// deltaColumn and deltaRows are the difference between the column/row of this desktop
|
||||
// compared to the column/row of the active one
|
||||
property real deltaColumn: column - allDesktopHeaps.currentBackgroundItem.column - deltaX
|
||||
property real deltaRow: row - allDesktopHeaps.currentBackgroundItem.row - deltaY
|
||||
|
||||
Behavior on deltaColumn {
|
||||
enabled: overviewVal > 0 && !container.desktopJustCreated
|
||||
NumberAnimation {
|
||||
duration: effect.animationDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
Behavior on deltaRow {
|
||||
enabled: overviewVal > 0 && !container.desktopJustCreated
|
||||
NumberAnimation {
|
||||
duration: effect.animationDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
// Note that transforms should be read from the last one to the first one
|
||||
transform: [
|
||||
// Scales down further, still in grid, to have some gaps between
|
||||
// the desktops.
|
||||
Scale {
|
||||
origin.x: width / 2
|
||||
origin.y: height / 2
|
||||
xScale: 1 - 0.02 * gridVal
|
||||
yScale: xScale
|
||||
},
|
||||
// Scales down the desktops so that they do not overlap in the grid
|
||||
Scale {
|
||||
id: gridScale
|
||||
xScale: 1 + (1 / gridSize - 1) * gridVal
|
||||
yScale: xScale
|
||||
},
|
||||
// Further little translation in the grids to align the elements
|
||||
// to the center of their cell
|
||||
Translate{
|
||||
x: (gridSize / columns - 1) * (width / gridSize) / 2 * gridVal
|
||||
y: (gridSize / rows - 1) * (height / gridSize) / 2 * gridVal
|
||||
},
|
||||
// When in desktop grid, translates the desktop so that the whole
|
||||
// grid fits in the view
|
||||
Translate {
|
||||
x: column * (width / columns) * gridVal
|
||||
y: row * (height / rows) * gridVal
|
||||
},
|
||||
// Scales down the preview slighly when in Overview mode
|
||||
Scale {
|
||||
origin.x: width / 2
|
||||
origin.y: height / 2
|
||||
property real scale: Math.min(maxWidth / width, maxHeight / height)
|
||||
xScale: 1 + (scale - 1) * overviewVal
|
||||
yScale:1 + (scale - 1) * overviewVal
|
||||
},
|
||||
// Initially places transition desktops in a grid around the current one,
|
||||
// and moves them slighly to avoid overlapping the UI
|
||||
Translate {
|
||||
x: minX * 0.5 * overviewVal + deltaColumn * width * (1 - gridVal)
|
||||
y: minY * 0.5 * overviewVal + deltaRow * height * (1 - gridVal)
|
||||
}
|
||||
]
|
||||
|
||||
KWinComponents.DesktopBackground {
|
||||
id: desktopElement
|
||||
anchors.fill: parent
|
||||
anchors.margins: gridVal !== 0 ? Math.round(mainBackground.current * gridVal * (1.5 / gridScale.xScale)) : 0
|
||||
activity: KWinComponents.Workspace.currentActivity
|
||||
desktop: KWinComponents.Workspace.currentDesktop
|
||||
outputName: targetScreen.name
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: desktopElement.width
|
||||
height: desktopElement.height
|
||||
radius: mainBackground.radius
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropArea {
|
||||
anchors.fill: parent
|
||||
onEntered: (drag) => {
|
||||
drag.accepted = true;
|
||||
}
|
||||
onDropped: (drop) => {
|
||||
drop.accepted = true;
|
||||
if (drag.source instanceof Kirigami.ShadowedRectangle) {
|
||||
// dragging a desktop as a whole
|
||||
if (drag.source === mainBackground) {
|
||||
drop.action = Qt.IgnoreAction;
|
||||
return;
|
||||
}
|
||||
effect.swapDesktops(drag.source.desktop.x11DesktopNumber, desktop.x11DesktopNumber);
|
||||
} else {
|
||||
// dragging a KWin::Window
|
||||
if (drag.source.desktops.length === 0 || drag.source.desktops.indexOf(mainBackground.desktop) !== -1) {
|
||||
drop.action = Qt.IgnoreAction;
|
||||
return;
|
||||
}
|
||||
drag.source.desktops = [mainBackground.desktop];
|
||||
}
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: effect
|
||||
function onItemDroppedOutOfScreen(globalPos, item, screen) {
|
||||
if (screen !== targetScreen) {
|
||||
return;
|
||||
}
|
||||
const pos = screen.mapFromGlobal(globalPos);
|
||||
if (!mainBackground.contains(mainBackground.mapFromItem(null, pos.x, pos.y))) {
|
||||
return;
|
||||
}
|
||||
item.client.desktops = [mainBackground.desktop];
|
||||
}
|
||||
}
|
||||
DragHandler {
|
||||
id: dragHandler
|
||||
target: heap
|
||||
enabled: gridVal !== 0
|
||||
grabPermissions: PointerHandler.ApprovesTakeOverByHandlersOfSameType
|
||||
onActiveChanged: {
|
||||
if (!active) {
|
||||
heap.Drag.drop();
|
||||
Qt.callLater(heap.resetPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: heap
|
||||
acceptedButtons: Qt.NoButton
|
||||
cursorShape: dragHandler.active ? Qt.ClosedHandCursor : Qt.ArrowCursor
|
||||
}
|
||||
|
||||
WindowHeap {
|
||||
id: heap
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
x: 0
|
||||
y: 0
|
||||
|
||||
required property QtObject desktop
|
||||
function resetPosition() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
z: 9999
|
||||
Drag.active: dragHandler.active
|
||||
Drag.proposedAction: Qt.MoveAction
|
||||
Drag.supportedActions: Qt.MoveAction
|
||||
Drag.source: mainBackground
|
||||
Drag.hotSpot: Qt.point(width * 0.5, height * 0.5)
|
||||
|
||||
visible: !(container.organized && effect.searchText.length > 0) || heap.count !== 0
|
||||
layout.mode: effect.layout
|
||||
focus: true
|
||||
padding: Kirigami.Units.gridUnit
|
||||
focus: current
|
||||
padding: Kirigami.Units.largeSpacing
|
||||
animationDuration: effect.animationDuration
|
||||
animationEnabled: container.animationEnabled
|
||||
animationEnabled: container.animationEnabled && (gridVal !== 0 || mainBackground.current)
|
||||
organized: container.organized
|
||||
dndManagerStore: desktopGrid.dndManagerStore
|
||||
Keys.priority: Keys.AfterItem
|
||||
Keys.forwardTo: searchResults
|
||||
Keys.forwardTo: [searchResults, searchField]
|
||||
model: KWinComponents.WindowFilterModel {
|
||||
activity: KWinComponents.Workspace.currentActivity
|
||||
desktop: heap.desktop
|
||||
desktop: mainBackground.desktop
|
||||
screenName: targetScreen.name
|
||||
windowModel: stackModel
|
||||
filter: effect.searchText
|
||||
|
@ -283,30 +569,93 @@ FocusScope {
|
|||
delegate: WindowHeapDelegate {
|
||||
windowHeap: heap
|
||||
|
||||
// This is preferable over using gestureInProgress values since gridVal and
|
||||
// overviewVal are animated even after the gesture ends, and since the partial
|
||||
// activation factor follows those two values, this results in a more
|
||||
// fluent animation.
|
||||
gestureInProgress: !Number.isInteger(gridVal) || !Number.isInteger(overviewVal)
|
||||
|
||||
partialActivationFactor: container.overviewVal + container.gridVal * effect.organizedGrid
|
||||
|
||||
targetScale: {
|
||||
if (!container.anyDesktopBar) return targetScale;
|
||||
if (overviewVal != 1) return targetScale;
|
||||
let coordinate = container.verticalDesktopBar ? 'x' : 'y'
|
||||
if (!activeDragHandler.active) {
|
||||
return targetScale; // leave it alone, so it won't affect transitions before they start
|
||||
}
|
||||
var localPressPosition = activeDragHandler.centroid.scenePressPosition.y - heap.layout.Kirigami.ScenePosition.y;
|
||||
var localPressPosition = activeDragHandler.centroid.scenePressPosition[coordinate] - heap.layout.Kirigami.ScenePosition[coordinate];
|
||||
if (localPressPosition === 0) {
|
||||
return 0.1;
|
||||
} else {
|
||||
var localPosition = activeDragHandler.centroid.scenePosition.y - heap.layout.Kirigami.ScenePosition.y;
|
||||
var localPosition = activeDragHandler.centroid.scenePosition[coordinate] - heap.layout.Kirigami.ScenePosition[coordinate];
|
||||
return Math.max(0.1, Math.min(localPosition / localPressPosition, 1));
|
||||
}
|
||||
}
|
||||
|
||||
opacity: 1 - downGestureProgress
|
||||
onDownGestureTriggered: window.closeWindow()
|
||||
|
||||
TapHandler {
|
||||
acceptedPointerTypes: PointerDevice.GenericPointer | PointerDevice.Pen
|
||||
acceptedButtons: Qt.MiddleButton
|
||||
onTapped: window.closeWindow()
|
||||
acceptedButtons: Qt.MiddleButton | Qt.RightButton
|
||||
onTapped: (eventPoint, button) => {
|
||||
if (button === Qt.MiddleButton) {
|
||||
window.closeWindow();
|
||||
} else if (button === Qt.RightButton) {
|
||||
if (window.desktops.length > 0) {
|
||||
window.desktops = [];
|
||||
} else {
|
||||
window.desktops = [desktopView.desktop];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onActivated: effect.deactivate();
|
||||
onActivated: effect.deactivate()
|
||||
}
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onTapped: {
|
||||
KWinComponents.Workspace.currentDesktop = mainBackground.desktop;
|
||||
container.effect.deactivate();
|
||||
}
|
||||
}
|
||||
onCurrentChanged: {
|
||||
if (current) {
|
||||
allDesktopHeaps.currentHeap = heap;
|
||||
allDesktopHeaps.currentBackgroundItem = mainBackground;
|
||||
}
|
||||
}
|
||||
Component.onCompleted: {
|
||||
if (current) {
|
||||
allDesktopHeaps.currentHeap = heap;
|
||||
allDesktopHeaps.currentBackgroundItem = mainBackground;
|
||||
}
|
||||
startTimer.running = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.left: container.verticalDesktopBar ? desktopBar.right : parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: topBar.bottom
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: parent.height - topBar.height
|
||||
visible: container.organized && effect.searchText.length > 0 && allDesktopHeaps.currentHeap.count === 0
|
||||
opacity: overviewVal
|
||||
|
||||
PlasmaExtras.PlaceholderMessage {
|
||||
id: placeholderMessage
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: i18ndc("kwin", "@info:placeholder", "No matching windows")
|
||||
}
|
||||
|
||||
Milou.ResultsView {
|
||||
|
@ -314,9 +663,8 @@ FocusScope {
|
|||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width / 2
|
||||
height: parent.height - placeholderMessage.height - Kirigami.Units.gridUnit
|
||||
height: parent.height - placeholderMessage.height - Kirigami.Units.largeSpacing
|
||||
queryString: effect.searchText
|
||||
visible: container.organized && effect.searchText.length > 0 && currentHeap.count === 0
|
||||
|
||||
onActivated: {
|
||||
effect.deactivate();
|
||||
|
@ -342,14 +690,7 @@ FocusScope {
|
|||
z: model.window.stackingOrder
|
||||
width: model.window.width
|
||||
height: model.window.height
|
||||
opacity: container.effect.gestureInProgress
|
||||
? 1 - container.effect.partialActivationFactor
|
||||
: (model.window.hidden || container.organized) ? 0 : 1
|
||||
|
||||
Behavior on opacity {
|
||||
enabled: !container.effect.gestureInProgress
|
||||
NumberAnimation { duration: effect.animationDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
opacity: 1 - (gridVal + overviewVal)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -361,5 +702,12 @@ FocusScope {
|
|||
id: desktopModel
|
||||
}
|
||||
|
||||
Component.onCompleted: start();
|
||||
Component.onCompleted: {
|
||||
// The following line unbinds the verticalDesktopBar, meaning that it
|
||||
// won't react to changes in number of desktops or rows. This is beacuse we
|
||||
// don't want the desktop bar changing screenside whilst the user is
|
||||
// interacting with it, e.g. by adding desktops
|
||||
container.verticalDesktopBar = container.verticalDesktopBar
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,12 @@
|
|||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.kwin as KWinComponents
|
||||
import org.kde.kwin.private.effects
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
import org.kde.plasma.workspace.components 2.0 as WorkspaceComponents
|
||||
import org.kde.ksvg 1.0 as KSvg
|
||||
|
||||
Item {
|
||||
|
@ -21,6 +23,8 @@ Item {
|
|||
required property Item windowHeap
|
||||
|
||||
readonly property bool selected: windowHeap.selectedIndex === index
|
||||
property real partialActivationFactor: effect.partialActivationFactor
|
||||
property bool gestureInProgress: effect.gestureInProgress
|
||||
|
||||
// no desktops is a special value which means "All Desktops"
|
||||
readonly property bool presentOnCurrentDesktop: !window.desktops.length || window.desktops.indexOf(KWinComponents.Workspace.currentDesktop) !== -1
|
||||
|
@ -59,10 +63,10 @@ Item {
|
|||
property string substate: "normal"
|
||||
|
||||
state: {
|
||||
if (effect.gestureInProgress) {
|
||||
if (thumb.gestureInProgress) {
|
||||
return "partial";
|
||||
}
|
||||
if (windowHeap.effectiveOrganized) {
|
||||
if (thumb.partialActivationFactor > 0.5 && cell.isReady) {
|
||||
return activeHidden ? "active-hidden" : `active-${substate}`;
|
||||
}
|
||||
return initialHidden ? "initial-hidden" : "initial";
|
||||
|
@ -163,10 +167,11 @@ Item {
|
|||
anchors.bottomMargin: -Math.round(height / 4)
|
||||
visible: !thumb.activeHidden && !activeDragHandler.active
|
||||
|
||||
PC3.Label {
|
||||
|
||||
WorkspaceComponents.ShadowedLabel {
|
||||
id: caption
|
||||
visible: thumb.windowTitleVisible
|
||||
width: Math.min(implicitWidth, thumbSource.width)
|
||||
width: Math.min(implicitWidth, thumb.width)
|
||||
anchors.top: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
elide: Text.ElideRight
|
||||
|
@ -187,6 +192,7 @@ Item {
|
|||
naturalHeight: thumb.window.height
|
||||
persistentKey: thumb.window.internalId
|
||||
bottomMargin: icon.height / 4 + (thumb.windowTitleVisible ? caption.height : 0)
|
||||
property bool isReady: width !== 0 && height !== 0
|
||||
}
|
||||
|
||||
states: [
|
||||
|
@ -219,13 +225,13 @@ Item {
|
|||
name: "partial"
|
||||
PropertyChanges {
|
||||
target: thumb
|
||||
x: (thumb.window.x - targetScreen.geometry.x - (thumb.windowHeap.absolutePositioning ? windowHeap.layout.Kirigami.ScenePosition.x : 0)) * (1 - effect.partialActivationFactor) + cell.x * effect.partialActivationFactor
|
||||
y: (thumb.window.y - targetScreen.geometry.y - (thumb.windowHeap.absolutePositioning ? windowHeap.layout.Kirigami.ScenePosition.y : 0)) * (1 - effect.partialActivationFactor) + cell.y * effect.partialActivationFactor
|
||||
width: thumb.window.width * (1 - effect.partialActivationFactor) + cell.width * effect.partialActivationFactor
|
||||
height: thumb.window.height * (1 - effect.partialActivationFactor) + cell.height * effect.partialActivationFactor
|
||||
x: (thumb.window.x - targetScreen.geometry.x - (thumb.windowHeap.absolutePositioning ? windowHeap.layout.Kirigami.ScenePosition.x : 0)) * (1 - thumb.partialActivationFactor) + cell.x * thumb.partialActivationFactor
|
||||
y: (thumb.window.y - targetScreen.geometry.y - (thumb.windowHeap.absolutePositioning ? windowHeap.layout.Kirigami.ScenePosition.y : 0)) * (1 - thumb.partialActivationFactor) + cell.y * thumb.partialActivationFactor
|
||||
width: thumb.window.width * (1 - thumb.partialActivationFactor) + cell.width * thumb.partialActivationFactor
|
||||
height: thumb.window.height * (1 - thumb.partialActivationFactor) + cell.height * thumb.partialActivationFactor
|
||||
opacity: thumb.initialHidden
|
||||
? (thumb.activeHidden ? 0 : effect.partialActivationFactor)
|
||||
: (thumb.activeHidden ? 1 - effect.partialActivationFactor : 1)
|
||||
? (thumb.activeHidden ? 0 : thumb.partialActivationFactor)
|
||||
: (thumb.activeHidden ? 1 - thumb.partialActivationFactor : 1)
|
||||
}
|
||||
PropertyChanges {
|
||||
target: thumbSource
|
||||
|
@ -236,11 +242,11 @@ Item {
|
|||
}
|
||||
PropertyChanges {
|
||||
target: icon
|
||||
opacity: effect.partialActivationFactor
|
||||
opacity: thumb.partialActivationFactor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: closeButton
|
||||
opacity: effect.partialActivationFactor
|
||||
opacity: thumb.partialActivationFactor
|
||||
}
|
||||
},
|
||||
State {
|
||||
|
@ -289,8 +295,8 @@ Item {
|
|||
target: thumbSource
|
||||
x: 0
|
||||
y: 0
|
||||
width: cell.width
|
||||
height: cell.height
|
||||
width: thumb.width
|
||||
height: thumb.height
|
||||
}
|
||||
},
|
||||
State {
|
||||
|
@ -298,8 +304,8 @@ Item {
|
|||
extend: "active"
|
||||
PropertyChanges {
|
||||
target: thumbSource
|
||||
width: cell.width
|
||||
height: cell.height
|
||||
width: thumb.width
|
||||
height: thumb.height
|
||||
}
|
||||
},
|
||||
State {
|
||||
|
@ -311,8 +317,8 @@ Item {
|
|||
thumb.activeDragHandler.centroid.position.x
|
||||
y: -thumb.activeDragHandler.centroid.pressPosition.y * thumb.targetScale +
|
||||
thumb.activeDragHandler.centroid.position.y
|
||||
width: cell.width * thumb.targetScale
|
||||
height: cell.height * thumb.targetScale
|
||||
width: thumb.width * thumb.targetScale
|
||||
height: thumb.height * thumb.targetScale
|
||||
}
|
||||
},
|
||||
State {
|
||||
|
|
|
@ -201,6 +201,7 @@ Item {
|
|||
}
|
||||
delegate: WindowHeapDelegate {
|
||||
windowHeap: heap
|
||||
partialActivationFactor: container.organized ? 1 : 0
|
||||
opacity: 1 - downGestureProgress
|
||||
onDownGestureTriggered: window.closeWindow()
|
||||
|
||||
|
|
|
@ -125,8 +125,6 @@ WindowViewEffect::WindowViewEffect()
|
|||
}
|
||||
}
|
||||
};
|
||||
effects->registerTouchpadSwipeShortcut(SwipeDirection::Down, 4, m_realtimeToggleAction, gestureCallback);
|
||||
effects->registerTouchscreenSwipeShortcut(SwipeDirection::Down, 3, m_realtimeToggleAction, gestureCallback);
|
||||
|
||||
reconfigure(ReconfigureAll);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue