You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-11 13:10:58 +00:00
Merge pull request #99844 from KoBeWi/give_back_the_focus
Fix progress dialog steals focus
This commit is contained in:
@@ -341,6 +341,19 @@ void EditorNode::_update_title() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorNode::input(const Ref<InputEvent> &p_event) {
|
||||||
|
// EditorNode::get_singleton()->set_process_input is set to true in ProgressDialog
|
||||||
|
// only when the progress dialog is visible.
|
||||||
|
// We need to discard all key events to disable all shortcuts while the progress
|
||||||
|
// dialog is displayed, simulating an exclusive popup. Mouse events are
|
||||||
|
// captured by a full-screen container in front of the EditorNode in ProgressDialog,
|
||||||
|
// allowing interaction with the actual dialog where a Cancel button may be visible.
|
||||||
|
Ref<InputEventKey> k = p_event;
|
||||||
|
if (k.is_valid()) {
|
||||||
|
get_tree()->get_root()->set_input_as_handled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EditorNode::shortcut_input(const Ref<InputEvent> &p_event) {
|
void EditorNode::shortcut_input(const Ref<InputEvent> &p_event) {
|
||||||
ERR_FAIL_COND(p_event.is_null());
|
ERR_FAIL_COND(p_event.is_null());
|
||||||
|
|
||||||
@@ -7079,7 +7092,7 @@ EditorNode::EditorNode() {
|
|||||||
resource_preview = memnew(EditorResourcePreview);
|
resource_preview = memnew(EditorResourcePreview);
|
||||||
add_child(resource_preview);
|
add_child(resource_preview);
|
||||||
progress_dialog = memnew(ProgressDialog);
|
progress_dialog = memnew(ProgressDialog);
|
||||||
progress_dialog->set_unparent_when_invisible(true);
|
add_child(progress_dialog);
|
||||||
progress_dialog->connect(SceneStringName(visibility_changed), callable_mp(this, &EditorNode::_progress_dialog_visibility_changed));
|
progress_dialog->connect(SceneStringName(visibility_changed), callable_mp(this, &EditorNode::_progress_dialog_visibility_changed));
|
||||||
|
|
||||||
gui_base = memnew(Panel);
|
gui_base = memnew(Panel);
|
||||||
|
|||||||
@@ -592,6 +592,7 @@ private:
|
|||||||
|
|
||||||
void _exit_editor(int p_exit_code);
|
void _exit_editor(int p_exit_code);
|
||||||
|
|
||||||
|
virtual void input(const Ref<InputEvent> &p_event) override;
|
||||||
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
|
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
|
||||||
|
|
||||||
bool has_main_screen() const { return true; }
|
bool has_main_screen() const { return true; }
|
||||||
|
|||||||
@@ -35,6 +35,8 @@
|
|||||||
#include "editor/editor_node.h"
|
#include "editor/editor_node.h"
|
||||||
#include "editor/themes/editor_scale.h"
|
#include "editor/themes/editor_scale.h"
|
||||||
#include "main/main.h"
|
#include "main/main.h"
|
||||||
|
#include "scene/gui/panel_container.h"
|
||||||
|
#include "scene/main/window.h"
|
||||||
#include "servers/display_server.h"
|
#include "servers/display_server.h"
|
||||||
|
|
||||||
void BackgroundProgress::_add_task(const String &p_task, const String &p_label, int p_steps) {
|
void BackgroundProgress::_add_task(const String &p_task, const String &p_label, int p_steps) {
|
||||||
@@ -126,6 +128,21 @@ void BackgroundProgress::end_task(const String &p_task) {
|
|||||||
|
|
||||||
ProgressDialog *ProgressDialog::singleton = nullptr;
|
ProgressDialog *ProgressDialog::singleton = nullptr;
|
||||||
|
|
||||||
|
void ProgressDialog::_notification(int p_what) {
|
||||||
|
switch (p_what) {
|
||||||
|
case NOTIFICATION_THEME_CHANGED: {
|
||||||
|
Ref<StyleBox> style = main->get_theme_stylebox(SceneStringName(panel), SNAME("PopupMenu"));
|
||||||
|
main_border_size = style->get_minimum_size();
|
||||||
|
main->set_offset(SIDE_LEFT, style->get_margin(SIDE_LEFT));
|
||||||
|
main->set_offset(SIDE_RIGHT, -style->get_margin(SIDE_RIGHT));
|
||||||
|
main->set_offset(SIDE_TOP, style->get_margin(SIDE_TOP));
|
||||||
|
main->set_offset(SIDE_BOTTOM, -style->get_margin(SIDE_BOTTOM));
|
||||||
|
|
||||||
|
center_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), "PopupPanel"));
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ProgressDialog::_update_ui() {
|
void ProgressDialog::_update_ui() {
|
||||||
// Run main loop for two frames.
|
// Run main loop for two frames.
|
||||||
if (is_inside_tree()) {
|
if (is_inside_tree()) {
|
||||||
@@ -135,33 +152,33 @@ void ProgressDialog::_update_ui() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ProgressDialog::_popup() {
|
void ProgressDialog::_popup() {
|
||||||
|
// Activate processing of all inputs in EditorNode, and the EditorNode::input method
|
||||||
|
// will discard every key input.
|
||||||
|
EditorNode::get_singleton()->set_process_input(true);
|
||||||
|
// Disable all other windows to prevent interaction with them.
|
||||||
|
for (Window *w : host_windows) {
|
||||||
|
w->set_process_mode(PROCESS_MODE_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
Size2 ms = main->get_combined_minimum_size();
|
Size2 ms = main->get_combined_minimum_size();
|
||||||
ms.width = MAX(500 * EDSCALE, ms.width);
|
ms.width = MAX(500 * EDSCALE, ms.width);
|
||||||
|
ms += main_border_size;
|
||||||
|
|
||||||
Ref<StyleBox> style = main->get_theme_stylebox(SceneStringName(panel), SNAME("PopupMenu"));
|
center_panel->set_custom_minimum_size(ms);
|
||||||
ms += style->get_minimum_size();
|
|
||||||
|
|
||||||
main->set_offset(SIDE_LEFT, style->get_margin(SIDE_LEFT));
|
Window *current_window = Window::get_from_id(DisplayServer::get_singleton()->get_focused_window());
|
||||||
main->set_offset(SIDE_RIGHT, -style->get_margin(SIDE_RIGHT));
|
if (!current_window) {
|
||||||
main->set_offset(SIDE_TOP, style->get_margin(SIDE_TOP));
|
current_window = get_tree()->get_root();
|
||||||
main->set_offset(SIDE_BOTTOM, -style->get_margin(SIDE_BOTTOM));
|
}
|
||||||
|
|
||||||
if (is_inside_tree()) {
|
reparent(current_window);
|
||||||
Rect2i adjust = _popup_adjust_rect();
|
|
||||||
if (adjust != Rect2i()) {
|
// Ensures that events are properly released before the dialog blocks input.
|
||||||
set_position(adjust.position);
|
bool window_is_input_disabled = current_window->is_input_disabled();
|
||||||
set_size(adjust.size);
|
current_window->set_disable_input(!window_is_input_disabled);
|
||||||
}
|
current_window->set_disable_input(window_is_input_disabled);
|
||||||
} else {
|
|
||||||
for (Window *window : host_windows) {
|
show();
|
||||||
if (window->has_focus()) {
|
|
||||||
popup_exclusive_centered(window, ms);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// No host window found, use main window.
|
|
||||||
EditorInterface::get_singleton()->popup_dialog_centered(this, ms);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgressDialog::add_task(const String &p_task, const String &p_label, int p_steps, bool p_can_cancel) {
|
void ProgressDialog::add_task(const String &p_task, const String &p_label, int p_steps, bool p_can_cancel) {
|
||||||
@@ -231,6 +248,10 @@ void ProgressDialog::end_task(const String &p_task) {
|
|||||||
|
|
||||||
if (tasks.is_empty()) {
|
if (tasks.is_empty()) {
|
||||||
hide();
|
hide();
|
||||||
|
EditorNode::get_singleton()->set_process_input(false);
|
||||||
|
for (Window *w : host_windows) {
|
||||||
|
w->set_process_mode(PROCESS_MODE_INHERIT);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_popup();
|
_popup();
|
||||||
}
|
}
|
||||||
@@ -241,17 +262,31 @@ void ProgressDialog::add_host_window(Window *p_window) {
|
|||||||
host_windows.push_back(p_window);
|
host_windows.push_back(p_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProgressDialog::remove_host_window(Window *p_window) {
|
||||||
|
ERR_FAIL_NULL(p_window);
|
||||||
|
host_windows.erase(p_window);
|
||||||
|
}
|
||||||
|
|
||||||
void ProgressDialog::_cancel_pressed() {
|
void ProgressDialog::_cancel_pressed() {
|
||||||
canceled = true;
|
canceled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgressDialog::ProgressDialog() {
|
ProgressDialog::ProgressDialog() {
|
||||||
main = memnew(VBoxContainer);
|
// We want to cover the entire screen to prevent the user from interacting with the Editor.
|
||||||
add_child(main);
|
set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
|
||||||
main->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
|
// Be sure it's the top most component.
|
||||||
set_exclusive(true);
|
set_z_index(RS::CANVAS_ITEM_Z_MAX);
|
||||||
set_flag(Window::FLAG_POPUP, false);
|
|
||||||
singleton = this;
|
singleton = this;
|
||||||
|
hide();
|
||||||
|
|
||||||
|
center_panel = memnew(PanelContainer);
|
||||||
|
add_child(center_panel);
|
||||||
|
center_panel->set_h_size_flags(SIZE_SHRINK_BEGIN);
|
||||||
|
center_panel->set_v_size_flags(SIZE_SHRINK_BEGIN);
|
||||||
|
|
||||||
|
main = memnew(VBoxContainer);
|
||||||
|
center_panel->add_child(main);
|
||||||
|
|
||||||
cancel_hb = memnew(HBoxContainer);
|
cancel_hb = memnew(HBoxContainer);
|
||||||
main->add_child(cancel_hb);
|
main->add_child(cancel_hb);
|
||||||
cancel_hb->hide();
|
cancel_hb->hide();
|
||||||
|
|||||||
@@ -33,8 +33,8 @@
|
|||||||
|
|
||||||
#include "scene/gui/box_container.h"
|
#include "scene/gui/box_container.h"
|
||||||
#include "scene/gui/button.h"
|
#include "scene/gui/button.h"
|
||||||
|
#include "scene/gui/center_container.h"
|
||||||
#include "scene/gui/label.h"
|
#include "scene/gui/label.h"
|
||||||
#include "scene/gui/popup.h"
|
|
||||||
#include "scene/gui/progress_bar.h"
|
#include "scene/gui/progress_bar.h"
|
||||||
|
|
||||||
class BackgroundProgress : public HBoxContainer {
|
class BackgroundProgress : public HBoxContainer {
|
||||||
@@ -64,8 +64,10 @@ public:
|
|||||||
BackgroundProgress() {}
|
BackgroundProgress() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProgressDialog : public PopupPanel {
|
class PanelContainer;
|
||||||
GDCLASS(ProgressDialog, PopupPanel);
|
|
||||||
|
class ProgressDialog : public CenterContainer {
|
||||||
|
GDCLASS(ProgressDialog, CenterContainer);
|
||||||
struct Task {
|
struct Task {
|
||||||
String task;
|
String task;
|
||||||
VBoxContainer *vb = nullptr;
|
VBoxContainer *vb = nullptr;
|
||||||
@@ -77,10 +79,13 @@ class ProgressDialog : public PopupPanel {
|
|||||||
Button *cancel = nullptr;
|
Button *cancel = nullptr;
|
||||||
|
|
||||||
HashMap<String, Task> tasks;
|
HashMap<String, Task> tasks;
|
||||||
|
PanelContainer *center_panel = nullptr;
|
||||||
VBoxContainer *main = nullptr;
|
VBoxContainer *main = nullptr;
|
||||||
|
|
||||||
LocalVector<Window *> host_windows;
|
LocalVector<Window *> host_windows;
|
||||||
|
|
||||||
|
Size2 main_border_size;
|
||||||
|
|
||||||
static ProgressDialog *singleton;
|
static ProgressDialog *singleton;
|
||||||
void _popup();
|
void _popup();
|
||||||
|
|
||||||
@@ -89,6 +94,9 @@ class ProgressDialog : public PopupPanel {
|
|||||||
void _update_ui();
|
void _update_ui();
|
||||||
bool canceled = false;
|
bool canceled = false;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _notification(int p_what);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static ProgressDialog *get_singleton() { return singleton; }
|
static ProgressDialog *get_singleton() { return singleton; }
|
||||||
void add_task(const String &p_task, const String &p_label, int p_steps, bool p_can_cancel = false);
|
void add_task(const String &p_task, const String &p_label, int p_steps, bool p_can_cancel = false);
|
||||||
@@ -96,6 +104,7 @@ public:
|
|||||||
void end_task(const String &p_task);
|
void end_task(const String &p_task);
|
||||||
|
|
||||||
void add_host_window(Window *p_window);
|
void add_host_window(Window *p_window);
|
||||||
|
void remove_host_window(Window *p_window);
|
||||||
|
|
||||||
ProgressDialog();
|
ProgressDialog();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -336,6 +336,7 @@ WindowWrapper::WindowWrapper() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window = memnew(Window);
|
window = memnew(Window);
|
||||||
|
window_id = window->get_instance_id();
|
||||||
window->set_wrap_controls(true);
|
window->set_wrap_controls(true);
|
||||||
|
|
||||||
add_child(window);
|
add_child(window);
|
||||||
@@ -354,6 +355,12 @@ WindowWrapper::WindowWrapper() {
|
|||||||
ProgressDialog::get_singleton()->add_host_window(window);
|
ProgressDialog::get_singleton()->add_host_window(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WindowWrapper::~WindowWrapper() {
|
||||||
|
if (ObjectDB::get_instance(window_id)) {
|
||||||
|
ProgressDialog::get_singleton()->remove_host_window(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ScreenSelect
|
// ScreenSelect
|
||||||
|
|
||||||
void ScreenSelect::_build_advanced_menu() {
|
void ScreenSelect::_build_advanced_menu() {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class WindowWrapper : public MarginContainer {
|
|||||||
Control *wrapped_control = nullptr;
|
Control *wrapped_control = nullptr;
|
||||||
MarginContainer *margins = nullptr;
|
MarginContainer *margins = nullptr;
|
||||||
Window *window = nullptr;
|
Window *window = nullptr;
|
||||||
|
ObjectID window_id;
|
||||||
|
|
||||||
Panel *window_background = nullptr;
|
Panel *window_background = nullptr;
|
||||||
|
|
||||||
@@ -84,6 +85,7 @@ public:
|
|||||||
void grab_window_focus();
|
void grab_window_focus();
|
||||||
|
|
||||||
WindowWrapper();
|
WindowWrapper();
|
||||||
|
~WindowWrapper();
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScreenSelect : public Button {
|
class ScreenSelect : public Button {
|
||||||
|
|||||||
Reference in New Issue
Block a user