abstract_client.h 41 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/********************************************************************
 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/>.
*********************************************************************/
#ifndef KWIN_ABSTRACT_CLIENT_H
#define KWIN_ABSTRACT_CLIENT_H

#include "toplevel.h"
24
#include "options.h"
25
#include "rules.h"
26
#include "tabgroup.h"
27

28 29
#include <memory>

30
#include <QElapsedTimer>
31
#include <QPointer>
32

33 34 35 36 37 38 39 40
namespace KWayland
{
namespace Server
{
class PlasmaWindowInterface;
}
}

41 42 43 44 45
namespace KDecoration2
{
class Decoration;
}

46 47 48 49 50 51 52 53
namespace KWin
{

namespace TabBox
{
class TabBoxClientImpl;
}

54 55
namespace Decoration
{
56
class DecoratedClientImpl;
57 58 59
class DecorationPalette;
}

60
class KWIN_EXPORT AbstractClient : public Toplevel
61 62
{
    Q_OBJECT
63 64 65 66 67 68 69 70 71 72 73
    /**
     * Whether this Client is fullScreen. A Client might either be fullScreen due to the _NET_WM property
     * or through a legacy support hack. The fullScreen state can only be changed if the Client does not
     * use the legacy hack. To be sure whether the state changed, connect to the notify signal.
     **/
    Q_PROPERTY(bool fullScreen READ isFullScreen WRITE setFullScreen NOTIFY fullScreenChanged)
    /**
     * Whether the Client can be set to fullScreen. The property is evaluated each time it is invoked.
     * Because of that there is no notify signal.
     **/
    Q_PROPERTY(bool fullScreenable READ isFullScreenable)
74 75 76 77 78
    /**
     * Whether this Client is the currently visible Client in its Client Group (Window Tabs).
     * For change connect to the visibleChanged signal on the Client's Group.
     **/
    Q_PROPERTY(bool isCurrentTab READ isCurrentTab)
79 80 81 82 83
    /**
     * Whether this Client is active or not. Use Workspace::activateClient() to activate a Client.
     * @see Workspace::activateClient
     **/
    Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
84 85 86 87 88 89 90 91
    /**
     * The desktop this Client is on. If the Client is on all desktops the property has value -1.
     **/
    Q_PROPERTY(int desktop READ desktop WRITE setDesktop NOTIFY desktopChanged)
    /**
     * Whether the Client is on all desktops. That is desktop is -1.
     **/
    Q_PROPERTY(bool onAllDesktops READ isOnAllDesktops WRITE setOnAllDesktops NOTIFY desktopChanged)
92 93 94 95
    /**
     * Indicates that the window should not be included on a taskbar.
     **/
    Q_PROPERTY(bool skipTaskbar READ skipTaskbar WRITE setSkipTaskbar NOTIFY skipTaskbarChanged)
96 97 98 99
    /**
     * Indicates that the window should not be included on a Pager.
     **/
    Q_PROPERTY(bool skipPager READ skipPager WRITE setSkipPager NOTIFY skipPagerChanged)
100 101 102 103
    /**
     * Whether the Client should be excluded from window switching effects.
     **/
    Q_PROPERTY(bool skipSwitcher READ skipSwitcher WRITE setSkipSwitcher NOTIFY skipSwitcherChanged)
104 105 106 107 108
    /**
     * Whether the window can be closed by the user. The value is evaluated each time the getter is called.
     * Because of that no changed signal is provided.
     **/
    Q_PROPERTY(bool closeable READ isCloseable)
109
    Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged)
110 111 112 113 114 115 116 117
    /**
     * Whether the Client is set to be kept above other windows.
     **/
    Q_PROPERTY(bool keepAbove READ keepAbove WRITE setKeepAbove NOTIFY keepAboveChanged)
    /**
     * Whether the Client is set to be kept below other windows.
     **/
    Q_PROPERTY(bool keepBelow READ keepBelow WRITE setKeepBelow NOTIFY keepBelowChanged)
118 119 120 121 122 123 124 125 126
    /**
     * Whether the Client can be shaded. The property is evaluated each time it is invoked.
     * Because of that there is no notify signal.
     **/
    Q_PROPERTY(bool shadeable READ isShadeable)
    /**
     * Whether the Client is shaded.
     **/
    Q_PROPERTY(bool shade READ isShade WRITE setShade NOTIFY shadeChanged)
127 128 129 130 131 132 133 134 135
    /**
     * Whether the Client can be minimized. The property is evaluated each time it is invoked.
     * Because of that there is no notify signal.
     **/
    Q_PROPERTY(bool minimizable READ isMinimizable)
    /**
     * Whether the Client is minimized.
     **/
    Q_PROPERTY(bool minimized READ isMinimized WRITE setMinimized NOTIFY minimizedChanged)
136 137 138 139 140 141 142
    /**
     * The optional geometry representing the minimized Client in e.g a taskbar.
     * See _NET_WM_ICON_GEOMETRY at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
     * The value is evaluated each time the getter is called.
     * Because of that no changed signal is provided.
     **/
    Q_PROPERTY(QRect iconGeometry READ iconGeometry)
143 144 145 146 147 148 149 150
    /**
     * Returns whether the window is any of special windows types (desktop, dock, splash, ...),
     * i.e. window types that usually don't have a window frame and the user does not use window
     * management (moving, raising,...) on them.
     * The value is evaluated each time the getter is called.
     * Because of that no changed signal is provided.
     **/
    Q_PROPERTY(bool specialWindow READ isSpecialWindow)
151 152 153 154 155 156 157 158 159
    /**
     * Whether window state _NET_WM_STATE_DEMANDS_ATTENTION is set. This state indicates that some
     * action in or with the window happened. For example, it may be set by the Window Manager if
     * the window requested activation but the Window Manager refused it, or the application may set
     * it if it finished some work. This state may be set by both the Client and the Window Manager.
     * It should be unset by the Window Manager when it decides the window got the required attention
     * (usually, that it got activated).
     **/
    Q_PROPERTY(bool demandsAttention READ isDemandingAttention WRITE demandAttention NOTIFY demandsAttentionChanged)
160 161 162 163 164
    /**
     * The Caption of the Client. Read from WM_NAME property together with a suffix for hostname and shortcut.
     * To read only the caption as provided by WM_NAME, use the getter with an additional @c false value.
     **/
    Q_PROPERTY(QString caption READ caption NOTIFY captionChanged)
165 166 167 168 169 170 171 172
    /**
     * Minimum size as specified in WM_NORMAL_HINTS
     **/
    Q_PROPERTY(QSize minSize READ minSize)
    /**
     * Maximum size as specified in WM_NORMAL_HINTS
     **/
    Q_PROPERTY(QSize maxSize READ maxSize)
173 174 175 176 177 178
    /**
     * Whether the Client can accept keyboard focus.
     * The value is evaluated each time the getter is called.
     * Because of that no changed signal is provided.
     **/
    Q_PROPERTY(bool wantsInput READ wantsInput)
179 180 181 182 183
    /**
     * Whether the Client is a transient Window to another Window.
     * @see transientFor
     **/
    Q_PROPERTY(bool transient READ isTransient NOTIFY transientChanged)
184 185 186 187
    /**
     * The Client to which this Client is a transient if any.
     **/
    Q_PROPERTY(KWin::AbstractClient *transientFor READ transientFor NOTIFY transientChanged)
188 189 190 191
    /**
     * Whether the Client represents a modal window.
     **/
    Q_PROPERTY(bool modal READ isModal NOTIFY modalChanged)
192 193 194 195 196
    /**
     * The geometry of this Client. Be aware that depending on resize mode the geometryChanged signal
     * might be emitted at each resize step or only at the end of the resize operation.
     **/
    Q_PROPERTY(QRect geometry READ geometry WRITE setGeometry)
197 198 199 200 201 202 203 204 205 206
    /**
     * Whether the Client is currently being moved by the user.
     * Notify signal is emitted when the Client starts or ends move/resize mode.
     **/
    Q_PROPERTY(bool move READ isMove NOTIFY moveResizedChanged)
    /**
     * Whether the Client is currently being resized by the user.
     * Notify signal is emitted when the Client starts or ends move/resize mode.
     **/
    Q_PROPERTY(bool resize READ isResize NOTIFY moveResizedChanged)
207 208 209 210
    /**
     * Whether the decoration is currently using an alpha channel.
     **/
    Q_PROPERTY(bool decorationHasAlpha READ decorationHasAlpha)
211 212 213 214 215 216 217
    /**
     * Whether the window has a decoration or not.
     * This property is not allowed to be set by applications themselves.
     * The decision whether a window has a border or not belongs to the window manager.
     * If this property gets abused by application developers, it will be removed again.
     **/
    Q_PROPERTY(bool noBorder READ noBorder WRITE setNoBorder)
218 219 220 221 222
    /**
     * Whether the Client provides context help. Mostly needed by decorations to decide whether to
     * show the help button or not.
     **/
    Q_PROPERTY(bool providesContextHelp READ providesContextHelp CONSTANT)
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
    /**
     * Whether the Client can be maximized both horizontally and vertically.
     * The property is evaluated each time it is invoked.
     * Because of that there is no notify signal.
     **/
    Q_PROPERTY(bool maximizable READ isMaximizable)
    /**
     * Whether the Client is moveable. Even if it is not moveable, it might be possible to move
     * it to another screen. The property is evaluated each time it is invoked.
     * Because of that there is no notify signal.
     * @see moveableAcrossScreens
     **/
    Q_PROPERTY(bool moveable READ isMovable)
    /**
     * Whether the Client can be moved to another screen. The property is evaluated each time it is invoked.
     * Because of that there is no notify signal.
     * @see moveable
     **/
    Q_PROPERTY(bool moveableAcrossScreens READ isMovableAcrossScreens)
    /**
     * Whether the Client can be resized. The property is evaluated each time it is invoked.
     * Because of that there is no notify signal.
     **/
    Q_PROPERTY(bool resizeable READ isResizable)
247 248 249 250 251 252 253 254 255 256 257

