358 lines
8.3 KiB
C++
358 lines
8.3 KiB
C++
/********************************************************************
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*********************************************************************/
|
|
#include "abstract_client.h"
|
|
#include "focuschain.h"
|
|
#ifdef KWIN_BUILD_TABBOX
|
|
#include "tabbox.h"
|
|
#endif
|
|
#include "workspace.h"
|
|
|
|
namespace KWin
|
|
{
|
|
|
|
AbstractClient::AbstractClient()
|
|
: Toplevel()
|
|
#ifdef KWIN_BUILD_TABBOX
|
|
, m_tabBoxClient(QSharedPointer<TabBox::TabBoxClientImpl>(new TabBox::TabBoxClientImpl(this)))
|
|
#endif
|
|
{
|
|
}
|
|
|
|
AbstractClient::~AbstractClient() = default;
|
|
|
|
void AbstractClient::updateMouseGrab()
|
|
{
|
|
}
|
|
|
|
bool AbstractClient::belongToSameApplication(const AbstractClient *c1, const AbstractClient *c2, bool active_hack)
|
|
{
|
|
return c1->belongsToSameApplication(c2, active_hack);
|
|
}
|
|
|
|
bool AbstractClient::isTransient() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TabGroup *AbstractClient::tabGroup() const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
bool AbstractClient::untab(const QRect &toGeometry, bool clientRemoved)
|
|
{
|
|
Q_UNUSED(toGeometry)
|
|
Q_UNUSED(clientRemoved)
|
|
return false;
|
|
}
|
|
|
|
bool AbstractClient::isCurrentTab() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void AbstractClient::growHorizontal()
|
|
{
|
|
}
|
|
|
|
void AbstractClient::growVertical()
|
|
{
|
|
}
|
|
|
|
void AbstractClient::shrinkHorizontal()
|
|
{
|
|
}
|
|
|
|
void AbstractClient::shrinkVertical()
|
|
{
|
|
}
|
|
|
|
void AbstractClient::packTo(int left, int top)
|
|
{
|
|
Q_UNUSED(left)
|
|
Q_UNUSED(top)
|
|
}
|
|
|
|
xcb_timestamp_t AbstractClient::userTime() const
|
|
{
|
|
return XCB_TIME_CURRENT_TIME;
|
|
}
|
|
|
|
void AbstractClient::setSkipSwitcher(bool set)
|
|
{
|
|
set = rules()->checkSkipSwitcher(set);
|
|
if (set == skipSwitcher())
|
|
return;
|
|
m_skipSwitcher = set;
|
|
updateWindowRules(Rules::SkipSwitcher);
|
|
emit skipSwitcherChanged();
|
|
}
|
|
|
|
void AbstractClient::setIcon(const QIcon &icon)
|
|
{
|
|
m_icon = icon;
|
|
emit iconChanged();
|
|
}
|
|
|
|
void AbstractClient::setActive(bool act)
|
|
{
|
|
if (m_active == act) {
|
|
return;
|
|
}
|
|
m_active = act;
|
|
const int ruledOpacity = m_active
|
|
? rules()->checkOpacityActive(qRound(opacity() * 100.0))
|
|
: rules()->checkOpacityInactive(qRound(opacity() * 100.0));
|
|
setOpacity(ruledOpacity / 100.0);
|
|
workspace()->setActiveClient(act ? this : NULL);
|
|
|
|
if (!m_active)
|
|
cancelAutoRaise();
|
|
|
|
if (!m_active && shadeMode() == ShadeActivated)
|
|
setShade(ShadeNormal);
|
|
|
|
doSetActive();
|
|
emit activeChanged();
|
|
updateMouseGrab();
|
|
}
|
|
|
|
void AbstractClient::doSetActive()
|
|
{
|
|
}
|
|
|
|
void AbstractClient::updateLayer()
|
|
{
|
|
}
|
|
|
|
void AbstractClient::setKeepAbove(bool b)
|
|
{
|
|
b = rules()->checkKeepAbove(b);
|
|
if (b && !rules()->checkKeepBelow(false))
|
|
setKeepBelow(false);
|
|
if (b == keepAbove()) {
|
|
// force hint change if different
|
|
if (info && bool(info->state() & NET::KeepAbove) != keepAbove())
|
|
info->setState(keepAbove() ? NET::KeepAbove : NET::States(0), NET::KeepAbove);
|
|
return;
|
|
}
|
|
m_keepAbove = b;
|
|
if (info) {
|
|
info->setState(keepAbove() ? NET::KeepAbove : NET::States(0), NET::KeepAbove);
|
|
}
|
|
workspace()->updateClientLayer(this);
|
|
updateWindowRules(Rules::Above);
|
|
|
|
doSetKeepAbove();
|
|
emit keepAboveChanged(m_keepAbove);
|
|
}
|
|
|
|
void AbstractClient::doSetKeepAbove()
|
|
{
|
|
}
|
|
|
|
void AbstractClient::setKeepBelow(bool b)
|
|
{
|
|
b = rules()->checkKeepBelow(b);
|
|
if (b && !rules()->checkKeepAbove(false))
|
|
setKeepAbove(false);
|
|
if (b == keepBelow()) {
|
|
// force hint change if different
|
|
if (info && bool(info->state() & NET::KeepBelow) != keepBelow())
|
|
info->setState(keepBelow() ? NET::KeepBelow : NET::States(0), NET::KeepBelow);
|
|
return;
|
|
}
|
|
m_keepBelow = b;
|
|
if (info) {
|
|
info->setState(keepBelow() ? NET::KeepBelow : NET::States(0), NET::KeepBelow);
|
|
}
|
|
workspace()->updateClientLayer(this);
|
|
updateWindowRules(Rules::Below);
|
|
|
|
doSetKeepBelow();
|
|
emit keepBelowChanged(m_keepBelow);
|
|
}
|
|
|
|
void AbstractClient::doSetKeepBelow()
|
|
{
|
|
}
|
|
|
|
void AbstractClient::startAutoRaise()
|
|
{
|
|
delete m_autoRaiseTimer;
|
|
m_autoRaiseTimer = new QTimer(this);
|
|
connect(m_autoRaiseTimer, &QTimer::timeout, this, &AbstractClient::autoRaise);
|
|
m_autoRaiseTimer->setSingleShot(true);
|
|
m_autoRaiseTimer->start(options->autoRaiseInterval());
|
|
}
|
|
|
|
void AbstractClient::cancelAutoRaise()
|
|
{
|
|
delete m_autoRaiseTimer;
|
|
m_autoRaiseTimer = nullptr;
|
|
}
|
|
|
|
void AbstractClient::autoRaise()
|
|
{
|
|
workspace()->raiseClient(this);
|
|
cancelAutoRaise();
|
|
}
|
|
|
|
bool AbstractClient::wantsTabFocus() const
|
|
{
|
|
return (isNormalWindow() || isDialog()) && wantsInput();
|
|
}
|
|
|
|
bool AbstractClient::isSpecialWindow() const
|
|
{
|
|
// TODO
|
|
return isDesktop() || isDock() || isSplash() || isToolbar() || isNotification() || isOnScreenDisplay();
|
|
}
|
|
|
|
void AbstractClient::demandAttention(bool set)
|
|
{
|
|
if (isActive())
|
|
set = false;
|
|
if (m_demandsAttention == set)
|
|
return;
|
|
m_demandsAttention = set;
|
|
if (info) {
|
|
info->setState(set ? NET::DemandsAttention : NET::States(0), NET::DemandsAttention);
|
|
}
|
|
workspace()->clientAttentionChanged(this, set);
|
|
emit demandsAttentionChanged();
|
|
}
|
|
|
|
void AbstractClient::setDesktop(int desktop)
|
|
{
|
|
const int numberOfDesktops = VirtualDesktopManager::self()->count();
|
|
if (desktop != NET::OnAllDesktops) // Do range check
|
|
desktop = qMax(1, qMin(numberOfDesktops, desktop));
|
|
desktop = qMin(numberOfDesktops, rules()->checkDesktop(desktop));
|
|
if (m_desktop == desktop)
|
|
return;
|
|
|
|
int was_desk = m_desktop;
|
|
const bool wasOnCurrentDesktop = isOnCurrentDesktop();
|
|
m_desktop = desktop;
|
|
|
|
doSetDesktop(desktop, was_desk);
|
|
|
|
FocusChain::self()->update(this, FocusChain::MakeFirst);
|
|
updateWindowRules(Rules::Desktop);
|
|
|
|
emit desktopChanged();
|
|
if (wasOnCurrentDesktop != isOnCurrentDesktop())
|
|
emit desktopPresenceChanged(this, was_desk);
|
|
}
|
|
|
|
void AbstractClient::doSetDesktop(int desktop, int was_desk)
|
|
{
|
|
Q_UNUSED(desktop)
|
|
Q_UNUSED(was_desk)
|
|
}
|
|
|
|
void AbstractClient::setOnAllDesktops(bool b)
|
|
{
|
|
if ((b && isOnAllDesktops()) ||
|
|
(!b && !isOnAllDesktops()))
|
|
return;
|
|
if (b)
|
|
setDesktop(NET::OnAllDesktops);
|
|
else
|
|
setDesktop(VirtualDesktopManager::self()->current());
|
|
}
|
|
|
|
bool AbstractClient::isShadeable() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void AbstractClient::setShade(bool set)
|
|
{
|
|
set ? setShade(ShadeNormal) : setShade(ShadeNone);
|
|
}
|
|
|
|
void AbstractClient::setShade(ShadeMode mode)
|
|
{
|
|
Q_UNUSED(mode)
|
|
}
|
|
|
|
ShadeMode AbstractClient::shadeMode() const
|
|
{
|
|
return ShadeNone;
|
|
}
|
|
|
|
AbstractClient::Position AbstractClient::titlebarPosition() const
|
|
{
|
|
// TODO: still needed, remove?
|
|
return PositionTop;
|
|
}
|
|
|
|
void AbstractClient::setMinimized(bool set)
|
|
{
|
|
set ? minimize() : unminimize();
|
|
}
|
|
|
|
void AbstractClient::minimize(bool avoid_animation)
|
|
{
|
|
if (!isMinimizable() || isMinimized())
|
|
return;
|
|
|
|
if (isShade() && info) // NETWM restriction - KWindowInfo::isMinimized() == Hidden && !Shaded
|
|
info->setState(0, NET::Shaded);
|
|
|
|
m_minimized = true;
|
|
|
|
doMinimize();
|
|
|
|
updateWindowRules(Rules::Minimize);
|
|
FocusChain::self()->update(this, FocusChain::MakeFirstMinimized);
|
|
// TODO: merge signal with s_minimized
|
|
emit clientMinimized(this, !avoid_animation);
|
|
emit minimizedChanged();
|
|
}
|
|
|
|
void AbstractClient::unminimize(bool avoid_animation)
|
|
{
|
|
if (!isMinimized())
|
|
return;
|
|
|
|
if (rules()->checkMinimize(false)) {
|
|
return;
|
|
}
|
|
|
|
if (isShade() && info) // NETWM restriction - KWindowInfo::isMinimized() == Hidden && !Shaded
|
|
info->setState(NET::Shaded, NET::Shaded);
|
|
|
|
m_minimized = false;
|
|
|
|
doMinimize();
|
|
|
|
updateWindowRules(Rules::Minimize);
|
|
emit clientUnminimized(this, !avoid_animation);
|
|
emit minimizedChanged();
|
|
}
|
|
|
|
void AbstractClient::doMinimize()
|
|
{
|
|
}
|
|
|
|
}
|