File indexing completed on 2024-04-28 05:30:42

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich <ettrich@kde.org>
0006     SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #pragma once
0012 
0013 // kwin
0014 #include "scene/decorationitem.h"
0015 #include "utils/xcbutils.h"
0016 #include "window.h"
0017 // Qt
0018 #include <QElapsedTimer>
0019 #include <QFlags>
0020 #include <QPixmap>
0021 #include <QPointer>
0022 #include <QWindow>
0023 // X
0024 #include <xcb/sync.h>
0025 
0026 // TODO: Cleanup the order of things in this .h file
0027 
0028 class QTimer;
0029 class KStartupInfoData;
0030 class KStartupInfoId;
0031 
0032 namespace KWin
0033 {
0034 
0035 class KillPrompt;
0036 
0037 /**
0038  * @brief Defines Predicates on how to search for a Client.
0039  *
0040  * Used by Workspace::findClient.
0041  */
0042 enum class Predicate {
0043     WindowMatch,
0044     WrapperIdMatch,
0045     FrameIdMatch,
0046     InputIdMatch,
0047 };
0048 
0049 /**
0050  * @todo Remove when the X11 platform support is dropped. This decoration renderer
0051  * will be used if compositing is off.
0052  */
0053 class X11DecorationRenderer : public DecorationRenderer
0054 {
0055     Q_OBJECT
0056 
0057 public:
0058     explicit X11DecorationRenderer(Decoration::DecoratedClientImpl *client);
0059     ~X11DecorationRenderer() override;
0060 
0061 protected:
0062     void render(const QRegion &region) override;
0063 
0064 private:
0065     void update();
0066 
0067     QTimer *m_scheduleTimer;
0068     xcb_gcontext_t m_gc;
0069 };
0070 
0071 class KWIN_EXPORT X11Window : public Window
0072 {
0073     Q_OBJECT
0074 
0075 public:
0076     explicit X11Window();
0077     ~X11Window() override; ///< Use destroyWindow() or releaseWindow()
0078 
0079     xcb_window_t frameId() const;
0080     xcb_window_t window() const;
0081     xcb_window_t wrapperId() const;
0082     xcb_window_t inputId() const
0083     {
0084         return m_decoInputExtent;
0085     }
0086 
0087     int desktopId() const;
0088     QByteArray sessionId() const;
0089     xcb_window_t wmClientLeader() const;
0090     QString wmCommand();
0091 
0092     QPointF framePosToClientPos(const QPointF &point) const override;
0093     QPointF clientPosToFramePos(const QPointF &point) const override;
0094     QSizeF frameSizeToClientSize(const QSizeF &size) const override;
0095     QSizeF clientSizeToFrameSize(const QSizeF &size) const override;
0096     QRectF frameRectToBufferRect(const QRectF &rect) const;
0097     QPointF wrapperPos() const;
0098     QSizeF implicitSize() const;
0099 
0100     xcb_visualid_t visual() const;
0101     int depth() const;
0102     bool hasAlpha() const;
0103     QRegion opaqueRegion() const;
0104     QList<QRectF> shapeRegion() const;
0105 
0106     pid_t pid() const override;
0107     QString windowRole() const override;
0108 
0109     bool isTransient() const override;
0110     bool groupTransient() const override;
0111     QList<Window *> mainWindows() const override; // Call once before loop , is not indirect
0112     bool hasTransient(const Window *c, bool indirect) const override;
0113     void checkTransient(xcb_window_t w);
0114     Window *findModal(bool allow_itself = false) override;
0115     const Group *group() const override;
0116     Group *group() override;
0117     void checkGroup(Group *gr = nullptr, bool force = false);
0118     void changeClientLeaderGroup(Group *gr);
0119     bool supportsWindowRules() const override;
0120     void updateWindowRules(Rules::Types selection) override;
0121     void applyWindowRules() override;
0122     void updateFullscreenMonitors(NETFullscreenMonitors topology);
0123 
0124     bool hasNETSupport() const;
0125 
0126     QSizeF minSize() const override;
0127     QSizeF maxSize() const override;
0128     QSizeF basicUnit() const;
0129     QPointF inputPos() const
0130     {
0131         return input_offset;
0132     } // Inside of geometry()
0133 
0134     bool windowEvent(xcb_generic_event_t *e);
0135     NET::WindowType windowType() const override;
0136 
0137     bool track(xcb_window_t w);
0138     bool manage(xcb_window_t w, bool isMapped);
0139 
0140     void releaseWindow(bool on_shutdown = false);
0141     bool hasScheduledRelease() const;
0142 
0143     void destroyWindow() override;
0144 
0145     QStringList activities() const override;
0146     void doSetOnActivities(const QStringList &newActivitiesList) override;
0147     void updateActivities(bool includeTransients) override;
0148 
0149     bool isShadeable() const override;
0150     bool isMaximizable() const override;
0151     MaximizeMode maximizeMode() const override;
0152     void maximize(MaximizeMode mode) override;
0153 
0154     bool isMinimizable() const override;
0155     QRectF iconGeometry() const override;
0156 
0157     bool isFullScreenable() const override;
0158     void setFullScreen(bool set) override;
0159     bool isFullScreen() const override;
0160     int fullScreenMode() const
0161     {
0162         return m_fullscreenMode; // only for session saving
0163     }
0164 
0165     bool userNoBorder() const;
0166     bool noBorder() const override;
0167     void setNoBorder(bool set) override;
0168     bool userCanSetNoBorder() const override;
0169     void checkNoBorder() override;
0170     void checkActivities() override;
0171 
0172     int sessionStackingOrder() const;
0173 
0174     // Auxiliary functions, depend on the windowType
0175     bool wantsInput() const override;
0176 
0177     bool isResizable() const override;
0178     bool isMovable() const override;
0179     bool isMovableAcrossScreens() const override;
0180     bool isCloseable() const override; ///< May be closed by the user (May have a close button)
0181 
0182     bool takeFocus() override;
0183 
0184     void invalidateDecoration() override;
0185 
0186     void detectShape();
0187     void updateShape();
0188 
0189     /// resizeWithChecks() resizes according to gravity, and checks workarea position
0190     QRectF resizeWithChecks(const QRectF &geometry, const QSizeF &size) override;
0191     QRectF resizeWithChecks(const QRectF &geometry, qreal w, qreal h, xcb_gravity_t gravity);
0192     QRectF resizeWithChecks(const QRectF &geometry, const QSizeF &s, xcb_gravity_t gravity);
0193     QSizeF constrainClientSize(const QSizeF &size, SizeMode mode = SizeModeAny) const override;
0194 
0195     bool providesContextHelp() const override;
0196 
0197     /// Updates visibility depending on being shaded, virtual desktop, etc.
0198     void updateVisibility();
0199     bool hiddenPreview() const; ///< Window is mapped in order to get a window pixmap
0200 
0201     bool setupCompositing() override;
0202     void finishCompositing() override;
0203     void setBlockingCompositing(bool block);
0204     void blockCompositing();
0205     void unblockCompositing();
0206 
0207     QString captionNormal() const override
0208     {
0209         return cap_normal;
0210     }
0211     QString captionSuffix() const override
0212     {
0213         return cap_suffix;
0214     }
0215 
0216     using Window::keyPressEvent;
0217     void keyPressEvent(uint key_code, xcb_timestamp_t time); // FRAME ??
0218     void updateMouseGrab() override;
0219     xcb_window_t moveResizeGrabWindow() const;
0220 
0221     QPointF gravityAdjustment(xcb_gravity_t gravity) const;
0222     const QPointF calculateGravitation(bool invert) const;
0223 
0224     void NETMoveResize(qreal x_root, qreal y_root, NET::Direction direction);
0225     void NETMoveResizeWindow(int flags, qreal x, qreal y, qreal width, qreal height);
0226     void GTKShowWindowMenu(qreal x_root, qreal y_root);
0227     void restackWindow(xcb_window_t above, int detail, NET::RequestSource source, xcb_timestamp_t timestamp,
0228                        bool send_event = false);
0229 
0230     void gotPing(xcb_timestamp_t timestamp);
0231 
0232     void updateUserTime(xcb_timestamp_t time = XCB_TIME_CURRENT_TIME);
0233     xcb_timestamp_t userTime() const override;
0234     bool hasUserTimeSupport() const;
0235 
0236     /// Does 'delete c;'
0237     static void deleteClient(X11Window *c);
0238 
0239     static bool belongToSameApplication(const X11Window *c1, const X11Window *c2, SameApplicationChecks checks = SameApplicationChecks());
0240     static bool sameAppWindowRoleMatch(const X11Window *c1, const X11Window *c2, bool active_hack);
0241 
0242     void killWindow() override;
0243     void showContextHelp() override;
0244     void checkActiveModal();
0245 
0246     StrutRect strutRect(StrutArea area) const override;
0247     bool hasStrut() const override;
0248 
0249     bool isClientSideDecorated() const;
0250 
0251     Xcb::StringProperty fetchPreferredColorScheme() const;
0252     QString readPreferredColorScheme(Xcb::StringProperty &property) const;
0253     QString preferredColorScheme() const override;
0254 
0255     // sets whether the client should be faked as being on all activities (and be shown during session save)
0256     void setSessionActivityOverride(bool needed);
0257     bool isClient() const override;
0258     bool isOutline() const override;
0259     bool isUnmanaged() const override;
0260 
0261     void cancelFocusOutTimer();
0262 
0263     /**
0264      * Restores the Client after it had been hidden due to show on screen edge functionality.
0265      * In addition the property gets deleted so that the Client knows that it is visible again.
0266      */
0267     void showOnScreenEdge() override;
0268 
0269     Xcb::StringProperty fetchApplicationMenuServiceName() const;
0270     void readApplicationMenuServiceName(Xcb::StringProperty &property);
0271     void checkApplicationMenuServiceName();
0272 
0273     Xcb::StringProperty fetchApplicationMenuObjectPath() const;
0274     void readApplicationMenuObjectPath(Xcb::StringProperty &property);
0275     void checkApplicationMenuObjectPath();
0276 
0277     struct SyncRequest
0278     {
0279         xcb_sync_counter_t counter;
0280         xcb_sync_int64_t value;
0281         xcb_sync_alarm_t alarm;
0282         xcb_timestamp_t lastTimestamp;
0283         QTimer *timeout, *failsafeTimeout;
0284         bool isPending;
0285         bool interactiveResize;
0286     };
0287     const SyncRequest &syncRequest() const
0288     {
0289         return m_syncRequest;
0290     }
0291     bool wantsSyncCounter() const;
0292     void handleSync();
0293     void handleSyncTimeout();
0294 
0295     bool allowWindowActivation(xcb_timestamp_t time = -1U, bool focus_in = false);
0296 
0297     static void cleanupX11();
0298 
0299     quint64 surfaceSerial() const;
0300     quint32 pendingSurfaceId() const;
0301 
0302 public Q_SLOTS:
0303     void closeWindow() override;
0304     void updateCaption() override;
0305 
0306 private:
0307     // Handlers for X11 events
0308     bool mapRequestEvent(xcb_map_request_event_t *e);
0309     void unmapNotifyEvent(xcb_unmap_notify_event_t *e);
0310     void destroyNotifyEvent(xcb_destroy_notify_event_t *e);
0311     void configureNotifyEvent(xcb_configure_notify_event_t *e);
0312     void configureRequestEvent(xcb_configure_request_event_t *e);
0313     void propertyNotifyEvent(xcb_property_notify_event_t *e);
0314     void clientMessageEvent(xcb_client_message_event_t *e);
0315     void enterNotifyEvent(xcb_enter_notify_event_t *e);
0316     void leaveNotifyEvent(xcb_leave_notify_event_t *e);
0317     void focusInEvent(xcb_focus_in_event_t *e);
0318     void focusOutEvent(xcb_focus_out_event_t *e);
0319     void damageNotifyEvent();
0320 
0321     bool buttonPressEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root, xcb_timestamp_t time = XCB_CURRENT_TIME);
0322     bool buttonReleaseEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root);
0323     bool motionNotifyEvent(xcb_window_t w, int state, int x, int y, int x_root, int y_root);
0324 
0325 protected:
0326     bool belongsToSameApplication(const Window *other, SameApplicationChecks checks) const override;
0327     void doSetActive() override;
0328     void doSetKeepAbove() override;
0329     void doSetKeepBelow() override;
0330     void doSetShade(ShadeMode previousShadeMode) override;
0331     void doSetDesktop() override;
0332     void doMinimize() override;
0333     void doSetSkipPager() override;
0334     void doSetSkipTaskbar() override;
0335     void doSetSkipSwitcher() override;
0336     void doSetDemandsAttention() override;
0337     void doSetHidden() override;
0338     void doSetHiddenByShowDesktop() override;
0339     bool belongsToDesktop() const override;
0340     bool doStartInteractiveMoveResize() override;
0341     bool isWaitingForInteractiveMoveResizeSync() const override;
0342     void doInteractiveResizeSync(const QRectF &rect) override;
0343     QSizeF resizeIncrements() const override;
0344     bool acceptsFocus() const override;
0345     void moveResizeInternal(const QRectF &rect, MoveResizeMode mode) override;
0346     std::unique_ptr<WindowItem> createItem(Scene *scene) override;
0347 
0348 Q_SIGNALS:
0349     void shapeChanged();
0350 
0351 private:
0352     void exportMappingState(int s); // ICCCM 4.1.3.1, 4.1.4, NETWM 2.5.1
0353     bool isManaged() const; ///< Returns false if this client is not yet managed
0354     void updateAllowedActions(bool force = false);
0355     QRect fullscreenMonitorsArea(NETFullscreenMonitors topology) const;
0356     void getResourceClass();
0357     void getWmNormalHints();
0358     void getWmClientMachine();
0359     void getMotifHints();
0360     void getIcons();
0361     void getWmOpaqueRegion();
0362     void discardShapeRegion();
0363     void fetchName();
0364     void fetchIconicName();
0365     QString readName() const;
0366     void setCaption(const QString &s, bool force = false);
0367     bool hasTransientInternal(const X11Window *c, bool indirect, QList<const X11Window *> &set) const;
0368     void setShortcutInternal() override;
0369     Xcb::Property fetchWmClientLeader() const;
0370     void readWmClientLeader(Xcb::Property &p);
0371     void getWmClientLeader();
0372     Xcb::Property fetchSkipCloseAnimation() const;
0373     void readSkipCloseAnimation(Xcb::Property &prop);
0374     void getSkipCloseAnimation();
0375 
0376     void configureRequest(int value_mask, qreal rx, qreal ry, qreal rw, qreal rh, int gravity, bool from_tool);
0377     NETExtendedStrut strut() const;
0378     int checkShadeGeometry(int w, int h);
0379     void getSyncCounter();
0380     void sendSyncRequest();
0381     void leaveInteractiveMoveResize() override;
0382     void performInteractiveResize();
0383     void establishCommandWindowGrab(uint8_t button);
0384     void establishCommandAllGrab(uint8_t button);
0385     void resizeDecoration();
0386 
0387     void pingWindow();
0388     void killProcess(bool ask, xcb_timestamp_t timestamp = XCB_TIME_CURRENT_TIME);
0389     void updateUrgency();
0390     static void sendClientMessage(xcb_window_t w, xcb_atom_t a, xcb_atom_t protocol,
0391                                   uint32_t data1 = 0, uint32_t data2 = 0, uint32_t data3 = 0);
0392 
0393     void embedClient(xcb_window_t w, xcb_visualid_t visualid, xcb_colormap_t colormap, uint8_t depth);
0394     void detectNoBorder();
0395     void updateFrameExtents();
0396     void setClientFrameExtents(const NETStrut &strut);
0397 
0398     void internalShow();
0399     void internalHide();
0400     void internalKeep();
0401     void map();
0402     void unmap();
0403     void updateHiddenPreview();
0404 
0405     void updateInputShape();
0406     void updateServerGeometry();
0407     void discardWindowPixmap();
0408     void updateWindowPixmap();
0409 
0410     xcb_timestamp_t readUserTimeMapTimestamp(const KStartupInfoId *asn_id, const KStartupInfoData *asn_data,
0411                                              bool session) const;
0412     xcb_timestamp_t readUserCreationTime() const;
0413     void startupIdChanged();
0414 
0415     void updateInputWindow();
0416 
0417     Xcb::Property fetchShowOnScreenEdge() const;
0418     void readShowOnScreenEdge(Xcb::Property &property);
0419     /**
0420      * Reads the property and creates/destroys the screen edge if required
0421      * and shows/hides the client.
0422      */
0423     void updateShowOnScreenEdge();
0424 
0425     void maybeCreateX11DecorationRenderer();
0426     void maybeDestroyX11DecorationRenderer();
0427     void updateDecoration(bool check_workspace_pos, bool force = false);
0428     void createDecoration();
0429     void destroyDecoration();
0430 
0431     QWindow *findInternalWindow() const;
0432     void checkOutput();
0433     void associate();
0434     void handleXwaylandScaleChanged();
0435 
0436     Xcb::Window m_client;
0437     Xcb::Window m_wrapper;
0438     Xcb::Window m_frame;
0439     xcb_window_t m_wmClientLeader = XCB_WINDOW_NONE;
0440     int m_activityUpdatesBlocked;
0441     bool m_blockedActivityUpdatesRequireTransients;
0442     Xcb::Window m_moveResizeGrabWindow;
0443     bool move_resize_has_keyboard_grab;
0444     bool m_managed;
0445 
0446     Xcb::GeometryHints m_geometryHints;
0447     void sendSyntheticConfigureNotify();
0448     enum MappingState {
0449         Withdrawn, ///< Not handled, as per ICCCM WithdrawnState
0450         Mapped, ///< The frame is mapped
0451         Unmapped, ///< The frame is not mapped
0452         Kept ///< The frame should be unmapped, but is kept (For compositing)
0453     };
0454     MappingState mapping_state;
0455 
0456     Xcb::TransientFor fetchTransient() const;
0457     void readTransientProperty(Xcb::TransientFor &transientFor);
0458     void readTransient();
0459     xcb_window_t verifyTransientFor(xcb_window_t transient_for, bool set);
0460     void addTransient(Window *cl) override;
0461     void removeFromMainClients();
0462     void cleanGrouping();
0463     void checkGroupTransients();
0464     void setTransient(xcb_window_t new_transient_for_id);
0465 
0466     NETWinInfo *info = nullptr;
0467     xcb_window_t m_transientForId;
0468     xcb_window_t m_originalTransientForId;
0469     X11Window *shade_below;
0470     Xcb::MotifHints m_motif;
0471     uint noborder : 1;
0472     uint app_noborder : 1; ///< App requested no border via window type, shape extension, etc.
0473     uint ignore_focus_stealing : 1; ///< Don't apply focus stealing prevention to this client
0474     bool blocks_compositing;
0475     bool is_shape = false;
0476 
0477     enum FullScreenMode {
0478         FullScreenNone,
0479         FullScreenNormal
0480     } m_fullscreenMode;
0481 
0482     MaximizeMode max_mode;
0483     QString cap_normal, cap_iconic, cap_suffix;
0484     Group *in_group;
0485     QTimer *ping_timer;
0486     std::unique_ptr<KillPrompt> m_killPrompt;
0487     xcb_timestamp_t m_pingTimestamp;
0488     xcb_timestamp_t m_userTime;
0489     NET::Actions allowed_actions;
0490     bool shade_geometry_change;
0491     SyncRequest m_syncRequest;
0492     static bool check_active_modal; ///< \see X11Window::checkActiveModal()
0493     int sm_stacking_order;
0494     xcb_visualid_t m_visual = XCB_NONE;
0495     int bit_depth = 24;
0496     QRegion opaque_region;
0497     mutable QList<QRectF> m_shapeRegion;
0498     mutable bool m_shapeRegionIsValid = false;
0499     friend struct ResetupRulesProcedure;
0500 
0501     friend bool performTransiencyCheck();
0502 
0503     Xcb::StringProperty fetchActivities() const;
0504     void readActivities(Xcb::StringProperty &property);
0505     bool activitiesDefined; // whether the x property was actually set
0506 
0507     bool sessionActivityOverride;
0508 
0509     Xcb::Window m_decoInputExtent;
0510     QPointF input_offset;
0511 
0512     QTimer *m_focusOutTimer;
0513     QTimer m_releaseTimer;
0514 
0515     QMetaObject::Connection m_edgeGeometryTrackingConnection;
0516 
0517     QMarginsF m_clientFrameExtents;
0518     Output *m_lastOutput = nullptr;
0519     QRectF m_lastBufferGeometry;
0520     QRectF m_lastFrameGeometry;
0521     QRectF m_lastClientGeometry;
0522     std::unique_ptr<X11DecorationRenderer> m_decorationRenderer;
0523 
0524     bool m_unmanaged = false;
0525     bool m_outline = false;
0526     quint32 m_pendingSurfaceId = 0;
0527     quint64 m_surfaceSerial = 0;
0528 };
0529 
0530 inline xcb_visualid_t X11Window::visual() const
0531 {
0532     return m_visual;
0533 }
0534 
0535 inline int X11Window::depth() const
0536 {
0537     return bit_depth;
0538 }
0539 
0540 inline bool X11Window::hasAlpha() const
0541 {
0542     return depth() == 32;
0543 }
0544 
0545 inline QRegion X11Window::opaqueRegion() const
0546 {
0547     return opaque_region;
0548 }
0549 
0550 inline bool X11Window::isClientSideDecorated() const
0551 {
0552     return !m_clientFrameExtents.isNull();
0553 }
0554 
0555 inline bool X11Window::groupTransient() const
0556 {
0557     return m_transientForId == kwinApp()->x11RootWindow();
0558 }
0559 
0560 inline bool X11Window::isTransient() const
0561 {
0562     return m_transientForId != XCB_WINDOW_NONE;
0563 }
0564 
0565 inline const Group *X11Window::group() const
0566 {
0567     return in_group;
0568 }
0569 
0570 inline Group *X11Window::group()
0571 {
0572     return in_group;
0573 }
0574 
0575 inline MaximizeMode X11Window::maximizeMode() const
0576 {
0577     return max_mode;
0578 }
0579 
0580 inline bool X11Window::isFullScreen() const
0581 {
0582     return m_fullscreenMode != FullScreenNone;
0583 }
0584 
0585 inline bool X11Window::hasNETSupport() const
0586 {
0587     return info->hasNETSupport();
0588 }
0589 
0590 inline int X11Window::sessionStackingOrder() const
0591 {
0592     return sm_stacking_order;
0593 }
0594 
0595 inline bool X11Window::isManaged() const
0596 {
0597     return m_managed;
0598 }
0599 
0600 inline QRectF X11Window::resizeWithChecks(const QRectF &geometry, const QSizeF &s)
0601 {
0602     return resizeWithChecks(geometry, s.width(), s.height(), XCB_GRAVITY_BIT_FORGET);
0603 }
0604 
0605 inline QRectF X11Window::resizeWithChecks(const QRectF &geometry, const QSizeF &s, xcb_gravity_t gravity)
0606 {
0607     return resizeWithChecks(geometry, s.width(), s.height(), gravity);
0608 }
0609 
0610 inline bool X11Window::hasUserTimeSupport() const
0611 {
0612     return info->userTime() != -1U;
0613 }
0614 
0615 inline xcb_window_t X11Window::moveResizeGrabWindow() const
0616 {
0617     return m_moveResizeGrabWindow;
0618 }
0619 
0620 inline bool X11Window::hiddenPreview() const
0621 {
0622     return mapping_state == Kept;
0623 }
0624 
0625 inline quint64 X11Window::surfaceSerial() const
0626 {
0627     return m_surfaceSerial;
0628 }
0629 
0630 inline quint32 X11Window::pendingSurfaceId() const
0631 {
0632     return m_pendingSurfaceId;
0633 }
0634 
0635 } // namespace
0636 Q_DECLARE_METATYPE(KWin::X11Window *)
0637 Q_DECLARE_METATYPE(QList<KWin::X11Window *>)