    /**
     * The desktop file name of the application this AbstractClient belongs to.
     *
     * This is either the base name without full path and without file extension of the
     * desktop file for the window's application (e.g. "org.kde.foo").
     *
     * The application's desktop file name can also be the full path to the desktop file
     * (e.g. "/opt/kde/share/org.kde.foo.desktop") in case it's not in a standard location.
     **/
    Q_PROPERTY(QByteArray desktopFileName READ desktopFileName NOTIFY desktopFileNameChanged)
Kai Uwe Broulik's avatar
Kai Uwe Broulik committed
258 259 260 261 262 263 264 265 266 267

    /**
     * Whether an application menu is available for this Client
     */
    Q_PROPERTY(bool hasApplicationMenu READ hasApplicationMenu NOTIFY hasApplicationMenuChanged)
    /**
     * Whether the application menu for this Client is currently opened
     */
    Q_PROPERTY(bool applicationMenuActive READ applicationMenuActive NOTIFY applicationMenuActiveChanged)

268 269 270 271 272 273 274 275
    /**
     * Whether this client is unresponsive.
     *
     * When an application failed to react on a ping request in time, it is
     * considered unresponsive. This usually indicates that the application froze or crashed.
     */
    Q_PROPERTY(bool unresponsive READ unresponsive NOTIFY unresponsiveChanged)

276 277 278
public:
    virtual ~AbstractClient();

279 280 281
    QWeakPointer<TabBox::TabBoxClientImpl> tabBoxClient() const {
        return m_tabBoxClient.toWeakRef();
    }
282 283 284
    bool isFirstInTabBox() const {
        return m_firstInTabBox;
    }
285 286 287 288
    bool skipSwitcher() const {
        return m_skipSwitcher;
    }
    void setSkipSwitcher(bool set);
289

290 291 292 293 294 295 296 297 298
    bool skipTaskbar() const {
        return m_skipTaskbar;
    }
    void setSkipTaskbar(bool set);
    void setOriginalSkipTaskbar(bool set);
    bool originalSkipTaskbar() const {
        return m_originalSkipTaskbar;
    }

299 300 301 302 303
    bool skipPager() const {
        return m_skipPager;
    }
    void setSkipPager(bool set);

304 305 306 307
    const QIcon &icon() const {
        return m_icon;
    }

308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
    bool isActive() const {
        return m_active;
    }
    /**
     * Sets the client's active state to \a act.
     *
     * This function does only change the visual appearance of the client,
     * it does not change the focus setting. Use
     * Workspace::activateClient() or Workspace::requestFocus() instead.
     *
     * If a client receives or looses the focus, it calls setActive() on
     * its own.
     **/
    void setActive(bool);

323 324 325 326 327 328 329 330 331
    bool keepAbove() const {
        return m_keepAbove;
    }
    void setKeepAbove(bool);
    bool keepBelow() const {
        return m_keepBelow;
    }
    void setKeepBelow(bool);

332 333 334 335 336
    void demandAttention(bool set = true);
    bool isDemandingAttention() const {
        return m_demandsAttention;
    }

337 338
    void cancelAutoRaise();

339 340
    bool wantsTabFocus() const;

341 342 343 344
    QPoint clientPos() const override {
        return QPoint(borderLeft(), borderTop());
    }

345
    virtual void updateMouseGrab();
346 347 348 349 350
    /**
     * @returns The caption consisting of @link{captionNormal} and @link{captionSuffix}
     * @see captionNormal
     * @see captionSuffix
     **/
351
    QString caption() const;
352 353 354 355 356 357 358 359 360 361 362 363
    /**
     * @returns The caption as set by the AbstractClient without any suffix.
     * @see caption
     * @see captionSuffix
     **/
    virtual QString captionNormal() const = 0;
    /**
     * @returns The suffix added to the caption (e.g. shortcut, machine name, etc.)
     * @see caption
     * @see captionNormal
     **/
    virtual QString captionSuffix() const = 0;
364 365 366
    virtual bool isCloseable() const = 0;
    // TODO: remove boolean trap
    virtual bool isShown(bool shaded_is_shown) const = 0;
367
    virtual bool isHiddenInternal() const = 0;
368 369
    // TODO: remove boolean trap
    virtual void hideClient(bool hide) = 0;
370 371
    bool isFullScreenable() const;
    bool isFullScreenable(bool fullscreen_hack) const;
372
    virtual bool isFullScreen() const = 0;
373 374
    // TODO: remove boolean trap
    virtual AbstractClient *findModal(bool allow_itself = false) = 0;
375
    virtual bool isTransient() const;
376 377 378 379 380 381 382 383 384
    /**
     * @returns Whether there is a hint available to place the AbstractClient on it's parent, default @c false.
     * @see transientPlacementHint
     **/
    virtual bool hasTransientPlacementHint() const;
    /**
     * @returns The recommended position of the transient in parent coordinates
     **/
    virtual QPoint transientPlacementHint() const;
385 386
    const AbstractClient* transientFor() const;
    AbstractClient* transientFor();
387 388 389 390 391 392
    /**
     * @returns @c true if c is the transient_for window for this client,
     *  or recursively the transient_for window
     * @todo: remove boolean trap
     **/
    virtual bool hasTransient(const AbstractClient* c, bool indirect) const;
393
    const QList<AbstractClient*>& transients() const; // Is not indirect
Martin Flöser's avatar
Martin Flöser committed
394
    virtual void removeTransient(AbstractClient* cl);
395 396
    virtual QList<AbstractClient*> mainClients() const; // Call once before loop , is not indirect
    QList<AbstractClient*> allMainClients() const; // Call once before loop , is indirect
397 398 399 400 401 402
    /**
     * Returns true for "special" windows and false for windows which are "normal"
     * (normal=window which has a border, can be moved by the user, can be closed, etc.)
     * true for Desktop, Dock, Splash, Override and TopMenu (and Toolbar??? - for now)
     * false for Normal, Dialog, Utility and Menu (and Toolbar??? - not yet) TODO
     */
403
    bool isSpecialWindow() const;
404
    void sendToScreen(int screen);
405 406 407 408
    const QKeySequence &shortcut() const {
        return _shortcut;
    }
    void setShortcut(const QString &cut);
409
    virtual bool performMouseCommand(Options::MouseCommand, const QPoint &globalPos);
410 411 412 413 414
    void setOnAllDesktops(bool set);
    void setDesktop(int);
    int desktop() const override {
        return m_desktop;
    }
415 416 417 418 419 420 421 422 423
    void setMinimized(bool set);
    /**
    * Minimizes this client plus its transients
    */
    void minimize(bool avoid_animation = false);
    void unminimize(bool avoid_animation = false);
    bool isMinimized() const {
        return m_minimized;
    }
424 425 426
    virtual void setFullScreen(bool set, bool user = true) = 0;
    virtual TabGroup *tabGroup() const;
    Q_INVOKABLE virtual bool untab(const QRect &toGeometry = QRect(), bool clientRemoved = false);
427
    virtual bool isCurrentTab() const;
428
    virtual QRect geometryRestore() const = 0;
429
    virtual MaximizeMode maximizeMode() const = 0;
430 431
    void maximize(MaximizeMode);
    void setMaximize(bool vertically, bool horizontally);
432 433
    virtual bool noBorder() const = 0;
    virtual void setNoBorder(bool set) = 0;
434
    virtual void blockActivityUpdates(bool b = true) = 0;
435 436
    QPalette palette() const;
    const Decoration::DecorationPalette *decorationPalette() const;
437 438 439
    virtual bool isResizable() const = 0;
    virtual bool isMovable() const = 0;
    virtual bool isMovableAcrossScreens() const = 0;
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
    /**
     * @c true only for @c ShadeNormal
     **/
    bool isShade() const {
        return shadeMode() == ShadeNormal;
    }
    /**
     * Default implementation returns @c ShadeNone
     **/
    virtual ShadeMode shadeMode() const; // Prefer isShade()
    void setShade(bool set);
    /**
     * Default implementation does nothing
     **/
    virtual void setShade(ShadeMode mode);
    /**
     * Whether the Client can be shaded. Default implementation returns @c false.
     **/
    virtual bool isShadeable() const;
459 460
    virtual bool isMaximizable() const = 0;
    virtual bool isMinimizable() const = 0;
461
    virtual QRect iconGeometry() const;
462 463
    virtual bool userCanSetFullScreen() const = 0;
    virtual bool userCanSetNoBorder() const = 0;
464
    virtual void checkNoBorder();
465
    virtual void setOnActivities(QStringList newActivitiesList);
466
    virtual void setOnAllActivities(bool set) = 0;
467 468 469 470 471 472 473
    const WindowRules* rules() const {
        return &m_rules;
    }
    void removeRule(Rules* r);
    void setupWindowRules(bool ignore_temporary);
    void evaluateWindowRules();
    void applyWindowRules();
474 475
    virtual void takeFocus() = 0;
    virtual bool wantsInput() const = 0;
476 477 478 479 480 481 482 483 484 485 486 487
    /**
     * Whether a dock window wants input.
     *
     * By default KWin doesn't pass focus to a dock window unless a force activate
     * request is provided.
     *
     * This method allows to have dock windows take focus also through flags set on
     * the window.
     *
     * The default implementation returns @c false.
     **/
    virtual bool dockWantsInput() const;
488
    void checkWorkspacePosition(QRect oldGeometry = QRect(), int oldDesktop = -2,  QRect oldClientGeometry = QRect());
489
    virtual xcb_timestamp_t userTime() const;
490
    virtual void updateWindowRules(Rules::Types selection);
491

492 493 494 495
    void growHorizontal();
    void shrinkHorizontal();
    void growVertical();
    void shrinkVertical();
496
    void updateMoveResize(const QPointF &currentGlobalCursor);
497 498 499 500
    /**
     * Ends move resize when all pointer buttons are up again.
     **/
    void endMoveResize();
501
    void keyPressEvent(uint key_code);
502

503
    void enterEvent(const QPoint &globalPos);
504
    void leaveEvent();
505

506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
    /**
     * These values represent positions inside an area
     */
    enum Position {
        // without prefix, they'd conflict with Qt::TopLeftCorner etc. :(
        PositionCenter         = 0x00,
        PositionLeft           = 0x01,
        PositionRight          = 0x02,
        PositionTop            = 0x04,
        PositionBottom         = 0x08,
        PositionTopLeft        = PositionLeft | PositionTop,
        PositionTopRight       = PositionRight | PositionTop,
        PositionBottomLeft     = PositionLeft | PositionBottom,
        PositionBottomRight    = PositionRight | PositionBottom
    };
521
    Position titlebarPosition() const;
522
    bool titlebarPositionUnderMouse() const;
523

524
    // a helper for the workspace window packing. tests for screen validity and updates since in maximization case as with normal moving
525
    void packTo(int left, int top);
526

527 528 529 530
    /** Set the quick tile mode ("snap") of this window.
     * This will also handle preserving and restoring of window geometry as necessary.
     * @param mode The tile mode (left/right) to give this window.
     */
531 532 533 534
    void setQuickTileMode(QuickTileMode mode, bool keyboard = false);
    QuickTileMode quickTileMode() const {
        return QuickTileMode(m_quickTileMode);
    }
535 536
    Layer layer() const override;
    void updateLayer();
537

538
    enum ForceGeometry_t { NormalGeometrySet, ForceGeometrySet };
539
    void move(int x, int y, ForceGeometry_t force = NormalGeometrySet);
540
    void move(const QPoint &p, ForceGeometry_t force = NormalGeometrySet);
541 542
    virtual void resizeWithChecks(int w, int h, ForceGeometry_t force = NormalGeometrySet) = 0;
    void resizeWithChecks(const QSize& s, ForceGeometry_t force = NormalGeometrySet);
543
    void keepInArea(QRect area, bool partial = false);
544 545
    virtual QSize minSize() const;
    virtual QSize maxSize() const;
546 547
    virtual void setGeometry(int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet) = 0;
    void setGeometry(const QRect& r, ForceGeometry_t force = NormalGeometrySet);
548 549 550 551 552 553 554
    /// How to resize the window in order to obey constains (mainly aspect ratios)
    enum Sizemode {
        SizemodeAny,
        SizemodeFixedW, ///< Try not to affect width
        SizemodeFixedH, ///< Try not to affect height
        SizemodeMax ///< Try not to make it larger in either direction
    };
555 556 557 558 559 560 561 562
    /**
     *Calculate the appropriate frame size for the given client size @p wsize.
     *
     * @p wsize is adapted according to the window's size hints (minimum, maximum and incremental size changes).
     *
     * Default implementation returns the passed in @p wsize.
     */
    virtual QSize sizeForClientSize(const QSize &wsize, Sizemode mode = SizemodeAny, bool noframe = false) const;
563

564 565 566
    QSize adjustedSize(const QSize&, Sizemode mode = SizemodeAny) const;
    QSize adjustedSize() const;

567 568 569 570 571 572
    bool isMove() const {
        return isMoveResize() && moveResizePointerMode() == PositionCenter;
    }
    bool isResize() const {
        return isMoveResize() && moveResizePointerMode() != PositionCenter;
    }
573 574 575 576 577 578
    /**
     * Cursor shape for move/resize mode.
     **/
    Qt::CursorShape cursor() const {
        return m_moveResize.cursor;
    }
579

580
    virtual bool hasStrut() const;
581

582 583 584
    void setModal(bool modal);
    bool isModal() const;

585 586 587 588 589 590 591 592 593 594
    /**
     * Determines the mouse command for the given @p button in the current state.
     *
     * The @p handled argument specifies whether the button was handled or not.
     * This value should be used to determine whether the mouse button should be
     * passed to the AbstractClient or being filtered out.
     **/
    Options::MouseCommand getMouseCommand(Qt::MouseButton button, bool *handled) const;
    Options::MouseCommand getWheelCommand(Qt::Orientation orientation, bool *handled) const;

595 596
    // decoration related
    KDecoration2::Decoration *decoration() {
597
        return m_decoration.decoration;
598 599
    }
    const KDecoration2::Decoration *decoration() const {
600
        return m_decoration.decoration;
601 602
    }
    bool isDecorated() const {
603
        return m_decoration.decoration != nullptr;
604
    }
605 606
    QPointer<Decoration::DecoratedClientImpl> decoratedClient() const;
    void setDecoratedClient(QPointer<Decoration::DecoratedClientImpl> client);
607
    bool decorationHasAlpha() const;
608
    void triggerDecorationRepaint();
609
    virtual void layoutDecorationRects(QRect &left, QRect &top, QRect &right, QRect &bottom) const;
610
    void processDecorationMove(const QPoint &localPos, const QPoint &globalPos);
611 612
    bool processDecorationButtonPress(QMouseEvent *event, bool ignoreMenu = false);
    void processDecorationButtonRelease(QMouseEvent *event);
613

614 615 616 617 618
    /**
     * TODO: fix boolean traps
     **/
    virtual void updateDecoration(bool check_workspace_pos, bool force = false) = 0;

619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
    /**
    * Returns whether the window provides context help or not. If it does,
    * you should show a help menu item or a help button like '?' and call
    * contextHelp() if this is invoked.
    *
    * Default implementation returns @c false.
    * @see showContextHelp;
    */
    virtual bool providesContextHelp() const;

