1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#pragma once
#include "content_control.hpp"
#include "cru/common/self_resolvable.hpp"
#include "cru/platform/native/event.hpp"
#include <memory>
#include <vector>
namespace cru::platform::native {
struct INativeWindow;
struct INativeWindowResolver;
} // namespace cru::platform::native
namespace cru::ui {
namespace render {
class WindowRenderObject;
}
// TODO: Make Window able to be invalid and handle operations in invalidity
// situation.
class Window final : public ContentControl, public SelfResolvable<Window> {
friend class Control;
public:
static constexpr std::string_view control_type = "Window";
public:
static Window* CreateOverlapped();
private:
struct tag_overlapped_constructor {};
explicit Window(tag_overlapped_constructor);
public:
Window(const Window& other) = delete;
Window(Window&& other) = delete;
Window& operator=(const Window& other) = delete;
Window& operator=(Window&& other) = delete;
~Window() override;
public:
std::string_view GetControlType() const final;
render::RenderObject* GetRenderObject() const override;
platform::native::INativeWindow* ResolveNativeWindow();
// Get current control that mouse hovers on. This ignores the mouse-capture
// control. Even when mouse is captured by another control, this function
// return the control under cursor. You can use `GetMouseCaptureControl` to
// get more info.
Control* GetMouseHoverControl() const { return mouse_hover_control_; }
//*************** region: focus ***************
// Request focus for specified control.
bool RequestFocusFor(Control* control);
// Get the control that has focus.
Control* GetFocusControl();
//*************** region: focus ***************
// Pass nullptr to release capture. If mouse is already capture by a control,
// this capture will fail and return false. If control is identical to the
// capturing control, capture is not changed and this function will return
// true.
//
// When capturing control changes,
// appropriate event will be sent. If mouse is not on the capturing control
// and capture is released, mouse enter event will be sent to the mouse-hover
// control. If mouse is not on the capturing control and capture is set, mouse
// leave event will be sent to the mouse-hover control.
bool CaptureMouseFor(Control* control);
// Return null if not captured.
Control* GetMouseCaptureControl();
protected:
void OnChildChanged(Control* old_child, Control* new_child) override;
private:
Control* HitTest(const Point& point);
//*************** region: native messages ***************
void OnNativeDestroy(platform::native::INativeWindow* window, std::nullptr_t);
void OnNativePaint(platform::native::INativeWindow* window, std::nullptr_t);
void OnNativeResize(platform::native::INativeWindow* window,
const Size& size);
void OnNativeFocus(platform::native::INativeWindow* window,
cru::platform::native::FocusChangeType focus);
void OnNativeMouseEnterLeave(
platform::native::INativeWindow* window,
cru::platform::native::MouseEnterLeaveType enter);
void OnNativeMouseMove(platform::native::INativeWindow* window,
const Point& point);
void OnNativeMouseDown(
platform::native::INativeWindow* window,
const platform::native::NativeMouseButtonEventArgs& args);
void OnNativeMouseUp(
platform::native::INativeWindow* window,
const platform::native::NativeMouseButtonEventArgs& args);
void OnNativeKeyDown(platform::native::INativeWindow* window,
int virtual_code);
void OnNativeKeyUp(platform::native::INativeWindow* window, int virtual_code);
//*************** region: event dispatcher helper ***************
void DispatchMouseHoverControlChangeEvent(Control* old_control,
Control* new_control,
const Point& point, bool no_leave,
bool no_enter);
void UpdateCursor();
private:
std::shared_ptr<platform::native::INativeWindowResolver>
native_window_resolver_;
std::vector<EventRevokerGuard> event_revoker_guards_;
std::unique_ptr<render::WindowRenderObject> render_object_;
Control* mouse_hover_control_;
Control* focus_control_; // "focus_control_" can't be nullptr
Control* mouse_captured_control_;
bool need_layout_ = false;
};
} // namespace cru::ui
|