summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--platform/linuxbsd/display_server_x11.cpp20
-rw-r--r--platform/linuxbsd/display_server_x11.h9
-rw-r--r--platform/windows/display_server_windows.cpp35
-rw-r--r--platform/windows/display_server_windows.h9
-rw-r--r--scene/main/viewport.cpp243
-rw-r--r--scene/main/viewport.h2
-rw-r--r--scene/main/window.cpp3
-rw-r--r--servers/display_server.cpp4
-rw-r--r--servers/display_server.h7
9 files changed, 250 insertions, 82 deletions
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 8e225d9b5d..ffe6af41e2 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -699,6 +699,26 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {
windows.erase(p_id);
}
+void DisplayServerX11::window_attach_instance_id(ObjectID p_instance, WindowID p_window) {
+
+ ERR_FAIL_COND(!windows.has(p_window));
+ WindowData &wd = windows[p_window];
+
+ wd.instance_id = p_instance;
+}
+
+ObjectID DisplayServerX11::window_get_attached_instance_id(WindowID p_window) const {
+
+ ERR_FAIL_COND_V(!windows.has(p_window), ObjectID());
+ const WindowData &wd = windows[p_window];
+ return wd.instance_id;
+}
+
+DisplayServerX11::WindowID DisplayServerX11::get_window_at_screen_position(const Point2i &p_position) const {
+
+ return INVALID_WINDOW_ID;
+}
+
void DisplayServerX11::window_set_title(const String &p_title, WindowID p_window) {
_THREAD_SAFE_METHOD_
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index bfce4dc88a..5747ac93ba 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -130,6 +130,8 @@ class DisplayServerX11 : public DisplayServer {
WindowID transient_parent = INVALID_WINDOW_ID;
Set<WindowID> transient_children;
+ ObjectID instance_id;
+
//better to guess on the fly, given WM can change it
//WindowMode mode;
bool fullscreen = false; //OS can't exit from this mode
@@ -263,11 +265,16 @@ public:
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Vector<int> get_window_list() const;
+ virtual Vector<DisplayServer::WindowID> get_window_list() const;
virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
virtual void delete_sub_window(WindowID p_id);
+ virtual WindowID get_window_at_screen_position(const Point2i &p_position) const;
+
+ virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID);
+ virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const;
+
virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID);
virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index bbf305da3a..707337bc8d 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -435,17 +435,32 @@ bool DisplayServerWindows::screen_is_kept_on() const {
return false;
}
-Vector<int> DisplayServerWindows::get_window_list() const {
+Vector<DisplayServer::WindowID> DisplayServerWindows::get_window_list() const {
_THREAD_SAFE_METHOD_
- Vector<int> ret;
+ Vector<DisplayServer::WindowID> ret;
for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
ret.push_back(E->key());
}
return ret;
}
+DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(const Point2i &p_position) const {
+
+ POINT p;
+ p.x = p_position.x;
+ p.y = p_position.y;
+ HWND hwnd = WindowFromPoint(p);
+ for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
+ if (E->get().hWnd == hwnd) {
+ return E->key();
+ }
+ }
+
+ return INVALID_WINDOW_ID;
+}
+
DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_
@@ -504,6 +519,22 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
windows.erase(p_window);
}
+void DisplayServerWindows::window_attach_instance_id(ObjectID p_instance, WindowID p_window) {
+
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND(!windows.has(p_window));
+ windows[p_window].instance_id = p_instance;
+}
+
+ObjectID DisplayServerWindows::window_get_attached_instance_id(WindowID p_window) const {
+
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND_V(!windows.has(p_window), ObjectID());
+ return windows[p_window].instance_id;
+}
+
void DisplayServerWindows::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) {
_THREAD_SAFE_METHOD_
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index c8ee39ecaf..47bb3f59a6 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -195,6 +195,8 @@ class DisplayServerWindows : public DisplayServer {
Size2 window_rect;
Point2 last_pos;
+ ObjectID instance_id;
+
// IME
HIMC im_himc;
Vector2 im_position;
@@ -291,11 +293,16 @@ public:
virtual void screen_set_keep_on(bool p_enable); //disable screensaver
virtual bool screen_is_kept_on() const;
- virtual Vector<int> get_window_list() const;
+ virtual Vector<DisplayServer::WindowID> get_window_list() const;
virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
virtual void delete_sub_window(WindowID p_window);
+ virtual WindowID get_window_at_screen_position(const Point2i &p_position) const;
+
+ virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID);
+ virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const;
+
virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 309c9ee47d..e49674663a 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -196,6 +196,7 @@ Viewport::GUI::GUI() {
mouse_focus_mask = 0;
key_focus = NULL;
mouse_over = NULL;
+ drag_mouse_over = NULL;
tooltip = NULL;
tooltip_popup = NULL;
@@ -1960,11 +1961,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) {
- if (gui.mouse_over) {
- Size2 pos = mpos;
- pos = gui.focus_inv_xform.xform(pos);
-
- _gui_drop(gui.mouse_over, pos, false);
+ if (gui.drag_mouse_over) {
+ _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false);
}
if (gui.drag_preview && mb->get_button_index() == BUTTON_LEFT) {
@@ -1974,6 +1972,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.drag_data = Variant();
gui.dragging = false;
+ gui.drag_mouse_over = nullptr;
_propagate_viewport_notification(this, NOTIFICATION_DRAG_END);
//change mouse accordingly
}
@@ -2098,107 +2097,195 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.mouse_over = over;
- if (gui.drag_preview) {
- gui.drag_preview->set_position(mpos);
- }
+ DisplayServer::CursorShape ds_cursor_shape = (DisplayServer::CursorShape)InputFilter::get_singleton()->get_default_cursor_shape();
- if (!over) {
- DisplayServer::get_singleton()->cursor_set_shape((DisplayServer::CursorShape)InputFilter::get_singleton()->get_default_cursor_shape());
- return;
- }
-
- Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse();
- Size2 pos = localizer.xform(mpos);
- Vector2 speed = localizer.basis_xform(mm->get_speed());
- Vector2 rel = localizer.basis_xform(mm->get_relative());
-
- mm = mm->xformed_by(Transform2D()); //make a copy
+ if (over) {
- mm->set_global_position(mpos);
- mm->set_speed(speed);
- mm->set_relative(rel);
+ Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse();
+ Size2 pos = localizer.xform(mpos);
+ Vector2 speed = localizer.basis_xform(mm->get_speed());
+ Vector2 rel = localizer.basis_xform(mm->get_relative());
- if (mm->get_button_mask() == 0) {
- //nothing pressed
+ mm = mm->xformed_by(Transform2D()); //make a copy
- bool can_tooltip = true;
+ mm->set_global_position(mpos);
+ mm->set_speed(speed);
+ mm->set_relative(rel);
- bool is_tooltip_shown = false;
+ if (mm->get_button_mask() == 0) {
+ //nothing pressed
- if (gui.tooltip_popup) {
- if (can_tooltip && gui.tooltip) {
- String tooltip = _gui_get_tooltip(over, gui.tooltip->get_global_transform().xform_inv(mpos));
+ bool can_tooltip = true;
- if (tooltip.length() == 0)
- _gui_cancel_tooltip();
- else if (gui.tooltip_label) {
- if (tooltip == gui.tooltip_label->get_text()) {
- is_tooltip_shown = true;
- }
- } else {
+ bool is_tooltip_shown = false;
- Variant t = gui.tooltip_popup->call("get_tooltip_text");
+ if (gui.tooltip_popup) {
+ if (can_tooltip && gui.tooltip) {
+ String tooltip = _gui_get_tooltip(over, gui.tooltip->get_global_transform().xform_inv(mpos));
- if (t.get_type() == Variant::STRING) {
- if (tooltip == String(t)) {
+ if (tooltip.length() == 0)
+ _gui_cancel_tooltip();
+ else if (gui.tooltip_label) {
+ if (tooltip == gui.tooltip_label->get_text()) {
is_tooltip_shown = true;
}
} else {
- is_tooltip_shown = true; //well, nothing to compare against, likely using custom control, so if it changes there is nothing we can do
+
+ Variant t = gui.tooltip_popup->call("get_tooltip_text");
+
+ if (t.get_type() == Variant::STRING) {
+ if (tooltip == String(t)) {
+ is_tooltip_shown = true;
+ }
+ } else {
+ is_tooltip_shown = true; //well, nothing to compare against, likely using custom control, so if it changes there is nothing we can do
+ }
}
- }
- } else
- _gui_cancel_tooltip();
+ } else
+ _gui_cancel_tooltip();
+ }
+
+ if (can_tooltip && !is_tooltip_shown) {
+
+ gui.tooltip = over;
+ gui.tooltip_pos = over->get_screen_transform().xform(pos); //(parent_xform * get_transform()).affine_inverse().xform(pos);
+ gui.tooltip_timer = gui.tooltip_delay;
+ }
}
- if (can_tooltip && !is_tooltip_shown) {
+ //pos = gui.focus_inv_xform.xform(pos);
- gui.tooltip = over;
- gui.tooltip_pos = over->get_screen_transform().xform(pos); //(parent_xform * get_transform()).affine_inverse().xform(pos);
- gui.tooltip_timer = gui.tooltip_delay;
+ mm->set_position(pos);
+
+ Control::CursorShape cursor_shape = Control::CURSOR_ARROW;
+ {
+ Control *c = over;
+ Vector2 cpos = pos;
+ while (c) {
+ cursor_shape = c->get_cursor_shape(cpos);
+ cpos = c->get_transform().xform(cpos);
+ if (cursor_shape != Control::CURSOR_ARROW)
+ break;
+ if (c->data.mouse_filter == Control::MOUSE_FILTER_STOP)
+ break;
+ if (c->is_set_as_toplevel())
+ break;
+ c = c->get_parent_control();
+ }
+ }
+
+ ds_cursor_shape = (DisplayServer::CursorShape)cursor_shape;
+
+ if (over && over->can_process()) {
+ _gui_call_input(over, mm);
}
+
+ set_input_as_handled();
}
- //pos = gui.focus_inv_xform.xform(pos);
+ if (gui.drag_data.get_type() != Variant::NIL) {
+ //handle dragandrop
- mm->set_position(pos);
+ if (gui.drag_preview) {
+ gui.drag_preview->set_position(mpos);
+ }
- Control::CursorShape cursor_shape = Control::CURSOR_ARROW;
- {
- Control *c = over;
- Vector2 cpos = pos;
- while (c) {
- cursor_shape = c->get_cursor_shape(cpos);
- cpos = c->get_transform().xform(cpos);
- if (cursor_shape != Control::CURSOR_ARROW)
- break;
- if (c->data.mouse_filter == Control::MOUSE_FILTER_STOP)
- break;
- if (c->is_set_as_toplevel())
- break;
- c = c->get_parent_control();
+ gui.drag_mouse_over = over;
+ gui.drag_mouse_over_pos = Vector2();
+
+ //find the window this is above of
+
+ //see if there is an embedder
+ Viewport *embedder = nullptr;
+ Vector2 viewport_pos;
+
+ if (is_embedding_subwindows()) {
+ embedder = this;
+ viewport_pos = mpos;
+ } else {
+ //not an embeder, but may be a subwindow of an embedder
+ Window *w = Object::cast_to<Window>(this);
+ if (w) {
+ if (w->is_embedded()) {
+ embedder = w->_get_embedder();
+
+ Transform2D ai = (get_final_transform().affine_inverse() * _get_input_pre_xform()).affine_inverse();
+
+ viewport_pos = ai.xform(mpos) + w->get_position(); //to parent coords
+ }
+ }
}
- }
- DisplayServer::get_singleton()->cursor_set_shape((DisplayServer::CursorShape)cursor_shape);
+ Viewport *viewport_under = nullptr;
- if (over && over->can_process()) {
- _gui_call_input(over, mm);
- }
+ if (embedder) {
+ //use embedder logic
- set_input_as_handled();
+ for (int i = embedder->gui.sub_windows.size() - 1; i >= 0; i--) {
+ Window *sw = embedder->gui.sub_windows[i].window;
+ Rect2 swrect = Rect2i(sw->get_position(), sw->get_size());
+ if (!sw->get_flag(Window::FLAG_BORDERLESS)) {
+ int title_height = sw->get_theme_constant("title_height");
+ swrect.position.y -= title_height;
+ swrect.size.y += title_height;
+ }
+
+ if (swrect.has_point(viewport_pos)) {
+ viewport_under = sw;
+ viewport_pos -= sw->get_position();
+ }
+ }
- if (gui.drag_data.get_type() != Variant::NIL && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (!viewport_under) {
+ //not in a subwindow, likely in embedder
+ viewport_under = embedder;
+ }
+ } else {
+ //use displayserver logic
+ Vector2i screen_mouse_pos = DisplayServer::get_singleton()->mouse_get_position();
+
+ DisplayServer::WindowID window_id = DisplayServer::get_singleton()->get_window_at_screen_position(screen_mouse_pos);
+
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ ObjectID object_under = DisplayServer::get_singleton()->window_get_attached_instance_id(window_id);
+
+ if (object_under != ObjectID()) { //fetch window
+ Window *w = Object::cast_to<Window>(ObjectDB::get_instance(object_under));
+ if (w) {
+ viewport_under = w;
+ viewport_pos = screen_mouse_pos - w->get_position();
+ }
+ }
+ }
+ }
- bool can_drop = _gui_drop(over, pos, true);
+ if (viewport_under) {
+ Transform2D ai = (viewport_under->get_final_transform().affine_inverse() * viewport_under->_get_input_pre_xform());
+ viewport_pos = ai.xform(viewport_pos);
+ //find control under at pos
+ gui.drag_mouse_over = viewport_under->_gui_find_control(viewport_pos);
+ if (gui.drag_mouse_over) {
+ Transform2D localizer = gui.drag_mouse_over->get_global_transform_with_canvas().affine_inverse();
+ gui.drag_mouse_over_pos = localizer.xform(viewport_pos);
+
+ if (mm->get_button_mask() & BUTTON_MASK_LEFT) {
+
+ bool can_drop = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, true);
+
+ if (!can_drop) {
+ ds_cursor_shape = DisplayServer::CURSOR_FORBIDDEN;
+ } else {
+ ds_cursor_shape = DisplayServer::CURSOR_CAN_DROP;
+ }
+ }
+ }
- if (!can_drop) {
- DisplayServer::get_singleton()->cursor_set_shape(DisplayServer::CURSOR_FORBIDDEN);
} else {
- DisplayServer::get_singleton()->cursor_set_shape(DisplayServer::CURSOR_CAN_DROP);
+ gui.drag_mouse_over = nullptr;
}
- //change mouse accordingly i guess
}
+
+ DisplayServer::get_singleton()->cursor_set_shape(ds_cursor_shape);
}
Ref<InputEventScreenTouch> touch_event = p_event;
@@ -2443,6 +2530,8 @@ void Viewport::_gui_hid_control(Control *p_control) {
_gui_remove_focus();
if (gui.mouse_over == p_control)
gui.mouse_over = NULL;
+ if (gui.drag_mouse_over == p_control)
+ gui.drag_mouse_over = NULL;
if (gui.tooltip == p_control)
_gui_cancel_tooltip();
}
@@ -2461,6 +2550,8 @@ void Viewport::_gui_remove_control(Control *p_control) {
gui.key_focus = NULL;
if (gui.mouse_over == p_control)
gui.mouse_over = NULL;
+ if (gui.drag_mouse_over == p_control)
+ gui.drag_mouse_over = NULL;
if (gui.tooltip == p_control)
gui.tooltip = NULL;
}
@@ -2852,7 +2943,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
_sub_window_update(sw.window);
} else {
- gui.subwindow_resize_mode = _sub_window_get_resize_margin(gui.subwindow_focused, mb->get_position());
+ gui.subwindow_resize_mode = _sub_window_get_resize_margin(sw.window, mb->get_position());
if (gui.subwindow_resize_mode != SUB_WINDOW_RESIZE_DISABLED) {
gui.subwindow_resize_from_rect = r;
gui.subwindow_drag_from = mb->get_position();
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index e9c5a05ce2..6b68bc0c94 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -310,6 +310,8 @@ private:
int mouse_focus_mask;
Control *key_focus;
Control *mouse_over;
+ Control *drag_mouse_over;
+ Vector2 drag_mouse_over_pos;
Control *tooltip;
Window *tooltip_popup;
Label *tooltip_label;
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index ea6d4a46bd..f8a86b0957 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -228,6 +228,7 @@ void Window::_make_window() {
DisplayServer::get_singleton()->window_set_max_size(max_size, window_id);
DisplayServer::get_singleton()->window_set_min_size(min_size, window_id);
DisplayServer::get_singleton()->window_set_title(title, window_id);
+ DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
_update_window_size();
@@ -715,6 +716,7 @@ void Window::_notification(int p_what) {
//it's the root window!
visible = true; //always visible
window_id = DisplayServer::MAIN_WINDOW_ID;
+ DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
_update_from_window();
//since this window already exists (created on start), we must update pos and size from it
{
@@ -869,7 +871,6 @@ void Window::child_controls_changed() {
}
void Window::_window_input(const Ref<InputEvent> &p_ev) {
-
if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_ev.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_ev)))
return; //avoid joy input on editor
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 8432842469..f2103a2856 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -263,6 +263,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("screen_is_kept_on"), &DisplayServer::screen_is_kept_on);
ClassDB::bind_method(D_METHOD("get_window_list"), &DisplayServer::get_window_list);
+ ClassDB::bind_method(D_METHOD("get_window_at_screen_position", "position"), &DisplayServer::get_window_at_screen_position);
ClassDB::bind_method(D_METHOD("create_sub_window", "mode", "rect"), &DisplayServer::create_sub_window, DEFVAL(Rect2i()));
ClassDB::bind_method(D_METHOD("delete_sub_window", "window_id"), &DisplayServer::delete_sub_window);
@@ -283,6 +284,9 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("window_set_input_text_callback", "callback", "window_id"), &DisplayServer::window_set_input_text_callback, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_set_drop_files_callback", "callback", "window_id"), &DisplayServer::window_set_drop_files_callback, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_attach_instance_id", "instance_id", "window_id"), &DisplayServer::window_get_max_size, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_get_attached_instance_id", "window_id"), &DisplayServer::window_get_max_size, DEFVAL(MAIN_WINDOW_ID));
+
ClassDB::bind_method(D_METHOD("window_get_max_size", "window_id"), &DisplayServer::window_get_max_size, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_set_max_size", "max_size", "window_id"), &DisplayServer::window_set_max_size, DEFVAL(MAIN_WINDOW_ID));
diff --git a/servers/display_server.h b/servers/display_server.h
index fd70c8919f..51acf637e5 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -166,7 +166,7 @@ public:
typedef int WindowID;
- virtual Vector<int> get_window_list() const = 0;
+ virtual Vector<DisplayServer::WindowID> get_window_list() const = 0;
enum WindowFlags {
WINDOW_FLAG_RESIZE_DISABLED,
@@ -185,6 +185,11 @@ public:
virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i & = Rect2i());
virtual void delete_sub_window(WindowID p_id);
+ virtual WindowID get_window_at_screen_position(const Point2i &p_position) const = 0;
+
+ virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) = 0;
+ virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const = 0;
+
virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0;
enum WindowEvent {