    /**
    * Invokes context help on the window. Only works if the window
    * actually provides context help.
    *
    * Default implementation does nothing.
    *
    * @see providesContextHelp()
    */
    virtual void showContextHelp();

639 640
    QRect inputGeometry() const override;

641 642 643 644 645 646 647
    /**
     * Restores the AbstractClient after it had been hidden due to show on screen edge functionality.
     * The AbstractClient also gets raised (e.g. Panel mode windows can cover) and the AbstractClient
     * gets informed in a window specific way that it is shown and raised again.
     **/
    virtual void showOnScreenEdge() = 0;

648 649 650 651
    QByteArray desktopFileName() const {
        return m_desktopFileName;
    }

652 653 654 655 656 657 658
    /**
     * Tries to terminate the process of this AbstractClient.
     *
     * Implementing subclasses can perform a windowing system solution for terminating.
     **/
    virtual void killWindow() = 0;

659 660 661 662 663 664
    enum class SameApplicationCheck {
        RelaxedForActive = 1 << 0,
        AllowCrossProcesses = 1 << 1
    };
    Q_DECLARE_FLAGS(SameApplicationChecks, SameApplicationCheck)
    static bool belongToSameApplication(const AbstractClient* c1, const AbstractClient* c2, SameApplicationChecks checks = SameApplicationChecks());
665

Kai Uwe Broulik's avatar
Kai Uwe Broulik committed
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
    bool hasApplicationMenu() const;
    bool applicationMenuActive() const {
        return m_applicationMenuActive;
    }
    void setApplicationMenuActive(bool applicationMenuActive);

