Move core shade code to AbstractClient

Summary:
In order to allow shading wayland clients, this change moves core shade
code from X11Client to AbstractClient.

Test Plan: Shading still works on X11.

Reviewers: #kwin, cblack

Reviewed By: cblack

Subscribers: cblack, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D29512
icc-effect-master
Vlad Zahorodnii 2020-05-07 19:26:24 +03:00
parent f29ca8a293
commit 44143ef7ae
7 changed files with 132 additions and 145 deletions

View File

@ -545,6 +545,11 @@ QVector<uint> AbstractClient::x11DesktopIds() const
return x11Ids;
}
ShadeMode AbstractClient::shadeMode() const
{
return m_shadeMode;
}
bool AbstractClient::isShadeable() const
{
return false;
@ -557,12 +562,85 @@ void AbstractClient::setShade(bool set)
void AbstractClient::setShade(ShadeMode mode)
{
Q_UNUSED(mode)
if (!isShadeable())
return;
if (mode == ShadeHover && isMove())
return; // causes geometry breaks and is probably nasty
if (isSpecialWindow() || noBorder())
mode = ShadeNone;
mode = rules()->checkShade(mode);
if (m_shadeMode == mode)
return;
const bool wasShade = isShade();
const ShadeMode previousShadeMode = shadeMode();
m_shadeMode = mode;
if (wasShade == isShade()) {
// Decoration may want to update after e.g. hover-shade changes
emit shadeChanged();
return; // No real change in shaded state
}
Q_ASSERT(isDecorated());
GeometryUpdatesBlocker blocker(this);
doSetShade(previousShadeMode);
discardWindowPixmap();
updateWindowRules(Rules::Shade);
emit shadeChanged();
}
ShadeMode AbstractClient::shadeMode() const
void AbstractClient::doSetShade(ShadeMode previousShadeMode)
{
return ShadeNone;
Q_UNUSED(previousShadeMode)
}
void AbstractClient::shadeHover()
{
setShade(ShadeHover);
cancelShadeHoverTimer();
}
void AbstractClient::shadeUnhover()
{
setShade(ShadeNormal);
cancelShadeHoverTimer();
}
void AbstractClient::startShadeHoverTimer()
{
if (!isShade())
return;
m_shadeHoverTimer = new QTimer(this);
connect(m_shadeHoverTimer, &QTimer::timeout, this, &AbstractClient::shadeHover);
m_shadeHoverTimer->setSingleShot(true);
m_shadeHoverTimer->start(options->shadeHoverInterval());
}
void AbstractClient::startShadeUnhoverTimer()
{
if (m_shadeMode == ShadeHover && !isMoveResize() && !isMoveResizePointerButtonDown()) {
m_shadeHoverTimer = new QTimer(this);
connect(m_shadeHoverTimer, &QTimer::timeout, this, &AbstractClient::shadeUnhover);
m_shadeHoverTimer->setSingleShot(true);
m_shadeHoverTimer->start(options->shadeHoverInterval());
}
}
void AbstractClient::cancelShadeHoverTimer()
{
delete m_shadeHoverTimer;
m_shadeHoverTimer = nullptr;
}
void AbstractClient::toggleShade()
{
// If the mode is ShadeHover or ShadeActive, cancel shade too.
setShade(shadeMode() == ShadeNone ? ShadeNormal : ShadeNone);
}
AbstractClient::Position AbstractClient::titlebarPosition() const
@ -1745,6 +1823,18 @@ bool AbstractClient::performMouseCommand(Options::MouseCommand cmd, const QPoint
updateCursor();
break;
}
case Options::MouseShade:
toggleShade();
cancelShadeHoverTimer();
break;
case Options::MouseSetShade:
setShade(ShadeNormal);
cancelShadeHoverTimer();
break;
case Options::MouseUnsetShade:
setShade(ShadeNone);
cancelShadeHoverTimer();
break;
case Options::MouseNothing:
default:
replay = true;
@ -2324,7 +2414,11 @@ void AbstractClient::setDecoratedClient(QPointer< Decoration::DecoratedClientImp
void AbstractClient::enterEvent(const QPoint &globalPos)
{
// TODO: shade hover
if (options->isShadeHover()) {
cancelShadeHoverTimer();
startShadeHoverTimer();
}
if (options->focusPolicy() == Options::ClickToFocus || workspace()->userActionsMenu()->isShown())
return;
@ -2350,7 +2444,8 @@ void AbstractClient::leaveEvent()
{
cancelAutoRaise();
workspace()->cancelDelayFocus();
// TODO: shade hover
cancelShadeHoverTimer();
startShadeUnhoverTimer();
// TODO: send hover leave to deco
// TODO: handle Options::FocusStrictlyUnderMouse
}

View File

@ -453,7 +453,7 @@ public:
return _shortcut;
}
void setShortcut(const QString &cut);
virtual bool performMouseCommand(Options::MouseCommand, const QPoint &globalPos);
bool performMouseCommand(Options::MouseCommand, const QPoint &globalPos);
void setOnAllDesktops(bool set);
void setDesktop(int);
void enterDesktop(VirtualDesktop *desktop);
@ -517,15 +517,11 @@ public:
bool isShade() const {
return shadeMode() == ShadeNormal;
}
/**
* Default implementation returns @c ShadeNone
*/
virtual ShadeMode shadeMode() const; // Prefer isShade()
ShadeMode shadeMode() const; // Prefer isShade()
void setShade(bool set);
/**
* Default implementation does nothing
*/
virtual void setShade(ShadeMode mode);
void setShade(ShadeMode mode);
void toggleShade();
void cancelShadeHoverTimer();
/**
* Whether the Client can be shaded. Default implementation returns @c false.
*/
@ -949,6 +945,13 @@ protected:
* Default implementation does nothing.
*/
virtual void doSetKeepBelow();
/**
* Called from setShade() once the shadeMode value got updated, but before the changed signal
* is emitted.
*
* Default implementation does nothing.
*/
virtual void doSetShade(ShadeMode previousShadeMode);
/**
* Called from setDeskop once the desktop value got updated, but before the changed signal
* is emitted.
@ -1203,6 +1206,13 @@ protected:
bool tabTo(AbstractClient *other, bool behind, bool activate);
void startShadeHoverTimer();
void startShadeUnhoverTimer();
private Q_SLOTS:
void shadeHover();
void shadeUnhover();
private:
void handlePaletteChange();
QSharedPointer<TabBox::TabBoxClientImpl> m_tabBoxClient;
@ -1221,6 +1231,8 @@ private:
bool m_demandsAttention = false;
bool m_minimized = false;
QTimer *m_autoRaiseTimer = nullptr;
QTimer *m_shadeHoverTimer = nullptr;
ShadeMode m_shadeMode = ShadeNone;
QVector <VirtualDesktop *> m_desktops;
QString m_colorScheme;

View File

@ -774,16 +774,6 @@ void X11Client::enterNotifyEvent(xcb_enter_notify_event_t *e)
#define MOUSE_DRIVEN_FOCUS (!options->focusPolicyIsReasonable() || \
(options->focusPolicy() == Options::FocusFollowsMouse && options->isNextFocusPrefersMouse()))
if (e->mode == XCB_NOTIFY_MODE_NORMAL || (e->mode == XCB_NOTIFY_MODE_UNGRAB && MOUSE_DRIVEN_FOCUS)) {
if (options->isShadeHover()) {
cancelShadeHoverTimer();
if (isShade()) {
shadeHoverTimer = new QTimer(this);
connect(shadeHoverTimer, SIGNAL(timeout()), this, SLOT(shadeHover()));
shadeHoverTimer->setSingleShot(true);
shadeHoverTimer->start(options->shadeHoverInterval());
}
}
#undef MOUSE_DRIVEN_FOCUS
enterEvent(QPoint(e->root_x, e->root_y));
@ -817,13 +807,6 @@ void X11Client::leaveNotifyEvent(xcb_leave_notify_event_t *e)
}
if (lostMouse) {
leaveEvent();
cancelShadeHoverTimer();
if (shade_mode == ShadeHover && !isMoveResize() && !isMoveResizePointerButtonDown()) {
shadeHoverTimer = new QTimer(this);
connect(shadeHoverTimer, SIGNAL(timeout()), this, SLOT(shadeUnhover()));
shadeHoverTimer->setSingleShot(true);
shadeHoverTimer->start(options->shadeHoverInterval());
}
if (isDecorated()) {
// sending a move instead of a leave. With leave we need to send proper coords, with move it's handled internally
QHoverEvent leaveEvent(QEvent::HoverMove, QPointF(-1, -1), QPointF(-1, -1), Qt::NoModifier);

View File

@ -318,16 +318,12 @@ void TabBoxHandlerImpl::elevateClient(TabBoxClient *c, QWindow *tabbox, bool b)
void TabBoxHandlerImpl::shadeClient(TabBoxClient *c, bool b) const
{
X11Client *cl = dynamic_cast<X11Client *>(static_cast<TabBoxClientImpl*>(c)->client());
if (!cl) {
// shading is X11 specific
return;
}
cl->cancelShadeHoverTimer(); // stop core shading action
if (!b && cl->shadeMode() == ShadeNormal)
cl->setShade(ShadeHover);
else if (b && cl->shadeMode() == ShadeHover)
cl->setShade(ShadeNormal);
AbstractClient *client = static_cast<TabBoxClientImpl *>(c)->client();
client->cancelShadeHoverTimer(); // stop core shading action
if (!b && client->shadeMode() == ShadeNormal)
client->setShade(ShadeHover);
else if (b && client->shadeMode() == ShadeHover)
client->setShade(ShadeNormal);
}
QWeakPointer<TabBoxClient> TabBoxHandlerImpl::desktopClient() const

View File

@ -1132,31 +1132,6 @@ void Workspace::performWindowOperation(AbstractClient* c, Options::WindowOperati
}
}
/**
* Performs a mouse command on this client (see options.h)
*/
bool X11Client::performMouseCommand(Options::MouseCommand command, const QPoint &globalPos)
{
bool replay = false;
switch(command) {
case Options::MouseShade :
toggleShade();
cancelShadeHoverTimer();
break;
case Options::MouseSetShade:
setShade(ShadeNormal);
cancelShadeHoverTimer();
break;
case Options::MouseUnsetShade:
setShade(ShadeNone);
cancelShadeHoverTimer();
break;
default:
return AbstractClient::performMouseCommand(command, globalPos);
}
return replay;
}
void Workspace::slotActivateAttentionWindow()
{
if (attention_chain.count() > 0)

View File

@ -120,7 +120,6 @@ X11Client::X11Client()
, shade_below(nullptr)
, m_motif(atoms->motif_wm_hints)
, blocks_compositing(false)
, shadeHoverTimer(nullptr)
, m_colormap(XCB_COLORMAP_NONE)
, in_group(nullptr)
, ping_timer(nullptr)
@ -147,7 +146,6 @@ X11Client::X11Client()
info = nullptr;
shade_mode = ShadeNone;
deleting = false;
m_fullscreenMode = FullScreenNone;
hidden = false;
@ -1468,35 +1466,8 @@ bool X11Client::isShadeable() const
return !isSpecialWindow() && !noBorder() && (rules()->checkShade(ShadeNormal) != rules()->checkShade(ShadeNone));
}
void X11Client::setShade(ShadeMode mode)
void X11Client::doSetShade(ShadeMode previousShadeMode)
{
if (mode == ShadeHover && isMove())
return; // causes geometry breaks and is probably nasty
if (isSpecialWindow() || noBorder())
mode = ShadeNone;
mode = rules()->checkShade(mode);
if (shade_mode == mode)
return;
bool was_shade = isShade();
ShadeMode was_shade_mode = shade_mode;
shade_mode = mode;
// Decorations may turn off some borders when shaded
// this has to happen _before_ the tab alignment since it will restrict the minimum geometry
#if 0
if (decoration)
decoration->borders(border_left, border_right, border_top, border_bottom);
#endif
if (was_shade == isShade()) {
// Decoration may want to update after e.g. hover-shade changes
emit shadeChanged();
return; // No real change in shaded state
}
Q_ASSERT(isDecorated()); // noborder windows can't be shaded
GeometryUpdatesBlocker blocker(this);
// TODO: All this unmapping, resizing etc. feels too much duplicated from elsewhere
if (isShade()) {
// shade_mode == ShadeNormal
@ -1512,7 +1483,7 @@ void X11Client::setShade(ShadeMode mode)
exportMappingState(XCB_ICCCM_WM_STATE_ICONIC);
plainResize(s);
shade_geometry_change = false;
if (was_shade_mode == ShadeHover) {
if (previousShadeMode == ShadeHover) {
if (shade_below && workspace()->stackingOrder().indexOf(shade_below) > -1)
workspace()->restack(this, shade_below, true);
if (isActive())
@ -1528,9 +1499,9 @@ void X11Client::setShade(ShadeMode mode)
shade_geometry_change = false;
plainResize(s);
setGeometryRestore(frameGeometry());
if ((shade_mode == ShadeHover || shade_mode == ShadeActivated) && rules()->checkAcceptFocus(info->input()))
if ((shadeMode() == ShadeHover || shadeMode() == ShadeActivated) && rules()->checkAcceptFocus(info->input()))
setActive(true);
if (shade_mode == ShadeHover) {
if (shadeMode() == ShadeHover) {
QList<Toplevel *> order = workspace()->stackingOrder();
// invalidate, since "this" could be the topmost toplevel and shade_below dangeling
shade_below = nullptr;
@ -1554,36 +1525,8 @@ void X11Client::setShade(ShadeMode mode)
}
info->setState(isShade() ? NET::Shaded : NET::States(), NET::Shaded);
info->setState(isShown(false) ? NET::States() : NET::Hidden, NET::Hidden);
discardWindowPixmap();
updateVisibility();
updateAllowedActions();
updateWindowRules(Rules::Shade);
emit shadeChanged();
}
void X11Client::shadeHover()
{
setShade(ShadeHover);
cancelShadeHoverTimer();
}
void X11Client::shadeUnhover()
{
setShade(ShadeNormal);
cancelShadeHoverTimer();
}
void X11Client::cancelShadeHoverTimer()
{
delete shadeHoverTimer;
shadeHoverTimer = nullptr;
}
void X11Client::toggleShade()
{
// If the mode is ShadeHover or ShadeActive, cancel shade too
setShade(shade_mode == ShadeNone ? ShadeNormal : ShadeNone);
}
void X11Client::updateVisibility()

View File

@ -144,10 +144,7 @@ public:
bool isShown(bool shaded_is_shown) const override;
bool isHiddenInternal() const override; // For compositing
ShadeMode shadeMode() const override; // Prefer isShade()
void setShade(ShadeMode mode) override;
bool isShadeable() const override;
bool isMaximizable() const override;
MaximizeMode maximizeMode() const override;
@ -201,8 +198,6 @@ public:
bool providesContextHelp() const override;
bool performMouseCommand(Options::MouseCommand, const QPoint& globalPos) override;
QRect adjustedClientArea(const QRect& desktop, const QRect& area) const;
xcb_colormap_t colormap() const;
@ -251,9 +246,7 @@ public:
static bool sameAppWindowRoleMatch(const X11Client *c1, const X11Client *c2, bool active_hack);
void killWindow() override;
void toggleShade();
void showContextHelp() override;
void cancelShadeHoverTimer();
void checkActiveModal();
StrutRect strutRect(StrutArea area) const;
StrutRects strutRects() const;
@ -330,10 +323,6 @@ public Q_SLOTS:
void closeWindow() override;
void updateCaption() override;
private Q_SLOTS:
void shadeHover();
void shadeUnhover();
private:
// Handlers for X11 events
bool mapRequestEvent(xcb_map_request_event_t *e);
@ -359,6 +348,7 @@ protected:
void doSetActive() override;
void doSetKeepAbove() override;
void doSetKeepBelow() override;
void doSetShade(ShadeMode previousShadeMode) override;
void doSetDesktop() override;
void doMinimize() override;
void doSetSkipPager() override;
@ -503,7 +493,6 @@ private:
void setTransient(xcb_window_t new_transient_for_id);
xcb_window_t m_transientForId;
xcb_window_t m_originalTransientForId;
ShadeMode shade_mode;
X11Client *shade_below;
uint deleting : 1; ///< True when doing cleanup and destroying the client
Xcb::MotifHints m_motif;
@ -522,7 +511,6 @@ private:
QRect m_bufferGeometry = QRect(0, 0, 100, 100);
QRect m_clientGeometry = QRect(0, 0, 100, 100);
QRect geom_fs_restore;
QTimer* shadeHoverTimer;
xcb_colormap_t m_colormap;
QString cap_normal, cap_iconic, cap_suffix;
Group* in_group;
@ -607,11 +595,6 @@ inline bool X11Client::isHiddenInternal() const
return hidden;
}
inline ShadeMode X11Client::shadeMode() const
{
return shade_mode;
}
inline MaximizeMode X11Client::maximizeMode() const
{
return max_mode;