Port FocusChain to VirtualDesktop

This commit is contained in:
Vlad Zahorodnii 2021-08-16 15:07:43 +03:00
parent 42f2afd80d
commit 7c8d9c5b1c
5 changed files with 45 additions and 48 deletions

View file

@ -482,7 +482,7 @@ bool Workspace::activateNextClient(AbstractClient* c)
}
if (!get_focus) {
// nope, ask the focus chain for the next candidate
get_focus = FocusChain::self()->nextForDesktop(c, desktop->x11DesktopNumber());
get_focus = FocusChain::self()->nextForDesktop(c, desktop);
}
}
@ -506,7 +506,7 @@ void Workspace::setCurrentScreen(int new_screen)
return;
closeActivePopup();
VirtualDesktop *desktop = VirtualDesktopManager::self()->currentDesktop();
AbstractClient *get_focus = FocusChain::self()->getForActivation(desktop->x11DesktopNumber(), new_screen);
AbstractClient *get_focus = FocusChain::self()->getForActivation(desktop, new_screen);
if (get_focus == nullptr)
get_focus = findDesktop(true, desktop);
if (get_focus != nullptr && get_focus != mostRecentlyActivatedClient())

View file

@ -19,7 +19,6 @@ FocusChain::FocusChain(QObject *parent)
: QObject(parent)
, m_separateScreenFocus(false)
, m_activeClient(nullptr)
, m_currentDesktop(0)
{
}
@ -38,22 +37,25 @@ void FocusChain::remove(AbstractClient *client)
m_mostRecentlyUsed.removeAll(client);
}
void FocusChain::resize(uint previousSize, uint newSize)
void FocusChain::addDesktop(VirtualDesktop *desktop)
{
for (uint i = previousSize + 1; i <= newSize; ++i) {
m_desktopFocusChains.insert(i, Chain());
}
for (uint i = previousSize; i > newSize; --i) {
m_desktopFocusChains.remove(i);
}
m_desktopFocusChains.insert(desktop, Chain());
}
AbstractClient *FocusChain::getForActivation(uint desktop) const
void FocusChain::removeDesktop(VirtualDesktop *desktop)
{
if (m_currentDesktop == desktop) {
m_currentDesktop = nullptr;
}
m_desktopFocusChains.remove(desktop);
}
AbstractClient *FocusChain::getForActivation(VirtualDesktop *desktop) const
{
return getForActivation(desktop, screens()->current());
}
AbstractClient *FocusChain::getForActivation(uint desktop, int screen) const
AbstractClient *FocusChain::getForActivation(VirtualDesktop *desktop, int screen) const
{
auto it = m_desktopFocusChains.constFind(desktop);
if (it == m_desktopFocusChains.constEnd()) {
@ -208,7 +210,7 @@ bool FocusChain::isUsableFocusCandidate(AbstractClient *c, AbstractClient *prev)
(!m_separateScreenFocus || c->isOnScreen(prev ? prev->screen() : screens()->current()));
}
AbstractClient *FocusChain::nextForDesktop(AbstractClient *reference, uint desktop) const
AbstractClient *FocusChain::nextForDesktop(AbstractClient *reference, VirtualDesktop *desktop) const
{
auto it = m_desktopFocusChains.constFind(desktop);
if (it == m_desktopFocusChains.constEnd()) {
@ -250,7 +252,7 @@ void FocusChain::makeLastInChain(AbstractClient *client, Chain &chain)
chain.prepend(client);
}
bool FocusChain::contains(AbstractClient *client, uint desktop) const
bool FocusChain::contains(AbstractClient *client, VirtualDesktop *desktop) const
{
auto it = m_desktopFocusChains.constFind(desktop);
if (it == m_desktopFocusChains.constEnd()) {

View file

@ -18,6 +18,7 @@ namespace KWin
{
// forward declarations
class AbstractClient;
class VirtualDesktop;
/**
* @brief Singleton class to handle the various focus chains.
@ -87,7 +88,7 @@ public:
* @param desktop The virtual desktop to look for a Client for activation
* @return :X11Client *The Client which could be activated or @c null if there is none.
*/
AbstractClient *getForActivation(uint desktop) const;
AbstractClient *getForActivation(VirtualDesktop *desktop) const;
/**
* @brief Finds the best Client to become the new active Client in the focus chain for the given
* virtual @p desktop on the given @p screen.
@ -100,7 +101,7 @@ public:
* @param screen The screen to constrain the search on with separate screen focus
* @return :X11Client *The Client which could be activated or @c null if there is none.
*/
AbstractClient *getForActivation(uint desktop, int screen) const;
AbstractClient *getForActivation(VirtualDesktop *desktop, int screen) const;
/**
* @brief Checks whether the most recently used focus chain contains the given @p client.
@ -119,7 +120,7 @@ public:
* @param desktop The virtual desktop whose focus chain should be used
* @return bool @c true if the focus chain for @p desktop contains @p client, @c false otherwise.
*/
bool contains(AbstractClient *client, uint desktop) const;
bool contains(AbstractClient *client, VirtualDesktop *desktop) const;
/**
* @brief Queries the most recently used focus chain for the next Client after the given
* @p reference Client.
@ -145,7 +146,7 @@ public:
* @param desktop The virtual desktop whose focus chain should be used
* @return :X11Client *The next usable Client or @c null if none can be found.
*/
AbstractClient *nextForDesktop(AbstractClient *reference, uint desktop) const;
AbstractClient *nextForDesktop(AbstractClient *reference, VirtualDesktop *desktop) const;
/**
* @brief Returns the first Client in the most recently used focus chain. First Client in this
* case means really the first Client in the chain and not the most recently used Client.
@ -157,16 +158,6 @@ public:
bool isUsableFocusCandidate(AbstractClient *c, AbstractClient *prev) const;
public Q_SLOTS:
/**
* @brief Resizes the per virtual desktop focus chains from @p previousSize to @p newSize.
* This means that for each virtual desktop between previous and new size a new focus chain is
* created and in case the number is reduced the focus chains are destroyed.
*
* @param previousSize The previous number of virtual desktops
* @param newSize The new number of virtual desktops
* @return void
*/
void resize(uint previousSize, uint newSize);
/**
* @brief Removes @p client from all focus chains.
*
@ -176,7 +167,9 @@ public Q_SLOTS:
void remove(KWin::AbstractClient *client);
void setSeparateScreenFocus(bool enabled);
void setActiveClient(KWin::AbstractClient *client);
void setCurrentDesktop(uint previous, uint newDesktop);
void setCurrentDesktop(VirtualDesktop *desktop);
void addDesktop(VirtualDesktop *desktop);
void removeDesktop(VirtualDesktop *desktop);
private:
using Chain = QList<AbstractClient*>;
@ -206,10 +199,10 @@ private:
void updateClientInChain(AbstractClient *client, Change change, Chain &chain);
void insertClientIntoChain(AbstractClient *client, Chain &chain);
Chain m_mostRecentlyUsed;
QHash<uint, Chain> m_desktopFocusChains;
QHash<VirtualDesktop *, Chain> m_desktopFocusChains;
bool m_separateScreenFocus;
AbstractClient *m_activeClient;
uint m_currentDesktop;
VirtualDesktop *m_currentDesktop = nullptr;
KWIN_SINGLETON_VARIABLE(FocusChain, s_manager)
};
@ -233,10 +226,9 @@ void FocusChain::setActiveClient(AbstractClient *client)
}
inline
void FocusChain::setCurrentDesktop(uint previous, uint newDesktop)
void FocusChain::setCurrentDesktop(VirtualDesktop *desktop)
{
Q_UNUSED(previous)
m_currentDesktop = newDesktop;
m_currentDesktop = desktop;
}
} // namespace

View file

@ -223,8 +223,11 @@ void Workspace::init()
FocusChain *focusChain = FocusChain::create(this);
connect(this, &Workspace::clientRemoved, focusChain, &FocusChain::remove);
connect(this, &Workspace::clientActivated, focusChain, &FocusChain::setActiveClient);
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::countChanged, focusChain, &FocusChain::resize);
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::currentChanged, focusChain, &FocusChain::setCurrentDesktop);
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::desktopCreated, focusChain, &FocusChain::addDesktop);
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::desktopRemoved, focusChain, &FocusChain::removeDesktop);
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::currentChanged, focusChain, [focusChain]() {
focusChain->setCurrentDesktop(VirtualDesktopManager::self()->currentDesktop());
});
connect(options, &Options::separateScreenFocusChanged, focusChain, &FocusChain::setSeparateScreenFocus);
focusChain->setSeparateScreenFocus(options->isSeparateScreenFocus());
@ -1018,15 +1021,15 @@ void Workspace::slotCurrentDesktopChanged(uint oldDesktop, uint newDesktop)
closeActivePopup();
++block_focus;
StackingUpdatesBlocker blocker(this);
updateClientVisibilityOnDesktopChange(newDesktop);
updateClientVisibilityOnDesktopChange(VirtualDesktopManager::self()->desktopForX11Id(newDesktop));
// Restore the focus on this desktop
--block_focus;
activateClientOnNewDesktop(newDesktop);
activateClientOnNewDesktop(VirtualDesktopManager::self()->desktopForX11Id(newDesktop));
Q_EMIT currentDesktopChanged(oldDesktop, movingClient);
}
void Workspace::updateClientVisibilityOnDesktopChange(uint newDesktop)
void Workspace::updateClientVisibilityOnDesktopChange(VirtualDesktop *newDesktop)
{
for (auto it = stacking_order.constBegin();
it != stacking_order.constEnd();
@ -1045,7 +1048,7 @@ void Workspace::updateClientVisibilityOnDesktopChange(uint newDesktop)
}
if (movingClient && !movingClient->isOnDesktop(newDesktop)) {
movingClient->setDesktop(newDesktop);
movingClient->setDesktops({newDesktop});
}
for (int i = stacking_order.size() - 1; i >= 0 ; --i) {
@ -1060,7 +1063,7 @@ void Workspace::updateClientVisibilityOnDesktopChange(uint newDesktop)
setShowingDesktop(false);
}
void Workspace::activateClientOnNewDesktop(uint desktop)
void Workspace::activateClientOnNewDesktop(VirtualDesktop *desktop)
{
AbstractClient* c = nullptr;
if (options->focusPolicyIsReasonable()) {
@ -1073,7 +1076,7 @@ void Workspace::activateClientOnNewDesktop(uint desktop)
c = active_client;
if (!c)
c = findDesktop(true, VirtualDesktopManager::self()->desktopForX11Id(desktop));
c = findDesktop(true, desktop);
if (c != active_client)
setActiveClient(nullptr);
@ -1084,7 +1087,7 @@ void Workspace::activateClientOnNewDesktop(uint desktop)
focusToNull();
}
AbstractClient *Workspace::findClientToActivateOnDesktop(uint desktop)
AbstractClient *Workspace::findClientToActivateOnDesktop(VirtualDesktop *desktop)
{
if (movingClient != nullptr && active_client == movingClient &&
FocusChain::self()->contains(active_client, desktop) &&
@ -1178,7 +1181,7 @@ void Workspace::updateCurrentActivity(const QString &new_activity)
//FIXME below here is a lot of focuschain stuff, probably all wrong now
if (options->focusPolicyIsReasonable()) {
// Search in focus chain
c = FocusChain::self()->getForActivation(VirtualDesktopManager::self()->current());
c = FocusChain::self()->getForActivation(VirtualDesktopManager::self()->currentDesktop());
}
// If "unreasonable focus policy" and active_client is on_all_desktops and
// under mouse (Hence == old_active_client), conserve focus.
@ -1393,7 +1396,7 @@ void Workspace::setShowingDesktop(bool showing)
if (showing_desktop && topDesk) {
requestFocus(topDesk);
} else if (!showing_desktop && changed) {
const auto client = FocusChain::self()->getForActivation(VirtualDesktopManager::self()->current());
const auto client = FocusChain::self()->getForActivation(VirtualDesktopManager::self()->currentDesktop());
if (client) {
activateClient(client);
}

View file

@ -558,9 +558,9 @@ private:
void closeActivePopup();
void updateClientArea(bool force);
void resetClientAreas(uint desktopCount);
void updateClientVisibilityOnDesktopChange(uint newDesktop);
void activateClientOnNewDesktop(uint desktop);
AbstractClient *findClientToActivateOnDesktop(uint desktop);
void updateClientVisibilityOnDesktopChange(VirtualDesktop *newDesktop);
void activateClientOnNewDesktop(VirtualDesktop *desktop);
AbstractClient *findClientToActivateOnDesktop(VirtualDesktop *desktop);
void removeAbstractClient(AbstractClient *client);
struct Constraint