mirror of
https://github.com/godotengine/godot.git
synced 2024-11-27 09:16:35 +08:00
Add exclusive window handling to DisplayServer (on macOS and Windows).
This commit is contained in:
parent
cf13f8af64
commit
7d59b81d79
@ -638,6 +638,16 @@
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_set_exclusive">
|
||||
<return type="void" />
|
||||
<argument index="0" name="window_id" type="int" />
|
||||
<argument index="1" name="exclusive" type="bool" />
|
||||
<description>
|
||||
If set to [code]true[/code], this window will always stay on top of its parent window, parent window will ignore input while this window is opened.
|
||||
[b]Note:[/b] On macOS, exclusive windows are confined to the same space (virtual desktop or screen) as the parent window.
|
||||
[b]Note:[/b] This method is implemented on macOS and Windows.
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_set_flag">
|
||||
<return type="void" />
|
||||
<argument index="0" name="flag" type="int" enum="DisplayServer.WindowFlags" />
|
||||
|
@ -95,6 +95,7 @@ public:
|
||||
ObjectID instance_id;
|
||||
|
||||
WindowID transient_parent = INVALID_WINDOW_ID;
|
||||
bool exclusive = false;
|
||||
Set<WindowID> transient_children;
|
||||
|
||||
bool layered_window = false;
|
||||
@ -274,6 +275,7 @@ public:
|
||||
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
|
||||
virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
|
||||
virtual void window_set_exclusive(WindowID p_window, bool p_exclusive) override;
|
||||
|
||||
virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||
|
@ -1471,6 +1471,24 @@ void DisplayServerOSX::window_set_current_screen(int p_screen, WindowID p_window
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayServerOSX::window_set_exclusive(WindowID p_window, bool p_exclusive) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
if (wd.exclusive != p_exclusive) {
|
||||
wd.exclusive = p_exclusive;
|
||||
if (wd.transient_parent != INVALID_WINDOW_ID) {
|
||||
WindowData &wd_parent = windows[wd.transient_parent];
|
||||
if (wd.exclusive) {
|
||||
ERR_FAIL_COND_MSG([[wd_parent.window_object childWindows] count] > 0, "Transient parent has another exclusive child.");
|
||||
[wd_parent.window_object addChildWindow:wd.window_object ordered:NSWindowAbove];
|
||||
} else {
|
||||
[wd_parent.window_object removeChildWindow:wd.window_object];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Point2i DisplayServerOSX::window_get_position(WindowID p_window) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
@ -1541,8 +1559,11 @@ void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent
|
||||
|
||||
wd_window.transient_parent = INVALID_WINDOW_ID;
|
||||
wd_parent.transient_children.erase(p_window);
|
||||
|
||||
[wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
|
||||
|
||||
if (wd_window.exclusive) {
|
||||
[wd_parent.window_object removeChildWindow:wd_window.window_object];
|
||||
}
|
||||
} else {
|
||||
ERR_FAIL_COND(!windows.has(p_parent));
|
||||
ERR_FAIL_COND_MSG(wd_window.transient_parent != INVALID_WINDOW_ID, "Window already has a transient parent");
|
||||
@ -1550,8 +1571,11 @@ void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent
|
||||
|
||||
wd_window.transient_parent = p_parent;
|
||||
wd_parent.transient_children.insert(p_window);
|
||||
|
||||
[wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
|
||||
|
||||
if (wd_window.exclusive) {
|
||||
[wd_parent.window_object addChildWindow:wd_window.window_object ordered:NSWindowAbove];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -830,6 +830,23 @@ void DisplayServerWindows::window_set_position(const Point2i &p_position, Window
|
||||
_update_real_mouse_position(p_window);
|
||||
}
|
||||
|
||||
void DisplayServerWindows::window_set_exclusive(WindowID p_window, bool p_exclusive) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
if (wd.exclusive != p_exclusive) {
|
||||
wd.exclusive = p_exclusive;
|
||||
if (wd.transient_parent != INVALID_WINDOW_ID) {
|
||||
WindowData &wd_parent = windows[wd.transient_parent];
|
||||
if (wd.exclusive) {
|
||||
SetWindowLongPtr(wd.hWnd, GWLP_HWNDPARENT, (LONG_PTR)wd_parent.hWnd);
|
||||
} else {
|
||||
SetWindowLongPtr(wd.hWnd, GWLP_HWNDPARENT, (LONG_PTR) nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayServerWindows::window_set_transient(WindowID p_window, WindowID p_parent) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
@ -852,7 +869,9 @@ void DisplayServerWindows::window_set_transient(WindowID p_window, WindowID p_pa
|
||||
wd_window.transient_parent = INVALID_WINDOW_ID;
|
||||
wd_parent.transient_children.erase(p_window);
|
||||
|
||||
SetWindowLongPtr(wd_window.hWnd, GWLP_HWNDPARENT, (LONG_PTR) nullptr);
|
||||
if (wd_window.exclusive) {
|
||||
SetWindowLongPtr(wd_window.hWnd, GWLP_HWNDPARENT, (LONG_PTR) nullptr);
|
||||
}
|
||||
} else {
|
||||
ERR_FAIL_COND(!windows.has(p_parent));
|
||||
ERR_FAIL_COND_MSG(wd_window.transient_parent != INVALID_WINDOW_ID, "Window already has a transient parent");
|
||||
@ -861,7 +880,9 @@ void DisplayServerWindows::window_set_transient(WindowID p_window, WindowID p_pa
|
||||
wd_window.transient_parent = p_parent;
|
||||
wd_parent.transient_children.insert(p_window);
|
||||
|
||||
SetWindowLongPtr(wd_window.hWnd, GWLP_HWNDPARENT, (LONG_PTR)wd_parent.hWnd);
|
||||
if (wd_window.exclusive) {
|
||||
SetWindowLongPtr(wd_window.hWnd, GWLP_HWNDPARENT, (LONG_PTR)wd_parent.hWnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,6 +339,7 @@ class DisplayServerWindows : public DisplayServer {
|
||||
bool always_on_top = false;
|
||||
bool no_focus = false;
|
||||
bool window_has_focus = false;
|
||||
bool exclusive = false;
|
||||
|
||||
// Used to transfer data between events using timer.
|
||||
WPARAM saved_wparam;
|
||||
@ -499,6 +500,7 @@ public:
|
||||
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
|
||||
virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
|
||||
virtual void window_set_exclusive(WindowID p_window, bool p_exclusive) override;
|
||||
|
||||
virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||
|
@ -254,6 +254,7 @@ void Window::_make_window() {
|
||||
#endif
|
||||
DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
|
||||
DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
|
||||
DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
|
||||
|
||||
_update_window_size();
|
||||
|
||||
@ -522,6 +523,10 @@ void Window::set_exclusive(bool p_exclusive) {
|
||||
|
||||
exclusive = p_exclusive;
|
||||
|
||||
if (!embedder && window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
|
||||
}
|
||||
|
||||
if (transient_parent) {
|
||||
if (p_exclusive && is_inside_tree() && is_visible()) {
|
||||
ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child.");
|
||||
|
@ -204,6 +204,10 @@ void DisplayServer::delete_sub_window(WindowID p_id) {
|
||||
ERR_FAIL_MSG("Sub-windows not supported by this display server.");
|
||||
}
|
||||
|
||||
void DisplayServer::window_set_exclusive(WindowID p_window, bool p_exclusive) {
|
||||
// Do nothing, if not supported.
|
||||
}
|
||||
|
||||
void DisplayServer::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) {
|
||||
ERR_FAIL_MSG("Mouse passthrough not supported by this display server.");
|
||||
}
|
||||
@ -436,6 +440,7 @@ void DisplayServer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("window_can_draw", "window_id"), &DisplayServer::window_can_draw, DEFVAL(MAIN_WINDOW_ID));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("window_set_transient", "window_id", "parent_window_id"), &DisplayServer::window_set_transient);
|
||||
ClassDB::bind_method(D_METHOD("window_set_exclusive", "window_id", "exclusive"), &DisplayServer::window_set_exclusive);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("window_set_ime_active", "active", "window_id"), &DisplayServer::window_set_ime_active, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_ime_position", "position", "window_id"), &DisplayServer::window_set_ime_position, DEFVAL(MAIN_WINDOW_ID));
|
||||
|
@ -277,6 +277,7 @@ public:
|
||||
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) = 0;
|
||||
|
||||
virtual void window_set_transient(WindowID p_window, WindowID p_parent) = 0;
|
||||
virtual void window_set_exclusive(WindowID p_window, bool p_exclusive);
|
||||
|
||||
virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) = 0;
|
||||
virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user