1 #pragma once
2 
3 #include "widgets/BaseWidget.hpp"
4 
5 #include <functional>
6 #include <pajlada/signals/signalholder.hpp>
7 #include "common/FlagsEnum.hpp"
8 
9 class QHBoxLayout;
10 struct tagMSG;
11 typedef struct tagMSG MSG;
12 
13 namespace chatterino {
14 
15 class Button;
16 class EffectLabel;
17 class TitleBarButton;
18 enum class TitleBarButtonStyle;
19 
20 class BaseWindow : public BaseWidget
21 {
22     Q_OBJECT
23 
24 public:
25     enum Flags {
26         None = 0,
27         EnableCustomFrame = 1,
28         Frameless = 2,
29         TopMost = 4,
30         DisableCustomScaling = 8,
31         FramelessDraggable = 16,
32         DontFocus = 32,
33         Dialog = 64,
34     };
35 
36     enum ActionOnFocusLoss { Nothing, Delete, Close, Hide };
37 
38     explicit BaseWindow(FlagsEnum<Flags> flags_ = None,
39                         QWidget *parent = nullptr);
40     ~BaseWindow() override;
41 
42     void setInitialBounds(const QRect &bounds);
43     QRect getBounds();
44 
45     QWidget *getLayoutContainer();
46     bool hasCustomWindowFrame();
47     TitleBarButton *addTitleBarButton(const TitleBarButtonStyle &style,
48                                       std::function<void()> onClicked);
49     EffectLabel *addTitleBarLabel(std::function<void()> onClicked);
50 
51     void setStayInScreenRect(bool value);
52     bool getStayInScreenRect() const;
53 
54     void setActionOnFocusLoss(ActionOnFocusLoss value);
55     ActionOnFocusLoss getActionOnFocusLoss() const;
56 
57     void moveTo(QWidget *widget, QPoint point, bool offset = true);
58 
59     virtual float scale() const override;
60     float qtFontScale() const;
61 
62     pajlada::Signals::NoArgSignal closing;
63 
64     static bool supportsCustomWindowFrame();
65 
66 protected:
67     virtual bool nativeEvent(const QByteArray &eventType, void *message,
68                              long *result) override;
69     virtual void scaleChangedEvent(float) override;
70 
71     virtual void paintEvent(QPaintEvent *) override;
72 
73     virtual void changeEvent(QEvent *) override;
74     virtual void leaveEvent(QEvent *) override;
75     virtual void resizeEvent(QResizeEvent *) override;
76     virtual void moveEvent(QMoveEvent *) override;
77     virtual void closeEvent(QCloseEvent *) override;
78     virtual void showEvent(QShowEvent *) override;
79 
80     virtual void themeChangedEvent() override;
81     virtual bool event(QEvent *event) override;
82     virtual void wheelEvent(QWheelEvent *event) override;
83 
84     void mousePressEvent(QMouseEvent *event) override;
85     void mouseReleaseEvent(QMouseEvent *event) override;
86     void mouseMoveEvent(QMouseEvent *event) override;
87     QPointF movingRelativePos;
88     bool moving{};
89 
90     void updateScale();
91 
92     boost::optional<QColor> overrideBackgroundColor_;
93 
94 private:
95     void init();
96     void moveIntoDesktopRect(QWidget *parent, QPoint point);
97     void calcButtonsSizes();
98     void drawCustomWindowFrame(QPainter &painter);
99     void onFocusLost();
100 
101     bool handleDPICHANGED(MSG *msg);
102     bool handleSHOWWINDOW(MSG *msg);
103     bool handleNCCALCSIZE(MSG *msg, long *result);
104     bool handleSIZE(MSG *msg);
105     bool handleMOVE(MSG *msg);
106     bool handleNCHITTEST(MSG *msg, long *result);
107 
108     bool enableCustomFrame_;
109     ActionOnFocusLoss actionOnFocusLoss_ = Nothing;
110     bool frameless_;
111     bool stayInScreenRect_ = false;
112     bool shown_ = false;
113     FlagsEnum<Flags> flags_;
114     float nativeScale_ = 1;
115     bool isResizeFixing_ = false;
116 
117     struct {
118         QLayout *windowLayout = nullptr;
119         QHBoxLayout *titlebarBox = nullptr;
120         QWidget *titleLabel = nullptr;
121         TitleBarButton *minButton = nullptr;
122         TitleBarButton *maxButton = nullptr;
123         TitleBarButton *exitButton = nullptr;
124         QWidget *layoutBase = nullptr;
125         std::vector<Button *> buttons;
126     } ui_;
127 
128 #ifdef USEWINSDK
129     QRect initalBounds_;
130     QRect currentBounds_;
131     QRect nextBounds_;
132     QTimer useNextBounds_;
133     bool isNotMinimizedOrMaximized_{};
134 #endif
135 
136     pajlada::Signals::SignalHolder connections_;
137     std::vector<pajlada::Signals::ScopedConnection> managedConnections_;
138 
139     friend class BaseWidget;
140 };
141 
142 }  // namespace chatterino
143