    QString applicationMenuServiceName() const {
        return m_applicationMenuServiceName;
    }
    QString applicationMenuObjectPath() const {
        return m_applicationMenuObjectPath;
    }

    /**
     * Request showing the application menu bar
     * @param actionId The DBus menu ID of the action that should be highlighted, 0 for the root menu
     */
    void showApplicationMenu(int actionId);

685 686
    bool unresponsive() const;

Martin Flöser's avatar
Martin Flöser committed
687 688 689 690
    virtual bool isInitialPositionSet() const {
        return false;
    }

691 692 693
public Q_SLOTS:
    virtual void closeWindow() = 0;

694
Q_SIGNALS:
695
    void fullScreenChanged();
696
    void skipTaskbarChanged();
697
    void skipPagerChanged();
698
    void skipSwitcherChanged();
699
    void iconChanged();
700
    void activeChanged();
701 702
    void keepAboveChanged(bool);
    void keepBelowChanged(bool);
703 704 705 706
    /**
     * Emitted whenever the demands attention state changes.
     **/
    void demandsAttentionChanged();
707
    void desktopPresenceChanged(KWin::AbstractClient*, int); // to be forwarded by Workspace
708
    void desktopChanged();
709
    void shadeChanged();
710 711 712
    void minimizedChanged();
    void clientMinimized(KWin::AbstractClient* client, bool animate);
    void clientUnminimized(KWin::AbstractClient* client, bool animate);
713
    void paletteChanged(const QPalette &p);
714
    void captionChanged();
715 716
    void clientMaximizedStateChanged(KWin::AbstractClient*, MaximizeMode);
    void clientMaximizedStateChanged(KWin::AbstractClient* c, bool h, bool v);
717
    void transientChanged();
718
    void modalChanged();
719
    void quickTileModeChanged();
720
    void moveResizedChanged();
721
    void moveResizeCursorChanged(Qt::CursorShape);
722 723 724
    void clientStartUserMovedResized(KWin::AbstractClient*);
    void clientStepUserMovedResized(KWin::AbstractClient *, const QRect&);
    void clientFinishUserMovedResized(KWin::AbstractClient*);
725 726 727 728
    void closeableChanged(bool);
    void minimizeableChanged(bool);
    void shadeableChanged(bool);
    void maximizeableChanged(bool);
729
    void desktopFileNameChanged();
Kai Uwe Broulik's avatar
Kai Uwe Broulik committed
730 731
    void hasApplicationMenuChanged(bool);
    void applicationMenuActiveChanged(bool);
732
    void unresponsiveChanged(bool);
733

734 735
protected:
    AbstractClient();
736 737 738
    void setFirstInTabBox(bool enable) {
        m_firstInTabBox = enable;
    }
739
    void setIcon(const QIcon &icon);
740 741
    void startAutoRaise();
    void autoRaise();
742 743 744 745 746 747
    /**
     * Whether the window accepts focus.
     * The difference to wantsInput is that the implementation should not check rules and return
     * what the window effectively supports.
     **/
    virtual bool acceptsFocus() const = 0;
748 749 750 751 752 753 754
    /**
     * Called from ::setActive once the active value got updated, but before the changed signal
     * is emitted.
     *
     * Default implementation does nothing.
     **/
    virtual void doSetActive();
755 756 757 758 759 760 761 762 763 764 765 766 767 768
    /**
     * Called from ::setKeepAbove once the keepBelow value got updated, but before the changed signal
     * is emitted.
     *
     * Default implementation does nothing.
     **/
    virtual void doSetKeepAbove();
    /**
     * Called from ::setKeepBelow once the keepBelow value got updated, but before the changed signal
     * is emitted.
     *
     * Default implementation does nothing.
     **/
    virtual void doSetKeepBelow();
769 770 771 772 773 774 775 776 777
    /**
     * Called from ::setDeskop once the desktop value got updated, but before the changed signal
     * is emitted.
     *
     * Default implementation does nothing.
     * @param desktop The new desktop the Client is on
     * @param was_desk The desktop the Client was on before
     **/
    virtual void doSetDesktop(int desktop, int was_desk);
778 779 780 781 782 783 784
    /**
     * Called from ::minimize and ::unminimize once the minimized value got updated, but before the
     * changed signal is emitted.
     *
     * Default implementation does nothig.
     **/
    virtual void doMinimize();
785
    virtual bool belongsToSameApplication(const AbstractClient *other, SameApplicationChecks checks) const = 0;
786

787
    virtual void doSetSkipTaskbar();
788 789
    virtual void doSetSkipPager();

790 791 792
    void setupWindowManagementInterface();
    void destroyWindowManagementInterface();

793
    void updateColorScheme(QString path);
794
    virtual void updateColorScheme() = 0;
795

796
    void setTransientFor(AbstractClient *transientFor);
797 798 799 800 801
    virtual void addTransient(AbstractClient* cl);
    /**
     * Just removes the @p cl from the transients without any further checks.
     **/
    void removeTransientFromList(AbstractClient* cl);
802

803 804 805
    Layer belongsToLayer() const;
    virtual bool belongsToDesktop() const;
    void invalidateLayer();
806
    bool isActiveFullScreen() const;
807
    virtual Layer layerForDock() const;
808

809 810 811 812 813
    // electric border / quick tiling
    void setElectricBorderMode(QuickTileMode mode);
    QuickTileMode electricBorderMode() const {
        return m_electricMode;
    }
814 815 816 817
    void setElectricBorderMaximizing(bool maximizing);
    bool isElectricBorderMaximizing() const {
        return m_electricMaximizing;
    }
818
    QRect electricBorderMaximizeGeometry(QPoint pos, int desktop);
819 820 821
    void updateQuickTileMode(QuickTileMode newMode) {
        m_quickTileMode = newMode;
    }
822

823 824 825 826
    KWayland::Server::PlasmaWindowInterface *windowManagementInterface() const {
        return m_windowManagementInterface;
    }

827 828
    // geometry handling
    void checkOffscreenPosition(QRect *geom, const QRect &screenArea);
829 830 831 832
    int borderLeft() const;
    int borderRight() const;
    int borderTop() const;
    int borderBottom() const;
833
    virtual void changeMaximize(bool horizontal, bool vertical, bool adjust) = 0;
834
    virtual void setGeometryRestore(const QRect &geo) = 0;
835 836 837 838 839
    /**
     * Called from move after updating the geometry. Can be reimplemented to perform specific tasks.
     * The base implementation does nothing.
     **/
    virtual void doMove(int x, int y);
840 841 842 843 844 845 846 847 848 849 850
    void blockGeometryUpdates(bool block);
    void blockGeometryUpdates();
    void unblockGeometryUpdates();
    bool areGeometryUpdatesBlocked() const;
    enum PendingGeometry_t {
        PendingGeometryNone,
        PendingGeometryNormal,
        PendingGeometryForced
    };
    PendingGeometry_t pendingGeometryUpdate() const;
    void setPendingGeometryUpdate(PendingGeometry_t update);
851 852 853 854
    QRect geometryBeforeUpdateBlocking() const {
        return m_geometryBeforeUpdateBlocking;
    }
    void updateGeometryBeforeUpdateBlocking();
855 856 857 858 859 860
    /**
     * Schedules a repaint for the visibleRect before and after a
     * geometry update. The current visibleRect is stored for the
     * next time this method is called as the before geometry.
     **/
    void addRepaintDuringGeometryUpdates();
861

862 863 864 865 866 867 868
    /**
     * Convenient method to update the TabGroup states if there is one present.
     * Marked as virtual as TabGroup does not yet handle AbstractClient, but only
     * subclasses of AbstractClient. Given that the default implementation does nothing.
     **/
    virtual void updateTabGroupStates(TabGroup::States states);

869 870 871 872 873 874 875 876 877 878 879 880
    /**
     * @returns whether the Client is currently in move resize mode
     **/
    bool isMoveResize() const {
        return m_moveResize.enabled;
    }
    /**
     * Sets whether the Client is in move resize mode to @p enabled.
     **/
    void setMoveResize(bool enabled) {
        m_moveResize.enabled = enabled;
    }
881 882 883 884 885 886 887 888 889 890 891 892
    /**
     * @returns whether the move resize mode is unrestricted.
     **/
    bool isUnrestrictedMoveResize() const {
        return m_moveResize.unrestricted;
    }
    /**
     * Sets whether move resize mode is unrestricted to @p set.
     **/
    void setUnrestrictedMoveResize(bool set) {
        m_moveResize.unrestricted = set;
    }
893 894 895 896 897 898 899 900 901 902 903 904
    QPoint moveOffset() const {
        return m_moveResize.offset;
    }
    void setMoveOffset(const QPoint &offset) {
        m_moveResize.offset = offset;
    }
    QPoint invertedMoveOffset() const {
        return m_moveResize.invertedOffset;
    }
    void setInvertedMoveOffset(const QPoint &offset) {
        m_moveResize.invertedOffset = offset;
    }
905 906 907 908 909 910 911
    QRect initialMoveResizeGeometry() const {
        return m_moveResize.initialGeometry;
    }
    /**
     * Sets the initial move resize geometry to the current geometry.
     **/
    void updateInitialMoveResizeGeometry();
912 913 914 915 916 917
    QRect moveResizeGeometry() const {
        return m_moveResize.geometry;
    }
    void setMoveResizeGeometry(const QRect &geo) {
        m_moveResize.geometry = geo;
    }
918 919 920 921 922 923
    Position moveResizePointerMode() const {
        return m_moveResize.pointer;
    }
    void setMoveResizePointerMode(Position mode) {
        m_moveResize.pointer = mode;
    }
924 925 926 927 928 929
    bool isMoveResizePointerButtonDown() const {
        return m_moveResize.buttonDown;
    }
    void setMoveResizePointerButtonDown(bool down) {
        m_moveResize.buttonDown = down;
    }
930 931 932
    int moveResizeStartScreen() const {
        return m_moveResize.startScreen;
    }
933
    void checkUnrestrictedMoveResize();
934 935 936 937
    /**
    * Sets an appropriate cursor shape for the logical mouse position.
    */
    void updateCursor();
938 939
    void startDelayedMoveResize();
    void stopDelayedMoveResize();
940 941 942 943 944 945 946 947 948 949
    bool startMoveResize();
    /**
     * Called from @link startMoveResize.
     *
     * Implementing classes should return @c false if starting move resize should
     * get aborted. In that case @link startMoveResize will also return @c false.
     *
     * Base implementation returns @c true.
     **/
    virtual bool doStartMoveResize();
950
    void finishMoveResize(bool cancel);
951 952 953 954 955 956 957
    /**
     * Leaves the move resize mode.
     *
     * Inheriting classes must invoke the base implementation which
     * ensures that the internal mode is properly ended.
     **/
    virtual void leaveMoveResize();
958
    virtual void positionGeometryTip();
959 960 961 962 963 964 965 966
    void performMoveResize();
    /**
     * Called from performMoveResize() after actually performing the change of geometry.
     * Implementing subclasses can perform windowing system specific handling here.
     *
     * Default implementation does nothing.
     **/
    virtual void doPerformMoveResize();
967 968 969 970 971
    /*
     * Checks if the mouse cursor is near the edge of the screen and if so
     * activates quick tiling or maximization
     */
    void checkQuickTilingMaximizationZones(int xroot, int yroot);
972 973 974 975 976 977 978 979 980 981 982 983 984 985
    /**
     * Whether a sync request is still pending.
     * Default implementation returns @c false.
     **/
    virtual bool isWaitingForMoveResizeSync() const;
    /**
     * Called during handling a resize. Implementing subclasses can use this
     * method to perform windowing system specific syncing.
     *
     * Default implementation does nothing.
     **/
    virtual void doResizeSync();
    void handleMoveResize(int x, int y, int x_root, int y_root);
    void handleMoveResize(const QPoint &local, const QPoint &global);
986
    void dontMoveResize();
987

988 989
    virtual QSize resizeIncrements() const;

990
    /**
991 992
     * Returns the position depending on the Decoration's section under mouse.
     * If no decoration it returns PositionCenter.
993
     **/
994
    Position mousePosition() const;
995

996 997 998 999 1000 1001 1002 1003
    static bool haveResizeEffect() {
        return s_haveResizeEffect;
    }
    static void updateHaveResizeEffect();
    static void resetHaveResizeEffect() {
        s_haveResizeEffect = false;
    }

1004
    void setDecoration(KDecoration2::Decoration *decoration) {
1005
        m_decoration.decoration = decoration;
1006 1007
    }
    virtual void destroyDecoration();
1008
    void startDecorationDoubleClickTimer();
1009
    void invalidateDecorationDoubleClickTimer();
1010

1011
    void setDesktopFileName(QByteArray name);
1012 1013
    QString iconFromDesktopFile() const;

Kai Uwe Broulik's avatar
Kai Uwe Broulik committed
1014 1015 1016
    void updateApplicationMenuServiceName(const QString &serviceName);
    void updateApplicationMenuObjectPath(const QString &objectPath);

1017 1018
    void setUnresponsive(bool unresponsive);

1019
    virtual void setShortcutInternal();
1020 1021
    QString shortcutCaptionSuffix() const;
    virtual void updateCaption() = 0;
1022

1023 1024 1025 1026 1027 1028
    /**
     * Looks for another AbstractClient with same @link{captionNormal} and @link{captionSuffix}.
     * If no such AbstractClient exists @c nullptr is returned.
     **/
    AbstractClient *findClientWithSameCaption() const;

1029 1030 1031
    void finishWindowRules();
    void discardTemporaryRules();

1032
private:
1033
    void handlePaletteChange();
1034
    QSharedPointer<TabBox::TabBoxClientImpl> m_tabBoxClient;
1035
    bool m_firstInTabBox = false;
1036 1037 1038 1039 1040
    bool m_skipTaskbar = false;
    /**
     * Unaffected by KWin
     **/
    bool m_originalSkipTaskbar = false;
1041
    bool m_skipPager = false;
1042
    bool m_skipSwitcher = false;
1043
    QIcon m_icon;
1044
    bool m_active = false;
1045 1046
    bool m_keepAbove = false;
    bool m_keepBelow = false;
1047
    bool m_demandsAttention = false;
1048
    bool m_minimized = false;
1049
    QTimer *m_autoRaiseTimer = nullptr;
1050
    int m_desktop = 0; // 0 means not on any desktop yet
1051 1052 1053 1054 1055

