You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
latte-dock/app/view/originalview.cpp

283 lines
7.2 KiB
C++

fix #96,FEATURE:AllScreens and AllSecondaryScreens --This is a HUGE FEATURE and so important for multi-screens users. It is introduced as one single commit because it reimplements plenty of infrastructure changes and it will be easier to identify newly introduced bugs. --Users can now choose for their docks and panels to belong at various screen groups. The first two screen groups introduced are AllScreens and AllSecondayScreens. In the future it might be possible to provide CustomScreensGroup that the user will be able to define specific screens in which a dock or panel should be always present. --Current solution specifies an Original dock or panel and clones/copies itself automatically to other screens. So docks and panels in other screens are just real docks and panels that reference themselves to original docks and panels. --Clones are destroyed during layout startup and are automaticaly recreated. It is suggested to export your layouts through the official Layouts Editor in order to share them because in that case clones are not included in the new generated layout file. If in any case you do not this and you share your layout with any previous versions then your clones will just appear as separate docks and panels that belong to specific screens. --Automatic syncing was introduced in order to keep up-to-date the configuration of Original docks and panels with their referenced Clones. --Automatic syncing currently works for all docks and panels settings, for all normal applets configurations and for all subcontaiments configuration such as systrays. --Automatic syncing does not work for applets inside subcontainments such as Group Plasmoid. In such case it is suggested to configure your applets inside your Group Plasmoid in the original dock or panel and afterwards to trigger a recreation for the relevant clones --Manual recreation of clones is easily possible by just choosing the dock or panel to be OnPrimary or OnSpecificScreen and rechoosing afterwards the AllScreensGroup or AllSecondaryScreensGroup
3 years ago
/*
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "originalview.h"
#include "clonedview.h"
#include "positioner.h"
#include "../lattecorona.h"
#include "../screenpool.h"
#include "../layouts/storage.h"
// KDE
#include <KLocalizedString>
namespace Latte {
OriginalView::OriginalView(Plasma::Corona *corona, QScreen *targetScreen, bool byPassX11WM)
: View(corona, targetScreen, byPassX11WM)
{
connect(this, &View::containmentChanged, this, [&]() {
if (!this->containment()) {
return;
}
connect(containment(), &Plasma::Applet::destroyedChanged, this, &OriginalView::syncClonesToScreens);
restoreConfig();
});
connect(this, &View::layoutChanged, this, &OriginalView::syncClonesToScreens);
connect(this, &OriginalView::screensGroupChanged, this, &OriginalView::syncClonesToScreens);
connect(this, &OriginalView::screensGroupChanged, this, &OriginalView::saveConfig);
}
OriginalView::~OriginalView()
{
cleanClones();
}
bool OriginalView::isSingle() const
{
return m_screensGroup == Latte::Types::SingleScreenGroup;
}
bool OriginalView::isOriginal() const
{
return true;
}
bool OriginalView::isCloned() const
{
return !isOriginal();
}
int OriginalView::clonesCount() const
{
return m_clones.count();
}
int OriginalView::expectedScreenIdFromScreenGroup(const Latte::Types::ScreensGroup &nextScreensGroup) const
{
Data::View view = data();
view.screensGroup = nextScreensGroup;
return Latte::Layouts::Storage::self()->expectedViewScreenId(m_corona, view);
}
Latte::Types::ScreensGroup OriginalView::screensGroup() const
{
return m_screensGroup;
}
void OriginalView::setScreensGroup(const Latte::Types::ScreensGroup &group)
{
if (m_screensGroup == group) {
return;
}
m_screensGroup = group;
emit screensGroupChanged();
}
void OriginalView::addClone(Latte::ClonedView *view)
{
if (m_clones.contains(view)) {
return;
}
m_clones << view;
m_waitingCreation.removeAll(view->positioner()->currentScreenId());
}
void OriginalView::removeClone(Latte::ClonedView *view)
{
if (!m_clones.contains(view)) {
return;
}
int idx = m_clones.indexOf(view);
auto cloned = m_clones.takeAt(idx);
if (!cloned->layout()) {
return;
}
cloned->positioner()->slideOutDuringExit();
cloned->layout()->removeView(cloned->data());
}
void OriginalView::createClone(int screenId)
{
if (!layout() || !containment()) {
return;
}
QString templateFile = layout()->storedView(containment()->id());
if (templateFile.isEmpty()) {
return;
}
Data::ViewsTable templateviews = Layouts::Storage::self()->views(templateFile);
if (templateviews.rowCount() <= 0) {
return;
}
Data::View nextdata = templateviews[0];
nextdata.name = i18nc("clone of original dock panel, name","Clone of %1", name());
nextdata.onPrimary = false;
nextdata.screensGroup = Latte::Types::SingleScreenGroup;
nextdata.isClonedFrom = containment()->id();
nextdata.screen = screenId;
nextdata.setState(Data::View::OriginFromViewTemplate, templateFile);
if (!m_waitingCreation.contains(screenId)) {
m_waitingCreation << screenId;
layout()->newView(nextdata);
}
}
void OriginalView::cleanClones()
{
if (m_clones.count()==0) {
return;
}
while(!m_clones.isEmpty()) {
removeClone(m_clones[0]);
}
}
void OriginalView::reconsiderScreen()
{
View::reconsiderScreen();
syncClonesToScreens();
}
void OriginalView::setNextLocationForClones(const QString layoutName, int edge, int alignment)
{
if (m_clones.count()==0) {
return;
}
for (const auto clone : m_clones) {
clone->positioner()->setNextLocation(layoutName, Latte::Types::SingleScreenGroup, "", edge, alignment);
}
}
void OriginalView::addApplet(const QString &pluginId, const int &excludecloneid)
{
if (m_clones.count() == 0) {
return;
}
// add applet in original view
extendedInterface()->addApplet(pluginId);
// add applet in clones and exclude the one that probably produced this triggering
for(const auto clone: m_clones) {
if (clone->containment()->id() == excludecloneid) {
// this way we make sure that an applet will not be double added
continue;
}
clone->extendedInterface()->addApplet(pluginId);
}
}
void OriginalView::addApplet(QObject *mimedata, const int &x, const int &y, const int &excludecloneid)
{
if (m_clones.count() == 0) {
return;
}
// add applet in original view
extendedInterface()->addApplet(mimedata, x, y);
// add applet in clones and exclude the one that probably produced this triggering
for(const auto clone: m_clones) {
if (clone->containment()->id() == excludecloneid) {
// this way we make sure that an applet will not be double added
continue;
}
clone->extendedInterface()->addApplet(mimedata, x, y);
}
}
void OriginalView::syncClonesToScreens()
{
if (isSingle() || (containment() && containment()->destroyed())) {
cleanClones();
return;
}
QList<int> secondaryscreens = m_corona->screenPool()->secondaryScreenIds();
for (const auto scrid : secondaryscreens) {
if (m_waitingCreation.contains(scrid)) {
secondaryscreens.removeAll(scrid);
}
}
if (m_screensGroup == Latte::Types::AllSecondaryScreensGroup) {
//! occuped screen from original view in "allsecondaryscreensgroup" must be ignored
secondaryscreens.removeAll(expectedScreenIdFromScreenGroup(m_screensGroup));
}
QList<Latte::ClonedView *> removable;
for (const auto clone : m_clones) {
if (secondaryscreens.contains(clone->positioner()->currentScreenId())) {
// do nothing valid clone
secondaryscreens.removeAll(clone->positioner()->currentScreenId());
} else {
// must be removed the screen is not active
removable << clone;
}
}
for (const auto scrid : secondaryscreens) {
if (removable.count() > 0) {
//! move deprecated and available clone to valid secondary screen
auto clone = removable.takeFirst();
clone->positioner()->setScreenToFollow(m_corona->screenPool()->screenForId(scrid));
} else {
//! create a new clone
createClone(scrid);
}
}
for (auto removableclone : removable) {
//! remove deprecated clones
removeClone(removableclone);
}
}
void OriginalView::saveConfig()
{
if (!this->containment()) {
return;
}
auto config = this->containment()->config();
config.writeEntry("screensGroup", (int)m_screensGroup);
}
void OriginalView::restoreConfig()
{
if (!this->containment()) {
return;
}
auto config = this->containment()->config();
m_screensGroup = static_cast<Latte::Types::ScreensGroup>(config.readEntry("screensGroup", (int)Latte::Types::SingleScreenGroup));
//! Send changed signals at the end in order to be sure that saveConfig
//! wont rewrite default/invalid values
emit screensGroupChanged();
}
}