Skip to content

Commit

Permalink
Merge pull request #25656 from bruvzg/macos_multi_instances
Browse files Browse the repository at this point in the history
[macOS] Add ability to open multiple editor instances and global/dock menu access
  • Loading branch information
akien-mga authored Aug 26, 2019
2 parents 2b202f3 + db6d435 commit 2f63811
Show file tree
Hide file tree
Showing 16 changed files with 305 additions and 1 deletion.
30 changes: 30 additions & 0 deletions core/bind/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,31 @@ _ResourceSaver::_ResourceSaver() {

/////////////////OS

void _OS::global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta) {

OS::get_singleton()->global_menu_add_item(p_menu, p_label, p_signal, p_meta);
}

void _OS::global_menu_add_separator(const String &p_menu) {

OS::get_singleton()->global_menu_add_separator(p_menu);
}

void _OS::global_menu_remove_item(const String &p_menu, int p_idx) {

OS::get_singleton()->global_menu_remove_item(p_menu, p_idx);
}

void _OS::global_menu_clear(const String &p_menu) {

OS::get_singleton()->global_menu_clear(p_menu);
}

Point2 _OS::get_mouse_position() const {

return OS::get_singleton()->get_mouse_position();
}

void _OS::set_window_title(const String &p_title) {

OS::get_singleton()->set_window_title(p_title);
Expand All @@ -202,6 +223,7 @@ int _OS::get_mouse_button_state() const {
String _OS::get_unique_id() const {
return OS::get_singleton()->get_unique_id();
}

bool _OS::has_touchscreen_ui_hint() const {

return OS::get_singleton()->has_touchscreen_ui_hint();
Expand All @@ -211,6 +233,7 @@ void _OS::set_clipboard(const String &p_text) {

OS::get_singleton()->set_clipboard(p_text);
}

String _OS::get_clipboard() const {

return OS::get_singleton()->get_clipboard();
Expand Down Expand Up @@ -257,12 +280,14 @@ void _OS::set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeab
vm.resizable = p_resizeable;
OS::get_singleton()->set_video_mode(vm, p_screen);
}

Size2 _OS::get_video_mode(int p_screen) const {

OS::VideoMode vm;
vm = OS::get_singleton()->get_video_mode(p_screen);
return Size2(vm.width, vm.height);
}

bool _OS::is_video_mode_fullscreen(int p_screen) const {

OS::VideoMode vm;
Expand Down Expand Up @@ -1125,6 +1150,11 @@ void _OS::_bind_methods() {
//ClassDB::bind_method(D_METHOD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0));
//ClassDB::bind_method(D_METHOD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0));

ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu", "label", "id", "meta"), &_OS::global_menu_add_item);
ClassDB::bind_method(D_METHOD("global_menu_add_separator", "menu"), &_OS::global_menu_add_separator);
ClassDB::bind_method(D_METHOD("global_menu_remove_item", "menu", "idx"), &_OS::global_menu_remove_item);
ClassDB::bind_method(D_METHOD("global_menu_clear", "menu"), &_OS::global_menu_clear);

ClassDB::bind_method(D_METHOD("get_video_driver_count"), &_OS::get_video_driver_count);
ClassDB::bind_method(D_METHOD("get_video_driver_name", "driver"), &_OS::get_video_driver_name);
ClassDB::bind_method(D_METHOD("get_current_video_driver"), &_OS::get_current_video_driver);
Expand Down
5 changes: 5 additions & 0 deletions core/bind/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ class _OS : public Object {
MONTH_DECEMBER
};

void global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta);
void global_menu_add_separator(const String &p_menu);
void global_menu_remove_item(const String &p_menu, int p_idx);
void global_menu_clear(const String &p_menu);

Point2 get_mouse_position() const;
void set_window_title(const String &p_title);
int get_mouse_button_state() const;
Expand Down
8 changes: 8 additions & 0 deletions core/os/main_loop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ void MainLoop::_bind_methods() {
BIND_VMETHOD(MethodInfo("_drop_files", PropertyInfo(Variant::POOL_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "from_screen")));
BIND_VMETHOD(MethodInfo("_finalize"));

BIND_VMETHOD(MethodInfo("_global_menu_action", PropertyInfo(Variant::NIL, "id"), PropertyInfo(Variant::NIL, "meta")));

BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER);
BIND_CONSTANT(NOTIFICATION_WM_MOUSE_EXIT);
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN);
Expand Down Expand Up @@ -115,6 +117,12 @@ void MainLoop::drop_files(const Vector<String> &p_files, int p_from_screen) {
get_script_instance()->call("_drop_files", p_files, p_from_screen);
}

void MainLoop::global_menu_action(const Variant &p_id, const Variant &p_meta) {

if (get_script_instance())
get_script_instance()->call("_global_menu_action", p_id, p_meta);
}

void MainLoop::finish() {

if (get_script_instance()) {
Expand Down
1 change: 1 addition & 0 deletions core/os/main_loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class MainLoop : public Object {
virtual void finish();

virtual void drop_files(const Vector<String> &p_files, int p_from_screen = 0);
virtual void global_menu_action(const Variant &p_id, const Variant &p_meta);

void set_init_script(const Ref<Script> &p_init_script);

Expand Down
5 changes: 5 additions & 0 deletions core/os/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ class OS {

static OS *get_singleton();

virtual void global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta){};
virtual void global_menu_add_separator(const String &p_menu){};
virtual void global_menu_remove_item(const String &p_menu, int p_idx){};
virtual void global_menu_clear(const String &p_menu){};

void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type = Logger::ERR_ERROR);
void print(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
void printerr(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
Expand Down
10 changes: 10 additions & 0 deletions doc/classes/MainLoop.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@
Called before the program exits.
</description>
</method>
<method name="_global_menu_action" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="id" type="Variant">
</argument>
<argument index="1" name="meta" type="Variant">
</argument>
<description>
</description>
</method>
<method name="_idle" qualifiers="virtual">
<return type="bool">
</return>
Expand Down
44 changes: 44 additions & 0 deletions doc/classes/OS.xml
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,50 @@
Returns unobscured area of the window where interactive controls should be rendered.
</description>
</method>
<method name="global_menu_add_item">
<return type="void">
</return>
<argument index="0" name="menu" type="String">
</argument>
<argument index="1" name="label" type="String">
</argument>
<argument index="2" name="id" type="Variant">
</argument>
<argument index="3" name="meta" type="Variant">
</argument>
<description>
Add a new item with text "label" to global menu. Use "_dock" menu to add item to the macOS dock icon menu.
</description>
</method>
<method name="global_menu_add_separator">
<return type="void">
</return>
<argument index="0" name="menu" type="String">
</argument>
<description>
Add a separator between items. Separators also occupy an index.
</description>
</method>
<method name="global_menu_clear">
<return type="void">
</return>
<argument index="0" name="menu" type="String">
</argument>
<description>
Clear the global menu, in effect removing all items.
</description>
</method>
<method name="global_menu_remove_item">
<return type="void">
</return>
<argument index="0" name="menu" type="String">
</argument>
<argument index="1" name="idx" type="int">
</argument>
<description>
Removes the item at index "idx" from the global menu. Note that the indexes of items after the removed item are going to be shifted by one.
</description>
</method>
<method name="has_environment" qualifiers="const">
<return type="bool">
</return>
Expand Down
9 changes: 9 additions & 0 deletions doc/classes/SceneTree.xml
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,15 @@
Emitted when files are dragged from the OS file manager and dropped in the game window. The arguments are a list of file paths and the identifier of the screen where the drag originated.
</description>
</signal>
<signal name="global_menu_action">
<argument index="0" name="id" type="Nil">
</argument>
<argument index="1" name="meta" type="Nil">
</argument>
<description>
Emitted whenever global menu item is clicked.
</description>
</signal>
<signal name="idle_frame">
<description>
Emitted immediately before [method Node._process] is called on every node in the [SceneTree].
Expand Down
26 changes: 26 additions & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ void EditorNode::_update_scene_tabs() {

bool show_rb = EditorSettings::get_singleton()->get("interface/scene_tabs/show_script_button");

OS::get_singleton()->global_menu_clear("_dock");

scene_tabs->clear_tabs();
Ref<Texture> script_icon = gui_base->get_icon("Script", "EditorIcons");
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
Expand All @@ -149,11 +151,16 @@ void EditorNode::_update_scene_tabs() {
bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0;
scene_tabs->add_tab(editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), icon);

OS::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), GLOBAL_SCENE, i);

if (show_rb && editor_data.get_scene_root_script(i).is_valid()) {
scene_tabs->set_tab_right_button(i, script_icon);
}
}

OS::get_singleton()->global_menu_add_separator("_dock");
OS::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant());

scene_tabs->set_current_tab(editor_data.get_edited_scene());

if (scene_tabs->get_offset_buttons_visible()) {
Expand Down Expand Up @@ -290,6 +297,7 @@ void EditorNode::_notification(int p_what) {
get_tree()->get_root()->set_as_audio_listener_2d(false);
get_tree()->set_auto_accept_quit(false);
get_tree()->connect("files_dropped", this, "_dropped_files");
get_tree()->connect("global_menu_action", this, "_global_menu_action");

/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
} break;
Expand Down Expand Up @@ -4941,6 +4949,23 @@ void EditorNode::remove_tool_menu_item(const String &p_name) {
}
}

void EditorNode::_global_menu_action(const Variant &p_id, const Variant &p_meta) {

int id = (int)p_id;
if (id == GLOBAL_NEW_WINDOW) {
if (OS::get_singleton()->get_main_loop()) {
List<String> args;
String exec = OS::get_singleton()->get_executable_path();

OS::ProcessID pid = 0;
OS::get_singleton()->execute(exec, args, false, &pid);
}
} else if (id == GLOBAL_SCENE) {
int idx = (int)p_meta;
scene_tabs->set_current_tab(idx);
}
}

void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) {

String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_selected_path());
Expand Down Expand Up @@ -5322,6 +5347,7 @@ void EditorNode::_bind_methods() {

ClassDB::bind_method("_clear_undo_history", &EditorNode::_clear_undo_history);
ClassDB::bind_method("_dropped_files", &EditorNode::_dropped_files);
ClassDB::bind_method(D_METHOD("_global_menu_action"), &EditorNode::_global_menu_action, DEFVAL(Variant()));
ClassDB::bind_method("_toggle_distraction_free_mode", &EditorNode::_toggle_distraction_free_mode);
ClassDB::bind_method("edit_item_resource", &EditorNode::edit_item_resource);

Expand Down
4 changes: 4 additions & 0 deletions editor/editor_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ class EditorNode : public Node {

SET_VIDEO_DRIVER_SAVE_AND_RESTART,

GLOBAL_NEW_WINDOW,
GLOBAL_SCENE,

IMPORT_PLUGIN_BASE = 100,

TOOL_MENU_BASE = 1000
Expand Down Expand Up @@ -504,6 +507,7 @@ class EditorNode : public Node {
void _add_to_recent_scenes(const String &p_scene);
void _update_recent_scenes();
void _open_recent_scene(int p_idx);
void _global_menu_action(const Variant &p_id, const Variant &p_meta);
void _dropped_files(const Vector<String> &p_files, int p_screen);
void _add_dropped_files_recursive(const Vector<String> &p_files, String to_path);
String _recent_scene;
Expand Down
35 changes: 35 additions & 0 deletions editor/project_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,11 @@ class ProjectList : public ScrollContainer {
static const char *SIGNAL_SELECTION_CHANGED;
static const char *SIGNAL_PROJECT_ASK_OPEN;

enum MenuOptions {
GLOBAL_NEW_WINDOW,
GLOBAL_OPEN_PROJECT
};

// Can often be passed by copy
struct Item {
String project_key;
Expand Down Expand Up @@ -1181,6 +1186,7 @@ void ProjectList::load_projects() {
_projects.clear();
_last_clicked = "";
_selected_project_keys.clear();
OS::get_singleton()->global_menu_clear("_dock");

// Load data
// TODO Would be nice to change how projects and favourites are stored... it complicates things a bit.
Expand Down Expand Up @@ -1218,6 +1224,9 @@ void ProjectList::load_projects() {
create_project_item_control(i);
}

OS::get_singleton()->global_menu_add_separator("_dock");
OS::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant());

sort_projects();

set_v_scroll(0);
Expand Down Expand Up @@ -1305,6 +1314,7 @@ void ProjectList::create_project_item_control(int p_index) {
fpath->set_clip_text(true);

_scroll_children->add_child(hb);
OS::get_singleton()->global_menu_add_item("_dock", item.project_name + " ( " + item.path + " )", GLOBAL_OPEN_PROJECT, Variant(item.path.plus_file("project.godot")));
item.control = hb;
}

Expand Down Expand Up @@ -1894,6 +1904,29 @@ void ProjectManager::_confirm_update_settings() {
_open_selected_projects();
}

void ProjectManager::_global_menu_action(const Variant &p_id, const Variant &p_meta) {

int id = (int)p_id;
if (id == ProjectList::GLOBAL_NEW_WINDOW) {
List<String> args;
String exec = OS::get_singleton()->get_executable_path();

OS::ProcessID pid = 0;
OS::get_singleton()->execute(exec, args, false, &pid);
} else if (id == ProjectList::GLOBAL_OPEN_PROJECT) {
String conf = (String)p_meta;

if (conf != String()) {
List<String> args;
args.push_back(conf);
String exec = OS::get_singleton()->get_executable_path();

OS::ProcessID pid = 0;
OS::get_singleton()->execute(exec, args, false, &pid);
}
}
}

void ProjectManager::_open_selected_projects() {

const Set<String> &selected_list = _project_list->get_selected_project_keys();
Expand Down Expand Up @@ -2236,6 +2269,7 @@ void ProjectManager::_bind_methods() {

ClassDB::bind_method("_open_selected_projects_ask", &ProjectManager::_open_selected_projects_ask);
ClassDB::bind_method("_open_selected_projects", &ProjectManager::_open_selected_projects);
ClassDB::bind_method(D_METHOD("_global_menu_action"), &ProjectManager::_global_menu_action, DEFVAL(Variant()));
ClassDB::bind_method("_run_project", &ProjectManager::_run_project);
ClassDB::bind_method("_run_project_confirm", &ProjectManager::_run_project_confirm);
ClassDB::bind_method("_scan_projects", &ProjectManager::_scan_projects);
Expand Down Expand Up @@ -2561,6 +2595,7 @@ ProjectManager::ProjectManager() {
}

SceneTree::get_singleton()->connect("files_dropped", this, "_files_dropped");
SceneTree::get_singleton()->connect("global_menu_action", this, "_global_menu_action");

run_error_diag = memnew(AcceptDialog);
gui_base->add_child(run_error_diag);
Expand Down
2 changes: 2 additions & 0 deletions editor/project_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class ProjectList;
class ProjectListFilter;

class ProjectManager : public Control {

GDCLASS(ProjectManager, Control);

Button *erase_btn;
Expand Down Expand Up @@ -96,6 +97,7 @@ class ProjectManager : public Control {
void _restart_confirm();
void _exit_dialog();
void _scan_begin(const String &p_base);
void _global_menu_action(const Variant &p_id, const Variant &p_meta);

void _confirm_update_settings();

Expand Down
Loading

0 comments on commit 2f63811

Please sign in to comment.