    QString m_colorScheme;
    std::shared_ptr<Decoration::DecorationPalette> m_palette;
    static QHash<QString, std::weak_ptr<Decoration::DecorationPalette>> s_palettes;
    static std::shared_ptr<Decoration::DecorationPalette> s_defaultPalette;
1056 1057

    KWayland::Server::PlasmaWindowInterface *m_windowManagementInterface = nullptr;
1058 1059

    AbstractClient *m_transientFor = nullptr;
1060
    QList<AbstractClient*> m_transients;
1061
    bool m_modal = false;
1062
    Layer m_layer = UnknownLayer;
1063 1064

    // electric border/quick tiling
1065
    QuickTileMode m_electricMode = QuickTileFlag::None;
1066
    bool m_electricMaximizing = false;
1067 1068
    /** The quick tile mode of this window.
     */
1069
    int m_quickTileMode = int(QuickTileFlag::None);
1070
    QTimer *m_electricMaximizingDelay = nullptr;
1071 1072 1073 1074 1075

    // geometry
    int m_blockGeometryUpdates = 0; // > 0 = New geometry is remembered, but not actually set
    PendingGeometry_t m_pendingGeometryUpdate = PendingGeometryNone;
    friend class GeometryUpdatesBlocker;
1076
    QRect m_visibleRectBeforeGeometryUpdate;
1077
    QRect m_geometryBeforeUpdateBlocking;
1078 1079 1080

