1 /*
2     SPDX-FileCopyrightText: 2016 Smith AR <audoban@openmailbox.org>
3     SPDX-FileCopyrightText: 2016 Michail Vourlakos <mvourlakos@gmail.com>
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #ifndef VISIBILITYMANAGER_H
8 #define VISIBILITYMANAGER_H
9 
10 #include <array>
11 
12 // local
13 #include <coretypes.h>
14 #include "../plasma/quick/containmentview.h"
15 
16 #include <array>
17 
18 // Qt
19 #include <QObject>
20 #include <QTimer>
21 
22 // Plasma
23 #include <Plasma/Containment>
24 
25 
26 namespace Latte {
27 class Corona;
28 class View;
29 namespace ViewPart {
30 class FloatingGapWindow;
31 class ScreenEdgeGhostWindow;
32 }
33 namespace WindowSystem {
34 class AbstractWindowInterface;
35 }
36 }
37 
38 namespace Latte {
39 namespace ViewPart {
40 
41 class VisibilityManager : public QObject
42 {
43     Q_OBJECT
44     Q_PROPERTY(bool hidingIsBlocked READ hidingIsBlocked NOTIFY hidingIsBlockedChanged)
45 
46     Q_PROPERTY(Latte::Types::Visibility mode READ mode WRITE setMode NOTIFY modeChanged)
47     Q_PROPERTY(bool raiseOnDesktop READ raiseOnDesktop WRITE setRaiseOnDesktop NOTIFY raiseOnDesktopChanged)
48     Q_PROPERTY(bool raiseOnActivity READ raiseOnActivity WRITE setRaiseOnActivity NOTIFY raiseOnActivityChanged)
49     Q_PROPERTY(bool isHidden READ isHidden WRITE setIsHidden NOTIFY isHiddenChanged)
50     Q_PROPERTY(bool isShownFully READ isShownFully WRITE setIsShownFully NOTIFY isShownFullyChanged)
51     Q_PROPERTY(bool isBelowLayer READ isBelowLayer NOTIFY isBelowLayerChanged)
52     Q_PROPERTY(bool isSidebar READ isSidebar NOTIFY isSidebarChanged)
53     Q_PROPERTY(bool containsMouse READ containsMouse NOTIFY containsMouseChanged)
54 
55     //! Floating Gap Window to identify mouse between the screenEdge and the view when it does not accept any other
56     //! user input
57     Q_PROPERTY(bool isFloatingGapWindowEnabled READ isFloatingGapWindowEnabled WRITE setIsFloatingGapWindowEnabled NOTIFY isFloatingGapWindowEnabledChanged)
58 
59     //! KWin Edges Support Options
60     Q_PROPERTY(bool enableKWinEdges READ enableKWinEdges WRITE setEnableKWinEdges NOTIFY enableKWinEdgesChanged)
61     Q_PROPERTY(bool supportsKWinEdges READ supportsKWinEdges NOTIFY supportsKWinEdgesChanged)
62 
63     Q_PROPERTY(int timerShow READ timerShow WRITE setTimerShow NOTIFY timerShowChanged)
64     Q_PROPERTY(int timerHide READ timerHide WRITE setTimerHide NOTIFY timerHideChanged)
65 
66     //! Struts
67     Q_PROPERTY(int strutsThickness READ strutsThickness WRITE setStrutsThickness NOTIFY strutsThicknessChanged)
68 
69 public:
70     static const QRect ISHIDDENMASK;
71 
72     explicit VisibilityManager(PlasmaQuick::ContainmentView *view);
73     virtual ~VisibilityManager();
74 
75     Latte::Types::Visibility mode() const;
76     void setMode(Latte::Types::Visibility mode);
77 
78     void applyActivitiesToHiddenWindows(const QStringList &activities);
79 
80     bool raiseOnDesktop() const;
81     void setRaiseOnDesktop(bool enable);
82 
83     bool raiseOnActivity() const;
84     void setRaiseOnActivity(bool enable);
85 
86     bool isBelowLayer() const;
87 
88     bool isHidden() const;
89     void setIsHidden(bool isHidden);
90 
91     bool isShownFully() const;
92     void setIsShownFully(bool fully);
93 
94     bool hidingIsBlocked() const;
95 
96     bool containsMouse() const;
97 
98     bool isFloatingGapWindowEnabled() const;
99     void setIsFloatingGapWindowEnabled(bool enabled);
100 
101     int timerShow() const;
102     void setTimerShow(int msec);
103 
104     int timerHide() const;
105     void setTimerHide(int msec);
106 
107     bool isSidebar() const;
108     bool hasBlockHidingEvent(const QString &type);
109 
110     //! KWin Edges Support functions
111     bool enableKWinEdges() const;
112     void setEnableKWinEdges(bool enable);
113 
114     bool supportsKWinEdges() const;
115 
116     //! Struts
117     int strutsThickness() const;
118     void setStrutsThickness(int thickness);
119 
120     //! Used mostly to show / hide Sidebars
121     void toggleHiddenState();
122 
123 public slots:
124     Q_INVOKABLE void hide();
125     Q_INVOKABLE void show();
126 
127     Q_INVOKABLE void setViewOnBackLayer();
128     Q_INVOKABLE void setViewOnFrontLayer();
129 
130     Q_INVOKABLE void addBlockHidingEvent(const QString &type);
131     Q_INVOKABLE void removeBlockHidingEvent(const QString &type);
132 
133     void initViewFlags();
134 
135 signals:
136     void mustBeShown();
137     void mustBeHide();
138 
139     void slideOutFinished();
140     void slideInFinished();
141 
142     void frameExtentsCleared();
143     void modeChanged();
144     void raiseOnDesktopChanged();
145     void raiseOnActivityChanged();
146     void isBelowLayerChanged();
147     void isFloatingGapWindowEnabledChanged();
148     void isHiddenChanged();
149     void isSidebarChanged();
150     void isShownFullyChanged();
151     void hidingIsBlockedChanged();
152     void containsMouseChanged();
153     void strutsThicknessChanged();
154     void timerShowChanged();
155     void timerHideChanged();
156 
157     //! KWin Edges Support signals
158     void enableKWinEdgesChanged();
159     void supportsKWinEdgesChanged();
160 
161 private slots:
162     void saveConfig();
163     void restoreConfig();
164 
165     void setIsBelowLayer(bool below);
166 
167     void onHeadThicknessChanged();
168     void onHidingIsBlockedChanged();
169     void onIsFloatingGapWindowEnabledChanged();
170 
171     void publishFrameExtents(bool forceUpdate = false); //! direct
172 
173     //! KWin Edges Support functions
174     void updateKWinEdgesSupport();
175 
176     void updateSidebarState();
177 
178 private:
179     void setContainsMouse(bool contains);
180 
181     void raiseView(bool raise);
182     void raiseViewTemporarily();
183 
184     //! KWin Edges Support functions
185     void createEdgeGhostWindow();
186     void deleteEdgeGhostWindow();
187     void updateGhostWindowState();
188 
189     //! Floating Gap Support functions
190     void createFloatingGapWindow();
191     void deleteFloatingGapWindow();
192     bool supportsFloatingGap() const;
193 
194     void updateStrutsBasedOnLayoutsAndActivities(bool forceUpdate = false);
195     void viewEventManager(QEvent *ev);
196 
197     void checkMouseInFloatingArea();
198 
199     bool windowContainsMouse();
200 
201     QRect acceptableStruts();
202 
203 private slots:
204     void dodgeAllWindows();
205     void dodgeActive();
206     void dodgeMaximized();
207     void updateHiddenState();
208 
209     void updateStrutsAfterTimer();
210 
211     bool isValidMode() const;
212 
213 private:
214     void startTimerHide(const int &msec = 0);
215 
216     bool canSetStrut() const;
217 
218 private:
219     WindowSystem::AbstractWindowInterface *m_wm;
220     Types::Visibility m_mode{Types::None};
221     std::array<QMetaObject::Connection, 6> m_connections;
222 
223     QTimer m_timerShow;
224     QTimer m_timerHide;
225     QTimer m_timerPublishFrameExtents;
226     //! This timer is very important because it blocks how fast struts are updated.
227     //! By using this timer we help the window manager in order to correspond to new
228     //! struts (for example changing windows maximized state or geometry) without
229     //! createing binding loops between the app and the window manager.
230     //! That was reproducable in a floating panel when we were dragging the active window.
231     QTimer m_timerBlockStrutsUpdate;
232 
233     bool m_isBelowLayer{false};
234     bool m_isHidden{false};
235     bool m_isFloatingGapWindowEnabled{false};
236     bool m_isSidebar{false};
237     bool m_isShownFully{false};
238     bool m_dragEnter{false};
239     bool m_containsMouse{false};
240     bool m_raiseTemporarily{false};
241     bool m_raiseOnDesktopChange{false};
242     bool m_raiseOnActivityChange{false};
243     bool m_hideNow{false};
244 
245     //! valid on demand sidebar hidden state in order to be checked after slide-ins/outs
246     bool m_isRequestedShownSidebarOnDemand{false};
247 
248     int m_frameExtentsHeadThicknessGap{0};
249     int m_timerHideInterval{700};
250     Plasma::Types::Location m_frameExtentsLocation{Plasma::Types::BottomEdge};
251 
252     int m_strutsThickness{0};
253 
254     QStringList m_blockHidingEvents;
255 
256     QRect m_publishedStruts;
257     QRect m_lastMask;
258 
259     //! KWin Edges
260     bool m_enableKWinEdgesFromUser{true};
261     std::array<QMetaObject::Connection, 1> m_connectionsKWinEdges;
262     ScreenEdgeGhostWindow *m_edgeGhostWindow{nullptr};
263 
264     //! Floating Gap
265     FloatingGapWindow *m_floatingGapWindow{nullptr};
266 
267     Latte::Corona *m_corona{nullptr};
268     Latte::View *m_latteView{nullptr};
269 
270 };
271 
272 }
273 }
274 #endif // VISIBILITYMANAGER_H
275