    struct {
        bool enabled = false;
1081
        bool unrestricted = false;
1082 1083
        QPoint offset;
        QPoint invertedOffset;
1084
        QRect initialGeometry;
1085
        QRect geometry;
1086
        Position pointer = PositionCenter;
1087
        bool buttonDown = false;
1088
        Qt::CursorShape cursor = Qt::ArrowCursor;
1089
        int startScreen = 0;
1090
        QTimer *delayedTimer = nullptr;
1091
    } m_moveResize;
1092

1093 1094 1095 1096 1097
    struct {
        KDecoration2::Decoration *decoration = nullptr;
        QPointer<Decoration::DecoratedClientImpl> client;
        QElapsedTimer doubleClickTimer;
    } m_decoration;
1098 1099
    QByteArray m_desktopFileName;

Kai Uwe Broulik's avatar
Kai Uwe Broulik committed
1100 1101 1102
    bool m_applicationMenuActive = false;
    QString m_applicationMenuServiceName;
    QString m_applicationMenuObjectPath;
1103

1104 1105
    bool m_unresponsive = false;

1106 1107
    QKeySequence _shortcut;

1108 1109
    WindowRules m_rules;

1110
    static bool s_haveResizeEffect;
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
};

/**
 * Helper for AbstractClient::blockGeometryUpdates() being called in pairs (true/false)
 */
class GeometryUpdatesBlocker
{
public:
    explicit GeometryUpdatesBlocker(AbstractClient* c)
        : cl(c) {
        cl->blockGeometryUpdates(true);
    }
    ~GeometryUpdatesBlocker() {
        cl->blockGeometryUpdates(false);
    }

private:
    AbstractClient* cl;
1129 1130
};

1131 1132 1133 1134 1135
inline void AbstractClient::move(const QPoint& p, ForceGeometry_t force)
{
    move(p.x(), p.y(), force);
}

1136 1137 1138 1139 1140
inline void AbstractClient::resizeWithChecks(const QSize& s, AbstractClient::ForceGeometry_t force)
{
    resizeWithChecks(s.width(), s.height(), force);
}

1141 1142 1143 1144 1145
inline void AbstractClient::setGeometry(const QRect& r, ForceGeometry_t force)
{
    setGeometry(r.x(), r.y(), r.width(), r.height(), force);
}

1146 1147 1148 1149 1150
inline const QList<AbstractClient*>& AbstractClient::transients() const
{
    return m_transients;
}

1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175
inline bool AbstractClient::areGeometryUpdatesBlocked() const
{
    return m_blockGeometryUpdates != 0;
}

inline void AbstractClient::blockGeometryUpdates()
{
    m_blockGeometryUpdates++;
}

inline void AbstractClient::unblockGeometryUpdates()
{
    m_blockGeometryUpdates--;
}

inline AbstractClient::PendingGeometry_t AbstractClient::pendingGeometryUpdate() const
{
    return m_pendingGeometryUpdate;
}

inline void AbstractClient::setPendingGeometryUpdate(PendingGeometry_t update)
{
    m_pendingGeometryUpdate = update;
}

1176 1177 1178 1179
}

Q_DECLARE_METATYPE(KWin::AbstractClient*)
Q_DECLARE_METATYPE(QList<KWin::AbstractClient*>)
1180
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::AbstractClient::SameApplicationChecks)
1181 1182

#endif