Browse Source

Effective DisplayServer separation, rename X11 -> LinuxBSD

Juan Linietsky 5 years ago
parent
commit
f8a79a97c7
83 changed files with 1298 additions and 5372 deletions
  1. 1 1
      SConstruct
  2. 3 536
      core/bind/core_bind.cpp
  3. 0 114
      core/bind/core_bind.h
  4. 2 1
      core/debugger/remote_debugger.cpp
  5. 14 20
      core/input/input.cpp
  6. 10 4
      core/input/input.h
  7. 1 226
      core/os/os.cpp
  8. 4 240
      core/os/os.h
  9. 1 1
      drivers/gl_context/SCsub
  10. 6 6
      drivers/gles2/rasterizer_canvas_gles2.cpp
  11. 1 1
      drivers/gles2/rasterizer_gles2.cpp
  12. 1 1
      drivers/gles2/rasterizer_scene_gles2.cpp
  13. 1 1
      drivers/vulkan/SCsub
  14. 2 1
      editor/debugger/editor_debugger_tree.cpp
  15. 5 4
      editor/debugger/script_editor_debugger.cpp
  16. 2 1
      editor/editor_dir_dialog.cpp
  17. 2 1
      editor/editor_file_dialog.cpp
  18. 37 20
      editor/editor_node.cpp
  19. 8 7
      editor/editor_run.cpp
  20. 1 1
      editor/editor_settings.cpp
  21. 2 1
      editor/filesystem_dock.cpp
  22. 4 3
      editor/plugins/script_editor_plugin.cpp
  23. 2 1
      editor/plugins/shader_editor_plugin.cpp
  24. 8 4
      editor/plugins/spatial_editor_plugin.cpp
  25. 2 1
      editor/plugins/visual_shader_editor_plugin.cpp
  26. 2 1
      editor/progress_dialog.cpp
  27. 3 2
      editor/project_export.cpp
  28. 15 10
      editor/project_manager.cpp
  29. 3 1
      editor/scene_tree_dock.cpp
  30. 183 84
      main/main.cpp
  31. 2 1
      main/tests/test_physics.cpp
  32. 2 1
      main/tests/test_physics_2d.cpp
  33. 2 1
      main/tests/test_render.cpp
  34. 1 1
      modules/gdnative/nativescript/SCsub
  35. 3 1
      modules/gdscript/language_server/gdscript_text_document.cpp
  36. 2 1
      modules/mobile_vr/mobile_vr_interface.cpp
  37. 9 8
      platform/linuxbsd/SCsub
  38. 0 0
      platform/linuxbsd/context_gl_x11.cpp
  39. 0 0
      platform/linuxbsd/context_gl_x11.h
  40. 2 2
      platform/linuxbsd/crash_handler_linuxbsd.cpp
  41. 1 1
      platform/linuxbsd/crash_handler_linuxbsd.h
  42. 4 4
      platform/linuxbsd/detect.py
  43. 1 1
      platform/linuxbsd/detect_prime_x11.cpp
  44. 1 1
      platform/linuxbsd/detect_prime_x11.h
  45. 179 48
      platform/linuxbsd/display_server_x11.cpp
  46. 16 8
      platform/linuxbsd/display_server_x11.h
  47. 3 3
      platform/linuxbsd/export/export.cpp
  48. 4 4
      platform/linuxbsd/export/export.h
  49. 3 3
      platform/linuxbsd/godot_linuxbsd.cpp
  50. 0 0
      platform/linuxbsd/joypad_linux.cpp
  51. 0 0
      platform/linuxbsd/joypad_linux.h
  52. 0 0
      platform/linuxbsd/key_mapping_x11.cpp
  53. 0 0
      platform/linuxbsd/key_mapping_x11.h
  54. 0 0
      platform/linuxbsd/logo.png
  55. 381 0
      platform/linuxbsd/os_linuxbsd.cpp
  56. 106 0
      platform/linuxbsd/os_linuxbsd.h
  57. 0 0
      platform/linuxbsd/pck_embed.ld
  58. 0 0
      platform/linuxbsd/pck_embed.legacy.ld
  59. 0 0
      platform/linuxbsd/platform_config.h
  60. 1 1
      platform/linuxbsd/platform_linuxbsd_builders.py
  61. 0 0
      platform/linuxbsd/vulkan_context_x11.cpp
  62. 0 0
      platform/linuxbsd/vulkan_context_x11.h
  63. 1 1
      platform/server/os_server.h
  64. 0 3568
      platform/x11/os_x11.cpp
  65. 0 338
      platform/x11/os_x11.h
  66. 1 1
      scene/2d/particles_2d.cpp
  67. 3 2
      scene/2d/touch_screen_button.cpp
  68. 1 1
      scene/3d/gi_probe.cpp
  69. 1 1
      scene/3d/particles.cpp
  70. 21 21
      scene/gui/line_edit.cpp
  71. 2 1
      scene/gui/rich_text_label.cpp
  72. 2 2
      scene/gui/scroll_bar.cpp
  73. 2 2
      scene/gui/scroll_container.cpp
  74. 17 17
      scene/gui/text_edit.cpp
  75. 1 1
      scene/gui/tree.cpp
  76. 4 3
      scene/main/scene_tree.cpp
  77. 10 5
      scene/main/viewport.cpp
  78. 3 0
      scene/main/viewport.h
  79. 1 1
      scene/register_scene_types.cpp
  80. 103 4
      servers/display_server.cpp
  81. 71 14
      servers/display_server.h
  82. 1 1
      servers/visual/visual_server_raster.cpp
  83. 4 3
      servers/visual/visual_server_wrap_mt.cpp

+ 1 - 1
SConstruct

@@ -236,7 +236,7 @@ elif env_base['p'] != "":
 else:
     # Missing `platform` argument, try to detect platform automatically
     if sys.platform.startswith('linux'):
-        selected_platform = 'x11'
+        selected_platform = 'linuxbsd'
     elif sys.platform == 'darwin':
         selected_platform = 'osx'
     elif sys.platform == 'win32':

+ 3 - 536
core/bind/core_bind.cpp

@@ -194,82 +194,6 @@ _ResourceSaver::_ResourceSaver() {
 	singleton = this;
 }
 
-/////////////////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);
-}
-
-int _OS::get_mouse_button_state() const {
-
-	return OS::get_singleton()->get_mouse_button_state();
-}
-
-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();
-}
-
-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();
-}
-
-int _OS::get_video_driver_count() const {
-	return OS::get_singleton()->get_video_driver_count();
-}
-
-String _OS::get_video_driver_name(VideoDriver p_driver) const {
-	return OS::get_singleton()->get_video_driver_name((int)p_driver);
-}
-
-_OS::VideoDriver _OS::get_current_video_driver() const {
-	return (VideoDriver)OS::get_singleton()->get_current_video_driver();
-}
-
-int _OS::get_audio_driver_count() const {
-	return OS::get_singleton()->get_audio_driver_count();
-}
-
-String _OS::get_audio_driver_name(int p_driver) const {
-	return OS::get_singleton()->get_audio_driver_name(p_driver);
-}
-
 PackedStringArray _OS::get_connected_midi_inputs() {
 	return OS::get_singleton()->get_connected_midi_inputs();
 }
@@ -282,198 +206,11 @@ void _OS::close_midi_inputs() {
 	OS::get_singleton()->close_midi_inputs();
 }
 
-void _OS::set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen) {
-
-	OS::VideoMode vm;
-	vm.width = p_size.width;
-	vm.height = p_size.height;
-	vm.fullscreen = p_fullscreen;
-	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;
-	vm = OS::get_singleton()->get_video_mode(p_screen);
-	return vm.fullscreen;
-}
-
-int _OS::get_screen_count() const {
-	return OS::get_singleton()->get_screen_count();
-}
-
-int _OS::get_current_screen() const {
-	return OS::get_singleton()->get_current_screen();
-}
-
-void _OS::set_current_screen(int p_screen) {
-	OS::get_singleton()->set_current_screen(p_screen);
-}
-
-Point2 _OS::get_screen_position(int p_screen) const {
-	return OS::get_singleton()->get_screen_position(p_screen);
-}
-
-Size2 _OS::get_screen_size(int p_screen) const {
-	return OS::get_singleton()->get_screen_size(p_screen);
-}
-
-int _OS::get_screen_dpi(int p_screen) const {
-
-	return OS::get_singleton()->get_screen_dpi(p_screen);
-}
-
-Point2 _OS::get_window_position() const {
-	return OS::get_singleton()->get_window_position();
-}
-
-void _OS::set_window_position(const Point2 &p_position) {
-	OS::get_singleton()->set_window_position(p_position);
-}
-
-Size2 _OS::get_max_window_size() const {
-	return OS::get_singleton()->get_max_window_size();
-}
-
-Size2 _OS::get_min_window_size() const {
-	return OS::get_singleton()->get_min_window_size();
-}
-
-Size2 _OS::get_window_size() const {
-	return OS::get_singleton()->get_window_size();
-}
-
-Size2 _OS::get_real_window_size() const {
-	return OS::get_singleton()->get_real_window_size();
-}
-
-void _OS::set_max_window_size(const Size2 &p_size) {
-	OS::get_singleton()->set_max_window_size(p_size);
-}
-
-void _OS::set_min_window_size(const Size2 &p_size) {
-	OS::get_singleton()->set_min_window_size(p_size);
-}
-
-void _OS::set_window_size(const Size2 &p_size) {
-	OS::get_singleton()->set_window_size(p_size);
-}
-
-Rect2 _OS::get_window_safe_area() const {
-	return OS::get_singleton()->get_window_safe_area();
-}
-
-void _OS::set_window_fullscreen(bool p_enabled) {
-	OS::get_singleton()->set_window_fullscreen(p_enabled);
-}
-
-bool _OS::is_window_fullscreen() const {
-	return OS::get_singleton()->is_window_fullscreen();
-}
-
-void _OS::set_window_resizable(bool p_enabled) {
-	OS::get_singleton()->set_window_resizable(p_enabled);
-}
-
-bool _OS::is_window_resizable() const {
-	return OS::get_singleton()->is_window_resizable();
-}
-
-void _OS::set_window_minimized(bool p_enabled) {
-	OS::get_singleton()->set_window_minimized(p_enabled);
-}
-
-bool _OS::is_window_minimized() const {
-	return OS::get_singleton()->is_window_minimized();
-}
-
-void _OS::set_window_maximized(bool p_enabled) {
-	OS::get_singleton()->set_window_maximized(p_enabled);
-}
-
-bool _OS::is_window_maximized() const {
-	return OS::get_singleton()->is_window_maximized();
-}
-
-void _OS::set_window_always_on_top(bool p_enabled) {
-	OS::get_singleton()->set_window_always_on_top(p_enabled);
-}
-
-bool _OS::is_window_always_on_top() const {
-	return OS::get_singleton()->is_window_always_on_top();
-}
-
-bool _OS::is_window_focused() const {
-	return OS::get_singleton()->is_window_focused();
-}
-
-void _OS::set_borderless_window(bool p_borderless) {
-	OS::get_singleton()->set_borderless_window(p_borderless);
-}
-
-bool _OS::get_window_per_pixel_transparency_enabled() const {
-	return OS::get_singleton()->get_window_per_pixel_transparency_enabled();
-}
-
-void _OS::set_window_per_pixel_transparency_enabled(bool p_enabled) {
-	OS::get_singleton()->set_window_per_pixel_transparency_enabled(p_enabled);
-}
-
-bool _OS::get_borderless_window() const {
-	return OS::get_singleton()->get_borderless_window();
-}
-
-void _OS::set_ime_active(const bool p_active) {
-
-	OS::get_singleton()->set_ime_active(p_active);
-}
-
-void _OS::set_ime_position(const Point2 &p_pos) {
-
-	OS::get_singleton()->set_ime_position(p_pos);
-}
-
-Point2 _OS::get_ime_selection() const {
-	return OS::get_singleton()->get_ime_selection();
-}
-
-String _OS::get_ime_text() const {
-	return OS::get_singleton()->get_ime_text();
-}
-
 void _OS::set_use_file_access_save_and_swap(bool p_enable) {
 
 	FileAccess::set_backup_save(p_enable);
 }
 
-bool _OS::is_video_mode_resizable(int p_screen) const {
-
-	OS::VideoMode vm;
-	vm = OS::get_singleton()->get_video_mode(p_screen);
-	return vm.resizable;
-}
-
-Array _OS::get_fullscreen_mode_list(int p_screen) const {
-
-	List<OS::VideoMode> vmlist;
-	OS::get_singleton()->get_fullscreen_mode_list(&vmlist, p_screen);
-	Array vmarr;
-	for (List<OS::VideoMode>::Element *E = vmlist.front(); E; E = E->next()) {
-
-		vmarr.push_back(Size2(E->get().width, E->get().height));
-	}
-
-	return vmarr;
-}
-
 void _OS::set_low_processor_usage_mode(bool p_enabled) {
 
 	OS::get_singleton()->set_low_processor_usage_mode(p_enabled);
@@ -562,52 +299,16 @@ String _OS::get_locale() const {
 	return OS::get_singleton()->get_locale();
 }
 
-String _OS::get_latin_keyboard_variant() const {
-	switch (OS::get_singleton()->get_latin_keyboard_variant()) {
-		case OS::LATIN_KEYBOARD_QWERTY: return "QWERTY";
-		case OS::LATIN_KEYBOARD_QWERTZ: return "QWERTZ";
-		case OS::LATIN_KEYBOARD_AZERTY: return "AZERTY";
-		case OS::LATIN_KEYBOARD_QZERTY: return "QZERTY";
-		case OS::LATIN_KEYBOARD_DVORAK: return "DVORAK";
-		case OS::LATIN_KEYBOARD_NEO: return "NEO";
-		case OS::LATIN_KEYBOARD_COLEMAK: return "COLEMAK";
-		default: return "ERROR";
-	}
-}
-
 String _OS::get_model_name() const {
 
 	return OS::get_singleton()->get_model_name();
 }
 
-bool _OS::is_ok_left_and_cancel_right() const {
-
-	return OS::get_singleton()->get_swap_ok_cancel();
-}
-
 Error _OS::set_thread_name(const String &p_name) {
 
 	return Thread::set_name(p_name);
 };
 
-void _OS::set_use_vsync(bool p_enable) {
-	OS::get_singleton()->set_use_vsync(p_enable);
-}
-
-bool _OS::is_vsync_enabled() const {
-
-	return OS::get_singleton()->is_vsync_enabled();
-}
-
-void _OS::set_vsync_via_compositor(bool p_enable) {
-	OS::get_singleton()->set_vsync_via_compositor(p_enable);
-}
-
-bool _OS::is_vsync_via_compositor_enabled() const {
-
-	return OS::get_singleton()->is_vsync_via_compositor_enabled();
-}
-
 bool _OS::has_feature(const String &p_feature) const {
 
 	return OS::get_singleton()->has_feature(p_feature);
@@ -667,16 +368,6 @@ uint64_t _OS::get_static_memory_peak_usage() const {
 	return OS::get_singleton()->get_static_memory_peak_usage();
 }
 
-void _OS::set_native_icon(const String &p_filename) {
-
-	OS::get_singleton()->set_native_icon(p_filename);
-}
-
-void _OS::set_icon(const Ref<Image> &p_icon) {
-
-	OS::get_singleton()->set_icon(p_icon);
-}
-
 int _OS::get_exit_code() const {
 
 	return OS::get_singleton()->get_exit_code();
@@ -924,11 +615,6 @@ bool _OS::can_use_threads() const {
 	return OS::get_singleton()->can_use_threads();
 }
 
-bool _OS::can_draw() const {
-
-	return OS::get_singleton()->can_draw();
-}
-
 bool _OS::is_userfs_persistent() const {
 
 	return OS::get_singleton()->is_userfs_persistent();
@@ -1025,22 +711,6 @@ void _OS::print_resources_by_type(const Vector<String> &p_types) {
 	}
 };
 
-bool _OS::has_virtual_keyboard() const {
-	return OS::get_singleton()->has_virtual_keyboard();
-}
-
-void _OS::show_virtual_keyboard(const String &p_existing_text) {
-	OS::get_singleton()->show_virtual_keyboard(p_existing_text, Rect2());
-}
-
-void _OS::hide_virtual_keyboard() {
-	OS::get_singleton()->hide_virtual_keyboard();
-}
-
-int _OS::get_virtual_keyboard_height() {
-	return OS::get_singleton()->get_virtual_keyboard_height();
-}
-
 void _OS::print_all_resources(const String &p_to_file) {
 
 	OS::get_singleton()->print_all_resources(p_to_file);
@@ -1061,45 +731,6 @@ String _OS::get_user_data_dir() const {
 	return OS::get_singleton()->get_user_data_dir();
 };
 
-Error _OS::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) {
-
-	return OS::get_singleton()->native_video_play(p_path, p_volume, p_audio_track, p_subtitle_track);
-};
-
-bool _OS::native_video_is_playing() {
-
-	return OS::get_singleton()->native_video_is_playing();
-};
-
-void _OS::native_video_pause() {
-
-	OS::get_singleton()->native_video_pause();
-};
-
-void _OS::native_video_unpause() {
-	OS::get_singleton()->native_video_unpause();
-};
-
-void _OS::native_video_stop() {
-
-	OS::get_singleton()->native_video_stop();
-};
-
-void _OS::request_attention() {
-
-	OS::get_singleton()->request_attention();
-}
-
-void _OS::center_window() {
-
-	OS::get_singleton()->center_window();
-}
-
-void _OS::move_window_to_foreground() {
-
-	OS::get_singleton()->move_window_to_foreground();
-}
-
 bool _OS::is_debug_build() const {
 
 #ifdef DEBUG_ENABLED
@@ -1109,26 +740,6 @@ bool _OS::is_debug_build() const {
 #endif
 }
 
-void _OS::set_screen_orientation(ScreenOrientation p_orientation) {
-
-	OS::get_singleton()->set_screen_orientation(OS::ScreenOrientation(p_orientation));
-}
-
-_OS::ScreenOrientation _OS::get_screen_orientation() const {
-
-	return ScreenOrientation(OS::get_singleton()->get_screen_orientation());
-}
-
-void _OS::set_keep_screen_on(bool p_enabled) {
-
-	OS::get_singleton()->set_keep_screen_on(p_enabled);
-}
-
-bool _OS::is_keep_screen_on() const {
-
-	return OS::get_singleton()->is_keep_screen_on();
-}
-
 String _OS::get_system_dir(SystemDir p_dir) const {
 
 	return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir));
@@ -1149,11 +760,6 @@ int _OS::find_keycode_from_string(const String &p_code) const {
 	return find_keycode(p_code);
 }
 
-void _OS::alert(const String &p_alert, const String &p_title) {
-
-	OS::get_singleton()->alert(p_alert, p_title);
-}
-
 bool _OS::request_permission(const String &p_name) {
 
 	return OS::get_singleton()->request_permission(p_name);
@@ -1169,90 +775,17 @@ Vector<String> _OS::get_granted_permissions() const {
 	return OS::get_singleton()->get_granted_permissions();
 }
 
+String _OS::get_unique_id() const {
+	return OS::get_singleton()->get_unique_id();
+}
 _OS *_OS::singleton = NULL;
 
 void _OS::_bind_methods() {
 
-	//ClassDB::bind_method(D_METHOD("get_mouse_position"),&_OS::get_mouse_position);
-	//ClassDB::bind_method(D_METHOD("is_mouse_grab_enabled"),&_OS::is_mouse_grab_enabled);
-
-	ClassDB::bind_method(D_METHOD("set_clipboard", "clipboard"), &_OS::set_clipboard);
-	ClassDB::bind_method(D_METHOD("get_clipboard"), &_OS::get_clipboard);
-
-	//will not delete for now, just unexpose
-	//ClassDB::bind_method(D_METHOD("set_video_mode","size","fullscreen","resizable","screen"),&_OS::set_video_mode,DEFVAL(0));
-	//ClassDB::bind_method(D_METHOD("get_video_mode_size","screen"),&_OS::get_video_mode,DEFVAL(0));
-	//ClassDB::bind_method(D_METHOD("is_video_mode_fullscreen","screen"),&_OS::is_video_mode_fullscreen,DEFVAL(0));
-	//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);
-
-	ClassDB::bind_method(D_METHOD("get_audio_driver_count"), &_OS::get_audio_driver_count);
-	ClassDB::bind_method(D_METHOD("get_audio_driver_name", "driver"), &_OS::get_audio_driver_name);
 	ClassDB::bind_method(D_METHOD("get_connected_midi_inputs"), &_OS::get_connected_midi_inputs);
 	ClassDB::bind_method(D_METHOD("open_midi_inputs"), &_OS::open_midi_inputs);
 	ClassDB::bind_method(D_METHOD("close_midi_inputs"), &_OS::close_midi_inputs);
 
-	ClassDB::bind_method(D_METHOD("get_screen_count"), &_OS::get_screen_count);
-	ClassDB::bind_method(D_METHOD("get_current_screen"), &_OS::get_current_screen);
-	ClassDB::bind_method(D_METHOD("set_current_screen", "screen"), &_OS::set_current_screen);
-	ClassDB::bind_method(D_METHOD("get_screen_position", "screen"), &_OS::get_screen_position, DEFVAL(-1));
-	ClassDB::bind_method(D_METHOD("get_screen_size", "screen"), &_OS::get_screen_size, DEFVAL(-1));
-	ClassDB::bind_method(D_METHOD("get_screen_dpi", "screen"), &_OS::get_screen_dpi, DEFVAL(-1));
-	ClassDB::bind_method(D_METHOD("get_window_position"), &_OS::get_window_position);
-	ClassDB::bind_method(D_METHOD("set_window_position", "position"), &_OS::set_window_position);
-	ClassDB::bind_method(D_METHOD("get_window_size"), &_OS::get_window_size);
-	ClassDB::bind_method(D_METHOD("get_max_window_size"), &_OS::get_max_window_size);
-	ClassDB::bind_method(D_METHOD("get_min_window_size"), &_OS::get_min_window_size);
-	ClassDB::bind_method(D_METHOD("set_max_window_size", "size"), &_OS::set_max_window_size);
-	ClassDB::bind_method(D_METHOD("set_min_window_size", "size"), &_OS::set_min_window_size);
-	ClassDB::bind_method(D_METHOD("set_window_size", "size"), &_OS::set_window_size);
-	ClassDB::bind_method(D_METHOD("get_window_safe_area"), &_OS::get_window_safe_area);
-	ClassDB::bind_method(D_METHOD("set_window_fullscreen", "enabled"), &_OS::set_window_fullscreen);
-	ClassDB::bind_method(D_METHOD("is_window_fullscreen"), &_OS::is_window_fullscreen);
-	ClassDB::bind_method(D_METHOD("set_window_resizable", "enabled"), &_OS::set_window_resizable);
-	ClassDB::bind_method(D_METHOD("is_window_resizable"), &_OS::is_window_resizable);
-	ClassDB::bind_method(D_METHOD("set_window_minimized", "enabled"), &_OS::set_window_minimized);
-	ClassDB::bind_method(D_METHOD("is_window_minimized"), &_OS::is_window_minimized);
-	ClassDB::bind_method(D_METHOD("set_window_maximized", "enabled"), &_OS::set_window_maximized);
-	ClassDB::bind_method(D_METHOD("is_window_maximized"), &_OS::is_window_maximized);
-	ClassDB::bind_method(D_METHOD("set_window_always_on_top", "enabled"), &_OS::set_window_always_on_top);
-	ClassDB::bind_method(D_METHOD("is_window_always_on_top"), &_OS::is_window_always_on_top);
-	ClassDB::bind_method(D_METHOD("is_window_focused"), &_OS::is_window_focused);
-	ClassDB::bind_method(D_METHOD("request_attention"), &_OS::request_attention);
-	ClassDB::bind_method(D_METHOD("get_real_window_size"), &_OS::get_real_window_size);
-	ClassDB::bind_method(D_METHOD("center_window"), &_OS::center_window);
-	ClassDB::bind_method(D_METHOD("move_window_to_foreground"), &_OS::move_window_to_foreground);
-
-	ClassDB::bind_method(D_METHOD("set_borderless_window", "borderless"), &_OS::set_borderless_window);
-	ClassDB::bind_method(D_METHOD("get_borderless_window"), &_OS::get_borderless_window);
-
-	ClassDB::bind_method(D_METHOD("get_window_per_pixel_transparency_enabled"), &_OS::get_window_per_pixel_transparency_enabled);
-	ClassDB::bind_method(D_METHOD("set_window_per_pixel_transparency_enabled", "enabled"), &_OS::set_window_per_pixel_transparency_enabled);
-
-	ClassDB::bind_method(D_METHOD("set_ime_active", "active"), &_OS::set_ime_active);
-	ClassDB::bind_method(D_METHOD("set_ime_position", "position"), &_OS::set_ime_position);
-	ClassDB::bind_method(D_METHOD("get_ime_selection"), &_OS::get_ime_selection);
-	ClassDB::bind_method(D_METHOD("get_ime_text"), &_OS::get_ime_text);
-
-	ClassDB::bind_method(D_METHOD("set_screen_orientation", "orientation"), &_OS::set_screen_orientation);
-	ClassDB::bind_method(D_METHOD("get_screen_orientation"), &_OS::get_screen_orientation);
-
-	ClassDB::bind_method(D_METHOD("set_keep_screen_on", "enabled"), &_OS::set_keep_screen_on);
-	ClassDB::bind_method(D_METHOD("is_keep_screen_on"), &_OS::is_keep_screen_on);
-
-	ClassDB::bind_method(D_METHOD("has_touchscreen_ui_hint"), &_OS::has_touchscreen_ui_hint);
-
-	ClassDB::bind_method(D_METHOD("set_window_title", "title"), &_OS::set_window_title);
-
 	ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode", "enable"), &_OS::set_low_processor_usage_mode);
 	ClassDB::bind_method(D_METHOD("is_in_low_processor_usage_mode"), &_OS::is_in_low_processor_usage_mode);
 
@@ -1283,9 +816,6 @@ void _OS::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_system_time_secs"), &_OS::get_system_time_secs);
 	ClassDB::bind_method(D_METHOD("get_system_time_msecs"), &_OS::get_system_time_msecs);
 
-	ClassDB::bind_method(D_METHOD("set_native_icon", "filename"), &_OS::set_native_icon);
-	ClassDB::bind_method(D_METHOD("set_icon", "icon"), &_OS::set_icon);
-
 	ClassDB::bind_method(D_METHOD("get_exit_code"), &_OS::get_exit_code);
 	ClassDB::bind_method(D_METHOD("set_exit_code", "code"), &_OS::set_exit_code);
 
@@ -1295,10 +825,8 @@ void _OS::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_ticks_usec"), &_OS::get_ticks_usec);
 	ClassDB::bind_method(D_METHOD("get_splash_tick_msec"), &_OS::get_splash_tick_msec);
 	ClassDB::bind_method(D_METHOD("get_locale"), &_OS::get_locale);
-	ClassDB::bind_method(D_METHOD("get_latin_keyboard_variant"), &_OS::get_latin_keyboard_variant);
 	ClassDB::bind_method(D_METHOD("get_model_name"), &_OS::get_model_name);
 
-	ClassDB::bind_method(D_METHOD("can_draw"), &_OS::can_draw);
 	ClassDB::bind_method(D_METHOD("is_userfs_persistent"), &_OS::is_userfs_persistent);
 	ClassDB::bind_method(D_METHOD("is_stdout_verbose"), &_OS::is_stdout_verbose);
 
@@ -1310,10 +838,6 @@ void _OS::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("dump_memory_to_file", "file"), &_OS::dump_memory_to_file);
 	ClassDB::bind_method(D_METHOD("dump_resources_to_file", "file"), &_OS::dump_resources_to_file);
-	ClassDB::bind_method(D_METHOD("has_virtual_keyboard"), &_OS::has_virtual_keyboard);
-	ClassDB::bind_method(D_METHOD("show_virtual_keyboard", "existing_text"), &_OS::show_virtual_keyboard, DEFVAL(""));
-	ClassDB::bind_method(D_METHOD("hide_virtual_keyboard"), &_OS::hide_virtual_keyboard);
-	ClassDB::bind_method(D_METHOD("get_virtual_keyboard_height"), &_OS::get_virtual_keyboard_height);
 	ClassDB::bind_method(D_METHOD("print_resources_in_use", "short"), &_OS::print_resources_in_use, DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("print_all_resources", "tofile"), &_OS::print_all_resources, DEFVAL(""));
 
@@ -1324,81 +848,32 @@ void _OS::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_system_dir", "dir"), &_OS::get_system_dir);
 	ClassDB::bind_method(D_METHOD("get_unique_id"), &_OS::get_unique_id);
 
-	ClassDB::bind_method(D_METHOD("is_ok_left_and_cancel_right"), &_OS::is_ok_left_and_cancel_right);
-
 	ClassDB::bind_method(D_METHOD("print_all_textures_by_size"), &_OS::print_all_textures_by_size);
 	ClassDB::bind_method(D_METHOD("print_resources_by_type", "types"), &_OS::print_resources_by_type);
 
-	ClassDB::bind_method(D_METHOD("native_video_play", "path", "volume", "audio_track", "subtitle_track"), &_OS::native_video_play);
-	ClassDB::bind_method(D_METHOD("native_video_is_playing"), &_OS::native_video_is_playing);
-	ClassDB::bind_method(D_METHOD("native_video_stop"), &_OS::native_video_stop);
-	ClassDB::bind_method(D_METHOD("native_video_pause"), &_OS::native_video_pause);
-	ClassDB::bind_method(D_METHOD("native_video_unpause"), &_OS::native_video_unpause);
-
 	ClassDB::bind_method(D_METHOD("get_keycode_string", "code"), &_OS::get_keycode_string);
 	ClassDB::bind_method(D_METHOD("is_keycode_unicode", "code"), &_OS::is_keycode_unicode);
 	ClassDB::bind_method(D_METHOD("find_keycode_from_string", "string"), &_OS::find_keycode_from_string);
 
 	ClassDB::bind_method(D_METHOD("set_use_file_access_save_and_swap", "enabled"), &_OS::set_use_file_access_save_and_swap);
 
-	ClassDB::bind_method(D_METHOD("alert", "text", "title"), &_OS::alert, DEFVAL("Alert!"));
-
 	ClassDB::bind_method(D_METHOD("set_thread_name", "name"), &_OS::set_thread_name);
 
-	ClassDB::bind_method(D_METHOD("set_use_vsync", "enable"), &_OS::set_use_vsync);
-	ClassDB::bind_method(D_METHOD("is_vsync_enabled"), &_OS::is_vsync_enabled);
-
-	ClassDB::bind_method(D_METHOD("set_vsync_via_compositor", "enable"), &_OS::set_vsync_via_compositor);
-	ClassDB::bind_method(D_METHOD("is_vsync_via_compositor_enabled"), &_OS::is_vsync_via_compositor_enabled);
-
 	ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &_OS::has_feature);
 
 	ClassDB::bind_method(D_METHOD("request_permission", "name"), &_OS::request_permission);
 	ClassDB::bind_method(D_METHOD("request_permissions"), &_OS::request_permissions);
 	ClassDB::bind_method(D_METHOD("get_granted_permissions"), &_OS::get_granted_permissions);
 
-	ADD_PROPERTY(PropertyInfo(Variant::STRING, "clipboard"), "set_clipboard", "get_clipboard");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen"), "set_current_screen", "get_current_screen");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "exit_code"), "set_exit_code", "get_exit_code");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vsync_enabled"), "set_use_vsync", "is_vsync_enabled");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vsync_via_compositor"), "set_vsync_via_compositor", "is_vsync_via_compositor_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec"), "set_low_processor_usage_mode_sleep_usec", "get_low_processor_usage_mode_sleep_usec");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_screen_on"), "set_keep_screen_on", "is_keep_screen_on");
-	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "min_window_size"), "set_min_window_size", "get_min_window_size");
-	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "max_window_size"), "set_max_window_size", "get_max_window_size");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait,Reverse Landscape,Reverse Portrait,Sensor Landscape,Sensor Portrait,Sensor"), "set_screen_orientation", "get_screen_orientation");
-	ADD_GROUP("Window", "window_");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_borderless"), "set_borderless_window", "get_borderless_window");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_per_pixel_transparency_enabled"), "set_window_per_pixel_transparency_enabled", "get_window_per_pixel_transparency_enabled");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_fullscreen"), "set_window_fullscreen", "is_window_fullscreen");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_maximized"), "set_window_maximized", "is_window_maximized");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_minimized"), "set_window_minimized", "is_window_minimized");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_resizable"), "set_window_resizable", "is_window_resizable");
-	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "window_position"), "set_window_position", "get_window_position");
-	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "window_size"), "set_window_size", "get_window_size");
 
 	// Those default values need to be specified for the docs generator,
 	// to avoid using values from the documentation writer's own OS instance.
-	ADD_PROPERTY_DEFAULT("clipboard", "");
-	ADD_PROPERTY_DEFAULT("current_screen", 0);
 	ADD_PROPERTY_DEFAULT("exit_code", 0);
-	ADD_PROPERTY_DEFAULT("vsync_enabled", true);
-	ADD_PROPERTY_DEFAULT("vsync_via_compositor", false);
 	ADD_PROPERTY_DEFAULT("low_processor_usage_mode", false);
 	ADD_PROPERTY_DEFAULT("low_processor_usage_mode_sleep_usec", 6900);
-	ADD_PROPERTY_DEFAULT("keep_screen_on", true);
-	ADD_PROPERTY_DEFAULT("min_window_size", Vector2());
-	ADD_PROPERTY_DEFAULT("max_window_size", Vector2());
-	ADD_PROPERTY_DEFAULT("screen_orientation", 0);
-	ADD_PROPERTY_DEFAULT("window_borderless", false);
-	ADD_PROPERTY_DEFAULT("window_per_pixel_transparency_enabled", false);
-	ADD_PROPERTY_DEFAULT("window_fullscreen", false);
-	ADD_PROPERTY_DEFAULT("window_maximized", false);
-	ADD_PROPERTY_DEFAULT("window_minimized", false);
-	ADD_PROPERTY_DEFAULT("window_resizable", true);
-	ADD_PROPERTY_DEFAULT("window_position", Vector2());
-	ADD_PROPERTY_DEFAULT("window_size", Vector2());
 
 	BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES2);
 	BIND_ENUM_CONSTANT(VIDEO_DRIVER_VULKAN);
@@ -1424,14 +899,6 @@ void _OS::_bind_methods() {
 	BIND_ENUM_CONSTANT(MONTH_NOVEMBER);
 	BIND_ENUM_CONSTANT(MONTH_DECEMBER);
 
-	BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_LANDSCAPE);
-	BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_PORTRAIT);
-	BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
-	BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_REVERSE_PORTRAIT);
-	BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
-	BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_SENSOR_PORTRAIT);
-	BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_SENSOR);
-
 	BIND_ENUM_CONSTANT(SYSTEM_DIR_DESKTOP);
 	BIND_ENUM_CONSTANT(SYSTEM_DIR_DCIM);
 	BIND_ENUM_CONSTANT(SYSTEM_DIR_DOCUMENTS);

+ 0 - 114
core/bind/core_bind.h

@@ -145,83 +145,10 @@ public:
 		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;
-
-	void set_clipboard(const String &p_text);
-	String get_clipboard() const;
-
-	void set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen = 0);
-	Size2 get_video_mode(int p_screen = 0) const;
-	bool is_video_mode_fullscreen(int p_screen = 0) const;
-	bool is_video_mode_resizable(int p_screen = 0) const;
-	Array get_fullscreen_mode_list(int p_screen = 0) const;
-
-	virtual int get_video_driver_count() const;
-	virtual String get_video_driver_name(VideoDriver p_driver) const;
-	virtual VideoDriver get_current_video_driver() const;
-
-	virtual int get_audio_driver_count() const;
-	virtual String get_audio_driver_name(int p_driver) const;
-
 	virtual PackedStringArray get_connected_midi_inputs();
 	virtual void open_midi_inputs();
 	virtual void close_midi_inputs();
 
-	virtual int get_screen_count() const;
-	virtual int get_current_screen() const;
-	virtual void set_current_screen(int p_screen);
-	virtual Point2 get_screen_position(int p_screen = -1) const;
-	virtual Size2 get_screen_size(int p_screen = -1) const;
-	virtual int get_screen_dpi(int p_screen = -1) const;
-	virtual Point2 get_window_position() const;
-	virtual void set_window_position(const Point2 &p_position);
-	virtual Size2 get_max_window_size() const;
-	virtual Size2 get_min_window_size() const;
-	virtual Size2 get_window_size() const;
-	virtual Size2 get_real_window_size() const;
-	virtual Rect2 get_window_safe_area() const;
-	virtual void set_max_window_size(const Size2 &p_size);
-	virtual void set_min_window_size(const Size2 &p_size);
-	virtual void set_window_size(const Size2 &p_size);
-	virtual void set_window_fullscreen(bool p_enabled);
-	virtual bool is_window_fullscreen() const;
-	virtual void set_window_resizable(bool p_enabled);
-	virtual bool is_window_resizable() const;
-	virtual void set_window_minimized(bool p_enabled);
-	virtual bool is_window_minimized() const;
-	virtual void set_window_maximized(bool p_enabled);
-	virtual bool is_window_maximized() const;
-	virtual void set_window_always_on_top(bool p_enabled);
-	virtual bool is_window_always_on_top() const;
-	virtual bool is_window_focused() const;
-	virtual void request_attention();
-	virtual void center_window();
-	virtual void move_window_to_foreground();
-
-	virtual void set_borderless_window(bool p_borderless);
-	virtual bool get_borderless_window() const;
-
-	virtual bool get_window_per_pixel_transparency_enabled() const;
-	virtual void set_window_per_pixel_transparency_enabled(bool p_enabled);
-
-	virtual void set_ime_active(const bool p_active);
-	virtual void set_ime_position(const Point2 &p_pos);
-	virtual Point2 get_ime_selection() const;
-	virtual String get_ime_text() const;
-
-	Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
-	bool native_video_is_playing();
-	void native_video_pause();
-	void native_video_unpause();
-	void native_video_stop();
-
 	void set_low_processor_usage_mode(bool p_enabled);
 	bool is_in_low_processor_usage_mode() const;
 
@@ -243,25 +170,17 @@ public:
 	Vector<String> get_cmdline_args();
 
 	String get_locale() const;
-	String get_latin_keyboard_variant() const;
 
 	String get_model_name() const;
 
 	void dump_memory_to_file(const String &p_file);
 	void dump_resources_to_file(const String &p_file);
 
-	bool has_virtual_keyboard() const;
-	void show_virtual_keyboard(const String &p_existing_text = "");
-	void hide_virtual_keyboard();
-	int get_virtual_keyboard_height();
-
 	void print_resources_in_use(bool p_short = false);
 	void print_all_resources(const String &p_to_file);
 	void print_all_textures_by_size();
 	void print_resources_by_type(const Vector<String> &p_types);
 
-	bool has_touchscreen_ui_hint() const;
-
 	bool is_debug_build() const;
 
 	String get_unique_id() const;
@@ -272,9 +191,6 @@ public:
 
 	void set_use_file_access_save_and_swap(bool p_enable);
 
-	void set_native_icon(const String &p_filename);
-	void set_icon(const Ref<Image> &p_icon);
-
 	int get_exit_code() const;
 	void set_exit_code(int p_code);
 	Dictionary get_date(bool utc) const;
@@ -298,8 +214,6 @@ public:
 
 	bool can_use_threads() const;
 
-	bool can_draw() const;
-
 	bool is_userfs_persistent() const;
 
 	bool is_stdout_verbose() const;
@@ -317,39 +231,12 @@ public:
 		SYSTEM_DIR_RINGTONES,
 	};
 
-	enum ScreenOrientation {
-
-		SCREEN_ORIENTATION_LANDSCAPE,
-		SCREEN_ORIENTATION_PORTRAIT,
-		SCREEN_ORIENTATION_REVERSE_LANDSCAPE,
-		SCREEN_ORIENTATION_REVERSE_PORTRAIT,
-		SCREEN_ORIENTATION_SENSOR_LANDSCAPE,
-		SCREEN_ORIENTATION_SENSOR_PORTRAIT,
-		SCREEN_ORIENTATION_SENSOR,
-	};
-
 	String get_system_dir(SystemDir p_dir) const;
 
 	String get_user_data_dir() const;
 
-	void alert(const String &p_alert, const String &p_title = "ALERT!");
-
-	void set_screen_orientation(ScreenOrientation p_orientation);
-	ScreenOrientation get_screen_orientation() const;
-
-	void set_keep_screen_on(bool p_enabled);
-	bool is_keep_screen_on() const;
-
-	bool is_ok_left_and_cancel_right() const;
-
 	Error set_thread_name(const String &p_name);
 
-	void set_use_vsync(bool p_enable);
-	bool is_vsync_enabled() const;
-
-	void set_vsync_via_compositor(bool p_enable);
-	bool is_vsync_via_compositor_enabled() const;
-
 	bool has_feature(const String &p_feature) const;
 
 	bool request_permission(const String &p_name);
@@ -365,7 +252,6 @@ VARIANT_ENUM_CAST(_OS::VideoDriver);
 VARIANT_ENUM_CAST(_OS::Weekday);
 VARIANT_ENUM_CAST(_OS::Month);
 VARIANT_ENUM_CAST(_OS::SystemDir);
-VARIANT_ENUM_CAST(_OS::ScreenOrientation);
 
 class _Geometry : public Object {
 

+ 2 - 1
core/debugger/remote_debugger.cpp

@@ -38,6 +38,7 @@
 #include "core/project_settings.h"
 #include "core/script_language.h"
 #include "scene/main/node.h"
+#include "servers/display_server.h"
 
 template <typename T>
 void RemoteDebugger::_bind_profiler(const String &p_name, T *p_prof) {
@@ -694,7 +695,7 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
 			} else if (command == "continue") {
 				script_debugger->set_depth(-1);
 				script_debugger->set_lines_left(-1);
-				OS::get_singleton()->move_window_to_foreground();
+				DisplayServer::get_singleton()->window_move_to_foreground();
 				break;
 
 			} else if (command == "break") {

+ 14 - 20
core/input/input.cpp

@@ -41,6 +41,12 @@
 
 Input *Input::singleton = NULL;
 
+void (*Input::set_mouse_mode_func)(Input::MouseMode) = nullptr;
+Input::MouseMode (*Input::get_mouse_mode_func)() = nullptr;
+void (*Input::warp_mouse_func)(const Vector2 &p_to_pos) = nullptr;
+Input::CursorShape (*Input::get_current_cursor_shape_func)() = nullptr;
+void (*Input::set_custom_mouse_cursor_func)(const RES &, Input::CursorShape, const Vector2 &) = nullptr;
+
 Input *Input::get_singleton() {
 
 	return singleton;
@@ -48,12 +54,12 @@ Input *Input::get_singleton() {
 
 void Input::set_mouse_mode(MouseMode p_mode) {
 	ERR_FAIL_INDEX((int)p_mode, 4);
-	OS::get_singleton()->set_mouse_mode((OS::MouseMode)p_mode);
+	set_mouse_mode_func(p_mode);
 }
 
 Input::MouseMode Input::get_mouse_mode() const {
 
-	return (MouseMode)OS::get_singleton()->get_mouse_mode();
+	return get_mouse_mode_func();
 }
 
 void Input::_bind_methods() {
@@ -654,10 +660,8 @@ int Input::get_mouse_button_mask() const {
 }
 
 void Input::warp_mouse_position(const Vector2 &p_to) {
-
-	OS::get_singleton()->warp_mouse_position(p_to);
+	warp_mouse_func(p_to);
 }
-
 Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) {
 
 	// The relative distance reported for the next event after a warp is in the boundaries of the
@@ -678,7 +682,7 @@ Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, con
 	const Point2i pos_local = p_motion->get_global_position() - p_rect.position;
 	const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y));
 	if (pos_warped != pos_local) {
-		OS::get_singleton()->warp_mouse_position(pos_warped + p_rect.position);
+		warp_mouse_position(pos_warped + p_rect.position);
 	}
 
 	return rel_warped;
@@ -774,14 +778,14 @@ void Input::set_default_cursor_shape(CursorShape p_shape) {
 
 Input::CursorShape Input::get_current_cursor_shape() const {
 
-	return (Input::CursorShape)OS::get_singleton()->get_cursor_shape();
+	return get_current_cursor_shape_func();
 }
 
 void Input::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
 	if (Engine::get_singleton()->is_editor_hint())
 		return;
 
-	OS::get_singleton()->set_custom_mouse_cursor(p_cursor, (OS::CursorShape)p_shape, p_hotspot);
+	set_custom_mouse_cursor_func(p_cursor, p_shape, p_hotspot);
 }
 
 void Input::accumulate_input_event(const Ref<InputEvent> &p_event) {
@@ -1171,23 +1175,13 @@ void Input::set_fallback_mapping(String p_guid) {
 	}
 }
 
-//Defaults to simple implementation for platforms with a fixed gamepad layout, like consoles.
-bool Input::is_joy_known(int p_device) {
-
-	return OS::get_singleton()->is_joy_known(p_device);
-}
-
-String Input::get_joy_guid(int p_device) const {
-	return OS::get_singleton()->get_joy_guid(p_device);
-}
-
 //platforms that use the remapping system can override and call to these ones
-bool Input::is_joy_mapped(int p_device) {
+bool Input::is_joy_known(int p_device) {
 	int mapping = joy_names[p_device].mapping;
 	return mapping != -1 ? (mapping != fallback_mapping) : false;
 }
 
-String Input::get_joy_guid_remapped(int p_device) const {
+String Input::get_joy_guid(int p_device) const {
 	ERR_FAIL_COND_V(!joy_names.has(p_device), "");
 	return joy_names[p_device].uid;
 }

+ 10 - 4
core/input/input.h

@@ -219,6 +219,14 @@ private:
 
 	List<Ref<InputEvent>> accumulated_events;
 	bool use_accumulated_input;
+	friend class DisplayServer;
+
+	static void (*set_mouse_mode_func)(MouseMode);
+	static MouseMode (*get_mouse_mode_func)();
+	static void (*warp_mouse_func)(const Vector2 &p_to_pos);
+
+	static CursorShape (*get_current_cursor_shape_func)();
+	static void (*set_custom_mouse_cursor_func)(const RES &, CursorShape, const Vector2 &);
 
 protected:
 	static void _bind_methods();
@@ -300,8 +308,6 @@ public:
 
 	void add_joy_mapping(String p_mapping, bool p_update_existing = false);
 	void remove_joy_mapping(String p_guid);
-	bool is_joy_known(int p_device);
-	String get_joy_guid(int p_device) const;
 
 	String get_joy_button_string(int p_button);
 	String get_joy_axis_string(int p_axis);
@@ -310,8 +316,8 @@ public:
 
 	int get_unused_joy_id();
 
-	bool is_joy_mapped(int p_device);
-	String get_joy_guid_remapped(int p_device) const;
+	bool is_joy_known(int p_device);
+	String get_joy_guid(int p_device) const;
 	void set_fallback_mapping(String p_guid);
 
 	void accumulate_input_event(const Ref<InputEvent> &p_event);

+ 1 - 226
core/os/os.cpp

@@ -139,14 +139,6 @@ void OS::printerr(const char *p_format, ...) {
 	va_end(argp);
 };
 
-void OS::set_keep_screen_on(bool p_enabled) {
-	_keep_screen_on = p_enabled;
-}
-
-bool OS::is_keep_screen_on() const {
-	return _keep_screen_on;
-}
-
 void OS::set_low_processor_usage_mode(bool p_enabled) {
 
 	low_processor_usage_mode = p_enabled;
@@ -167,15 +159,6 @@ int OS::get_low_processor_usage_mode_sleep_usec() const {
 	return low_processor_usage_mode_sleep_usec;
 }
 
-void OS::set_clipboard(const String &p_text) {
-
-	_local_clipboard = p_text;
-}
-String OS::get_clipboard() const {
-
-	return _local_clipboard;
-}
-
 String OS::get_executable_path() const {
 
 	return _execpath;
@@ -216,31 +199,6 @@ static void _OS_printres(Object *p_obj) {
 		print_line(str);
 }
 
-bool OS::has_virtual_keyboard() const {
-
-	return false;
-}
-
-void OS::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_input_length) {
-}
-
-void OS::hide_virtual_keyboard() {
-}
-
-int OS::get_virtual_keyboard_height() const {
-	return 0;
-}
-
-void OS::set_cursor_shape(CursorShape p_shape) {
-}
-
-OS::CursorShape OS::get_cursor_shape() const {
-	return CURSOR_ARROW;
-}
-
-void OS::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
-}
-
 void OS::print_all_resources(String p_to_file) {
 
 	ERR_FAIL_COND(p_to_file != "" && _OSPRF);
@@ -372,45 +330,6 @@ Error OS::shell_open(String p_uri) {
 };
 
 // implement these with the canvas?
-Error OS::dialog_show(String p_title, String p_description, Vector<String> p_buttons, Object *p_obj, String p_callback) {
-
-	while (true) {
-
-		print("%ls\n--------\n%ls\n", p_title.c_str(), p_description.c_str());
-		for (int i = 0; i < p_buttons.size(); i++) {
-			if (i > 0) print(", ");
-			print("%i=%ls", i + 1, p_buttons[i].c_str());
-		};
-		print("\n");
-		String res = get_stdin_string().strip_edges();
-		if (!res.is_numeric())
-			continue;
-		int n = res.to_int();
-		if (n < 0 || n >= p_buttons.size())
-			continue;
-		if (p_obj && p_callback != "")
-			p_obj->call_deferred(p_callback, n);
-		break;
-	};
-	return OK;
-};
-
-Error OS::dialog_input_text(String p_title, String p_description, String p_partial, Object *p_obj, String p_callback) {
-
-	ERR_FAIL_COND_V(!p_obj, FAILED);
-	ERR_FAIL_COND_V(p_callback == "", FAILED);
-	print("%ls\n---------\n%ls\n[%ls]:\n", p_title.c_str(), p_description.c_str(), p_partial.c_str());
-
-	String res = get_stdin_string().strip_edges();
-	bool success = true;
-	if (res == "") {
-		res = p_partial;
-	};
-
-	p_obj->call_deferred(p_callback, success, res);
-
-	return OK;
-};
 
 uint64_t OS::get_static_memory_usage() const {
 
@@ -427,12 +346,6 @@ Error OS::set_cwd(const String &p_cwd) {
 	return ERR_CANT_OPEN;
 }
 
-bool OS::has_touchscreen_ui_hint() const {
-
-	//return false;
-	return Input::get_singleton() && Input::get_singleton()->is_emulating_touch_from_mouse();
-}
-
 uint64_t OS::get_free_static_memory() const {
 
 	return Memory::get_mem_available();
@@ -441,17 +354,7 @@ uint64_t OS::get_free_static_memory() const {
 void OS::yield() {
 }
 
-void OS::set_screen_orientation(ScreenOrientation p_orientation) {
-
-	_orientation = p_orientation;
-}
-
-OS::ScreenOrientation OS::get_screen_orientation() const {
-
-	return (OS::ScreenOrientation)_orientation;
-}
-
-void OS::_ensure_user_data_dir() {
+void OS::ensure_user_data_dir() {
 
 	String dd = get_user_data_dir();
 	DirAccess *da = DirAccess::open(dd);
@@ -467,12 +370,6 @@ void OS::_ensure_user_data_dir() {
 	memdelete(da);
 }
 
-void OS::set_native_icon(const String &p_filename) {
-}
-
-void OS::set_icon(const Ref<Image> &p_icon) {
-}
-
 String OS::get_model_name() const {
 
 	return "GenericDevice";
@@ -484,15 +381,6 @@ void OS::set_cmdline(const char *p_execpath, const List<String> &p_args) {
 	_cmdline = p_args;
 };
 
-void OS::release_rendering_thread() {
-}
-
-void OS::make_rendering_thread() {
-}
-
-void OS::swap_buffers() {
-}
-
 String OS::get_unique_id() const {
 
 	ERR_FAIL_V("");
@@ -503,31 +391,6 @@ int OS::get_processor_count() const {
 	return 1;
 }
 
-Error OS::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) {
-
-	return FAILED;
-};
-
-bool OS::native_video_is_playing() const {
-
-	return false;
-};
-
-void OS::native_video_pause(){
-
-};
-
-void OS::native_video_unpause(){
-
-};
-
-void OS::native_video_stop(){
-
-};
-
-void OS::set_mouse_mode(MouseMode p_mode) {
-}
-
 bool OS::can_use_threads() const {
 
 #ifdef NO_THREADS
@@ -537,51 +400,6 @@ bool OS::can_use_threads() const {
 #endif
 }
 
-OS::MouseMode OS::get_mouse_mode() const {
-
-	return MOUSE_MODE_VISIBLE;
-}
-
-OS::LatinKeyboardVariant OS::get_latin_keyboard_variant() const {
-
-	return LATIN_KEYBOARD_QWERTY;
-}
-
-bool OS::is_joy_known(int p_device) {
-	return true;
-}
-
-String OS::get_joy_guid(int p_device) const {
-	return "Default Joypad";
-}
-
-void OS::set_context(int p_context) {
-}
-
-OS::SwitchVSyncCallbackInThread OS::switch_vsync_function = NULL;
-
-void OS::set_use_vsync(bool p_enable) {
-	_use_vsync = p_enable;
-	if (switch_vsync_function) { //if a function was set, use function
-		switch_vsync_function(p_enable);
-	} else { //otherwise just call here
-		_set_use_vsync(p_enable);
-	}
-}
-
-bool OS::is_vsync_enabled() const {
-
-	return _use_vsync;
-}
-
-void OS::set_vsync_via_compositor(bool p_enable) {
-	_vsync_via_compositor = p_enable;
-}
-
-bool OS::is_vsync_via_compositor_enabled() const {
-	return _vsync_via_compositor;
-}
-
 void OS::set_has_server_feature_callback(HasServerFeatureCallback p_callback) {
 
 	has_server_feature_callback = p_callback;
@@ -653,48 +471,6 @@ bool OS::has_feature(const String &p_feature) {
 	return false;
 }
 
-void OS::center_window() {
-
-	if (is_window_fullscreen()) return;
-
-	Point2 sp = get_screen_position(get_current_screen());
-	Size2 scr = get_screen_size(get_current_screen());
-	Size2 wnd = get_real_window_size();
-
-	int x = sp.width + (scr.width - wnd.width) / 2;
-	int y = sp.height + (scr.height - wnd.height) / 2;
-
-	set_window_position(Vector2(x, y));
-}
-
-int OS::get_video_driver_count() const {
-
-	return 2;
-}
-
-const char *OS::get_video_driver_name(int p_driver) const {
-
-	switch (p_driver) {
-		case VIDEO_DRIVER_GLES2:
-			return "GLES2";
-		case VIDEO_DRIVER_VULKAN:
-		default:
-			return "Vulkan";
-	}
-}
-
-int OS::get_audio_driver_count() const {
-
-	return AudioDriverManager::get_driver_count();
-}
-
-const char *OS::get_audio_driver_name(int p_driver) const {
-
-	AudioDriver *driver = AudioDriverManager::get_driver(p_driver);
-	ERR_FAIL_COND_V_MSG(!driver, "", "Cannot get audio driver at index '" + itos(p_driver) + "'.");
-	return AudioDriverManager::get_driver(p_driver)->get_name();
-}
-
 void OS::set_restart_on_exit(bool p_restart, const List<String> &p_restart_arguments) {
 	restart_on_exit = p_restart;
 	restart_commandline = p_restart_arguments;
@@ -740,7 +516,6 @@ OS::OS() {
 	_verbose_stdout = false;
 	_no_window = false;
 	_exit_code = 0;
-	_orientation = SCREEN_LANDSCAPE;
 
 	_render_thread_mode = RENDER_THREAD_SAFE;
 

+ 4 - 240
core/os/os.h

@@ -82,31 +82,6 @@ public:
 		RENDER_THREAD_SAFE,
 		RENDER_SEPARATE_THREAD
 	};
-	struct VideoMode {
-
-		int width, height;
-		bool fullscreen;
-		bool resizable;
-		bool borderless_window;
-		bool maximized;
-		bool always_on_top;
-		bool use_vsync;
-		bool vsync_via_compositor;
-		bool layered;
-		float get_aspect() const { return (float)width / (float)height; }
-		VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_always_on_top = false, bool p_use_vsync = false, bool p_vsync_via_compositor = false) {
-			width = p_width;
-			height = p_height;
-			fullscreen = p_fullscreen;
-			resizable = p_resizable;
-			borderless_window = p_borderless_window;
-			maximized = p_maximized;
-			always_on_top = p_always_on_top;
-			use_vsync = p_use_vsync;
-			vsync_via_compositor = p_vsync_via_compositor;
-			layered = false;
-		}
-	};
 
 protected:
 	friend class Main;
@@ -117,8 +92,8 @@ protected:
 	// functions used by main to initialize/deinitialize the OS
 	void add_logger(Logger *p_logger);
 
-	virtual void initialize_core() = 0;
-	virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) = 0;
+	virtual void initialize() = 0;
+	virtual void initialize_joypads() = 0;
 
 	virtual void set_main_loop(MainLoop *p_main_loop) = 0;
 	virtual void delete_main_loop() = 0;
@@ -128,7 +103,6 @@ protected:
 
 	virtual void set_cmdline(const char *p_execpath, const List<String> &p_args);
 
-	void _ensure_user_data_dir();
 	virtual bool _check_internal_feature_support(const String &p_feature) = 0;
 
 public:
@@ -136,121 +110,20 @@ public:
 
 	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;
 
-	virtual void alert(const String &p_alert, const String &p_title = "ALERT!") = 0;
 	virtual String get_stdin_string(bool p_block = true) = 0;
 
-	enum MouseMode {
-		MOUSE_MODE_VISIBLE,
-		MOUSE_MODE_HIDDEN,
-		MOUSE_MODE_CAPTURED,
-		MOUSE_MODE_CONFINED
-	};
-
-	virtual void set_mouse_mode(MouseMode p_mode);
-	virtual MouseMode get_mouse_mode() const;
-
-	virtual void warp_mouse_position(const Point2 &p_to) {}
-	virtual Point2 get_mouse_position() const = 0;
-	virtual int get_mouse_button_state() const = 0;
-	virtual void set_window_title(const String &p_title) = 0;
-
-	virtual void set_clipboard(const String &p_text);
-	virtual String get_clipboard() const;
-
-	virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0) = 0;
-	virtual VideoMode get_video_mode(int p_screen = 0) const = 0;
-	virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const = 0;
-
-	enum VideoDriver {
-		VIDEO_DRIVER_VULKAN,
-		VIDEO_DRIVER_GLES2,
-		VIDEO_DRIVER_MAX,
-	};
-
-	virtual int get_video_driver_count() const;
-	virtual const char *get_video_driver_name(int p_driver) const;
-	virtual int get_current_video_driver() const = 0;
-
-	virtual int get_audio_driver_count() const;
-	virtual const char *get_audio_driver_name(int p_driver) const;
-
 	virtual PackedStringArray get_connected_midi_inputs();
 	virtual void open_midi_inputs();
 	virtual void close_midi_inputs();
 
-	virtual int get_screen_count() const { return 1; }
-	virtual int get_current_screen() const { return 0; }
-	virtual void set_current_screen(int p_screen) {}
-	virtual Point2 get_screen_position(int p_screen = -1) const { return Point2(); }
-	virtual Size2 get_screen_size(int p_screen = -1) const { return get_window_size(); }
-	virtual int get_screen_dpi(int p_screen = -1) const { return 72; }
-	virtual Point2 get_window_position() const { return Vector2(); }
-	virtual void set_window_position(const Point2 &p_position) {}
-	virtual Size2 get_max_window_size() const { return Size2(); };
-	virtual Size2 get_min_window_size() const { return Size2(); };
-	virtual Size2 get_window_size() const = 0;
-	virtual Size2 get_real_window_size() const { return get_window_size(); }
-	virtual void set_min_window_size(const Size2 p_size) {}
-	virtual void set_max_window_size(const Size2 p_size) {}
-	virtual void set_window_size(const Size2 p_size) {}
-	virtual void set_window_fullscreen(bool p_enabled) {}
-	virtual bool is_window_fullscreen() const { return true; }
-	virtual void set_window_resizable(bool p_enabled) {}
-	virtual bool is_window_resizable() const { return false; }
-	virtual void set_window_minimized(bool p_enabled) {}
-	virtual bool is_window_minimized() const { return false; }
-	virtual void set_window_maximized(bool p_enabled) {}
-	virtual bool is_window_maximized() const { return true; }
-	virtual void set_window_always_on_top(bool p_enabled) {}
-	virtual bool is_window_always_on_top() const { return false; }
-	virtual bool is_window_focused() const { return true; }
-	virtual void set_console_visible(bool p_enabled) {}
-	virtual bool is_console_visible() const { return false; }
-	virtual void request_attention() {}
-	virtual void center_window();
-
-	// Returns window area free of hardware controls and other obstacles.
-	// The application should use this to determine where to place UI elements.
-	//
-	// Keep in mind the area returned is in window coordinates rather than
-	// viewport coordinates - you should perform the conversion on your own.
-	//
-	// The maximum size of the area is Rect2(0, 0, window_size.width, window_size.height).
-	virtual Rect2 get_window_safe_area() const {
-		Size2 window_size = get_window_size();
-		return Rect2(0, 0, window_size.width, window_size.height);
-	}
-
-	virtual void set_borderless_window(bool p_borderless) {}
-	virtual bool get_borderless_window() { return 0; }
-
-	virtual bool get_window_per_pixel_transparency_enabled() const { return false; }
-	virtual void set_window_per_pixel_transparency_enabled(bool p_enabled) {}
-
-	virtual uint8_t *get_layered_buffer_data() { return NULL; }
-	virtual Size2 get_layered_buffer_size() { return Size2(0, 0); }
-	virtual void swap_layered_buffer() {}
-
-	virtual void set_ime_active(const bool p_active) {}
-	virtual void set_ime_position(const Point2 &p_pos) {}
-	virtual Point2 get_ime_selection() const { return Point2(); }
-	virtual String get_ime_text() const { return String(); }
-
 	virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) { return ERR_UNAVAILABLE; }
 	virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; }
 	virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) { return ERR_UNAVAILABLE; }
 
-	virtual void set_keep_screen_on(bool p_enabled);
-	virtual bool is_keep_screen_on() const;
 	virtual void set_low_processor_usage_mode(bool p_enabled);
 	virtual bool is_in_low_processor_usage_mode() const;
 	virtual void set_low_processor_usage_mode_sleep_usec(int p_usec);
@@ -273,6 +146,8 @@ public:
 	virtual List<String> get_cmdline_args() const { return _cmdline; }
 	virtual String get_model_name() const;
 
+	void ensure_user_data_dir();
+
 	virtual MainLoop *get_main_loop() const = 0;
 
 	virtual void yield();
@@ -338,8 +213,6 @@ public:
 	uint32_t get_ticks_msec() const;
 	uint64_t get_splash_tick_msec() const;
 
-	virtual bool can_draw() const = 0;
-
 	virtual bool is_userfs_persistent() const { return true; }
 
 	bool is_stdout_verbose() const;
@@ -348,39 +221,6 @@ public:
 	virtual bool is_disable_crash_handler() const { return false; }
 	virtual void initialize_debugging() {}
 
-	enum CursorShape {
-		CURSOR_ARROW,
-		CURSOR_IBEAM,
-		CURSOR_POINTING_HAND,
-		CURSOR_CROSS,
-		CURSOR_WAIT,
-		CURSOR_BUSY,
-		CURSOR_DRAG,
-		CURSOR_CAN_DROP,
-		CURSOR_FORBIDDEN,
-		CURSOR_VSIZE,
-		CURSOR_HSIZE,
-		CURSOR_BDIAGSIZE,
-		CURSOR_FDIAGSIZE,
-		CURSOR_MOVE,
-		CURSOR_VSPLIT,
-		CURSOR_HSPLIT,
-		CURSOR_HELP,
-		CURSOR_MAX
-	};
-
-	virtual bool has_virtual_keyboard() const;
-	virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_input_length = -1);
-	virtual void hide_virtual_keyboard();
-
-	// returns height of the currently shown virtual keyboard (0 if keyboard is hidden)
-	virtual int get_virtual_keyboard_height() const;
-
-	virtual void set_cursor_shape(CursorShape p_shape);
-	virtual CursorShape get_cursor_shape() const;
-	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
-
-	virtual bool get_swap_ok_cancel() { return false; }
 	virtual void dump_memory_to_file(const char *p_file);
 	virtual void dump_resources_to_file(const char *p_file);
 	virtual void print_resources_in_use(bool p_short = false);
@@ -423,34 +263,8 @@ public:
 	virtual void set_no_window_mode(bool p_enable);
 	virtual bool is_no_window_mode_enabled() const;
 
-	virtual bool has_touchscreen_ui_hint() const;
-
-	enum ScreenOrientation {
-
-		SCREEN_LANDSCAPE,
-		SCREEN_PORTRAIT,
-		SCREEN_REVERSE_LANDSCAPE,
-		SCREEN_REVERSE_PORTRAIT,
-		SCREEN_SENSOR_LANDSCAPE,
-		SCREEN_SENSOR_PORTRAIT,
-		SCREEN_SENSOR,
-	};
-
-	virtual void set_screen_orientation(ScreenOrientation p_orientation);
-	ScreenOrientation get_screen_orientation() const;
-
-	virtual void enable_for_stealing_focus(ProcessID pid) {}
-	virtual void move_window_to_foreground() {}
-
 	virtual void debug_break();
 
-	virtual void release_rendering_thread();
-	virtual void make_rendering_thread();
-	virtual void swap_buffers();
-
-	virtual void set_native_icon(const String &p_filename);
-	virtual void set_icon(const Ref<Image> &p_icon);
-
 	virtual int get_exit_code() const;
 	virtual void set_exit_code(int p_code);
 
@@ -458,62 +272,12 @@ public:
 
 	virtual String get_unique_id() const;
 
-	virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
-	virtual bool native_video_is_playing() const;
-	virtual void native_video_pause();
-	virtual void native_video_unpause();
-	virtual void native_video_stop();
-
 	virtual bool can_use_threads() const;
 
-	virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, Object *p_obj, String p_callback);
-	virtual Error dialog_input_text(String p_title, String p_description, String p_partial, Object *p_obj, String p_callback);
-
-	enum LatinKeyboardVariant {
-		LATIN_KEYBOARD_QWERTY,
-		LATIN_KEYBOARD_QWERTZ,
-		LATIN_KEYBOARD_AZERTY,
-		LATIN_KEYBOARD_QZERTY,
-		LATIN_KEYBOARD_DVORAK,
-		LATIN_KEYBOARD_NEO,
-		LATIN_KEYBOARD_COLEMAK,
-	};
-
-	virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
-
-	virtual bool is_joy_known(int p_device);
-	virtual String get_joy_guid(int p_device) const;
-
-	enum EngineContext {
-		CONTEXT_EDITOR,
-		CONTEXT_PROJECTMAN,
-		CONTEXT_ENGINE,
-	};
-
-	virtual void set_context(int p_context);
-
-	//amazing hack because OpenGL needs this to be set on a separate thread..
-	//also core can't access servers, so a callback must be used
-	typedef void (*SwitchVSyncCallbackInThread)(bool);
-
-	static SwitchVSyncCallbackInThread switch_vsync_function;
-	void set_use_vsync(bool p_enable);
-	bool is_vsync_enabled() const;
-
-	//real, actual overridable function to switch vsync, which needs to be called from graphics thread if needed
-	virtual void _set_use_vsync(bool p_enable) {}
-
-	void set_vsync_via_compositor(bool p_enable);
-	bool is_vsync_via_compositor_enabled() const;
-
-	virtual void force_process_input(){};
 	bool has_feature(const String &p_feature);
 
 	void set_has_server_feature_callback(HasServerFeatureCallback p_callback);
 
-	bool is_layered_allowed() const { return _allow_layered; }
-	bool is_hidpi_allowed() const { return _allow_hidpi; }
-
 	void set_restart_on_exit(bool p_restart, const List<String> &p_restart_arguments);
 	bool is_restart_on_exit_set() const;
 	List<String> get_restart_on_exit_arguments() const;

+ 1 - 1
drivers/gl_context/SCsub

@@ -2,7 +2,7 @@
 
 Import('env')
 
-if (env["platform"] in ["haiku", "osx", "windows", "x11"]):
+if (env["platform"] in ["haiku", "osx", "windows", "linuxbsd"]):
     # Thirdparty source files
     thirdparty_dir = "#thirdparty/glad/"
     thirdparty_sources = [

+ 6 - 6
drivers/gles2/rasterizer_canvas_gles2.cpp

@@ -124,7 +124,7 @@ void RasterizerCanvasGLES2::canvas_begin() {
 			viewport_width = storage->frame.current_rt->width;
 			viewport_height = storage->frame.current_rt->height;
 			viewport_x = storage->frame.current_rt->x;
-			viewport_y = OS::get_singleton()->get_window_size().height - viewport_height - storage->frame.current_rt->y;
+			viewport_y = DisplayServer::get_singleton()->window_get_size().height - viewport_height - storage->frame.current_rt->y;
 			glScissor(viewport_x, viewport_y, viewport_width, viewport_height);
 			glViewport(viewport_x, viewport_y, viewport_width, viewport_height);
 			glEnable(GL_SCISSOR_TEST);
@@ -168,7 +168,7 @@ void RasterizerCanvasGLES2::canvas_begin() {
 		canvas_transform.translate(-(storage->frame.current_rt->width / 2.0f), -(storage->frame.current_rt->height / 2.0f), 0.0f);
 		canvas_transform.scale(Vector3(2.0f / storage->frame.current_rt->width, csy * -2.0f / storage->frame.current_rt->height, 1.0f));
 	} else {
-		Vector2 ssize = OS::get_singleton()->get_window_size();
+		Vector2 ssize = DisplayServer::get_singleton()->window_get_size();
 		canvas_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
 		canvas_transform.scale(Vector3(2.0f / ssize.width, -2.0f / ssize.height, 1.0f));
 	}
@@ -194,8 +194,8 @@ void RasterizerCanvasGLES2::canvas_end() {
 
 	if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
 		//reset viewport to full window size
-		int viewport_width = OS::get_singleton()->get_window_size().width;
-		int viewport_height = OS::get_singleton()->get_window_size().height;
+		int viewport_width = DisplayServer::get_singleton()->window_get_size().width;
+		int viewport_height = DisplayServer::get_singleton()->window_get_size().height;
 		glViewport(0, 0, viewport_width, viewport_height);
 		glScissor(0, 0, viewport_width, viewport_height);
 	}
@@ -1995,7 +1995,7 @@ void RasterizerCanvasGLES2::draw_lens_distortion_rect(const Rect2 &p_rect, float
 	if (storage->frame.current_rt) {
 		half_size = Vector2(storage->frame.current_rt->width, storage->frame.current_rt->height);
 	} else {
-		half_size = OS::get_singleton()->get_window_size();
+		half_size = DisplayServer::get_singleton()->window_get_size();
 	}
 	half_size *= 0.5;
 	Vector2 offset((p_rect.position.x - half_size.x) / half_size.x, (p_rect.position.y - half_size.y) / half_size.y);
@@ -2029,7 +2029,7 @@ void RasterizerCanvasGLES2::draw_lens_distortion_rect(const Rect2 &p_rect, float
 
 void RasterizerCanvasGLES2::draw_window_margins(int *black_margin, RID *black_image) {
 
-	Vector2 window_size = OS::get_singleton()->get_window_size();
+	Vector2 window_size = DisplayServer::get_singleton()->window_get_size();
 	int window_h = window_size.height;
 	int window_w = window_size.width;
 

+ 1 - 1
drivers/gles2/rasterizer_gles2.cpp

@@ -318,7 +318,7 @@ void RasterizerGLES2::set_current_render_target(RID p_render_target) {
 	} else {
 		storage->frame.current_rt = NULL;
 		storage->frame.clear_request = false;
-		glViewport(0, 0, OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
+		glViewport(0, 0, DisplayServer::get_singleton()->window_get_size().width, DisplayServer::get_singleton()->window_get_size().height);
 		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
 	}
 }

+ 1 - 1
drivers/gles2/rasterizer_scene_gles2.cpp

@@ -3261,7 +3261,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
 		viewport_x = storage->frame.current_rt->x;
 
 		if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
-			viewport_y = OS::get_singleton()->get_window_size().height - viewport_height - storage->frame.current_rt->y;
+			viewport_y = DisplayServer::get_singleton()->window_get_size().height - viewport_height - storage->frame.current_rt->y;
 		} else {
 			viewport_y = storage->frame.current_rt->y;
 		}

+ 1 - 1
drivers/vulkan/SCsub

@@ -57,7 +57,7 @@ if env['builtin_vulkan']:
             'FALLBACK_DATA_DIRS=\\"%s\\"' % '/usr/local/share:/usr/share',
             'FALLBACK_CONFIG_DIRS=\\"%s\\"' % '/etc/xdg'
         ])
-    elif env['platform'] == "x11":
+    elif env['platform'] == "linuxbsd":
         env_thirdparty.AppendUnique(CPPDEFINES=[
             'VK_USE_PLATFORM_XLIB_KHR',
             'VULKAN_NON_CMAKE_BUILD',

+ 2 - 1
editor/debugger/editor_debugger_tree.cpp

@@ -33,6 +33,7 @@
 #include "editor/editor_node.h"
 #include "scene/debugger/scene_debugger.h"
 #include "scene/resources/packed_scene.h"
+#include "servers/display_server.h"
 
 EditorDebuggerTree::EditorDebuggerTree() {
 	set_v_size_flags(SIZE_EXPAND_FILL);
@@ -257,7 +258,7 @@ void EditorDebuggerTree::_item_menu_id_pressed(int p_option) {
 					text = text.substr(slash + 1);
 				}
 			}
-			OS::get_singleton()->set_clipboard(text);
+			DisplayServer::get_singleton()->clipboard_set(text);
 		} break;
 	}
 }

+ 5 - 4
editor/debugger/script_editor_debugger.cpp

@@ -58,6 +58,7 @@
 #include "scene/gui/texture_button.h"
 #include "scene/gui/tree.h"
 #include "scene/resources/packed_scene.h"
+#include "servers/display_server.h"
 
 using CameraOverride = EditorDebuggerNode::CameraOverride;
 
@@ -73,7 +74,7 @@ void ScriptEditorDebugger::_put_msg(String p_message, Array p_data) {
 void ScriptEditorDebugger::debug_copy() {
 	String msg = reason->get_text();
 	if (msg == "") return;
-	OS::get_singleton()->set_clipboard(msg);
+	DisplayServer::get_singleton()->clipboard_set(msg);
 }
 
 void ScriptEditorDebugger::debug_skip_breakpoints() {
@@ -116,7 +117,7 @@ void ScriptEditorDebugger::debug_continue() {
 
 	// Allow focus stealing only if we actually run this client for security.
 	if (remote_pid && EditorNode::get_singleton()->has_child_process(remote_pid))
-		OS::get_singleton()->enable_for_stealing_focus(remote_pid);
+		DisplayServer::get_singleton()->enable_for_stealing_focus(remote_pid);
 
 	_clear_execution();
 	_put_msg("continue", Array());
@@ -253,7 +254,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
 		_update_buttons_state();
 		_set_reason_text(error, MESSAGE_ERROR);
 		emit_signal("breaked", true, can_continue);
-		OS::get_singleton()->move_window_to_foreground();
+		DisplayServer::get_singleton()->window_move_to_foreground();
 		if (error != "") {
 			tabs->set_current_tab(0);
 		}
@@ -1420,7 +1421,7 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) {
 		ci = ci->get_next();
 	}
 
-	OS::get_singleton()->set_clipboard(text);
+	DisplayServer::get_singleton()->clipboard_set(text);
 }
 
 void ScriptEditorDebugger::_tab_changed(int p_tab) {

+ 2 - 1
editor/editor_dir_dialog.cpp

@@ -35,6 +35,7 @@
 #include "editor/editor_file_system.h"
 #include "editor/editor_settings.h"
 #include "editor_scale.h"
+#include "servers/display_server.h"
 
 void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p_dir, const String &p_select_path) {
 
@@ -188,7 +189,7 @@ EditorDirDialog::EditorDirDialog() {
 
 	tree->connect("item_activated", callable_mp(this, &EditorDirDialog::_item_activated));
 
-	makedir = add_button(TTR("Create Folder"), OS::get_singleton()->get_swap_ok_cancel(), "makedir");
+	makedir = add_button(TTR("Create Folder"), DisplayServer::get_singleton()->get_swap_ok_cancel(), "makedir");
 	makedir->connect("pressed", callable_mp(this, &EditorDirDialog::_make_dir));
 
 	makedialog = memnew(ConfirmationDialog);

+ 2 - 1
editor/editor_file_dialog.cpp

@@ -42,6 +42,7 @@
 #include "scene/gui/center_container.h"
 #include "scene/gui/label.h"
 #include "scene/gui/margin_container.h"
+#include "servers/display_server.h"
 
 EditorFileDialog::GetIconFunc EditorFileDialog::get_icon_func = NULL;
 EditorFileDialog::GetIconFunc EditorFileDialog::get_large_icon_func = NULL;
@@ -631,7 +632,7 @@ void EditorFileDialog::_item_menu_id_pressed(int p_option) {
 
 		case ITEM_MENU_COPY_PATH: {
 			Dictionary item_meta = item_list->get_item_metadata(item_list->get_current());
-			OS::get_singleton()->set_clipboard(item_meta["path"]);
+			DisplayServer::get_singleton()->clipboard_set(item_meta["path"]);
 		} break;
 
 		case ITEM_MENU_DELETE: {

+ 37 - 20
editor/editor_node.cpp

@@ -169,7 +169,7 @@
 #include "editor/register_exporters.h"
 #include "editor/run_settings_dialog.h"
 #include "editor/settings_config_dialog.h"
-
+#include "servers/display_server.h"
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -179,7 +179,9 @@ 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");
+	if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) {
+		DisplayServer::get_singleton()->global_menu_clear("_dock");
+	}
 
 	scene_tabs->clear_tabs();
 	Ref<Texture2D> script_icon = gui_base->get_icon("Script", "EditorIcons");
@@ -195,15 +197,19 @@ 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 (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) {
+			DisplayServer::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());
+	if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) {
+		DisplayServer::get_singleton()->global_menu_add_separator("_dock");
+		DisplayServer::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant());
+	}
 
 	scene_tabs->set_current_tab(editor_data.get_edited_scene());
 
@@ -252,7 +258,7 @@ void EditorNode::_update_title() {
 	if (unsaved_cache)
 		title += " (*)";
 
-	OS::get_singleton()->set_window_title(title);
+	DisplayServer::get_singleton()->window_set_title(title);
 }
 
 void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) {
@@ -2537,7 +2543,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
 					}
 				}
 
-				OS::get_singleton()->request_attention();
+				DisplayServer::get_singleton()->window_request_attention();
 				break;
 			}
 
@@ -2585,13 +2591,13 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
 		} break;
 		case SETTINGS_TOGGLE_FULLSCREEN: {
 
-			OS::get_singleton()->set_window_fullscreen(!OS::get_singleton()->is_window_fullscreen());
+			DisplayServer::get_singleton()->window_set_mode(DisplayServer::get_singleton()->window_get_mode() == DisplayServer::WINDOW_MODE_FULLSCREEN ? DisplayServer::WINDOW_MODE_WINDOWED : DisplayServer::WINDOW_MODE_FULLSCREEN);
 
 		} break;
 		case SETTINGS_TOGGLE_CONSOLE: {
 
-			bool was_visible = OS::get_singleton()->is_console_visible();
-			OS::get_singleton()->set_console_visible(!was_visible);
+			bool was_visible = DisplayServer::get_singleton()->is_console_visible();
+			DisplayServer::get_singleton()->console_set_visible(!was_visible);
 			EditorSettings::get_singleton()->set_setting("interface/editor/hide_console_window", was_visible);
 		} break;
 		case EDITOR_SCREENSHOT: {
@@ -3937,7 +3943,7 @@ void EditorNode::show_warning(const String &p_text, const String &p_title) {
 
 void EditorNode::_copy_warning(const String &p_str) {
 
-	OS::get_singleton()->set_clipboard(warning->get_text());
+	DisplayServer::get_singleton()->clipboard_set(warning->get_text());
 }
 
 void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) {
@@ -5286,7 +5292,7 @@ void EditorNode::_video_driver_selected(int p_which) {
 
 	String driver = video_driver->get_item_metadata(p_which);
 
-	String current = OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver());
+	String current = ""; //OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver());
 
 	if (driver == current) {
 		return;
@@ -5485,11 +5491,18 @@ EditorNode::EditorNode() {
 
 	if (id) {
 
-		if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) {
+		bool found_touchscreen = false;
+		for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) {
+			if (DisplayServer::get_singleton()->screen_is_touchscreen(i)) {
+				found_touchscreen = true;
+			}
+		}
+
+		if (!found_touchscreen && Input::get_singleton()) {
 			//only if no touchscreen ui hint, set emulation
 			id->set_emulate_touch_from_mouse(false); //just disable just in case
 		}
-		id->set_custom_mouse_cursor(RES());
+		DisplayServer::get_singleton()->cursor_set_custom_image(RES());
 	}
 
 	singleton = this;
@@ -5518,8 +5531,8 @@ EditorNode::EditorNode() {
 		switch (display_scale) {
 			case 0: {
 				// Try applying a suitable display scale automatically
-				const int screen = OS::get_singleton()->get_current_screen();
-				editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0);
+				const int screen = DisplayServer::get_singleton()->window_get_current_screen();
+				editor_set_scale(DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).x > 2000 ? 2.0 : 1.0);
 			} break;
 
 			case 1: {
@@ -5553,7 +5566,7 @@ EditorNode::EditorNode() {
 	}
 
 	// Define a minimum window size to prevent UI elements from overlapping or being cut off
-	OS::get_singleton()->set_min_window_size(Size2(1024, 600) * EDSCALE);
+	DisplayServer::get_singleton()->window_set_min_size(Size2(1024, 600) * EDSCALE);
 
 	ResourceLoader::set_abort_on_missing_resources(false);
 	FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files"));
@@ -6257,6 +6270,10 @@ EditorNode::EditorNode() {
 	video_driver->set_disabled(true);
 	right_menu_hb->add_child(video_driver);
 
+#ifndef _MSC_VER
+#warning neeeds to be reimplemented
+#endif
+#if 0
 	String video_drivers = ProjectSettings::get_singleton()->get_custom_property_info()["rendering/quality/driver/driver_name"].hint_string;
 	String current_video_driver = OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver());
 	video_driver_current = 0;
@@ -6272,7 +6289,7 @@ EditorNode::EditorNode() {
 	}
 
 	_update_video_driver_color();
-
+#endif
 	video_restart_dialog = memnew(ConfirmationDialog);
 	video_restart_dialog->set_text(TTR("Changing the video driver requires restarting the editor."));
 	video_restart_dialog->get_ok()->set_text(TTR("Save & Restart"));
@@ -6413,7 +6430,7 @@ EditorNode::EditorNode() {
 	confirmation->connect("confirmed", callable_mp(this, &EditorNode::_menu_confirm_current));
 
 	save_confirmation = memnew(ConfirmationDialog);
-	save_confirmation->add_button(TTR("Don't Save"), OS::get_singleton()->get_swap_ok_cancel(), "discard");
+	save_confirmation->add_button(TTR("Don't Save"), DisplayServer::get_singleton()->get_swap_ok_cancel(), "discard");
 	gui_base->add_child(save_confirmation);
 	save_confirmation->connect("confirmed", callable_mp(this, &EditorNode::_menu_confirm_current));
 	save_confirmation->connect("custom_action", callable_mp(this, &EditorNode::_discard_changes));
@@ -6624,7 +6641,7 @@ EditorNode::EditorNode() {
 
 	open_imported = memnew(ConfirmationDialog);
 	open_imported->get_ok()->set_text(TTR("Open Anyway"));
-	new_inherited_button = open_imported->add_button(TTR("New Inherited"), !OS::get_singleton()->get_swap_ok_cancel(), "inherit");
+	new_inherited_button = open_imported->add_button(TTR("New Inherited"), !DisplayServer::get_singleton()->get_swap_ok_cancel(), "inherit");
 	open_imported->connect("confirmed", callable_mp(this, &EditorNode::_open_imported));
 	open_imported->connect("custom_action", callable_mp(this, &EditorNode::_inherit_imported));
 	gui_base->add_child(open_imported);

+ 8 - 7
editor/editor_run.cpp

@@ -32,6 +32,7 @@
 
 #include "core/project_settings.h"
 #include "editor_settings.h"
+#include "servers/display_server.h"
 
 EditorRun::Status EditorRun::get_status() const {
 
@@ -70,19 +71,19 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L
 	int screen = EditorSettings::get_singleton()->get("run/window_placement/screen");
 	if (screen == 0) {
 		// Same as editor
-		screen = OS::get_singleton()->get_current_screen();
+		screen = DisplayServer::get_singleton()->window_get_current_screen();
 	} else if (screen == 1) {
 		// Previous monitor (wrap to the other end if needed)
 		screen = Math::wrapi(
-				OS::get_singleton()->get_current_screen() - 1,
+				DisplayServer::get_singleton()->window_get_current_screen() - 1,
 				0,
-				OS::get_singleton()->get_screen_count());
+				DisplayServer::get_singleton()->get_screen_count());
 	} else if (screen == 2) {
 		// Next monitor (wrap to the other end if needed)
 		screen = Math::wrapi(
-				OS::get_singleton()->get_current_screen() + 1,
+				DisplayServer::get_singleton()->window_get_current_screen() + 1,
 				0,
-				OS::get_singleton()->get_screen_count());
+				DisplayServer::get_singleton()->get_screen_count());
 	} else {
 		// Fixed monitor ID
 		// There are 3 special options, so decrement the option ID by 3 to get the monitor ID
@@ -94,8 +95,8 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L
 	}
 
 	Rect2 screen_rect;
-	screen_rect.position = OS::get_singleton()->get_screen_position(screen);
-	screen_rect.size = OS::get_singleton()->get_screen_size(screen);
+	screen_rect.position = DisplayServer::get_singleton()->screen_get_position(screen);
+	screen_rect.size = DisplayServer::get_singleton()->screen_get_size(screen);
 
 	Size2 desired_size;
 	desired_size.x = ProjectSettings::get_singleton()->get("display/window/size/width");

+ 1 - 1
editor/editor_settings.cpp

@@ -599,7 +599,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 	_initial_set("run/window_placement/rect", 1);
 	hints["run/window_placement/rect"] = PropertyInfo(Variant::INT, "run/window_placement/rect", PROPERTY_HINT_ENUM, "Top Left,Centered,Custom Position,Force Maximized,Force Fullscreen");
 	String screen_hints = "Same as Editor,Previous Monitor,Next Monitor";
-	for (int i = 0; i < OS::get_singleton()->get_screen_count(); i++) {
+	for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) {
 		screen_hints += ",Monitor " + itos(i + 1);
 	}
 	_initial_set("run/window_placement/rect_custom_position", Vector2());

+ 2 - 1
editor/filesystem_dock.cpp

@@ -44,6 +44,7 @@
 #include "import_dock.h"
 #include "scene/main/viewport.h"
 #include "scene/resources/packed_scene.h"
+#include "servers/display_server.h"
 
 Ref<Texture2D> FileSystemDock::_get_tree_item_icon(EditorFileSystemDirectory *p_dir, int p_idx) {
 	Ref<Texture2D> file_icon;
@@ -1765,7 +1766,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
 		case FILE_COPY_PATH: {
 			if (!p_selected.empty()) {
 				String fpath = p_selected[0];
-				OS::get_singleton()->set_clipboard(fpath);
+				DisplayServer::get_singleton()->clipboard_set(fpath);
 			}
 		} break;
 

+ 4 - 3
editor/plugins/script_editor_plugin.cpp

@@ -48,6 +48,7 @@
 #include "scene/main/viewport.h"
 #include "scene/scene_string_names.h"
 #include "script_text_editor.h"
+#include "servers/display_server.h"
 #include "text_editor.h"
 
 /*** SCRIPT EDITOR ****/
@@ -651,7 +652,7 @@ void ScriptEditor::_close_docs_tab() {
 void ScriptEditor::_copy_script_path() {
 	ScriptEditorBase *se = _get_current_editor();
 	RES script = se->get_edited_resource();
-	OS::get_singleton()->set_clipboard(script->get_path());
+	DisplayServer::get_singleton()->clipboard_set(script->get_path());
 }
 
 void ScriptEditor::_close_other_tabs() {
@@ -3291,7 +3292,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
 
 	erase_tab_confirm = memnew(ConfirmationDialog);
 	erase_tab_confirm->get_ok()->set_text(TTR("Save"));
-	erase_tab_confirm->add_button(TTR("Discard"), OS::get_singleton()->get_swap_ok_cancel(), "discard");
+	erase_tab_confirm->add_button(TTR("Discard"), DisplayServer::get_singleton()->get_swap_ok_cancel(), "discard");
 	erase_tab_confirm->connect("confirmed", callable_mp(this, &ScriptEditor::_close_current_tab));
 	erase_tab_confirm->connect("custom_action", callable_mp(this, &ScriptEditor::_close_discard_current_tab));
 	add_child(erase_tab_confirm);
@@ -3325,7 +3326,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
 		disk_changed->connect("confirmed", callable_mp(this, &ScriptEditor::_reload_scripts));
 		disk_changed->get_ok()->set_text(TTR("Reload"));
 
-		disk_changed->add_button(TTR("Resave"), !OS::get_singleton()->get_swap_ok_cancel(), "resave");
+		disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_ok_cancel(), "resave");
 		disk_changed->connect("custom_action", callable_mp(this, &ScriptEditor::_resave_scripts));
 	}
 

+ 2 - 1
editor/plugins/shader_editor_plugin.cpp

@@ -38,6 +38,7 @@
 #include "editor/editor_scale.h"
 #include "editor/editor_settings.h"
 #include "editor/property_editor.h"
+#include "servers/display_server.h"
 #include "servers/visual/shader_types.h"
 
 /*** SHADER SCRIPT EDITOR ****/
@@ -699,7 +700,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
 	disk_changed->connect("confirmed", callable_mp(this, &ShaderEditor::_reload_shader_from_disk));
 	disk_changed->get_ok()->set_text(TTR("Reload"));
 
-	disk_changed->add_button(TTR("Resave"), !OS::get_singleton()->get_swap_ok_cancel(), "resave");
+	disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_ok_cancel(), "resave");
 	disk_changed->connect("custom_action", callable_mp(this, &ShaderEditor::save_external_data));
 
 	add_child(disk_changed);

+ 8 - 4
editor/plugins/spatial_editor_plugin.cpp

@@ -51,6 +51,7 @@
 #include "scene/gui/viewport_container.h"
 #include "scene/resources/packed_scene.h"
 #include "scene/resources/surface_tool.h"
+#include "servers/display_server.h"
 
 #define DISTANCE_DEFAULT 4
 
@@ -2213,14 +2214,14 @@ void SpatialEditorViewport::set_freelook_active(bool active_now) {
 		}
 
 		// Hide mouse like in an FPS (warping doesn't work)
-		OS::get_singleton()->set_mouse_mode(OS::MOUSE_MODE_CAPTURED);
+		DisplayServer::get_singleton()->mouse_set_mode(DisplayServer::MOUSE_MODE_CAPTURED);
 
 	} else if (freelook_active && !active_now) {
 		// Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential
 		cursor = camera_cursor;
 
 		// Restore mouse
-		OS::get_singleton()->set_mouse_mode(OS::MOUSE_MODE_VISIBLE);
+		DisplayServer::get_singleton()->mouse_set_mode(DisplayServer::MOUSE_MODE_VISIBLE);
 	}
 
 	freelook_active = active_now;
@@ -3926,8 +3927,11 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
 	view_menu->get_popup()->connect("id_pressed", callable_mp(this, &SpatialEditorViewport::_menu_option));
 	display_submenu->connect("id_pressed", callable_mp(this, &SpatialEditorViewport::_menu_option));
 	view_menu->set_disable_shortcuts(true);
-
-	if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
+#ifndef _MSC_VER
+#warning this needs to be fixed
+#endif
+	//if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
+	if (false) {
 		// Alternate display modes only work when using the Vulkan renderer; make this explicit.
 		const int normal_idx = view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL);
 		const int wireframe_idx = view_menu->get_popup()->get_item_index(VIEW_DISPLAY_WIREFRAME);

+ 2 - 1
editor/plugins/visual_shader_editor_plugin.cpp

@@ -44,6 +44,7 @@
 #include "scene/gui/panel.h"
 #include "scene/main/viewport.h"
 #include "scene/resources/visual_shader_nodes.h"
+#include "servers/display_server.h"
 #include "servers/visual/shader_types.h"
 
 Control *VisualShaderNodePlugin::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) {
@@ -1646,7 +1647,7 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) {
 	}
 
 	// keep dialog within window bounds
-	Size2 window_size = OS::get_singleton()->get_window_size();
+	Size2 window_size = DisplayServer::get_singleton()->window_get_size();
 	Rect2 dialog_rect = members_dialog->get_global_rect();
 	if (dialog_rect.position.y + dialog_rect.size.y > window_size.y) {
 		int difference = dialog_rect.position.y + dialog_rect.size.y - window_size.y;

+ 2 - 1
editor/progress_dialog.cpp

@@ -34,6 +34,7 @@
 #include "core/os/os.h"
 #include "editor_scale.h"
 #include "main/main.h"
+#include "servers/display_server.h"
 
 void BackgroundProgress::_add_task(const String &p_task, const String &p_label, int p_steps) {
 
@@ -219,7 +220,7 @@ bool ProgressDialog::task_step(const String &p_task, const String &p_state, int
 	t.state->set_text(p_state);
 	last_progress_tick = OS::get_singleton()->get_ticks_usec();
 	if (cancel_hb->is_visible()) {
-		OS::get_singleton()->force_process_input();
+		DisplayServer::get_singleton()->process_events();
 	}
 
 	Main::iteration(); // this will not work on a lot of platforms, so it's only meant for the editor

+ 3 - 2
editor/project_export.cpp

@@ -46,6 +46,7 @@
 #include "scene/gui/margin_container.h"
 #include "scene/gui/scroll_container.h"
 #include "scene/gui/tab_container.h"
+#include "servers/display_server.h"
 
 void ProjectExportDialog::_notification(int p_what) {
 
@@ -1250,7 +1251,7 @@ ProjectExportDialog::ProjectExportDialog() {
 
 	get_cancel()->set_text(TTR("Close"));
 	get_ok()->set_text(TTR("Export PCK/Zip"));
-	export_button = add_button(TTR("Export Project"), !OS::get_singleton()->get_swap_ok_cancel(), "export");
+	export_button = add_button(TTR("Export Project"), !DisplayServer::get_singleton()->get_swap_ok_cancel(), "export");
 	export_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_project));
 	// Disable initially before we select a valid preset
 	export_button->set_disabled(true);
@@ -1265,7 +1266,7 @@ ProjectExportDialog::ProjectExportDialog() {
 	export_all_dialog->add_button(TTR("Release"), true, "release");
 	export_all_dialog->connect("custom_action", callable_mp(this, &ProjectExportDialog::_export_all_dialog_action));
 
-	export_all_button = add_button(TTR("Export All"), !OS::get_singleton()->get_swap_ok_cancel(), "export");
+	export_all_button = add_button(TTR("Export All"), !DisplayServer::get_singleton()->get_swap_ok_cancel(), "export");
 	export_all_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_all_dialog));
 	export_all_button->set_disabled(true);
 

+ 15 - 10
editor/project_manager.cpp

@@ -51,6 +51,7 @@
 #include "scene/gui/separator.h"
 #include "scene/gui/texture_rect.h"
 #include "scene/gui/tool_button.h"
+#include "servers/display_server.h"
 
 static inline String get_project_key_from_path(const String &dir) {
 	return dir.replace("/", "::");
@@ -1284,7 +1285,11 @@ void ProjectList::load_projects() {
 }
 
 void ProjectList::update_dock_menu() {
-	OS::get_singleton()->global_menu_clear("_dock");
+
+	if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) {
+		return;
+	}
+	DisplayServer::get_singleton()->global_menu_clear("_dock");
 
 	int favs_added = 0;
 	int total_added = 0;
@@ -1294,18 +1299,18 @@ void ProjectList::update_dock_menu() {
 				favs_added++;
 			} else {
 				if (favs_added != 0) {
-					OS::get_singleton()->global_menu_add_separator("_dock");
+					DisplayServer::get_singleton()->global_menu_add_separator("_dock");
 				}
 				favs_added = 0;
 			}
-			OS::get_singleton()->global_menu_add_item("_dock", _projects[i].project_name + " ( " + _projects[i].path + " )", GLOBAL_OPEN_PROJECT, Variant(_projects[i].path.plus_file("project.godot")));
+			DisplayServer::get_singleton()->global_menu_add_item("_dock", _projects[i].project_name + " ( " + _projects[i].path + " )", GLOBAL_OPEN_PROJECT, Variant(_projects[i].path.plus_file("project.godot")));
 			total_added++;
 		}
 	}
 	if (total_added != 0) {
-		OS::get_singleton()->global_menu_add_separator("_dock");
+		DisplayServer::get_singleton()->global_menu_add_separator("_dock");
 	}
-	OS::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant());
+	DisplayServer::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant());
 }
 
 void ProjectList::create_project_item_control(int p_index) {
@@ -2413,8 +2418,8 @@ ProjectManager::ProjectManager() {
 		switch (display_scale) {
 			case 0: {
 				// Try applying a suitable display scale automatically
-				const int screen = OS::get_singleton()->get_current_screen();
-				editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0);
+				const int screen = DisplayServer::get_singleton()->window_get_current_screen();
+				editor_set_scale(DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).x > 2000 ? 2.0 : 1.0);
 			} break;
 
 			case 1: editor_set_scale(0.75); break;
@@ -2430,12 +2435,12 @@ ProjectManager::ProjectManager() {
 		}
 
 		// Define a minimum window size to prevent UI elements from overlapping or being cut off
-		OS::get_singleton()->set_min_window_size(Size2(750, 420) * EDSCALE);
+		DisplayServer::get_singleton()->window_set_min_size(Size2(750, 420) * EDSCALE);
 
 #ifndef OSX_ENABLED
 		// The macOS platform implementation uses its own hiDPI window resizing code
 		// TODO: Resize windows on hiDPI displays on Windows and Linux and remove the line below
-		OS::get_singleton()->set_window_size(OS::get_singleton()->get_window_size() * MAX(1, EDSCALE));
+		DisplayServer::get_singleton()->window_set_size(DisplayServer::get_singleton()->window_get_size() * MAX(1, EDSCALE));
 #endif
 	}
 
@@ -2459,7 +2464,7 @@ ProjectManager::ProjectManager() {
 
 	String cp;
 	cp += 0xA9;
-	OS::get_singleton()->set_window_title(VERSION_NAME + String(" - ") + TTR("Project Manager") + " - " + cp + " 2007-2020 Juan Linietsky, Ariel Manzur & Godot Contributors");
+	DisplayServer::get_singleton()->window_set_title(VERSION_NAME + String(" - ") + TTR("Project Manager") + " - " + cp + " 2007-2020 Juan Linietsky, Ariel Manzur & Godot Contributors");
 
 	Control *center_box = memnew(Control);
 	center_box->set_v_size_flags(SIZE_EXPAND_FILL);

+ 3 - 1
editor/scene_tree_dock.cpp

@@ -46,6 +46,8 @@
 #include "editor/plugins/spatial_editor_plugin.h"
 #include "scene/main/viewport.h"
 #include "scene/resources/packed_scene.h"
+#include "servers/display_server.h"
+#include "servers/visual_server.h"
 
 void SceneTreeDock::_nodes_drag_begin() {
 
@@ -822,7 +824,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
 				if (node) {
 					Node *root = EditorNode::get_singleton()->get_edited_scene();
 					NodePath path = root->get_path().rel_path_to(node->get_path());
-					OS::get_singleton()->set_clipboard(path);
+					DisplayServer::get_singleton()->clipboard_set(path);
 				}
 			}
 		} break;

+ 183 - 84
main/main.cpp

@@ -64,11 +64,14 @@
 #include "servers/arvr_server.h"
 #include "servers/audio_server.h"
 #include "servers/camera_server.h"
+#include "servers/display_server.h"
 #include "servers/navigation_2d_server.h"
 #include "servers/navigation_server.h"
 #include "servers/physics_2d_server.h"
 #include "servers/physics_server.h"
 #include "servers/register_server_types.h"
+#include "servers/visual/visual_server_raster.h"
+#include "servers/visual/visual_server_wrap_mt.h"
 
 #ifdef TOOLS_ENABLED
 #include "editor/doc_data.h"
@@ -86,6 +89,7 @@
 // Initialized in setup()
 static Engine *engine = NULL;
 static ProjectSettings *globals = NULL;
+static Input *input = NULL;
 static InputMap *input_map = NULL;
 static TranslationServer *translation_server = NULL;
 static Performance *performance = NULL;
@@ -98,6 +102,8 @@ static MessageQueue *message_queue = NULL;
 
 // Initialized in setup2()
 static AudioServer *audio_server = NULL;
+static DisplayServer *display_server = NULL;
+static VisualServer *visual_server = NULL;
 static CameraServer *camera_server = NULL;
 static ARVRServer *arvr_server = NULL;
 static PhysicsServer *physics_server = NULL;
@@ -109,7 +115,7 @@ static bool _start_success = false;
 
 // Drivers
 
-static int video_driver_idx = -1;
+static int display_driver_idx = -1;
 static int audio_driver_idx = -1;
 
 // Engine config/tools
@@ -126,7 +132,12 @@ static bool auto_build_solutions = false;
 
 // Display
 
-static OS::VideoMode video_mode;
+static DisplayServer::WindowMode window_mode = DisplayServer::WINDOW_MODE_WINDOWED;
+static DisplayServer::ScreenOrientation window_orientation = DisplayServer::SCREEN_LANDSCAPE;
+static uint32_t window_flags = 0;
+static Size2i window_size = Size2i(1024, 600);
+static bool window_vsync_via_compositor = false;
+
 static int init_screen = -1;
 static bool init_fullscreen = false;
 static bool init_maximized = false;
@@ -191,6 +202,7 @@ void initialize_physics() {
 }
 
 void finalize_physics() {
+
 	physics_server->finish();
 	memdelete(physics_server);
 
@@ -198,6 +210,14 @@ void finalize_physics() {
 	memdelete(physics_2d_server);
 }
 
+void finalize_display() {
+
+	visual_server->finish();
+	memdelete(visual_server);
+
+	memdelete(display_server);
+}
+
 void initialize_navigation_server() {
 	ERR_FAIL_COND(navigation_server != NULL);
 
@@ -251,20 +271,25 @@ void Main::print_help(const char *p_binary) {
 	OS::get_singleton()->print("  --remote-fs <address>            Remote filesystem (<host/IP>[:<port>] address).\n");
 	OS::get_singleton()->print("  --remote-fs-password <password>  Password for remote filesystem.\n");
 	OS::get_singleton()->print("  --audio-driver <driver>          Audio driver (");
-	for (int i = 0; i < OS::get_singleton()->get_audio_driver_count(); i++) {
+	for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
 		if (i != 0)
 			OS::get_singleton()->print(", ");
-		OS::get_singleton()->print("'%s'", OS::get_singleton()->get_audio_driver_name(i));
+		OS::get_singleton()->print("'%s'", AudioDriverManager::get_driver(i)->get_name());
 	}
 	OS::get_singleton()->print(").\n");
-	OS::get_singleton()->print("  --video-driver <driver>          Video driver (");
-	for (int i = 0; i < OS::get_singleton()->get_video_driver_count(); i++) {
-		if (i != 0)
-			OS::get_singleton()->print(", ");
-		OS::get_singleton()->print("'%s'", OS::get_singleton()->get_video_driver_name(i));
+	OS::get_singleton()->print("  --display-driver <driver>          Display driver (and rendering driver):\n");
+	for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
+		OS::get_singleton()->print("\t\t'%s' (", DisplayServer::get_create_function_name(i));
+		Vector<String> rd = DisplayServer::get_create_function_rendering_drivers(i);
+		for (int j = 0; j < rd.size(); j++) {
+			if (j > 0) {
+				OS::get_singleton()->print(", ");
+			}
+			OS::get_singleton()->print("'%s'", rd[j].utf8().get_data());
+		}
+		OS::get_singleton()->print(")\n");
 	}
-	OS::get_singleton()->print(").\n");
-	OS::get_singleton()->print("\n");
+	OS::get_singleton()->print("  --rendering-driver <driver>          Rendering driver (depends on display driver).\n");
 
 #ifndef SERVER_ENABLED
 	OS::get_singleton()->print("Display options:\n");
@@ -353,7 +378,7 @@ void Main::print_help(const char *p_binary) {
 
 Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_phase) {
 
-	OS::get_singleton()->initialize_core();
+	OS::get_singleton()->initialize();
 
 	engine = memnew(Engine);
 
@@ -403,7 +428,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 
 	I = args.front();
 
-	String video_driver = "";
+	String display_driver = "";
 	String audio_driver = "";
 	String project_path = ".";
 	bool upwards = false;
@@ -423,6 +448,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 #ifdef TOOLS_ENABLED
 	bool found_project = false;
 #endif
+	bool use_vsync = false;
 
 	packed_data = PackedData::get_singleton();
 	if (!packed_data)
@@ -469,8 +495,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 				audio_driver = I->next()->get();
 
 				bool found = false;
-				for (int i = 0; i < OS::get_singleton()->get_audio_driver_count(); i++) {
-					if (audio_driver == OS::get_singleton()->get_audio_driver_name(i)) {
+				for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
+					if (audio_driver == AudioDriverManager::get_driver(i)->get_name()) {
 						found = true;
 					}
 				}
@@ -478,14 +504,14 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 				if (!found) {
 					OS::get_singleton()->print("Unknown audio driver '%s', aborting.\nValid options are ", audio_driver.utf8().get_data());
 
-					for (int i = 0; i < OS::get_singleton()->get_audio_driver_count(); i++) {
-						if (i == OS::get_singleton()->get_audio_driver_count() - 1) {
+					for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
+						if (i == AudioDriverManager::get_driver_count() - 1) {
 							OS::get_singleton()->print(" and ");
 						} else if (i != 0) {
 							OS::get_singleton()->print(", ");
 						}
 
-						OS::get_singleton()->print("'%s'", OS::get_singleton()->get_audio_driver_name(i));
+						OS::get_singleton()->print("'%s'", AudioDriverManager::get_driver(i)->get_name());
 					}
 
 					OS::get_singleton()->print(".\n");
@@ -499,30 +525,30 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 				goto error;
 			}
 
-		} else if (I->get() == "--video-driver") { // force video driver
+		} else if (I->get() == "--display-driver") { // force video driver
 
 			if (I->next()) {
 
-				video_driver = I->next()->get();
+				display_driver = I->next()->get();
 
 				bool found = false;
-				for (int i = 0; i < OS::get_singleton()->get_video_driver_count(); i++) {
-					if (video_driver == OS::get_singleton()->get_video_driver_name(i)) {
+				for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
+					if (display_driver == DisplayServer::get_create_function_name(i)) {
 						found = true;
 					}
 				}
 
 				if (!found) {
-					OS::get_singleton()->print("Unknown video driver '%s', aborting.\nValid options are ", video_driver.utf8().get_data());
+					OS::get_singleton()->print("Unknown display driver '%s', aborting.\nValid options are ", display_driver.utf8().get_data());
 
-					for (int i = 0; i < OS::get_singleton()->get_video_driver_count(); i++) {
-						if (i == OS::get_singleton()->get_video_driver_count() - 1) {
+					for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
+						if (i == DisplayServer::get_create_function_count() - 1) {
 							OS::get_singleton()->print(" and ");
 						} else if (i != 0) {
 							OS::get_singleton()->print(", ");
 						}
 
-						OS::get_singleton()->print("'%s'", OS::get_singleton()->get_video_driver_name(i));
+						OS::get_singleton()->print("'%s'", DisplayServer::get_create_function_name(i));
 					}
 
 					OS::get_singleton()->print(".\n");
@@ -542,7 +568,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 		} else if (I->get() == "-m" || I->get() == "--maximized") { // force maximized window
 
 			init_maximized = true;
-			video_mode.maximized = true;
+			window_mode = DisplayServer::WINDOW_MODE_MAXIMIZED;
 
 		} else if (I->get() == "-w" || I->get() == "--windowed") { // force windowed window
 
@@ -574,8 +600,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 					goto error;
 				}
 
-				video_mode.width = w;
-				video_mode.height = h;
+				window_size.width = w;
+				window_size.height = h;
 				force_res = true;
 
 				N = I->next()->next();
@@ -616,11 +642,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 			OS::get_singleton()->set_no_window_mode(true);
 		} else if (I->get() == "--enable-vsync-via-compositor") {
 
-			video_mode.vsync_via_compositor = true;
+			window_vsync_via_compositor = true;
 			saw_vsync_via_compositor_override = true;
 		} else if (I->get() == "--disable-vsync-via-compositor") {
 
-			video_mode.vsync_via_compositor = false;
+			window_vsync_via_compositor = false;
 			saw_vsync_via_compositor_override = true;
 #endif
 		} else if (I->get() == "--profiling") { // enable profiling
@@ -917,7 +943,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 		main_args.push_back("--editor");
 		if (!init_windowed) {
 			init_maximized = true;
-			video_mode.maximized = true;
+			window_mode = DisplayServer::WINDOW_MODE_MAXIMIZED;
 		}
 	}
 
@@ -960,8 +986,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 
 	GLOBAL_DEF("rendering/quality/driver/driver_name", "Vulkan");
 	ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/driver/driver_name", PropertyInfo(Variant::STRING, "rendering/quality/driver/driver_name", PROPERTY_HINT_ENUM, "Vulkan,GLES2"));
-	if (video_driver == "") {
-		video_driver = GLOBAL_GET("rendering/quality/driver/driver_name");
+	if (display_driver == "") {
+		display_driver = GLOBAL_GET("rendering/quality/driver/driver_name");
 	}
 
 	// Assigning here even though it's GLES2-specific, to be sure that it appears in docs
@@ -983,48 +1009,58 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 	if (use_custom_res) {
 
 		if (!force_res) {
-			video_mode.width = GLOBAL_GET("display/window/size/width");
-			video_mode.height = GLOBAL_GET("display/window/size/height");
+			window_size.width = GLOBAL_GET("display/window/size/width");
+			window_size.height = GLOBAL_GET("display/window/size/height");
 
 			if (globals->has_setting("display/window/size/test_width") && globals->has_setting("display/window/size/test_height")) {
 
 				int tw = globals->get("display/window/size/test_width");
 				if (tw > 0) {
-					video_mode.width = tw;
+					window_size.width = tw;
 				}
 				int th = globals->get("display/window/size/test_height");
 				if (th > 0) {
-					video_mode.height = th;
+					window_size.height = th;
 				}
 			}
 		}
 
-		video_mode.resizable = GLOBAL_GET("display/window/size/resizable");
-		video_mode.borderless_window = GLOBAL_GET("display/window/size/borderless");
-		video_mode.fullscreen = GLOBAL_GET("display/window/size/fullscreen");
-		video_mode.always_on_top = GLOBAL_GET("display/window/size/always_on_top");
+		if (!bool(GLOBAL_GET("display/window/size/resizable"))) {
+			window_flags |= DisplayServer::WINDOW_FLAG_RESIZE_DISABLED_BIT;
+		}
+		if (bool(GLOBAL_GET("display/window/size/borderless"))) {
+			window_flags |= DisplayServer::WINDOW_FLAG_BORDERLESS_BIT;
+		}
+		if (bool(GLOBAL_GET("display/window/size/fullscreen"))) {
+			window_mode = DisplayServer::WINDOW_MODE_FULLSCREEN;
+		}
+
+		if (bool(GLOBAL_GET("display/window/size/always_on_top"))) {
+			window_flags |= DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP;
+		}
 	}
 
 	if (!force_lowdpi) {
 		OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false);
 	}
 
-	video_mode.use_vsync = GLOBAL_DEF_RST("display/window/vsync/use_vsync", true);
-	OS::get_singleton()->_use_vsync = video_mode.use_vsync;
+	use_vsync = GLOBAL_DEF_RST("display/window/vsync/use_vsync", true);
+	OS::get_singleton()->_use_vsync = use_vsync;
 
 	if (!saw_vsync_via_compositor_override) {
 		// If one of the command line options to enable/disable vsync via the
 		// window compositor ("--enable-vsync-via-compositor" or
 		// "--disable-vsync-via-compositor") was present then it overrides the
 		// project setting.
-		video_mode.vsync_via_compositor = GLOBAL_DEF("display/window/vsync/vsync_via_compositor", false);
+		window_vsync_via_compositor = GLOBAL_DEF("display/window/vsync/vsync_via_compositor", false);
 	}
 
-	OS::get_singleton()->_vsync_via_compositor = video_mode.vsync_via_compositor;
+	OS::get_singleton()->_vsync_via_compositor = window_vsync_via_compositor;
 
+	/* todo restore
 	OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false);
 	video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false);
-
+*/
 	GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation", 2);
 	GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation.mobile", 3);
 
@@ -1049,26 +1085,26 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 
 	/* Determine audio and video drivers */
 
-	for (int i = 0; i < OS::get_singleton()->get_video_driver_count(); i++) {
+	for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
 
-		if (video_driver == OS::get_singleton()->get_video_driver_name(i)) {
+		if (display_driver == DisplayServer::get_create_function_name(i)) {
 
-			video_driver_idx = i;
+			display_driver_idx = i;
 			break;
 		}
 	}
 
-	if (video_driver_idx < 0) {
-		video_driver_idx = 0;
+	if (display_driver_idx < 0) {
+		display_driver_idx = 0;
 	}
 
 	if (audio_driver == "") { // specified in project.godot
-		audio_driver = GLOBAL_DEF_RST("audio/driver", OS::get_singleton()->get_audio_driver_name(0));
+		audio_driver = GLOBAL_DEF_RST("audio/driver", AudioDriverManager::get_driver(0)->get_name());
 	}
 
-	for (int i = 0; i < OS::get_singleton()->get_audio_driver_count(); i++) {
+	for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
 
-		if (audio_driver == OS::get_singleton()->get_audio_driver_name(i)) {
+		if (audio_driver == AudioDriverManager::get_driver(i)->get_name()) {
 
 			audio_driver_idx = i;
 			break;
@@ -1083,19 +1119,19 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 		String orientation = GLOBAL_DEF("display/window/handheld/orientation", "landscape");
 
 		if (orientation == "portrait")
-			OS::get_singleton()->set_screen_orientation(OS::SCREEN_PORTRAIT);
+			window_orientation = DisplayServer::SCREEN_PORTRAIT;
 		else if (orientation == "reverse_landscape")
-			OS::get_singleton()->set_screen_orientation(OS::SCREEN_REVERSE_LANDSCAPE);
+			window_orientation = DisplayServer::SCREEN_REVERSE_LANDSCAPE;
 		else if (orientation == "reverse_portrait")
-			OS::get_singleton()->set_screen_orientation(OS::SCREEN_REVERSE_PORTRAIT);
+			window_orientation = DisplayServer::SCREEN_REVERSE_PORTRAIT;
 		else if (orientation == "sensor_landscape")
-			OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR_LANDSCAPE);
+			window_orientation = DisplayServer::SCREEN_SENSOR_LANDSCAPE;
 		else if (orientation == "sensor_portrait")
-			OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR_PORTRAIT);
+			window_orientation = DisplayServer::SCREEN_SENSOR_PORTRAIT;
 		else if (orientation == "sensor")
-			OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR);
+			window_orientation = DisplayServer::SCREEN_SENSOR;
 		else
-			OS::get_singleton()->set_screen_orientation(OS::SCREEN_LANDSCAPE);
+			window_orientation = DisplayServer::SCREEN_LANDSCAPE;
 	}
 
 	Engine::get_singleton()->set_iterations_per_second(GLOBAL_DEF("physics/common/physics_fps", 60));
@@ -1131,7 +1167,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 
 error:
 
-	video_driver = "";
+	display_driver = "";
 	audio_driver = "";
 	project_path = "";
 
@@ -1183,15 +1219,64 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
 		Thread::_main_thread_id = p_main_tid_override;
 	}
 
-	Error err = OS::get_singleton()->initialize(video_mode, video_driver_idx, audio_driver_idx);
-	if (err != OK) {
-		return err;
+	/* Initialize user data dir */
+
+	OS::get_singleton()->ensure_user_data_dir();
+
+	/* Initialize Input */
+
+	input = memnew(Input);
+
+	/* Iniitalize Display Server */
+
+	{
+
+		String rendering_driver; // temp broken
+
+		Error err;
+		display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_flags, window_size, err);
+		if (err != OK) {
+			//ok i guess we can't use this display server, try other ones
+			for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
+				if (i == display_driver_idx) {
+					continue; //don't try the same twice
+				}
+				display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_flags, window_size, err);
+				if (err == OK) {
+					break;
+				}
+			}
+		}
+
+		if (!display_server) {
+			ERR_PRINT("Unable to create DisplayServer, all display drivers failed.");
+			return err;
+		}
+	}
+
+	if (display_server->has_feature(DisplayServer::FEATURE_ORIENTATION)) {
+		display_server->screen_set_orientation(window_orientation);
 	}
 
+	/* Initialize Visual Server */
+
+	visual_server = memnew(VisualServerRaster);
+	if (OS::get_singleton()->get_render_thread_mode() != OS::RENDER_THREAD_UNSAFE) {
+		visual_server = memnew(VisualServerWrapMT(visual_server, OS::get_singleton()->get_render_thread_mode() == OS::RENDER_SEPARATE_THREAD));
+	}
+
+	visual_server->init();
+
+	OS::get_singleton()->initialize_joypads();
+
+	/* Initialize Audio Driver */
+
+	AudioDriverManager::initialize(audio_driver_idx);
+
 	print_line(" "); //add a blank line for readability
 
 	if (init_use_custom_pos) {
-		OS::get_singleton()->set_window_position(init_custom_pos);
+		display_server->window_set_position(init_custom_pos);
 	}
 
 	// right moment to create and initialize the audio server
@@ -1213,21 +1298,21 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
 #endif
 
 	if (init_screen != -1) {
-		OS::get_singleton()->set_current_screen(init_screen);
+		DisplayServer::get_singleton()->window_set_current_screen(init_screen);
 	}
 	if (init_windowed) {
 		//do none..
 	} else if (init_maximized) {
-		OS::get_singleton()->set_window_maximized(true);
+		DisplayServer::get_singleton()->window_set_mode(DisplayServer::WINDOW_MODE_MAXIMIZED);
 	} else if (init_fullscreen) {
-		OS::get_singleton()->set_window_fullscreen(true);
+		DisplayServer::get_singleton()->window_set_mode(DisplayServer::WINDOW_MODE_FULLSCREEN);
 	}
 	if (init_always_on_top) {
-		OS::get_singleton()->set_window_always_on_top(true);
+		DisplayServer::get_singleton()->window_set_flag(DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP, true);
 	}
 
 	if (allow_focus_steal_pid) {
-		OS::get_singleton()->enable_for_stealing_focus(allow_focus_steal_pid);
+		DisplayServer::get_singleton()->enable_for_stealing_focus(allow_focus_steal_pid);
 	}
 
 	register_server_types();
@@ -1277,7 +1362,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
 
 #ifdef TOOLS_ENABLED
 		Ref<Image> icon = memnew(Image(app_icon_png));
-		OS::get_singleton()->set_icon(icon);
+		DisplayServer::get_singleton()->set_icon(icon);
 #endif
 	}
 
@@ -1297,7 +1382,14 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
 	Input *id = Input::get_singleton();
 	if (id) {
 		if (bool(GLOBAL_DEF("input_devices/pointing/emulate_touch_from_mouse", false)) && !(editor || project_manager)) {
-			if (!OS::get_singleton()->has_touchscreen_ui_hint()) {
+
+			bool found_touchscreen = false;
+			for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) {
+				if (DisplayServer::get_singleton()->screen_is_touchscreen(i)) {
+					found_touchscreen = true;
+				}
+			}
+			if (!found_touchscreen) {
 				//only if no touchscreen ui hint, set emulation
 				id->set_emulate_touch_from_mouse(true);
 			}
@@ -1589,7 +1681,7 @@ bool Main::start() {
 
 	if (!main_loop) {
 		if (!ClassDB::class_exists(main_loop_type)) {
-			OS::get_singleton()->alert("Error: MainLoop type doesn't exist: " + main_loop_type);
+			DisplayServer::get_singleton()->alert("Error: MainLoop type doesn't exist: " + main_loop_type);
 			return false;
 		} else {
 
@@ -1751,7 +1843,7 @@ bool Main::start() {
 			sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true));
 			String appname = ProjectSettings::get_singleton()->get("application/config/name");
 			appname = TranslationServer::get_singleton()->translate(appname);
-			OS::get_singleton()->set_window_title(appname);
+			DisplayServer::get_singleton()->window_set_title(appname);
 
 			int shadow_atlas_size = GLOBAL_GET("rendering/quality/shadow_atlas/size");
 			int shadow_atlas_q0_subdiv = GLOBAL_GET("rendering/quality/shadow_atlas/quadrant_0_subdiv");
@@ -1838,11 +1930,11 @@ bool Main::start() {
 					if (serr != OK)
 						ERR_PRINT("Failed to load scene");
 				}
-				OS::get_singleton()->set_context(OS::CONTEXT_EDITOR);
+				DisplayServer::get_singleton()->set_context(DisplayServer::CONTEXT_EDITOR);
 			}
 #endif
 			if (!editor) {
-				OS::get_singleton()->set_context(OS::CONTEXT_ENGINE);
+				DisplayServer::get_singleton()->set_context(DisplayServer::CONTEXT_ENGINE);
 			}
 		}
 
@@ -1881,7 +1973,7 @@ bool Main::start() {
 					Ref<Image> icon;
 					icon.instance();
 					if (ImageLoader::load_image(iconpath, icon) == OK) {
-						OS::get_singleton()->set_icon(icon);
+						DisplayServer::get_singleton()->set_icon(icon);
 						hasicon = true;
 					}
 				}
@@ -1896,14 +1988,14 @@ bool Main::start() {
 			ProgressDialog *progress_dialog = memnew(ProgressDialog);
 			pmanager->add_child(progress_dialog);
 			sml->get_root()->add_child(pmanager);
-			OS::get_singleton()->set_context(OS::CONTEXT_PROJECTMAN);
+			DisplayServer::get_singleton()->set_context(DisplayServer::CONTEXT_PROJECTMAN);
 			project_manager = true;
 		}
 
 		if (project_manager || editor) {
 			// Hide console window if requested (Windows-only).
 			bool hide_console = EditorSettings::get_singleton()->get_setting("interface/editor/hide_console_window");
-			OS::get_singleton()->set_console_visible(!hide_console);
+			DisplayServer::get_singleton()->console_set_visible(!hide_console);
 
 			// Load SSL Certificates from Editor Settings (or builtin)
 			Crypto::load_default_certificates(EditorSettings::get_singleton()->get_setting("network/ssl/editor_ssl_certificates").operator String());
@@ -1913,9 +2005,10 @@ bool Main::start() {
 
 	if (!hasicon) {
 		Ref<Image> icon = memnew(Image(app_icon_png));
-		OS::get_singleton()->set_icon(icon);
+		DisplayServer::get_singleton()->set_icon(icon);
 	}
 
+	Input::get_singleton()->set_main_loop(main_loop);
 	OS::get_singleton()->set_main_loop(main_loop);
 
 	return true;
@@ -2030,7 +2123,7 @@ bool Main::iteration() {
 
 	VisualServer::get_singleton()->sync(); //sync if still drawing from previous frames.
 
-	if (OS::get_singleton()->can_draw() && !disable_render_loop) {
+	if (DisplayServer::get_singleton()->can_any_window_draw() && !disable_render_loop) {
 
 		if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
 			if (VisualServer::get_singleton()->has_changed()) {
@@ -2085,7 +2178,7 @@ bool Main::iteration() {
 	if (fixed_fps != -1)
 		return exit;
 
-	if (OS::get_singleton()->is_in_low_processor_usage_mode() || !OS::get_singleton()->can_draw())
+	if (OS::get_singleton()->is_in_low_processor_usage_mode() || !DisplayServer::get_singleton()->can_any_window_draw())
 		OS::get_singleton()->delay_usec(OS::get_singleton()->get_low_processor_usage_mode_sleep_usec()); //apply some delay to force idle time
 	else {
 		uint32_t frame_delay = Engine::get_singleton()->get_frame_delay();
@@ -2182,8 +2275,14 @@ void Main::cleanup() {
 	}
 
 	OS::get_singleton()->finalize();
+
 	finalize_physics();
 	finalize_navigation_server();
+	finalize_display();
+
+	if (input) {
+		memdelete(input);
+	}
 
 	if (packed_data)
 		memdelete(packed_data);

+ 2 - 1
main/tests/test_physics.cpp

@@ -36,6 +36,7 @@
 #include "core/os/main_loop.h"
 #include "core/os/os.h"
 #include "core/print_string.h"
+#include "servers/display_server.h"
 #include "servers/physics_server.h"
 #include "servers/visual_server.h"
 
@@ -313,7 +314,7 @@ public:
 		camera = vs->camera_create();
 
 		RID viewport = vs->viewport_create();
-		Size2i screen_size = OS::get_singleton()->get_window_size();
+		Size2i screen_size = DisplayServer::get_singleton()->window_get_size();
 		vs->viewport_set_size(viewport, screen_size.x, screen_size.y);
 		vs->viewport_attach_to_screen(viewport, Rect2(Vector2(), screen_size));
 		vs->viewport_set_active(viewport, true);

+ 2 - 1
main/tests/test_physics_2d.cpp

@@ -35,6 +35,7 @@
 #include "core/os/os.h"
 #include "core/print_string.h"
 #include "scene/resources/texture.h"
+#include "servers/display_server.h"
 #include "servers/physics_2d_server.h"
 #include "servers/visual_server.h"
 
@@ -354,7 +355,7 @@ public:
 			RID vp = vs->viewport_create();
 			canvas = vs->canvas_create();
 
-			Size2i screen_size = OS::get_singleton()->get_window_size();
+			Size2i screen_size = DisplayServer::get_singleton()->window_get_size();
 			vs->viewport_attach_canvas(vp, canvas);
 			vs->viewport_set_size(vp, screen_size.x, screen_size.y);
 			vs->viewport_attach_to_screen(vp, Rect2(Vector2(), screen_size));

+ 2 - 1
main/tests/test_render.cpp

@@ -36,6 +36,7 @@
 #include "core/os/main_loop.h"
 #include "core/os/os.h"
 #include "core/print_string.h"
+#include "servers/display_server.h"
 #include "servers/visual_server.h"
 
 #define OBJECT_COUNT 50
@@ -163,7 +164,7 @@ public:
 		// 		vs->camera_set_perspective( camera, 60.0,0.1, 100.0 );
 
 		viewport = vs->viewport_create();
-		Size2i screen_size = OS::get_singleton()->get_window_size();
+		Size2i screen_size = DisplayServer::get_singleton()->window_get_size();
 		vs->viewport_set_size(viewport, screen_size.x, screen_size.y);
 		vs->viewport_attach_to_screen(viewport, Rect2(Vector2(), screen_size));
 		vs->viewport_set_active(viewport, true);

+ 1 - 1
modules/gdnative/nativescript/SCsub

@@ -5,5 +5,5 @@ Import('env_gdnative')
 
 env_gdnative.add_source_files(env.modules_sources, '*.cpp')
 
-if "platform" in env and env["platform"] in ["x11", "iphone"]:
+if "platform" in env and env["platform"] in ["linuxbsd", "iphone"]:
     env.Append(LINKFLAGS=["-rdynamic"])

+ 3 - 1
modules/gdscript/language_server/gdscript_text_document.cpp

@@ -35,6 +35,7 @@
 #include "editor/plugins/script_text_editor.h"
 #include "gdscript_extend_parser.h"
 #include "gdscript_language_protocol.h"
+#include "servers/display_server.h"
 
 void GDScriptTextDocument::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("didOpen"), &GDScriptTextDocument::didOpen);
@@ -419,7 +420,8 @@ void GDScriptTextDocument::sync_script_content(const String &p_path, const Strin
 
 void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_id) {
 	ScriptEditor::get_singleton()->call_deferred("_help_class_goto", p_symbol_id);
-	OS::get_singleton()->move_window_to_foreground();
+
+	DisplayServer::get_singleton()->window_move_to_foreground();
 }
 
 Array GDScriptTextDocument::find_symbols(const lsp::TextDocumentPositionParams &p_location, List<const lsp::DocumentSymbol *> &r_list) {

+ 2 - 1
modules/mobile_vr/mobile_vr_interface.cpp

@@ -31,6 +31,7 @@
 #include "mobile_vr_interface.h"
 #include "core/input/input.h"
 #include "core/os/os.h"
+#include "servers/display_server.h"
 #include "servers/visual/visual_server_globals.h"
 
 StringName MobileVRInterface::get_name() const {
@@ -339,7 +340,7 @@ Size2 MobileVRInterface::get_render_targetsize() {
 	_THREAD_SAFE_METHOD_
 
 	// we use half our window size
-	Size2 target_size = OS::get_singleton()->get_window_size();
+	Size2 target_size = DisplayServer::get_singleton()->window_get_size();
 
 	target_size.x *= 0.5 * oversample;
 	target_size.y *= oversample;

+ 9 - 8
platform/x11/SCsub → platform/linuxbsd/SCsub

@@ -3,20 +3,21 @@
 Import('env')
 
 from platform_methods import run_in_subprocess
-import platform_x11_builders
+import platform_linuxbsd_builders
 
 common_x11 = [
+    "crash_handler_linuxbsd.cpp",
+    "os_linuxbsd.cpp",
+    "joypad_linux.cpp",
     "context_gl_x11.cpp",
+    "detect_prime_x11.cpp",
+    "display_server_x11.cpp",
     "vulkan_context_x11.cpp",
-    "crash_handler_x11.cpp",
-    "os_x11.cpp",
     "key_mapping_x11.cpp",
-    "display_server_x11.cpp",
-    "joypad_linux.cpp",
-    "detect_prime.cpp"
+
 ]
 
-prog = env.add_program('#bin/godot', ['godot_x11.cpp'] + common_x11)
+prog = env.add_program('#bin/godot', ['godot_linuxbsd.cpp'] + common_x11)
 
 if (env["debug_symbols"] == "full" or env["debug_symbols"] == "yes") and env["separate_debug_symbols"]:
-    env.AddPostAction(prog, run_in_subprocess(platform_x11_builders.make_debug_x11))
+    env.AddPostAction(prog, run_in_subprocess(platform_linuxbsd_builders.make_debug_linuxbsd))

+ 0 - 0
platform/x11/context_gl_x11.cpp → platform/linuxbsd/context_gl_x11.cpp


+ 0 - 0
platform/x11/context_gl_x11.h → platform/linuxbsd/context_gl_x11.h


+ 2 - 2
platform/x11/crash_handler_x11.cpp → platform/linuxbsd/crash_handler_linuxbsd.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  crash_handler_x11.cpp                                                */
+/*  crash_handler_linuxbsd.cpp                                           */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,7 +28,7 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "crash_handler_x11.h"
+#include "crash_handler_linuxbsd.h"
 
 #include "core/os/os.h"
 #include "core/project_settings.h"

+ 1 - 1
platform/x11/crash_handler_x11.h → platform/linuxbsd/crash_handler_linuxbsd.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  crash_handler_x11.h                                                  */
+/*  crash_handler_linuxbsd.h                                             */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */

+ 4 - 4
platform/x11/detect.py → platform/linuxbsd/detect.py

@@ -8,7 +8,7 @@ def is_active():
 
 
 def get_name():
-    return "X11"
+    return "LinuxBSD"
 
 
 def can_build():
@@ -317,7 +317,7 @@ def configure(env):
     if not env['builtin_zlib']:
         env.ParseConfig('pkg-config zlib --cflags --libs')
 
-    env.Prepend(CPPPATH=['#platform/x11'])
+    env.Prepend(CPPPATH=['#platform/linuxbsd'])
     env.Append(CPPDEFINES=['X11_ENABLED', 'UNIX_ENABLED'])
 
     env.Append(CPPDEFINES=['VULKAN_ENABLED'])
@@ -350,9 +350,9 @@ def configure(env):
             print("Warning: Creating template binaries enabled for PCK embedding is currently only supported with GNU ld")
         else:
             if float(gnu_ld_version.group(1)) >= 2.30:
-                env.Append(LINKFLAGS=['-T', 'platform/x11/pck_embed.ld'])
+                env.Append(LINKFLAGS=['-T', 'platform/linuxbsd/pck_embed.ld'])
             else:
-                env.Append(LINKFLAGS=['-T', 'platform/x11/pck_embed.legacy.ld'])
+                env.Append(LINKFLAGS=['-T', 'platform/linuxbsd/pck_embed.legacy.ld'])
 
     ## Cross-compilation
 

+ 1 - 1
platform/x11/detect_prime.cpp → platform/linuxbsd/detect_prime_x11.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  detect_prime.cpp                                                     */
+/*  detect_prime_x11.cpp                                                 */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */

+ 1 - 1
platform/x11/detect_prime.h → platform/linuxbsd/detect_prime_x11.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  detect_prime.h                                                       */
+/*  detect_prime_x11.h                                                   */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */

+ 179 - 48
platform/x11/display_server_x11.cpp → platform/linuxbsd/display_server_x11.cpp

@@ -32,7 +32,7 @@
 
 #ifdef X11_ENABLED
 
-#include "detect_prime.h"
+#include "detect_prime_x11.h"
 
 #include "core/os/dir_access.h"
 #include "core/print_string.h"
@@ -608,7 +608,8 @@ bool DisplayServerX11::screen_is_touchscreen(int p_screen) const {
 #ifndef _MSC_VER
 #warning Need to get from proper window
 #endif
-	return false; //?
+
+	return DisplayServer::screen_is_touchscreen(p_screen);
 }
 
 Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
@@ -638,6 +639,11 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {
 
 	WindowData &wd = windows[p_id];
 
+#ifdef VULKAN_ENABLED
+	if (rendering_driver == "vulkan") {
+		context_vulkan->window_destroy(wd.vulkan_window);
+	}
+#endif
 	XUnmapWindow(x11_display, wd.x11_window);
 	XDestroyWindow(x11_display, wd.x11_window);
 	if (wd.xic) {
@@ -649,7 +655,7 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {
 
 void DisplayServerX11::window_set_title(const String &p_title, WindowID p_window) {
 
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	XStoreName(x11_display, wd.x11_window, p_title.utf8().get_data());
@@ -660,7 +666,7 @@ void DisplayServerX11::window_set_title(const String &p_title, WindowID p_window
 }
 
 int DisplayServerX11::window_get_current_screen(WindowID p_window) const {
-	ERR_FAIL_COND_V(windows.has(p_window), -1);
+	ERR_FAIL_COND_V(!windows.has(p_window), -1);
 	const WindowData &wd = windows[p_window];
 
 	int x, y;
@@ -677,7 +683,7 @@ int DisplayServerX11::window_get_current_screen(WindowID p_window) const {
 	return 0;
 }
 void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	int count = get_screen_count();
@@ -697,7 +703,7 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
 }
 
 Point2i DisplayServerX11::window_get_position(WindowID p_window) const {
-	ERR_FAIL_COND_V(windows.has(p_window), Point2i());
+	ERR_FAIL_COND_V(!windows.has(p_window), Point2i());
 	const WindowData &wd = windows[p_window];
 	int x, y;
 	Window child;
@@ -705,7 +711,7 @@ Point2i DisplayServerX11::window_get_position(WindowID p_window) const {
 	return Point2i(x, y);
 }
 void DisplayServerX11::window_set_position(const Point2i &p_position, WindowID p_window) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	int x = 0;
@@ -735,7 +741,7 @@ void DisplayServerX11::window_set_position(const Point2i &p_position, WindowID p
 }
 
 void DisplayServerX11::window_set_max_size(const Size2i p_size, WindowID p_window) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	if ((p_size != Size2i()) && ((p_size.x < wd.min_size.x) || (p_size.y < wd.min_size.y))) {
@@ -765,14 +771,14 @@ void DisplayServerX11::window_set_max_size(const Size2i p_size, WindowID p_windo
 	}
 }
 Size2i DisplayServerX11::window_get_max_size(WindowID p_window) const {
-	ERR_FAIL_COND_V(windows.has(p_window), Size2i());
+	ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
 	const WindowData &wd = windows[p_window];
 
 	return wd.max_size;
 }
 
 void DisplayServerX11::window_set_min_size(const Size2i p_size, WindowID p_window) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	if ((p_size != Size2i()) && (wd.max_size != Size2i()) && ((p_size.x > wd.max_size.x) || (p_size.y > wd.max_size.y))) {
@@ -802,14 +808,14 @@ void DisplayServerX11::window_set_min_size(const Size2i p_size, WindowID p_windo
 	}
 }
 Size2i DisplayServerX11::window_get_min_size(WindowID p_window) const {
-	ERR_FAIL_COND_V(windows.has(p_window), Size2i());
+	ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
 	const WindowData &wd = windows[p_window];
 
 	return wd.min_size;
 }
 
 void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	if (wd.size.width == p_size.width && wd.size.height == p_size.height)
@@ -863,12 +869,12 @@ void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) {
 	}
 }
 Size2i DisplayServerX11::window_get_size(WindowID p_window) const {
-	ERR_FAIL_COND_V(windows.has(p_window), Size2i());
+	ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
 	const WindowData &wd = windows[p_window];
 	return wd.size;
 }
 Size2i DisplayServerX11::window_get_real_size(WindowID p_window) const {
-	ERR_FAIL_COND_V(windows.has(p_window), Size2i());
+	ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
 	const WindowData &wd = windows[p_window];
 
 	XWindowAttributes xwa;
@@ -897,7 +903,7 @@ Size2i DisplayServerX11::window_get_real_size(WindowID p_window) const {
 
 bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const {
 
-	ERR_FAIL_COND_V(windows.has(p_window), false);
+	ERR_FAIL_COND_V(!windows.has(p_window), false);
 	const WindowData &wd = windows[p_window];
 
 	Atom property = XInternAtom(x11_display, "_NET_WM_ALLOWED_ACTIONS", False);
@@ -944,7 +950,7 @@ bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const {
 }
 
 void DisplayServerX11::_set_wm_maximized(WindowID p_window, bool p_enabled) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	// Using EWMH -- Extended Window Manager Hints
@@ -976,7 +982,7 @@ void DisplayServerX11::_set_wm_maximized(WindowID p_window, bool p_enabled) {
 
 void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled) {
 
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	if (p_enabled && !window_get_flag(WINDOW_FLAG_BORDERLESS, p_window)) {
@@ -1060,7 +1066,7 @@ void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled) {
 }
 
 void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	WindowMode old_mode = window_get_mode(p_window);
@@ -1171,7 +1177,7 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
 }
 
 DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) const {
-	ERR_FAIL_COND_V(windows.has(p_window), WINDOW_MODE_WINDOWED);
+	ERR_FAIL_COND_V(!windows.has(p_window), WINDOW_MODE_WINDOWED);
 	const WindowData &wd = windows[p_window];
 
 	if (wd.fullscreen) { //if fullscreen, it's not in another mode
@@ -1263,7 +1269,7 @@ DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) c
 }
 
 void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	switch (p_flag) {
@@ -1348,7 +1354,7 @@ void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
 	}
 }
 bool DisplayServerX11::window_get_flag(WindowFlags p_flag, WindowID p_window) const {
-	ERR_FAIL_COND_V(windows.has(p_window), false);
+	ERR_FAIL_COND_V(!windows.has(p_window), false);
 	const WindowData &wd = windows[p_window];
 
 	switch (p_flag) {
@@ -1391,7 +1397,7 @@ bool DisplayServerX11::window_get_flag(WindowFlags p_flag, WindowID p_window) co
 }
 
 void DisplayServerX11::window_request_attention(WindowID p_window) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 	// Using EWMH -- Extended Window Manager Hints
 	//
@@ -1415,7 +1421,7 @@ void DisplayServerX11::window_request_attention(WindowID p_window) {
 }
 
 void DisplayServerX11::window_move_to_foreground(WindowID p_window) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	XEvent xev;
@@ -1437,9 +1443,19 @@ bool DisplayServerX11::window_can_draw(WindowID p_window) const {
 	//this seems to be all that is provided by X11
 	return window_get_mode(p_window) != WINDOW_MODE_MINIMIZED;
 }
+bool DisplayServerX11::can_any_window_draw() const {
+
+	for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
+		if (window_get_mode(E->key()) != WINDOW_MODE_MINIMIZED) {
+			return true;
+		}
+	}
+
+	return false;
+}
 
 void DisplayServerX11::window_set_ime_active(const bool p_active, WindowID p_window) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	wd.im_active = p_active;
@@ -1455,7 +1471,7 @@ void DisplayServerX11::window_set_ime_active(const bool p_active, WindowID p_win
 	}
 }
 void DisplayServerX11::window_set_ime_position(const Point2i &p_pos, WindowID p_window) {
-	ERR_FAIL_COND(windows.has(p_window));
+	ERR_FAIL_COND(!windows.has(p_window));
 	WindowData &wd = windows[p_window];
 
 	wd.im_position = p_pos;
@@ -2003,7 +2019,7 @@ void DisplayServerX11::_window_changed(XEvent *event) {
 	wd.size.height = event->xconfigure.height;
 
 #if defined(VULKAN_ENABLED)
-	if (video_driver == "vulkan") {
+	if (rendering_driver == "vulkan") {
 		context_vulkan->window_resize(wd.vulkan_window, wd.size.width, wd.size.height);
 	}
 #endif
@@ -2634,15 +2650,59 @@ void DisplayServerX11::process_events() {
 }
 
 void DisplayServerX11::release_rendering_thread() {
-	WARN_PRINT("Rendering thread not supported by this display server.");
 }
+
 void DisplayServerX11::make_rendering_thread() {
-	WARN_PRINT("Rendering thread not supported by this display server.");
 }
+
 void DisplayServerX11::swap_buffers() {
-	WARN_PRINT("Swap buffers not supported by this display server.");
 }
 
+void DisplayServerX11::_update_context(WindowData &wd) {
+	XClassHint *classHint = XAllocClassHint();
+
+	if (classHint) {
+
+		CharString name_str;
+		switch (context) {
+			case CONTEXT_EDITOR:
+				name_str = "Godot_Editor";
+				break;
+			case CONTEXT_PROJECTMAN:
+				name_str = "Godot_ProjectList";
+				break;
+			case CONTEXT_ENGINE:
+				name_str = "Godot_Engine";
+				break;
+		}
+
+		CharString class_str;
+		if (context == CONTEXT_ENGINE) {
+			String config_name = GLOBAL_GET("application/config/name");
+			if (config_name.length() == 0) {
+				class_str = "Godot_Engine";
+			} else {
+				class_str = config_name.utf8();
+			}
+		} else {
+			class_str = "Godot";
+		}
+
+		classHint->res_class = class_str.ptrw();
+		classHint->res_name = name_str.ptrw();
+
+		XSetClassHint(x11_display, wd.x11_window, classHint);
+		XFree(classHint);
+	}
+}
+void DisplayServerX11::set_context(Context p_context) {
+
+	context = p_context;
+
+	for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
+		_update_context(E->get());
+	}
+}
 void DisplayServerX11::set_native_icon(const String &p_filename) {
 	WARN_PRINT("Native icon not supported by this display server.");
 }
@@ -2650,9 +2710,22 @@ void DisplayServerX11::set_icon(const Ref<Image> &p_icon) {
 	WARN_PRINT("Icon not supported by this display server.");
 }
 
-DisplayServer *DisplayServerX11::create_func(const String &p_video_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+Vector<String> DisplayServerX11::get_rendering_drivers_func() {
+	Vector<String> drivers;
+
+#ifdef VULKAN_ENABLED
+	drivers.push_back("vulkan");
+#endif
+#ifdef OPENGL_ENABLED
+	drivers.push_back("opengl");
+#endif
+
+	return drivers;
+}
+
+DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
 
-	return memnew(DisplayServerX11(p_video_driver, p_mode, p_flags, p_resolution, r_error));
+	return memnew(DisplayServerX11(p_rendering_driver, p_mode, p_flags, p_resolution, r_error));
 }
 
 DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, const Vector2i &p_resolution) {
@@ -2678,7 +2751,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, c
 	WindowID id;
 	{
 		WindowData wd;
-		wd.x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo->screen), 0, 0, OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height, 0, visualInfo->depth, InputOutput, visualInfo->visual, valuemask, &windowAttributes);
+		wd.x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo->screen), 0, 0, p_resolution.width, p_resolution.height, 0, visualInfo->depth, InputOutput, visualInfo->visual, valuemask, &windowAttributes);
 
 		//set_class_hint(x11_display, wd.x11_window);
 		XMapWindow(x11_display, wd.x11_window);
@@ -2771,6 +2844,8 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, c
 			WARN_PRINT("XCreateIC couldn't create wd.xic");
 		}
 
+		_update_context(wd);
+
 		id = window_id_counter++;
 
 		windows[id] = wd;
@@ -2788,7 +2863,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, c
 	return id;
 }
 
-DisplayServerX11::DisplayServerX11(const String &p_video_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
 
 	r_error = OK;
 
@@ -2870,8 +2945,8 @@ DisplayServerX11::DisplayServerX11(const String &p_video_driver, WindowMode p_mo
 	}
 
 	if (!_refresh_device_info()) {
-		OS::get_singleton()->alert("Your system does not support XInput 2.\n"
-								   "Please upgrade your distribution.",
+		alert("Your system does not support XInput 2.\n"
+			  "Please upgrade your distribution.",
 				"Unable to initialize XInput");
 		r_error = ERR_UNAVAILABLE;
 		return;
@@ -2930,15 +3005,15 @@ DisplayServerX11::DisplayServerX11(const String &p_video_driver, WindowMode p_mo
 
 	//!!!!!!!!!!!!!!!!!!!!!!!!!!
 	//TODO - do Vulkan and GLES2 support checks, driver selection and fallback
-	video_driver = p_video_driver;
+	rendering_driver = p_rendering_driver;
 
 #ifndef _MSC_VER
-#warning Forcing vulkan video driver because OpenGL not implemented yet
+#warning Forcing vulkan rendering driver because OpenGL not implemented yet
 #endif
-	video_driver = "vulkan";
+	rendering_driver = "vulkan";
 
 #if defined(VULKAN_ENABLED)
-	if (video_driver == "vulkan") {
+	if (rendering_driver == "vulkan") {
 
 		context_vulkan = memnew(VulkanContextX11);
 		if (context_vulkan->initialize() != OK) {
@@ -2947,17 +3022,11 @@ DisplayServerX11::DisplayServerX11(const String &p_video_driver, WindowMode p_mo
 			r_error = ERR_CANT_CREATE;
 			ERR_FAIL_MSG("Could not initialize Vulkan");
 		}
-
-		//temporary
-		rendering_device_vulkan = memnew(RenderingDeviceVulkan);
-		rendering_device_vulkan->initialize(context_vulkan);
-
-		RasterizerRD::make_current();
 	}
 #endif
 	// Init context and rendering device
 #if defined(OPENGL_ENABLED)
-	if (video_driver == "opengl_es") {
+	if (rendering_driver == "opengl_es") {
 		if (getenv("DRI_PRIME") == NULL) {
 			int use_prime = -1;
 
@@ -3028,6 +3097,18 @@ DisplayServerX11::DisplayServerX11(const String &p_video_driver, WindowMode p_mo
 		}
 	}
 
+//create RenderingDevice if used
+#if defined(VULKAN_ENABLED)
+	if (rendering_driver == "vulkan") {
+
+		//temporary
+		rendering_device_vulkan = memnew(RenderingDeviceVulkan);
+		rendering_device_vulkan->initialize(context_vulkan);
+
+		RasterizerRD::make_current();
+	}
+#endif
+
 	/*
 	visual_server = memnew(VisualServerRaster);
 	if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
@@ -3190,8 +3271,6 @@ DisplayServerX11::DisplayServerX11(const String &p_video_driver, WindowMode p_mo
 
 	requested = None;
 
-	visual_server->init();
-
 	window_has_focus = true; // Set focus to true at init
 
 	/*if (p_desired.layered) {
@@ -3211,6 +3290,58 @@ DisplayServerX11::DisplayServerX11(const String &p_video_driver, WindowMode p_mo
 	r_error = OK;
 }
 DisplayServerX11::~DisplayServerX11() {
+
+	//destroy all windows
+	for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
+#ifdef VULKAN_ENABLED
+		if (rendering_driver == "vulkan") {
+			context_vulkan->window_destroy(E->get().vulkan_window);
+		}
+#endif
+
+		if (E->get().xic) {
+			XDestroyIC(E->get().xic);
+		}
+		XUnmapWindow(x11_display, E->get().x11_window);
+		XDestroyWindow(x11_display, E->get().x11_window);
+	}
+
+	//destroy drivers
+#if defined(VULKAN_ENABLED)
+	if (rendering_driver == "vulkan") {
+
+		if (rendering_device_vulkan) {
+			rendering_device_vulkan->finalize();
+			memdelete(rendering_device_vulkan);
+		}
+
+		if (context_vulkan)
+			memdelete(context_vulkan);
+	}
+#endif
+
+	if (xrandr_handle)
+		dlclose(xrandr_handle);
+
+	for (int i = 0; i < CURSOR_MAX; i++) {
+		if (cursors[i] != None)
+			XFreeCursor(x11_display, cursors[i]);
+		if (img[i] != NULL)
+			XcursorImageDestroy(img[i]);
+	};
+
+	if (xim) {
+		XCloseIM(xim);
+	}
+
+	XCloseDisplay(x11_display);
+	if (xmbstring)
+		memfree(xmbstring);
+}
+
+void DisplayServerX11::register_x11_driver() {
+
+	register_create_function("x11", create_func, get_rendering_drivers_func);
 }
 
 #endif // X11 enabled

+ 16 - 8
platform/x11/display_server_x11.h → platform/linuxbsd/display_server_x11.h

@@ -36,7 +36,7 @@
 #include "servers/display_server.h"
 
 #include "core/input/input.h"
-#include "crash_handler_x11.h"
+
 #include "drivers/alsa/audio_driver_alsa.h"
 #include "drivers/alsamidi/midi_driver_alsamidi.h"
 #include "drivers/pulseaudio/audio_driver_pulseaudio.h"
@@ -52,7 +52,7 @@
 
 #if defined(VULKAN_ENABLED)
 #include "drivers/vulkan/rendering_device_vulkan.h"
-#include "platform/x11/vulkan_context_x11.h"
+#include "platform/linuxbsd/vulkan_context_x11.h"
 #endif
 
 #include <X11/Xcursor/Xcursor.h>
@@ -110,9 +110,6 @@ class DisplayServerX11 : public DisplayServer {
 	RenderingDeviceVulkan *rendering_device_vulkan;
 #endif
 
-	//Rasterizer *rasterizer;
-	VisualServer *visual_server;
-
 	struct WindowData {
 		Window x11_window;
 		::XIC xic;
@@ -200,7 +197,7 @@ class DisplayServerX11 : public DisplayServer {
 
 	bool layered_window;
 
-	String video_driver;
+	String rendering_driver;
 	bool window_focused;
 	//void set_wm_border(bool p_enabled);
 	void set_wm_fullscreen(bool p_enabled);
@@ -224,6 +221,10 @@ class DisplayServerX11 : public DisplayServer {
 	void _set_wm_fullscreen(WindowID p_window, bool p_enabled);
 	void _set_wm_maximized(WindowID p_window, bool p_enabled);
 
+	void _update_context(WindowData &wd);
+
+	Context context = CONTEXT_ENGINE;
+
 protected:
 	void _window_changed(XEvent *event);
 
@@ -286,6 +287,8 @@ public:
 
 	virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const;
 
+	virtual bool can_any_window_draw() const;
+
 	virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
 	virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
 
@@ -301,12 +304,17 @@ public:
 	virtual void make_rendering_thread();
 	virtual void swap_buffers();
 
+	virtual void set_context(Context p_context);
+
 	virtual void set_native_icon(const String &p_filename);
 	virtual void set_icon(const Ref<Image> &p_icon);
 
-	static DisplayServer *create_func(const String &p_video_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+	static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+	static Vector<String> get_rendering_drivers_func();
+
+	static void register_x11_driver();
 
-	DisplayServerX11(const String &p_video_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+	DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
 	~DisplayServerX11();
 };
 

+ 3 - 3
platform/x11/export/export.cpp → platform/linuxbsd/export/export.cpp

@@ -32,17 +32,17 @@
 
 #include "core/os/file_access.h"
 #include "editor/editor_export.h"
-#include "platform/x11/logo.gen.h"
+#include "platform/linuxbsd/logo.gen.h"
 #include "scene/resources/texture.h"
 
 static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size);
 
-void register_x11_exporter() {
+void register_linuxbsd_exporter() {
 
 	Ref<EditorExportPlatformPC> platform;
 	platform.instance();
 
-	Ref<Image> img = memnew(Image(_x11_logo));
+	Ref<Image> img = memnew(Image(_linuxbsd_logo));
 	Ref<ImageTexture> logo;
 	logo.instance();
 	logo->create_from_image(img);

+ 4 - 4
platform/x11/export/export.h → platform/linuxbsd/export/export.h

@@ -28,9 +28,9 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef X11_EXPORT_H
-#define X11_EXPORT_H
+#ifndef LINUXBSD_EXPORT_H
+#define LINUXBSD_EXPORT_H
 
-void register_x11_exporter();
+void register_linuxbsd_exporter();
 
-#endif // X11_EXPORT_H
+#endif // LINUXBSD_EXPORT_H

+ 3 - 3
platform/x11/godot_x11.cpp → platform/linuxbsd/godot_linuxbsd.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  godot_x11.cpp                                                        */
+/*  godot_linuxbsd.cpp                                                   */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -34,11 +34,11 @@
 #include <unistd.h>
 
 #include "main/main.h"
-#include "os_x11.h"
+#include "os_linuxbsd.h"
 
 int main(int argc, char *argv[]) {
 
-	OS_X11 os;
+	OS_LinuxBSD os;
 
 	setlocale(LC_CTYPE, "");
 

+ 0 - 0
platform/x11/joypad_linux.cpp → platform/linuxbsd/joypad_linux.cpp


+ 0 - 0
platform/x11/joypad_linux.h → platform/linuxbsd/joypad_linux.h


+ 0 - 0
platform/x11/key_mapping_x11.cpp → platform/linuxbsd/key_mapping_x11.cpp


+ 0 - 0
platform/x11/key_mapping_x11.h → platform/linuxbsd/key_mapping_x11.h


+ 0 - 0
platform/x11/logo.png → platform/linuxbsd/logo.png


+ 381 - 0
platform/linuxbsd/os_linuxbsd.cpp

@@ -0,0 +1,381 @@
+/*************************************************************************/
+/*  os_linuxbsd.cpp                                                      */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "os_linuxbsd.h"
+
+#include "core/os/dir_access.h"
+#include "core/print_string.h"
+#include "errno.h"
+
+#ifdef HAVE_MNTENT
+#include <mntent.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "main/main.h"
+
+#ifdef X11_ENABLED
+#include "display_server_x11.h"
+#endif
+
+void OS_LinuxBSD::initialize() {
+
+	crash_handler.initialize();
+
+	OS_Unix::initialize_core();
+}
+
+void OS_LinuxBSD::initialize_joypads() {
+
+#ifdef JOYDEV_ENABLED
+	joypad = memnew(JoypadLinux(Input::get_singleton()));
+#endif
+}
+
+String OS_LinuxBSD::get_unique_id() const {
+
+	static String machine_id;
+	if (machine_id.empty()) {
+		if (FileAccess *f = FileAccess::open("/etc/machine-id", FileAccess::READ)) {
+			while (machine_id.empty() && !f->eof_reached()) {
+				machine_id = f->get_line().strip_edges();
+			}
+			f->close();
+			memdelete(f);
+		}
+	}
+	return machine_id;
+}
+
+void OS_LinuxBSD::finalize() {
+
+	if (main_loop)
+		memdelete(main_loop);
+	main_loop = NULL;
+
+#ifdef ALSAMIDI_ENABLED
+	driver_alsamidi.close();
+#endif
+
+#ifdef JOYDEV_ENABLED
+	memdelete(joypad);
+#endif
+}
+
+MainLoop *OS_LinuxBSD::get_main_loop() const {
+
+	return main_loop;
+}
+
+void OS_LinuxBSD::delete_main_loop() {
+
+	if (main_loop)
+		memdelete(main_loop);
+	main_loop = NULL;
+}
+
+void OS_LinuxBSD::set_main_loop(MainLoop *p_main_loop) {
+
+	main_loop = p_main_loop;
+}
+
+String OS_LinuxBSD::get_name() const {
+
+#ifdef __linux__
+	return "Linux";
+#elif defined(__FreeBSD__)
+	return "FreeBSD";
+#elif defined(__NetBSD__)
+	return "NetBSD";
+#else
+	return "BSD";
+#endif
+}
+
+Error OS_LinuxBSD::shell_open(String p_uri) {
+
+	Error ok;
+	List<String> args;
+	args.push_back(p_uri);
+	ok = execute("xdg-open", args, false);
+	if (ok == OK)
+		return OK;
+	ok = execute("gnome-open", args, false);
+	if (ok == OK)
+		return OK;
+	ok = execute("kde-open", args, false);
+	return ok;
+}
+
+bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) {
+
+	return p_feature == "pc";
+}
+
+String OS_LinuxBSD::get_config_path() const {
+
+	if (has_environment("XDG_CONFIG_HOME")) {
+		return get_environment("XDG_CONFIG_HOME");
+	} else if (has_environment("HOME")) {
+		return get_environment("HOME").plus_file(".config");
+	} else {
+		return ".";
+	}
+}
+
+String OS_LinuxBSD::get_data_path() const {
+
+	if (has_environment("XDG_DATA_HOME")) {
+		return get_environment("XDG_DATA_HOME");
+	} else if (has_environment("HOME")) {
+		return get_environment("HOME").plus_file(".local/share");
+	} else {
+		return get_config_path();
+	}
+}
+
+String OS_LinuxBSD::get_cache_path() const {
+
+	if (has_environment("XDG_CACHE_HOME")) {
+		return get_environment("XDG_CACHE_HOME");
+	} else if (has_environment("HOME")) {
+		return get_environment("HOME").plus_file(".cache");
+	} else {
+		return get_config_path();
+	}
+}
+
+String OS_LinuxBSD::get_system_dir(SystemDir p_dir) const {
+
+	String xdgparam;
+
+	switch (p_dir) {
+		case SYSTEM_DIR_DESKTOP: {
+
+			xdgparam = "DESKTOP";
+		} break;
+		case SYSTEM_DIR_DCIM: {
+
+			xdgparam = "PICTURES";
+
+		} break;
+		case SYSTEM_DIR_DOCUMENTS: {
+
+			xdgparam = "DOCUMENTS";
+
+		} break;
+		case SYSTEM_DIR_DOWNLOADS: {
+
+			xdgparam = "DOWNLOAD";
+
+		} break;
+		case SYSTEM_DIR_MOVIES: {
+
+			xdgparam = "VIDEOS";
+
+		} break;
+		case SYSTEM_DIR_MUSIC: {
+
+			xdgparam = "MUSIC";
+
+		} break;
+		case SYSTEM_DIR_PICTURES: {
+
+			xdgparam = "PICTURES";
+
+		} break;
+		case SYSTEM_DIR_RINGTONES: {
+
+			xdgparam = "MUSIC";
+
+		} break;
+	}
+
+	String pipe;
+	List<String> arg;
+	arg.push_back(xdgparam);
+	Error err = const_cast<OS_LinuxBSD *>(this)->execute("xdg-user-dir", arg, true, NULL, &pipe);
+	if (err != OK)
+		return ".";
+	return pipe.strip_edges();
+}
+
+void OS_LinuxBSD::run() {
+
+	force_quit = false;
+
+	if (!main_loop)
+		return;
+
+	main_loop->init();
+
+	//uint64_t last_ticks=get_ticks_usec();
+
+	//int frames=0;
+	//uint64_t frame=0;
+
+	while (!force_quit) {
+
+		DisplayServer::get_singleton()->process_events(); // get rid of pending events
+#ifdef JOYDEV_ENABLED
+		joypad->process_joypads();
+#endif
+		if (Main::iteration())
+			break;
+	};
+
+	main_loop->finish();
+}
+
+void OS_LinuxBSD::disable_crash_handler() {
+	crash_handler.disable();
+}
+
+bool OS_LinuxBSD::is_disable_crash_handler() const {
+	return crash_handler.is_disabled();
+}
+
+static String get_mountpoint(const String &p_path) {
+	struct stat s;
+	if (stat(p_path.utf8().get_data(), &s)) {
+		return "";
+	}
+
+#ifdef HAVE_MNTENT
+	dev_t dev = s.st_dev;
+	FILE *fd = setmntent("/proc/mounts", "r");
+	if (!fd) {
+		return "";
+	}
+
+	struct mntent mnt;
+	char buf[1024];
+	size_t buflen = 1024;
+	while (getmntent_r(fd, &mnt, buf, buflen)) {
+		if (!stat(mnt.mnt_dir, &s) && s.st_dev == dev) {
+			endmntent(fd);
+			return String(mnt.mnt_dir);
+		}
+	}
+
+	endmntent(fd);
+#endif
+	return "";
+}
+
+Error OS_LinuxBSD::move_to_trash(const String &p_path) {
+	String trash_can = "";
+	String mnt = get_mountpoint(p_path);
+
+	// If there is a directory "[Mountpoint]/.Trash-[UID]/files", use it as the trash can.
+	if (mnt != "") {
+		String path(mnt + "/.Trash-" + itos(getuid()) + "/files");
+		struct stat s;
+		if (!stat(path.utf8().get_data(), &s)) {
+			trash_can = path;
+		}
+	}
+
+	// Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash/files" as the trash can.
+	if (trash_can == "") {
+		char *dhome = getenv("XDG_DATA_HOME");
+		if (dhome) {
+			trash_can = String(dhome) + "/Trash/files";
+		}
+	}
+
+	// Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash/files" as the trash can.
+	if (trash_can == "") {
+		char *home = getenv("HOME");
+		if (home) {
+			trash_can = String(home) + "/.local/share/Trash/files";
+		}
+	}
+
+	// Issue an error if none of the previous locations is appropriate for the trash can.
+	if (trash_can == "") {
+		ERR_PRINT("move_to_trash: Could not determine the trash can location");
+		return FAILED;
+	}
+
+	// Create needed directories for decided trash can location.
+	DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Error err = dir_access->make_dir_recursive(trash_can);
+	memdelete(dir_access);
+
+	// Issue an error if trash can is not created proprely.
+	if (err != OK) {
+		ERR_PRINT("move_to_trash: Could not create the trash can \"" + trash_can + "\"");
+		return err;
+	}
+
+	// The trash can is successfully created, now move the given resource to it.
+	// Do not use DirAccess:rename() because it can't move files across multiple mountpoints.
+	List<String> mv_args;
+	mv_args.push_back(p_path);
+	mv_args.push_back(trash_can);
+	int retval;
+	err = execute("mv", mv_args, true, NULL, NULL, &retval);
+
+	// Issue an error if "mv" failed to move the given resource to the trash can.
+	if (err != OK || retval != 0) {
+		ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_can + "\"");
+		return FAILED;
+	}
+
+	return OK;
+}
+
+OS_LinuxBSD::OS_LinuxBSD() {
+
+	main_loop = NULL;
+	force_quit = false;
+
+#ifdef PULSEAUDIO_ENABLED
+	AudioDriverManager::add_driver(&driver_pulseaudio);
+#endif
+
+#ifdef ALSA_ENABLED
+	AudioDriverManager::add_driver(&driver_alsa);
+#endif
+
+#ifdef X11_ENABLED
+	DisplayServerX11::register_x11_driver();
+#endif
+}

+ 106 - 0
platform/linuxbsd/os_linuxbsd.h

@@ -0,0 +1,106 @@
+/*************************************************************************/
+/*  os_linuxbsd.h                                                        */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef OS_LINUXBSD_H
+#define OS_LINUXBSD_H
+
+#include "core/input/input.h"
+#include "crash_handler_linuxbsd.h"
+#include "drivers/alsa/audio_driver_alsa.h"
+#include "drivers/alsamidi/midi_driver_alsamidi.h"
+#include "drivers/pulseaudio/audio_driver_pulseaudio.h"
+#include "drivers/unix/os_unix.h"
+#include "joypad_linux.h"
+#include "servers/audio_server.h"
+#include "servers/visual/rasterizer.h"
+#include "servers/visual_server.h"
+
+class OS_LinuxBSD : public OS_Unix {
+
+	virtual void delete_main_loop();
+
+	bool force_quit;
+
+#ifdef JOYDEV_ENABLED
+	JoypadLinux *joypad;
+#endif
+
+#ifdef ALSA_ENABLED
+	AudioDriverALSA driver_alsa;
+#endif
+
+#ifdef ALSAMIDI_ENABLED
+	MIDIDriverALSAMidi driver_alsamidi;
+#endif
+
+#ifdef PULSEAUDIO_ENABLED
+	AudioDriverPulseAudio driver_pulseaudio;
+#endif
+
+	CrashHandler crash_handler;
+
+	MainLoop *main_loop;
+
+protected:
+	virtual void initialize();
+	virtual void finalize();
+
+	virtual void initialize_joypads();
+
+	virtual void set_main_loop(MainLoop *p_main_loop);
+
+public:
+	virtual String get_name() const;
+
+	virtual MainLoop *get_main_loop() const;
+
+	virtual String get_config_path() const;
+	virtual String get_data_path() const;
+	virtual String get_cache_path() const;
+
+	virtual String get_system_dir(SystemDir p_dir) const;
+
+	virtual Error shell_open(String p_uri);
+
+	virtual String get_unique_id() const;
+
+	virtual bool _check_internal_feature_support(const String &p_feature);
+
+	void run();
+
+	void disable_crash_handler();
+	bool is_disable_crash_handler() const;
+
+	virtual Error move_to_trash(const String &p_path);
+
+	OS_LinuxBSD();
+};
+
+#endif

+ 0 - 0
platform/x11/pck_embed.ld → platform/linuxbsd/pck_embed.ld


+ 0 - 0
platform/x11/pck_embed.legacy.ld → platform/linuxbsd/pck_embed.legacy.ld


+ 0 - 0
platform/x11/platform_config.h → platform/linuxbsd/platform_config.h


+ 1 - 1
platform/x11/platform_x11_builders.py → platform/linuxbsd/platform_linuxbsd_builders.py

@@ -7,7 +7,7 @@ import os
 from platform_methods import subprocess_main
 
 
-def make_debug_x11(target, source, env):
+def make_debug_linuxbsd(target, source, env):
     os.system('objcopy --only-keep-debug {0} {0}.debugsymbols'.format(target[0]))
     os.system('strip --strip-debug --strip-unneeded {0}'.format(target[0]))
     os.system('objcopy --add-gnu-debuglink={0}.debugsymbols {0}'.format(target[0]))

+ 0 - 0
platform/x11/vulkan_context_x11.cpp → platform/linuxbsd/vulkan_context_x11.cpp


+ 0 - 0
platform/x11/vulkan_context_x11.h → platform/linuxbsd/vulkan_context_x11.h


+ 1 - 1
platform/server/os_server.h

@@ -38,7 +38,7 @@
 #include "platform/osx/crash_handler_osx.h"
 #include "platform/osx/semaphore_osx.h"
 #else
-#include "platform/x11/crash_handler_x11.h"
+#include "platform/x11/crash_handler_linuxbsd.h"
 #endif
 #include "servers/audio_server.h"
 #include "servers/visual/rasterizer.h"

+ 0 - 3568
platform/x11/os_x11.cpp

@@ -1,3568 +0,0 @@
-/*************************************************************************/
-/*  os_x11.cpp                                                           */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the       */
-/* "Software"), to deal in the Software without restriction, including   */
-/* without limitation the rights to use, copy, modify, merge, publish,   */
-/* distribute, sublicense, and/or sell copies of the Software, and to    */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions:                                             */
-/*                                                                       */
-/* The above copyright notice and this permission notice shall be        */
-/* included in all copies or substantial portions of the Software.       */
-/*                                                                       */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
-/*************************************************************************/
-
-#include "os_x11.h"
-#include "detect_prime.h"
-
-#include "core/os/dir_access.h"
-#include "core/print_string.h"
-#include "errno.h"
-#include "key_mapping_x11.h"
-
-#if defined(OPENGL_ENABLED)
-#include "drivers/gles2/rasterizer_gles2.h"
-#endif
-
-#if defined(VULKAN_ENABLED)
-#include "servers/visual/rasterizer_rd/rasterizer_rd.h"
-#endif
-
-#include "servers/visual/visual_server_raster.h"
-#include "servers/visual/visual_server_wrap_mt.h"
-
-#ifdef HAVE_MNTENT
-#include <mntent.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "X11/Xutil.h"
-
-#include "X11/Xatom.h"
-#include "X11/extensions/Xinerama.h"
-// ICCCM
-#define WM_NormalState 1L // window normal state
-#define WM_IconicState 3L // window minimized
-// EWMH
-#define _NET_WM_STATE_REMOVE 0L // remove/unset property
-#define _NET_WM_STATE_ADD 1L // add/set property
-#define _NET_WM_STATE_TOGGLE 2L // toggle property
-
-#include "main/main.h"
-
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-//stupid linux.h
-#ifdef KEY_TAB
-#undef KEY_TAB
-#endif
-
-#include <X11/Xatom.h>
-
-#undef CursorShape
-
-#include <X11/XKBlib.h>
-
-// 2.2 is the first release with multitouch
-#define XINPUT_CLIENT_VERSION_MAJOR 2
-#define XINPUT_CLIENT_VERSION_MINOR 2
-
-#define VALUATOR_ABSX 0
-#define VALUATOR_ABSY 1
-#define VALUATOR_PRESSURE 2
-#define VALUATOR_TILTX 3
-#define VALUATOR_TILTY 4
-
-static const double abs_resolution_mult = 10000.0;
-static const double abs_resolution_range_mult = 10.0;
-
-void OS_X11::initialize_core() {
-
-	crash_handler.initialize();
-
-	OS_Unix::initialize_core();
-}
-
-int OS_X11::get_current_video_driver() const {
-	return video_driver_index;
-}
-
-Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
-
-	long im_event_mask = 0;
-	last_button_state = 0;
-
-	xmbstring = NULL;
-	x11_window = 0;
-	last_click_ms = 0;
-	last_click_button_index = -1;
-	last_click_pos = Point2(-100, -100);
-	args = OS::get_singleton()->get_cmdline_args();
-	current_videomode = p_desired;
-	main_loop = NULL;
-	last_timestamp = 0;
-	last_mouse_pos_valid = false;
-	last_keyrelease_time = 0;
-	xdnd_version = 0;
-
-	if (get_render_thread_mode() == RENDER_SEPARATE_THREAD) {
-		XInitThreads();
-	}
-
-	/** XLIB INITIALIZATION **/
-	x11_display = XOpenDisplay(NULL);
-
-	if (!x11_display) {
-		ERR_PRINT("X11 Display is not available");
-		return ERR_UNAVAILABLE;
-	}
-
-	char *modifiers = NULL;
-	Bool xkb_dar = False;
-	XAutoRepeatOn(x11_display);
-	xkb_dar = XkbSetDetectableAutoRepeat(x11_display, True, NULL);
-
-	// Try to support IME if detectable auto-repeat is supported
-	if (xkb_dar == True) {
-
-#ifdef X_HAVE_UTF8_STRING
-		// Xutf8LookupString will be used later instead of XmbLookupString before
-		// the multibyte sequences can be converted to unicode string.
-		modifiers = XSetLocaleModifiers("");
-#endif
-	}
-
-	if (modifiers == NULL) {
-		if (is_stdout_verbose()) {
-			WARN_PRINT("IME is disabled");
-		}
-		XSetLocaleModifiers("@im=none");
-		WARN_PRINT("Error setting locale modifiers");
-	}
-
-	const char *err;
-	xrr_get_monitors = NULL;
-	xrr_free_monitors = NULL;
-	int xrandr_major = 0;
-	int xrandr_minor = 0;
-	int event_base, error_base;
-	xrandr_ext_ok = XRRQueryExtension(x11_display, &event_base, &error_base);
-	xrandr_handle = dlopen("libXrandr.so.2", RTLD_LAZY);
-	if (!xrandr_handle) {
-		err = dlerror();
-		fprintf(stderr, "could not load libXrandr.so.2, Error: %s\n", err);
-	} else {
-		XRRQueryVersion(x11_display, &xrandr_major, &xrandr_minor);
-		if (((xrandr_major << 8) | xrandr_minor) >= 0x0105) {
-			xrr_get_monitors = (xrr_get_monitors_t)dlsym(xrandr_handle, "XRRGetMonitors");
-			if (!xrr_get_monitors) {
-				err = dlerror();
-				fprintf(stderr, "could not find symbol XRRGetMonitors\nError: %s\n", err);
-			} else {
-				xrr_free_monitors = (xrr_free_monitors_t)dlsym(xrandr_handle, "XRRFreeMonitors");
-				if (!xrr_free_monitors) {
-					err = dlerror();
-					fprintf(stderr, "could not find XRRFreeMonitors\nError: %s\n", err);
-					xrr_get_monitors = NULL;
-				}
-			}
-		}
-	}
-
-	if (!refresh_device_info()) {
-		OS::get_singleton()->alert("Your system does not support XInput 2.\n"
-								   "Please upgrade your distribution.",
-				"Unable to initialize XInput");
-		return ERR_UNAVAILABLE;
-	}
-
-	xim = XOpenIM(x11_display, NULL, NULL, NULL);
-
-	if (xim == NULL) {
-		WARN_PRINT("XOpenIM failed");
-		xim_style = 0L;
-	} else {
-		::XIMCallback im_destroy_callback;
-		im_destroy_callback.client_data = (::XPointer)(this);
-		im_destroy_callback.callback = (::XIMProc)(xim_destroy_callback);
-		if (XSetIMValues(xim, XNDestroyCallback, &im_destroy_callback,
-					NULL) != NULL) {
-			WARN_PRINT("Error setting XIM destroy callback");
-		}
-
-		::XIMStyles *xim_styles = NULL;
-		xim_style = 0L;
-		char *imvalret = XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
-		if (imvalret != NULL || xim_styles == NULL) {
-			fprintf(stderr, "Input method doesn't support any styles\n");
-		}
-
-		if (xim_styles) {
-			xim_style = 0L;
-			for (int i = 0; i < xim_styles->count_styles; i++) {
-
-				if (xim_styles->supported_styles[i] ==
-						(XIMPreeditNothing | XIMStatusNothing)) {
-
-					xim_style = xim_styles->supported_styles[i];
-					break;
-				}
-			}
-
-			XFree(xim_styles);
-		}
-		XFree(imvalret);
-	}
-
-	//!!!!!!!!!!!!!!!!!!!!!!!!!!
-	//TODO - do Vulkan and GLES2 support checks, driver selection and fallback
-	video_driver_index = p_video_driver;
-#ifndef _MSC_VER
-#warning Forcing vulkan video driver because OpenGL not implemented yet
-#endif
-	video_driver_index = VIDEO_DRIVER_VULKAN;
-
-	print_verbose("Driver: " + String(get_video_driver_name(video_driver_index)) + " [" + itos(video_driver_index) + "]");
-	//!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-	//Create window
-
-	long visualMask = VisualScreenMask;
-	int numberOfVisuals;
-	XVisualInfo vInfoTemplate = {};
-	vInfoTemplate.screen = DefaultScreen(x11_display);
-	XVisualInfo *visualInfo = XGetVisualInfo(x11_display, visualMask, &vInfoTemplate, &numberOfVisuals);
-
-	Colormap colormap = XCreateColormap(x11_display, RootWindow(x11_display, vInfoTemplate.screen), visualInfo->visual, AllocNone);
-
-	XSetWindowAttributes windowAttributes = {};
-	windowAttributes.colormap = colormap;
-	windowAttributes.background_pixel = 0xFFFFFFFF;
-	windowAttributes.border_pixel = 0;
-	windowAttributes.event_mask = KeyPressMask | KeyReleaseMask | StructureNotifyMask | ExposureMask;
-
-	unsigned long valuemask = CWBorderPixel | CWColormap | CWEventMask;
-	x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo->screen), 0, 0, OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height, 0, visualInfo->depth, InputOutput, visualInfo->visual, valuemask, &windowAttributes);
-
-	wm_delete = XInternAtom(x11_display, "WM_DELETE_WINDOW", true);
-	XSetWMProtocols(x11_display, x11_window, &wm_delete, 1);
-
-	//set_class_hint(x11_display, x11_window);
-	XMapWindow(x11_display, x11_window);
-	XFlush(x11_display);
-
-	XSync(x11_display, False);
-	//XSetErrorHandler(oldHandler);
-
-	XFree(visualInfo);
-
-	// Init context and rendering device
-#if defined(OPENGL_ENABLED)
-	if (video_driver_index == VIDEO_DRIVER_GLES2) {
-		if (getenv("DRI_PRIME") == NULL) {
-			int use_prime = -1;
-
-			if (getenv("PRIMUS_DISPLAY") ||
-					getenv("PRIMUS_libGLd") ||
-					getenv("PRIMUS_libGLa") ||
-					getenv("PRIMUS_libGL") ||
-					getenv("PRIMUS_LOAD_GLOBAL") ||
-					getenv("BUMBLEBEE_SOCKET")) {
-
-				print_verbose("Optirun/primusrun detected. Skipping GPU detection");
-				use_prime = 0;
-			}
-
-			if (getenv("LD_LIBRARY_PATH")) {
-				String ld_library_path(getenv("LD_LIBRARY_PATH"));
-				Vector<String> libraries = ld_library_path.split(":");
-
-				for (int i = 0; i < libraries.size(); ++i) {
-					if (FileAccess::exists(libraries[i] + "/libGL.so.1") ||
-							FileAccess::exists(libraries[i] + "/libGL.so")) {
-
-						print_verbose("Custom libGL override detected. Skipping GPU detection");
-						use_prime = 0;
-					}
-				}
-			}
-
-			if (use_prime == -1) {
-				print_verbose("Detecting GPUs, set DRI_PRIME in the environment to override GPU detection logic.");
-				use_prime = detect_prime();
-			}
-
-			if (use_prime) {
-				print_line("Found discrete GPU, setting DRI_PRIME=1 to use it.");
-				print_line("Note: Set DRI_PRIME=0 in the environment to disable Godot from using the discrete GPU.");
-				setenv("DRI_PRIME", "1", 1);
-			}
-		}
-
-		ContextGL_X11::ContextType opengl_api_type = ContextGL_X11::GLES_2_0_COMPATIBLE;
-
-		context_gles2 = memnew(ContextGL_X11(x11_display, x11_window, current_videomode, opengl_api_type));
-
-		if (context_gles2->initialize() != OK) {
-			memdelete(context_gles2);
-			context_gles2 = NULL;
-			ERR_FAIL_V(ERR_UNAVAILABLE);
-		}
-
-		context_gles2->set_use_vsync(current_videomode.use_vsync);
-
-		if (RasterizerGLES2::is_viable() == OK) {
-			RasterizerGLES2::register_config();
-			RasterizerGLES2::make_current();
-		} else {
-			memdelete(context_gles2);
-			context_gles2 = NULL;
-			ERR_FAIL_V(ERR_UNAVAILABLE);
-		}
-	}
-#endif
-#if defined(VULKAN_ENABLED)
-	if (video_driver_index == VIDEO_DRIVER_VULKAN) {
-
-		context_vulkan = memnew(VulkanContextX11);
-		if (context_vulkan->initialize() != OK) {
-			memdelete(context_vulkan);
-			context_vulkan = NULL;
-			ERR_FAIL_V(ERR_UNAVAILABLE);
-		}
-		if (context_vulkan->window_create(x11_window, x11_display, get_video_mode().width, get_video_mode().height) == -1) {
-			memdelete(context_vulkan);
-			context_vulkan = NULL;
-			ERR_FAIL_V(ERR_UNAVAILABLE);
-		}
-
-		//temporary
-		rendering_device_vulkan = memnew(RenderingDeviceVulkan);
-		rendering_device_vulkan->initialize(context_vulkan);
-
-		RasterizerRD::make_current();
-	}
-#endif
-
-	visual_server = memnew(VisualServerRaster);
-	if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
-		visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
-	}
-
-	if (current_videomode.maximized) {
-		current_videomode.maximized = false;
-		set_window_maximized(true);
-		// borderless fullscreen window mode
-	} else if (current_videomode.fullscreen) {
-		current_videomode.fullscreen = false;
-		set_window_fullscreen(true);
-	} else if (current_videomode.borderless_window) {
-		Hints hints;
-		Atom property;
-		hints.flags = 2;
-		hints.decorations = 0;
-		property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
-		XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
-	}
-
-	// make PID known to X11
-	{
-		const long pid = this->get_process_id();
-		Atom net_wm_pid = XInternAtom(x11_display, "_NET_WM_PID", False);
-		XChangeProperty(x11_display, x11_window, net_wm_pid, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&pid, 1);
-	}
-
-	// disable resizable window
-	if (!current_videomode.resizable && !current_videomode.fullscreen) {
-		XSizeHints *xsh;
-		xsh = XAllocSizeHints();
-		xsh->flags = PMinSize | PMaxSize;
-		XWindowAttributes xwa;
-		if (current_videomode.fullscreen) {
-			XGetWindowAttributes(x11_display, DefaultRootWindow(x11_display), &xwa);
-		} else {
-			XGetWindowAttributes(x11_display, x11_window, &xwa);
-		}
-		xsh->min_width = xwa.width;
-		xsh->max_width = xwa.width;
-		xsh->min_height = xwa.height;
-		xsh->max_height = xwa.height;
-		XSetWMNormalHints(x11_display, x11_window, xsh);
-		XFree(xsh);
-	}
-
-	if (current_videomode.always_on_top) {
-		current_videomode.always_on_top = false;
-		set_window_always_on_top(true);
-	}
-
-	ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE);
-	ERR_FAIL_COND_V(x11_window == 0, ERR_UNAVAILABLE);
-
-	XSetWindowAttributes new_attr;
-
-	new_attr.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask |
-						  ButtonReleaseMask | EnterWindowMask |
-						  LeaveWindowMask | PointerMotionMask |
-						  Button1MotionMask |
-						  Button2MotionMask | Button3MotionMask |
-						  Button4MotionMask | Button5MotionMask |
-						  ButtonMotionMask | KeymapStateMask |
-						  ExposureMask | VisibilityChangeMask |
-						  StructureNotifyMask |
-						  SubstructureNotifyMask | SubstructureRedirectMask |
-						  FocusChangeMask | PropertyChangeMask |
-						  ColormapChangeMask | OwnerGrabButtonMask |
-						  im_event_mask;
-
-	XChangeWindowAttributes(x11_display, x11_window, CWEventMask, &new_attr);
-
-	static unsigned char all_mask_data[XIMaskLen(XI_LASTEVENT)] = {};
-	static unsigned char all_master_mask_data[XIMaskLen(XI_LASTEVENT)] = {};
-
-	xi.all_event_mask.deviceid = XIAllDevices;
-	xi.all_event_mask.mask_len = sizeof(all_mask_data);
-	xi.all_event_mask.mask = all_mask_data;
-
-	xi.all_master_event_mask.deviceid = XIAllMasterDevices;
-	xi.all_master_event_mask.mask_len = sizeof(all_master_mask_data);
-	xi.all_master_event_mask.mask = all_master_mask_data;
-
-	XISetMask(xi.all_event_mask.mask, XI_HierarchyChanged);
-	XISetMask(xi.all_master_event_mask.mask, XI_DeviceChanged);
-	XISetMask(xi.all_master_event_mask.mask, XI_RawMotion);
-
-#ifdef TOUCH_ENABLED
-	if (xi.touch_devices.size()) {
-		XISetMask(xi.all_event_mask.mask, XI_TouchBegin);
-		XISetMask(xi.all_event_mask.mask, XI_TouchUpdate);
-		XISetMask(xi.all_event_mask.mask, XI_TouchEnd);
-		XISetMask(xi.all_event_mask.mask, XI_TouchOwnership);
-	}
-#endif
-
-	XISelectEvents(x11_display, x11_window, &xi.all_event_mask, 1);
-	XISelectEvents(x11_display, DefaultRootWindow(x11_display), &xi.all_master_event_mask, 1);
-
-	// Disabled by now since grabbing also blocks mouse events
-	// (they are received as extended events instead of standard events)
-	/*XIClearMask(xi.touch_event_mask.mask, XI_TouchOwnership);
-
-	// Grab touch devices to avoid OS gesture interference
-	for (int i = 0; i < xi.touch_devices.size(); ++i) {
-		XIGrabDevice(x11_display, xi.touch_devices[i], x11_window, CurrentTime, None, XIGrabModeAsync, XIGrabModeAsync, False, &xi.touch_event_mask);
-	}*/
-
-	/* set the titlebar name */
-	XStoreName(x11_display, x11_window, "Godot");
-
-	im_active = false;
-	im_position = Vector2();
-
-	if (xim && xim_style) {
-
-		xic = XCreateIC(xim, XNInputStyle, xim_style, XNClientWindow, x11_window, XNFocusWindow, x11_window, (char *)NULL);
-		if (XGetICValues(xic, XNFilterEvents, &im_event_mask, NULL) != NULL) {
-			WARN_PRINT("XGetICValues couldn't obtain XNFilterEvents value");
-			XDestroyIC(xic);
-			xic = NULL;
-		}
-		if (xic) {
-			XUnsetICFocus(xic);
-		} else {
-			WARN_PRINT("XCreateIC couldn't create xic");
-		}
-	} else {
-
-		xic = NULL;
-		WARN_PRINT("XCreateIC couldn't create xic");
-	}
-
-	cursor_size = XcursorGetDefaultSize(x11_display);
-	cursor_theme = XcursorGetTheme(x11_display);
-
-	if (!cursor_theme) {
-		print_verbose("XcursorGetTheme could not get cursor theme");
-		cursor_theme = "default";
-	}
-
-	for (int i = 0; i < CURSOR_MAX; i++) {
-
-		cursors[i] = None;
-		img[i] = NULL;
-	}
-
-	current_cursor = CURSOR_ARROW;
-
-	for (int i = 0; i < CURSOR_MAX; i++) {
-
-		static const char *cursor_file[] = {
-			"left_ptr",
-			"xterm",
-			"hand2",
-			"cross",
-			"watch",
-			"left_ptr_watch",
-			"fleur",
-			"dnd-move",
-			"crossed_circle",
-			"v_double_arrow",
-			"h_double_arrow",
-			"size_bdiag",
-			"size_fdiag",
-			"move",
-			"row_resize",
-			"col_resize",
-			"question_arrow"
-		};
-
-		img[i] = XcursorLibraryLoadImage(cursor_file[i], cursor_theme, cursor_size);
-		if (!img[i]) {
-			const char *fallback = NULL;
-
-			switch (i) {
-				case CURSOR_POINTING_HAND:
-					fallback = "pointer";
-					break;
-				case CURSOR_CROSS:
-					fallback = "crosshair";
-					break;
-				case CURSOR_WAIT:
-					fallback = "wait";
-					break;
-				case CURSOR_BUSY:
-					fallback = "progress";
-					break;
-				case CURSOR_DRAG:
-					fallback = "grabbing";
-					break;
-				case CURSOR_CAN_DROP:
-					fallback = "hand1";
-					break;
-				case CURSOR_FORBIDDEN:
-					fallback = "forbidden";
-					break;
-				case CURSOR_VSIZE:
-					fallback = "ns-resize";
-					break;
-				case CURSOR_HSIZE:
-					fallback = "ew-resize";
-					break;
-				case CURSOR_BDIAGSIZE:
-					fallback = "fd_double_arrow";
-					break;
-				case CURSOR_FDIAGSIZE:
-					fallback = "bd_double_arrow";
-					break;
-				case CURSOR_MOVE:
-					img[i] = img[CURSOR_DRAG];
-					break;
-				case CURSOR_VSPLIT:
-					fallback = "sb_v_double_arrow";
-					break;
-				case CURSOR_HSPLIT:
-					fallback = "sb_h_double_arrow";
-					break;
-				case CURSOR_HELP:
-					fallback = "help";
-					break;
-			}
-			if (fallback != NULL) {
-				img[i] = XcursorLibraryLoadImage(fallback, cursor_theme, cursor_size);
-			}
-		}
-		if (img[i]) {
-			cursors[i] = XcursorImageLoadCursor(x11_display, img[i]);
-		} else {
-			print_verbose("Failed loading custom cursor: " + String(cursor_file[i]));
-		}
-	}
-
-	{
-		// Creating an empty/transparent cursor
-
-		// Create 1x1 bitmap
-		Pixmap cursormask = XCreatePixmap(x11_display,
-				RootWindow(x11_display, DefaultScreen(x11_display)), 1, 1, 1);
-
-		// Fill with zero
-		XGCValues xgc;
-		xgc.function = GXclear;
-		GC gc = XCreateGC(x11_display, cursormask, GCFunction, &xgc);
-		XFillRectangle(x11_display, cursormask, gc, 0, 0, 1, 1);
-
-		// Color value doesn't matter. Mask zero means no foreground or background will be drawn
-		XColor col = {};
-
-		Cursor cursor = XCreatePixmapCursor(x11_display,
-				cursormask, // source (using cursor mask as placeholder, since it'll all be ignored)
-				cursormask, // mask
-				&col, &col, 0, 0);
-
-		XFreePixmap(x11_display, cursormask);
-		XFreeGC(x11_display, gc);
-
-		if (cursor == None) {
-			ERR_PRINT("FAILED CREATING CURSOR");
-		}
-
-		null_cursor = cursor;
-	}
-	set_cursor_shape(CURSOR_BUSY);
-
-	//Set Xdnd (drag & drop) support
-	Atom XdndAware = XInternAtom(x11_display, "XdndAware", False);
-	Atom version = 5;
-	XChangeProperty(x11_display, x11_window, XdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char *)&version, 1);
-
-	xdnd_enter = XInternAtom(x11_display, "XdndEnter", False);
-	xdnd_position = XInternAtom(x11_display, "XdndPosition", False);
-	xdnd_status = XInternAtom(x11_display, "XdndStatus", False);
-	xdnd_action_copy = XInternAtom(x11_display, "XdndActionCopy", False);
-	xdnd_drop = XInternAtom(x11_display, "XdndDrop", False);
-	xdnd_finished = XInternAtom(x11_display, "XdndFinished", False);
-	xdnd_selection = XInternAtom(x11_display, "XdndSelection", False);
-	requested = None;
-
-	visual_server->init();
-
-	AudioDriverManager::initialize(p_audio_driver);
-
-	input = memnew(Input);
-
-	window_has_focus = true; // Set focus to true at init
-#ifdef JOYDEV_ENABLED
-	joypad = memnew(JoypadLinux(input));
-#endif
-	_ensure_user_data_dir();
-
-	if (p_desired.layered) {
-		set_window_per_pixel_transparency_enabled(true);
-	}
-
-	XEvent xevent;
-	while (XPending(x11_display) > 0) {
-		XNextEvent(x11_display, &xevent);
-		if (xevent.type == ConfigureNotify) {
-			_window_changed(&xevent);
-		}
-	}
-
-	update_real_mouse_position();
-
-	return OK;
-}
-
-bool OS_X11::refresh_device_info() {
-	int event_base, error_base;
-
-	print_verbose("XInput: Refreshing devices.");
-
-	if (!XQueryExtension(x11_display, "XInputExtension", &xi.opcode, &event_base, &error_base)) {
-		print_verbose("XInput extension not available. Please upgrade your distribution.");
-		return false;
-	}
-
-	int xi_major_query = XINPUT_CLIENT_VERSION_MAJOR;
-	int xi_minor_query = XINPUT_CLIENT_VERSION_MINOR;
-
-	if (XIQueryVersion(x11_display, &xi_major_query, &xi_minor_query) != Success) {
-		print_verbose(vformat("XInput 2 not available (server supports %d.%d).", xi_major_query, xi_minor_query));
-		xi.opcode = 0;
-		return false;
-	}
-
-	if (xi_major_query < XINPUT_CLIENT_VERSION_MAJOR || (xi_major_query == XINPUT_CLIENT_VERSION_MAJOR && xi_minor_query < XINPUT_CLIENT_VERSION_MINOR)) {
-		print_verbose(vformat("XInput %d.%d not available (server supports %d.%d). Touch input unavailable.",
-				XINPUT_CLIENT_VERSION_MAJOR, XINPUT_CLIENT_VERSION_MINOR, xi_major_query, xi_minor_query));
-	}
-
-	xi.absolute_devices.clear();
-	xi.touch_devices.clear();
-
-	int dev_count;
-	XIDeviceInfo *info = XIQueryDevice(x11_display, XIAllDevices, &dev_count);
-
-	for (int i = 0; i < dev_count; i++) {
-		XIDeviceInfo *dev = &info[i];
-		if (!dev->enabled)
-			continue;
-		if (!(dev->use == XIMasterPointer || dev->use == XIFloatingSlave))
-			continue;
-
-		bool direct_touch = false;
-		bool absolute_mode = false;
-		int resolution_x = 0;
-		int resolution_y = 0;
-		int range_min_x = 0;
-		int range_min_y = 0;
-		int range_max_x = 0;
-		int range_max_y = 0;
-		int pressure_resolution = 0;
-		int tilt_resolution_x = 0;
-		int tilt_resolution_y = 0;
-		for (int j = 0; j < dev->num_classes; j++) {
-#ifdef TOUCH_ENABLED
-			if (dev->classes[j]->type == XITouchClass && ((XITouchClassInfo *)dev->classes[j])->mode == XIDirectTouch) {
-				direct_touch = true;
-			}
-#endif
-			if (dev->classes[j]->type == XIValuatorClass) {
-				XIValuatorClassInfo *class_info = (XIValuatorClassInfo *)dev->classes[j];
-
-				if (class_info->number == VALUATOR_ABSX && class_info->mode == XIModeAbsolute) {
-					resolution_x = class_info->resolution;
-					range_min_x = class_info->min;
-					range_max_x = class_info->max;
-					absolute_mode = true;
-				} else if (class_info->number == VALUATOR_ABSY && class_info->mode == XIModeAbsolute) {
-					resolution_y = class_info->resolution;
-					range_min_y = class_info->min;
-					range_max_y = class_info->max;
-					absolute_mode = true;
-				} else if (class_info->number == VALUATOR_PRESSURE && class_info->mode == XIModeAbsolute) {
-					pressure_resolution = (class_info->max - class_info->min);
-					if (pressure_resolution == 0) pressure_resolution = 1;
-				} else if (class_info->number == VALUATOR_TILTX && class_info->mode == XIModeAbsolute) {
-					tilt_resolution_x = (class_info->max - class_info->min);
-					if (tilt_resolution_x == 0) tilt_resolution_x = 1;
-				} else if (class_info->number == VALUATOR_TILTY && class_info->mode == XIModeAbsolute) {
-					tilt_resolution_y = (class_info->max - class_info->min);
-					if (tilt_resolution_y == 0) tilt_resolution_y = 1;
-				}
-			}
-		}
-		if (direct_touch) {
-			xi.touch_devices.push_back(dev->deviceid);
-			print_verbose("XInput: Using touch device: " + String(dev->name));
-		}
-		if (absolute_mode) {
-			// If no resolution was reported, use the min/max ranges.
-			if (resolution_x <= 0) {
-				resolution_x = (range_max_x - range_min_x) * abs_resolution_range_mult;
-			}
-			if (resolution_y <= 0) {
-				resolution_y = (range_max_y - range_min_y) * abs_resolution_range_mult;
-			}
-
-			xi.absolute_devices[dev->deviceid] = Vector2(abs_resolution_mult / resolution_x, abs_resolution_mult / resolution_y);
-			print_verbose("XInput: Absolute pointing device: " + String(dev->name));
-		}
-
-		xi.pressure = 0;
-		xi.pen_devices[dev->deviceid] = Vector3(pressure_resolution, tilt_resolution_x, tilt_resolution_y);
-	}
-
-	XIFreeDeviceInfo(info);
-#ifdef TOUCH_ENABLED
-	if (!xi.touch_devices.size()) {
-		print_verbose("XInput: No touch devices found.");
-	}
-#endif
-
-	return true;
-}
-
-void OS_X11::xim_destroy_callback(::XIM im, ::XPointer client_data,
-		::XPointer call_data) {
-
-	WARN_PRINT("Input method stopped");
-	OS_X11 *os = reinterpret_cast<OS_X11 *>(client_data);
-	os->xim = NULL;
-	os->xic = NULL;
-}
-
-void OS_X11::set_ime_active(const bool p_active) {
-
-	im_active = p_active;
-
-	if (!xic)
-		return;
-
-	if (p_active) {
-		XSetICFocus(xic);
-		set_ime_position(im_position);
-	} else {
-		XUnsetICFocus(xic);
-	}
-}
-
-void OS_X11::set_ime_position(const Point2 &p_pos) {
-
-	im_position = p_pos;
-
-	if (!xic)
-		return;
-
-	::XPoint spot;
-	spot.x = short(p_pos.x);
-	spot.y = short(p_pos.y);
-	XVaNestedList preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
-	XSetICValues(xic, XNPreeditAttributes, preedit_attr, NULL);
-	XFree(preedit_attr);
-}
-
-String OS_X11::get_unique_id() const {
-
-	static String machine_id;
-	if (machine_id.empty()) {
-		if (FileAccess *f = FileAccess::open("/etc/machine-id", FileAccess::READ)) {
-			while (machine_id.empty() && !f->eof_reached()) {
-				machine_id = f->get_line().strip_edges();
-			}
-			f->close();
-			memdelete(f);
-		}
-	}
-	return machine_id;
-}
-
-void OS_X11::finalize() {
-
-	if (main_loop)
-		memdelete(main_loop);
-	main_loop = NULL;
-
-	/*
-	if (debugger_connection_console) {
-		memdelete(debugger_connection_console);
-	}
-	*/
-#ifdef ALSAMIDI_ENABLED
-	driver_alsamidi.close();
-#endif
-
-#ifdef JOYDEV_ENABLED
-	memdelete(joypad);
-#endif
-
-	xi.touch_devices.clear();
-	xi.state.clear();
-
-	memdelete(input);
-
-	cursors_cache.clear();
-	visual_server->finish();
-	memdelete(visual_server);
-
-#if defined(OPENGL_ENABLED)
-	if (video_driver_index == VIDEO_DRIVER_GLES2) {
-
-		if (context_gles2)
-			memdelete(context_gles2);
-	}
-#endif
-#if defined(VULKAN_ENABLED)
-	if (video_driver_index == VIDEO_DRIVER_VULKAN) {
-
-		if (rendering_device_vulkan) {
-			rendering_device_vulkan->finalize();
-			memdelete(rendering_device_vulkan);
-		}
-
-		if (context_vulkan)
-			memdelete(context_vulkan);
-	}
-#endif
-
-	if (xrandr_handle)
-		dlclose(xrandr_handle);
-
-	XUnmapWindow(x11_display, x11_window);
-	XDestroyWindow(x11_display, x11_window);
-
-	for (int i = 0; i < CURSOR_MAX; i++) {
-		if (cursors[i] != None)
-			XFreeCursor(x11_display, cursors[i]);
-		if (img[i] != NULL)
-			XcursorImageDestroy(img[i]);
-	};
-
-	if (xic) {
-		XDestroyIC(xic);
-	}
-	if (xim) {
-		XCloseIM(xim);
-	}
-
-	XCloseDisplay(x11_display);
-	if (xmbstring)
-		memfree(xmbstring);
-
-	args.clear();
-}
-
-void OS_X11::set_mouse_mode(MouseMode p_mode) {
-
-	if (p_mode == mouse_mode)
-		return;
-
-	if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED)
-		XUngrabPointer(x11_display, CurrentTime);
-
-	// The only modes that show a cursor are VISIBLE and CONFINED
-	bool showCursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED);
-
-	if (showCursor) {
-		XDefineCursor(x11_display, x11_window, cursors[current_cursor]); // show cursor
-	} else {
-		XDefineCursor(x11_display, x11_window, null_cursor); // hide cursor
-	}
-
-	mouse_mode = p_mode;
-
-	if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) {
-
-		//flush pending motion events
-		flush_mouse_motion();
-
-		if (XGrabPointer(
-					x11_display, x11_window, True,
-					ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
-					GrabModeAsync, GrabModeAsync, x11_window, None, CurrentTime) != GrabSuccess) {
-			ERR_PRINT("NO GRAB");
-		}
-
-		if (mouse_mode == MOUSE_MODE_CAPTURED) {
-			center.x = current_videomode.width / 2;
-			center.y = current_videomode.height / 2;
-
-			XWarpPointer(x11_display, None, x11_window,
-					0, 0, 0, 0, (int)center.x, (int)center.y);
-
-			input->set_mouse_position(center);
-		}
-	} else {
-		do_mouse_warp = false;
-	}
-
-	XFlush(x11_display);
-}
-
-void OS_X11::warp_mouse_position(const Point2 &p_to) {
-
-	if (mouse_mode == MOUSE_MODE_CAPTURED) {
-
-		last_mouse_pos = p_to;
-	} else {
-
-		/*XWindowAttributes xwa;
-		XGetWindowAttributes(x11_display, x11_window, &xwa);
-		printf("%d %d\n", xwa.x, xwa.y); needed? */
-
-		XWarpPointer(x11_display, None, x11_window,
-				0, 0, 0, 0, (int)p_to.x, (int)p_to.y);
-	}
-}
-
-void OS_X11::flush_mouse_motion() {
-	while (true) {
-		if (XPending(x11_display) > 0) {
-			XEvent event;
-			XPeekEvent(x11_display, &event);
-
-			if (XGetEventData(x11_display, &event.xcookie) && event.xcookie.type == GenericEvent && event.xcookie.extension == xi.opcode) {
-				XIDeviceEvent *event_data = (XIDeviceEvent *)event.xcookie.data;
-
-				if (event_data->evtype == XI_RawMotion) {
-					XNextEvent(x11_display, &event);
-				} else {
-					break;
-				}
-			} else {
-				break;
-			}
-		} else {
-			break;
-		}
-	}
-
-	xi.relative_motion.x = 0;
-	xi.relative_motion.y = 0;
-}
-
-OS::MouseMode OS_X11::get_mouse_mode() const {
-	return mouse_mode;
-}
-
-int OS_X11::get_mouse_button_state() const {
-	return last_button_state;
-}
-
-Point2 OS_X11::get_mouse_position() const {
-	return last_mouse_pos;
-}
-
-bool OS_X11::get_window_per_pixel_transparency_enabled() const {
-
-	if (!is_layered_allowed()) return false;
-	return layered_window;
-}
-
-void OS_X11::set_window_per_pixel_transparency_enabled(bool p_enabled) {
-
-	if (!is_layered_allowed()) return;
-	if (layered_window != p_enabled) {
-		if (p_enabled) {
-			set_borderless_window(true);
-			layered_window = true;
-		} else {
-			layered_window = false;
-		}
-	}
-}
-
-void OS_X11::set_window_title(const String &p_title) {
-	XStoreName(x11_display, x11_window, p_title.utf8().get_data());
-
-	Atom _net_wm_name = XInternAtom(x11_display, "_NET_WM_NAME", false);
-	Atom utf8_string = XInternAtom(x11_display, "UTF8_STRING", false);
-	XChangeProperty(x11_display, x11_window, _net_wm_name, utf8_string, 8, PropModeReplace, (unsigned char *)p_title.utf8().get_data(), p_title.utf8().length());
-}
-
-void OS_X11::set_video_mode(const VideoMode &p_video_mode, int p_screen) {
-}
-
-OS::VideoMode OS_X11::get_video_mode(int p_screen) const {
-	return current_videomode;
-}
-
-void OS_X11::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const {
-}
-
-void OS_X11::set_wm_fullscreen(bool p_enabled) {
-	if (p_enabled && !get_borderless_window()) {
-		// remove decorations if the window is not already borderless
-		Hints hints;
-		Atom property;
-		hints.flags = 2;
-		hints.decorations = 0;
-		property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
-		XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
-	}
-
-	if (p_enabled && !is_window_resizable()) {
-		// Set the window as resizable to prevent window managers to ignore the fullscreen state flag.
-		XSizeHints *xsh;
-
-		xsh = XAllocSizeHints();
-		xsh->flags = 0L;
-		XSetWMNormalHints(x11_display, x11_window, xsh);
-		XFree(xsh);
-	}
-
-	// Using EWMH -- Extended Window Manager Hints
-	XEvent xev;
-	Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
-	Atom wm_fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False);
-
-	memset(&xev, 0, sizeof(xev));
-	xev.type = ClientMessage;
-	xev.xclient.window = x11_window;
-	xev.xclient.message_type = wm_state;
-	xev.xclient.format = 32;
-	xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
-	xev.xclient.data.l[1] = wm_fullscreen;
-	xev.xclient.data.l[2] = 0;
-
-	XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
-
-	// set bypass compositor hint
-	Atom bypass_compositor = XInternAtom(x11_display, "_NET_WM_BYPASS_COMPOSITOR", False);
-	unsigned long compositing_disable_on = p_enabled ? 1 : 0;
-	XChangeProperty(x11_display, x11_window, bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&compositing_disable_on, 1);
-
-	XFlush(x11_display);
-
-	if (!p_enabled) {
-		// Reset the non-resizable flags if we un-set these before.
-		Size2 size = get_window_size();
-		XSizeHints *xsh;
-		xsh = XAllocSizeHints();
-		if (!is_window_resizable()) {
-			xsh->flags = PMinSize | PMaxSize;
-			xsh->min_width = size.x;
-			xsh->max_width = size.x;
-			xsh->min_height = size.y;
-			xsh->max_height = size.y;
-		} else {
-			xsh->flags = 0L;
-			if (min_size != Size2()) {
-				xsh->flags |= PMinSize;
-				xsh->min_width = min_size.x;
-				xsh->min_height = min_size.y;
-			}
-			if (max_size != Size2()) {
-				xsh->flags |= PMaxSize;
-				xsh->max_width = max_size.x;
-				xsh->max_height = max_size.y;
-			}
-		}
-		XSetWMNormalHints(x11_display, x11_window, xsh);
-		XFree(xsh);
-
-		// put back or remove decorations according to the last set borderless state
-		Hints hints;
-		Atom property;
-		hints.flags = 2;
-		hints.decorations = current_videomode.borderless_window ? 0 : 1;
-		property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
-		XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
-	}
-}
-
-void OS_X11::set_wm_above(bool p_enabled) {
-	Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
-	Atom wm_above = XInternAtom(x11_display, "_NET_WM_STATE_ABOVE", False);
-
-	XClientMessageEvent xev;
-	memset(&xev, 0, sizeof(xev));
-	xev.type = ClientMessage;
-	xev.window = x11_window;
-	xev.message_type = wm_state;
-	xev.format = 32;
-	xev.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
-	xev.data.l[1] = wm_above;
-	xev.data.l[3] = 1;
-	XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xev);
-}
-
-int OS_X11::get_screen_count() const {
-	// Using Xinerama Extension
-	int event_base, error_base;
-	const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base);
-	if (!ext_okay) return 0;
-
-	int count;
-	XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
-	XFree(xsi);
-	return count;
-}
-
-int OS_X11::get_current_screen() const {
-	int x, y;
-	Window child;
-	XTranslateCoordinates(x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child);
-
-	int count = get_screen_count();
-	for (int i = 0; i < count; i++) {
-		Point2i pos = get_screen_position(i);
-		Size2i size = get_screen_size(i);
-		if ((x >= pos.x && x < pos.x + size.width) && (y >= pos.y && y < pos.y + size.height))
-			return i;
-	}
-	return 0;
-}
-
-void OS_X11::set_current_screen(int p_screen) {
-	int count = get_screen_count();
-	if (p_screen >= count) return;
-
-	if (current_videomode.fullscreen) {
-		Point2i position = get_screen_position(p_screen);
-		Size2i size = get_screen_size(p_screen);
-
-		XMoveResizeWindow(x11_display, x11_window, position.x, position.y, size.x, size.y);
-	} else {
-		if (p_screen != get_current_screen()) {
-			Point2i position = get_screen_position(p_screen);
-			XMoveWindow(x11_display, x11_window, position.x, position.y);
-		}
-	}
-}
-
-Point2 OS_X11::get_screen_position(int p_screen) const {
-	if (p_screen == -1) {
-		p_screen = get_current_screen();
-	}
-
-	// Using Xinerama Extension
-	int event_base, error_base;
-	const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base);
-	if (!ext_okay) {
-		return Point2i(0, 0);
-	}
-
-	int count;
-	XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
-	if (p_screen >= count) {
-		return Point2i(0, 0);
-	}
-
-	Point2i position = Point2i(xsi[p_screen].x_org, xsi[p_screen].y_org);
-
-	XFree(xsi);
-
-	return position;
-}
-
-Size2 OS_X11::get_screen_size(int p_screen) const {
-	if (p_screen == -1) {
-		p_screen = get_current_screen();
-	}
-
-	// Using Xinerama Extension
-	int event_base, error_base;
-	const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base);
-	if (!ext_okay) return Size2i(0, 0);
-
-	int count;
-	XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
-	if (p_screen >= count) return Size2i(0, 0);
-
-	Size2i size = Point2i(xsi[p_screen].width, xsi[p_screen].height);
-	XFree(xsi);
-	return size;
-}
-
-int OS_X11::get_screen_dpi(int p_screen) const {
-	if (p_screen == -1) {
-		p_screen = get_current_screen();
-	}
-
-	//invalid screen?
-	ERR_FAIL_INDEX_V(p_screen, get_screen_count(), 0);
-
-	//Get physical monitor Dimensions through XRandR and calculate dpi
-	Size2 sc = get_screen_size(p_screen);
-	if (xrandr_ext_ok) {
-		int count = 0;
-		if (xrr_get_monitors) {
-			xrr_monitor_info *monitors = xrr_get_monitors(x11_display, x11_window, true, &count);
-			if (p_screen < count) {
-				double xdpi = sc.width / (double)monitors[p_screen].mwidth * 25.4;
-				double ydpi = sc.height / (double)monitors[p_screen].mheight * 25.4;
-				xrr_free_monitors(monitors);
-				return (xdpi + ydpi) / 2;
-			}
-			xrr_free_monitors(monitors);
-		} else if (p_screen == 0) {
-			XRRScreenSize *sizes = XRRSizes(x11_display, 0, &count);
-			if (sizes) {
-				double xdpi = sc.width / (double)sizes[0].mwidth * 25.4;
-				double ydpi = sc.height / (double)sizes[0].mheight * 25.4;
-				return (xdpi + ydpi) / 2;
-			}
-		}
-	}
-
-	int width_mm = DisplayWidthMM(x11_display, p_screen);
-	int height_mm = DisplayHeightMM(x11_display, p_screen);
-	double xdpi = (width_mm ? sc.width / (double)width_mm * 25.4 : 0);
-	double ydpi = (height_mm ? sc.height / (double)height_mm * 25.4 : 0);
-	if (xdpi || ydpi)
-		return (xdpi + ydpi) / (xdpi && ydpi ? 2 : 1);
-
-	//could not get dpi
-	return 96;
-}
-
-Point2 OS_X11::get_window_position() const {
-	int x, y;
-	Window child;
-	XTranslateCoordinates(x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child);
-	return Point2i(x, y);
-}
-
-void OS_X11::set_window_position(const Point2 &p_position) {
-	int x = 0;
-	int y = 0;
-	if (!get_borderless_window()) {
-		//exclude window decorations
-		XSync(x11_display, False);
-		Atom prop = XInternAtom(x11_display, "_NET_FRAME_EXTENTS", True);
-		if (prop != None) {
-			Atom type;
-			int format;
-			unsigned long len;
-			unsigned long remaining;
-			unsigned char *data = NULL;
-			if (XGetWindowProperty(x11_display, x11_window, prop, 0, 4, False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) {
-				if (format == 32 && len == 4) {
-					long *extents = (long *)data;
-					x = extents[0];
-					y = extents[2];
-				}
-				XFree(data);
-			}
-		}
-	}
-	XMoveWindow(x11_display, x11_window, p_position.x - x, p_position.y - y);
-	update_real_mouse_position();
-}
-
-Size2 OS_X11::get_window_size() const {
-	// Use current_videomode width and height instead of XGetWindowAttributes
-	// since right after a XResizeWindow the attributes may not be updated yet
-	return Size2i(current_videomode.width, current_videomode.height);
-}
-
-Size2 OS_X11::get_real_window_size() const {
-	XWindowAttributes xwa;
-	XSync(x11_display, False);
-	XGetWindowAttributes(x11_display, x11_window, &xwa);
-	int w = xwa.width;
-	int h = xwa.height;
-	Atom prop = XInternAtom(x11_display, "_NET_FRAME_EXTENTS", True);
-	if (prop != None) {
-		Atom type;
-		int format;
-		unsigned long len;
-		unsigned long remaining;
-		unsigned char *data = NULL;
-		if (XGetWindowProperty(x11_display, x11_window, prop, 0, 4, False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) {
-			if (format == 32 && len == 4) {
-				long *extents = (long *)data;
-				w += extents[0] + extents[1]; // left, right
-				h += extents[2] + extents[3]; // top, bottom
-			}
-			XFree(data);
-		}
-	}
-	return Size2(w, h);
-}
-
-Size2 OS_X11::get_max_window_size() const {
-	return max_size;
-}
-
-Size2 OS_X11::get_min_window_size() const {
-	return min_size;
-}
-
-void OS_X11::set_min_window_size(const Size2 p_size) {
-
-	if ((p_size != Size2()) && (max_size != Size2()) && ((p_size.x > max_size.x) || (p_size.y > max_size.y))) {
-		ERR_PRINT("Minimum window size can't be larger than maximum window size!");
-		return;
-	}
-	min_size = p_size;
-
-	if (is_window_resizable()) {
-		XSizeHints *xsh;
-		xsh = XAllocSizeHints();
-		xsh->flags = 0L;
-		if (min_size != Size2()) {
-			xsh->flags |= PMinSize;
-			xsh->min_width = min_size.x;
-			xsh->min_height = min_size.y;
-		}
-		if (max_size != Size2()) {
-			xsh->flags |= PMaxSize;
-			xsh->max_width = max_size.x;
-			xsh->max_height = max_size.y;
-		}
-		XSetWMNormalHints(x11_display, x11_window, xsh);
-		XFree(xsh);
-
-		XFlush(x11_display);
-	}
-}
-
-void OS_X11::set_max_window_size(const Size2 p_size) {
-
-	if ((p_size != Size2()) && ((p_size.x < min_size.x) || (p_size.y < min_size.y))) {
-		ERR_PRINT("Maximum window size can't be smaller than minimum window size!");
-		return;
-	}
-	max_size = p_size;
-
-	if (is_window_resizable()) {
-		XSizeHints *xsh;
-		xsh = XAllocSizeHints();
-		xsh->flags = 0L;
-		if (min_size != Size2()) {
-			xsh->flags |= PMinSize;
-			xsh->min_width = min_size.x;
-			xsh->min_height = min_size.y;
-		}
-		if (max_size != Size2()) {
-			xsh->flags |= PMaxSize;
-			xsh->max_width = max_size.x;
-			xsh->max_height = max_size.y;
-		}
-		XSetWMNormalHints(x11_display, x11_window, xsh);
-		XFree(xsh);
-
-		XFlush(x11_display);
-	}
-}
-
-void OS_X11::set_window_size(const Size2 p_size) {
-
-	if (current_videomode.width == p_size.width && current_videomode.height == p_size.height)
-		return;
-
-	XWindowAttributes xwa;
-	XSync(x11_display, False);
-	XGetWindowAttributes(x11_display, x11_window, &xwa);
-	int old_w = xwa.width;
-	int old_h = xwa.height;
-
-	// If window resizable is disabled we need to update the attributes first
-	XSizeHints *xsh;
-	xsh = XAllocSizeHints();
-	if (!is_window_resizable()) {
-		xsh->flags = PMinSize | PMaxSize;
-		xsh->min_width = p_size.x;
-		xsh->max_width = p_size.x;
-		xsh->min_height = p_size.y;
-		xsh->max_height = p_size.y;
-	} else {
-		xsh->flags = 0L;
-		if (min_size != Size2()) {
-			xsh->flags |= PMinSize;
-			xsh->min_width = min_size.x;
-			xsh->min_height = min_size.y;
-		}
-		if (max_size != Size2()) {
-			xsh->flags |= PMaxSize;
-			xsh->max_width = max_size.x;
-			xsh->max_height = max_size.y;
-		}
-	}
-	XSetWMNormalHints(x11_display, x11_window, xsh);
-	XFree(xsh);
-
-	// Resize the window
-	XResizeWindow(x11_display, x11_window, p_size.x, p_size.y);
-
-	// Update our videomode width and height
-	current_videomode.width = p_size.x;
-	current_videomode.height = p_size.y;
-
-	for (int timeout = 0; timeout < 50; ++timeout) {
-		XSync(x11_display, False);
-		XGetWindowAttributes(x11_display, x11_window, &xwa);
-
-		if (old_w != xwa.width || old_h != xwa.height)
-			break;
-
-		usleep(10000);
-	}
-}
-
-void OS_X11::set_window_fullscreen(bool p_enabled) {
-
-	if (current_videomode.fullscreen == p_enabled)
-		return;
-
-	if (layered_window)
-		set_window_per_pixel_transparency_enabled(false);
-
-	if (p_enabled && current_videomode.always_on_top) {
-		// Fullscreen + Always-on-top requires a maximized window on some window managers (Metacity)
-		set_window_maximized(true);
-	}
-	set_wm_fullscreen(p_enabled);
-	if (!p_enabled && current_videomode.always_on_top) {
-		// Restore
-		set_window_maximized(false);
-	}
-	if (!p_enabled) {
-		set_window_position(last_position_before_fs);
-	} else {
-		last_position_before_fs = get_window_position();
-	}
-	current_videomode.fullscreen = p_enabled;
-}
-
-bool OS_X11::is_window_fullscreen() const {
-	return current_videomode.fullscreen;
-}
-
-void OS_X11::set_window_resizable(bool p_enabled) {
-
-	XSizeHints *xsh;
-	xsh = XAllocSizeHints();
-	if (!p_enabled) {
-		Size2 size = get_window_size();
-
-		xsh->flags = PMinSize | PMaxSize;
-		xsh->min_width = size.x;
-		xsh->max_width = size.x;
-		xsh->min_height = size.y;
-		xsh->max_height = size.y;
-	} else {
-		xsh->flags = 0L;
-		if (min_size != Size2()) {
-			xsh->flags |= PMinSize;
-			xsh->min_width = min_size.x;
-			xsh->min_height = min_size.y;
-		}
-		if (max_size != Size2()) {
-			xsh->flags |= PMaxSize;
-			xsh->max_width = max_size.x;
-			xsh->max_height = max_size.y;
-		}
-	}
-
-	XSetWMNormalHints(x11_display, x11_window, xsh);
-	XFree(xsh);
-
-	current_videomode.resizable = p_enabled;
-
-	XFlush(x11_display);
-}
-
-bool OS_X11::is_window_resizable() const {
-	return current_videomode.resizable;
-}
-
-void OS_X11::set_window_minimized(bool p_enabled) {
-	// Using ICCCM -- Inter-Client Communication Conventions Manual
-	XEvent xev;
-	Atom wm_change = XInternAtom(x11_display, "WM_CHANGE_STATE", False);
-
-	memset(&xev, 0, sizeof(xev));
-	xev.type = ClientMessage;
-	xev.xclient.window = x11_window;
-	xev.xclient.message_type = wm_change;
-	xev.xclient.format = 32;
-	xev.xclient.data.l[0] = p_enabled ? WM_IconicState : WM_NormalState;
-
-	XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
-
-	Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
-	Atom wm_hidden = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False);
-
-	memset(&xev, 0, sizeof(xev));
-	xev.type = ClientMessage;
-	xev.xclient.window = x11_window;
-	xev.xclient.message_type = wm_state;
-	xev.xclient.format = 32;
-	xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
-	xev.xclient.data.l[1] = wm_hidden;
-
-	XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
-}
-
-bool OS_X11::is_window_minimized() const {
-	// Using ICCCM -- Inter-Client Communication Conventions Manual
-	Atom property = XInternAtom(x11_display, "WM_STATE", True);
-	Atom type;
-	int format;
-	unsigned long len;
-	unsigned long remaining;
-	unsigned char *data = NULL;
-
-	int result = XGetWindowProperty(
-			x11_display,
-			x11_window,
-			property,
-			0,
-			32,
-			False,
-			AnyPropertyType,
-			&type,
-			&format,
-			&len,
-			&remaining,
-			&data);
-
-	if (result == Success) {
-		long *state = (long *)data;
-		if (state[0] == WM_IconicState)
-			return true;
-	}
-	return false;
-}
-
-void OS_X11::set_window_maximized(bool p_enabled) {
-	if (is_window_maximized() == p_enabled)
-		return;
-
-	// Using EWMH -- Extended Window Manager Hints
-	XEvent xev;
-	Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
-	Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
-	Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
-
-	memset(&xev, 0, sizeof(xev));
-	xev.type = ClientMessage;
-	xev.xclient.window = x11_window;
-	xev.xclient.message_type = wm_state;
-	xev.xclient.format = 32;
-	xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
-	xev.xclient.data.l[1] = wm_max_horz;
-	xev.xclient.data.l[2] = wm_max_vert;
-
-	XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
-
-	if (p_enabled && is_window_maximize_allowed()) {
-		// Wait for effective resizing (so the GLX context is too).
-		// Give up after 0.5s, it's not going to happen on this WM.
-		// https://github.com/godotengine/godot/issues/19978
-		for (int attempt = 0; !is_window_maximized() && attempt < 50; attempt++) {
-			usleep(10000);
-		}
-	}
-
-	maximized = p_enabled;
-}
-
-bool OS_X11::is_window_maximize_allowed() {
-	Atom property = XInternAtom(x11_display, "_NET_WM_ALLOWED_ACTIONS", False);
-	Atom type;
-	int format;
-	unsigned long len;
-	unsigned long remaining;
-	unsigned char *data = NULL;
-
-	int result = XGetWindowProperty(
-			x11_display,
-			x11_window,
-			property,
-			0,
-			1024,
-			False,
-			XA_ATOM,
-			&type,
-			&format,
-			&len,
-			&remaining,
-			&data);
-
-	if (result == Success) {
-		Atom *atoms = (Atom *)data;
-		Atom wm_act_max_horz = XInternAtom(x11_display, "_NET_WM_ACTION_MAXIMIZE_HORZ", False);
-		Atom wm_act_max_vert = XInternAtom(x11_display, "_NET_WM_ACTION_MAXIMIZE_VERT", False);
-		bool found_wm_act_max_horz = false;
-		bool found_wm_act_max_vert = false;
-
-		for (uint64_t i = 0; i < len; i++) {
-			if (atoms[i] == wm_act_max_horz)
-				found_wm_act_max_horz = true;
-			if (atoms[i] == wm_act_max_vert)
-				found_wm_act_max_vert = true;
-
-			if (found_wm_act_max_horz || found_wm_act_max_vert)
-				return true;
-		}
-		XFree(atoms);
-	}
-
-	return false;
-}
-
-bool OS_X11::is_window_maximized() const {
-	// Using EWMH -- Extended Window Manager Hints
-	Atom property = XInternAtom(x11_display, "_NET_WM_STATE", False);
-	Atom type;
-	int format;
-	unsigned long len;
-	unsigned long remaining;
-	unsigned char *data = NULL;
-	bool retval = false;
-
-	int result = XGetWindowProperty(
-			x11_display,
-			x11_window,
-			property,
-			0,
-			1024,
-			False,
-			XA_ATOM,
-			&type,
-			&format,
-			&len,
-			&remaining,
-			&data);
-
-	if (result == Success) {
-		Atom *atoms = (Atom *)data;
-		Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
-		Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
-		bool found_wm_max_horz = false;
-		bool found_wm_max_vert = false;
-
-		for (uint64_t i = 0; i < len; i++) {
-			if (atoms[i] == wm_max_horz)
-				found_wm_max_horz = true;
-			if (atoms[i] == wm_max_vert)
-				found_wm_max_vert = true;
-
-			if (found_wm_max_horz && found_wm_max_vert) {
-				retval = true;
-				break;
-			}
-		}
-	}
-
-	XFree(data);
-	return retval;
-}
-
-void OS_X11::set_window_always_on_top(bool p_enabled) {
-	if (is_window_always_on_top() == p_enabled)
-		return;
-
-	if (p_enabled && current_videomode.fullscreen) {
-		// Fullscreen + Always-on-top requires a maximized window on some window managers (Metacity)
-		set_window_maximized(true);
-	}
-	set_wm_above(p_enabled);
-	if (!p_enabled && !current_videomode.fullscreen) {
-		// Restore
-		set_window_maximized(false);
-	}
-
-	current_videomode.always_on_top = p_enabled;
-}
-
-bool OS_X11::is_window_always_on_top() const {
-	return current_videomode.always_on_top;
-}
-
-bool OS_X11::is_window_focused() const {
-	return window_focused;
-}
-
-void OS_X11::set_borderless_window(bool p_borderless) {
-
-	if (get_borderless_window() == p_borderless)
-		return;
-
-	if (!p_borderless && layered_window)
-		set_window_per_pixel_transparency_enabled(false);
-
-	current_videomode.borderless_window = p_borderless;
-
-	Hints hints;
-	Atom property;
-	hints.flags = 2;
-	hints.decorations = current_videomode.borderless_window ? 0 : 1;
-	property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
-	XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
-
-	// Preserve window size
-	set_window_size(Size2(current_videomode.width, current_videomode.height));
-}
-
-bool OS_X11::get_borderless_window() {
-
-	bool borderless = current_videomode.borderless_window;
-	Atom prop = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
-	if (prop != None) {
-
-		Atom type;
-		int format;
-		unsigned long len;
-		unsigned long remaining;
-		unsigned char *data = NULL;
-		if (XGetWindowProperty(x11_display, x11_window, prop, 0, sizeof(Hints), False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) {
-			if (data && (format == 32) && (len >= 5)) {
-				borderless = !((Hints *)data)->decorations;
-			}
-			XFree(data);
-		}
-	}
-	return borderless;
-}
-
-void OS_X11::request_attention() {
-	// Using EWMH -- Extended Window Manager Hints
-	//
-	// Sets the _NET_WM_STATE_DEMANDS_ATTENTION atom for WM_STATE
-	// Will be unset by the window manager after user react on the request for attention
-
-	XEvent xev;
-	Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
-	Atom wm_attention = XInternAtom(x11_display, "_NET_WM_STATE_DEMANDS_ATTENTION", False);
-
-	memset(&xev, 0, sizeof(xev));
-	xev.type = ClientMessage;
-	xev.xclient.window = x11_window;
-	xev.xclient.message_type = wm_state;
-	xev.xclient.format = 32;
-	xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
-	xev.xclient.data.l[1] = wm_attention;
-
-	XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
-	XFlush(x11_display);
-}
-
-void OS_X11::get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state) {
-
-	state->set_shift((p_x11_state & ShiftMask));
-	state->set_control((p_x11_state & ControlMask));
-	state->set_alt((p_x11_state & Mod1Mask /*|| p_x11_state&Mod5Mask*/)); //altgr should not count as alt
-	state->set_metakey((p_x11_state & Mod4Mask));
-}
-
-unsigned int OS_X11::get_mouse_button_state(unsigned int p_x11_button, int p_x11_type) {
-
-	unsigned int mask = 1 << (p_x11_button - 1);
-
-	if (p_x11_type == ButtonPress) {
-		last_button_state |= mask;
-	} else {
-		last_button_state &= ~mask;
-	}
-
-	return last_button_state;
-}
-
-void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
-
-	// X11 functions don't know what const is
-	XKeyEvent *xkeyevent = p_event;
-
-	// This code was pretty difficult to write.
-	// The docs stink and every toolkit seems to
-	// do it in a different way.
-
-	/* Phase 1, obtain a proper keysym */
-
-	// This was also very difficult to figure out.
-	// You'd expect you could just use Keysym provided by
-	// XKeycodeToKeysym to obtain internationalized
-	// input.. WRONG!!
-	// you must use XLookupString (???) which not only wastes
-	// cycles generating an unnecessary string, but also
-	// still works in half the cases. (won't handle deadkeys)
-	// For more complex input methods (deadkeys and more advanced)
-	// you have to use XmbLookupString (??).
-	// So.. then you have to chosse which of both results
-	// you want to keep.
-	// This is a real bizarreness and cpu waster.
-
-	KeySym keysym_keycode = 0; // keysym used to find a keycode
-	KeySym keysym_unicode = 0; // keysym used to find unicode
-
-	// XLookupString returns keysyms usable as nice scancodes/
-	char str[256 + 1];
-	XKeyEvent xkeyevent_no_mod = *xkeyevent;
-	xkeyevent_no_mod.state &= ~ShiftMask;
-	xkeyevent_no_mod.state &= ~ControlMask;
-	XLookupString(xkeyevent, str, 256, &keysym_unicode, NULL);
-	XLookupString(&xkeyevent_no_mod, NULL, 0, &keysym_keycode, NULL);
-
-	// Meanwhile, XLookupString returns keysyms useful for unicode.
-
-	if (!xmbstring) {
-		// keep a temporary buffer for the string
-		xmbstring = (char *)memalloc(sizeof(char) * 8);
-		xmblen = 8;
-	}
-
-	if (xkeyevent->type == KeyPress && xic) {
-
-		Status status;
-#ifdef X_HAVE_UTF8_STRING
-		int utf8len = 8;
-		char *utf8string = (char *)memalloc(sizeof(char) * utf8len);
-		int utf8bytes = Xutf8LookupString(xic, xkeyevent, utf8string,
-				utf8len - 1, &keysym_unicode, &status);
-		if (status == XBufferOverflow) {
-			utf8len = utf8bytes + 1;
-			utf8string = (char *)memrealloc(utf8string, utf8len);
-			utf8bytes = Xutf8LookupString(xic, xkeyevent, utf8string,
-					utf8len - 1, &keysym_unicode, &status);
-		}
-		utf8string[utf8bytes] = '\0';
-
-		if (status == XLookupChars) {
-			bool keypress = xkeyevent->type == KeyPress;
-			unsigned int keycode = KeyMappingX11::get_keycode(keysym_keycode);
-			unsigned int physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
-
-			if (keycode >= 'a' && keycode <= 'z')
-				keycode -= 'a' - 'A';
-
-			String tmp;
-			tmp.parse_utf8(utf8string, utf8bytes);
-			for (int i = 0; i < tmp.length(); i++) {
-				Ref<InputEventKey> k;
-				k.instance();
-				if (physical_keycode == 0 && keycode == 0 && tmp[i] == 0) {
-					continue;
-				}
-
-				if (keycode == 0)
-					keycode = physical_keycode;
-
-				get_key_modifier_state(xkeyevent->state, k);
-
-				k->set_unicode(tmp[i]);
-
-				k->set_pressed(keypress);
-
-				k->set_keycode(keycode);
-
-				k->set_physical_keycode(physical_keycode);
-
-				k->set_echo(false);
-
-				if (k->get_keycode() == KEY_BACKTAB) {
-					//make it consistent across platforms.
-					k->set_keycode(KEY_TAB);
-					k->set_physical_keycode(KEY_TAB);
-					k->set_shift(true);
-				}
-
-				input->accumulate_input_event(k);
-			}
-			memfree(utf8string);
-			return;
-		}
-		memfree(utf8string);
-#else
-		do {
-
-			int mnbytes = XmbLookupString(xic, xkeyevent, xmbstring, xmblen - 1, &keysym_unicode, &status);
-			xmbstring[mnbytes] = '\0';
-
-			if (status == XBufferOverflow) {
-				xmblen = mnbytes + 1;
-				xmbstring = (char *)memrealloc(xmbstring, xmblen);
-			}
-		} while (status == XBufferOverflow);
-#endif
-	}
-
-	/* Phase 2, obtain a pigui keycode from the keysym */
-
-	// KeyMappingX11 just translated the X11 keysym to a PIGUI
-	// keysym, so it works in all platforms the same.
-
-	unsigned int keycode = KeyMappingX11::get_keycode(keysym_keycode);
-	unsigned int physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
-
-	/* Phase 3, obtain a unicode character from the keysym */
-
-	// KeyMappingX11 also translates keysym to unicode.
-	// It does a binary search on a table to translate
-	// most properly.
-	unsigned int unicode = keysym_unicode > 0 ? KeyMappingX11::get_unicode_from_keysym(keysym_unicode) : 0;
-
-	/* Phase 4, determine if event must be filtered */
-
-	// This seems to be a side-effect of using XIM.
-	// XEventFilter looks like a core X11 function,
-	// but it's actually just used to see if we must
-	// ignore a deadkey, or events XIM determines
-	// must not reach the actual gui.
-	// Guess it was a design problem of the extension
-
-	bool keypress = xkeyevent->type == KeyPress;
-
-	if (physical_keycode == 0 && keycode == 0 && unicode == 0)
-		return;
-
-	if (keycode == 0)
-		keycode = physical_keycode;
-
-	/* Phase 5, determine modifier mask */
-
-	// No problems here, except I had no way to
-	// know Mod1 was ALT and Mod4 was META (applekey/winkey)
-	// just tried Mods until i found them.
-
-	//print_verbose("mod1: "+itos(xkeyevent->state&Mod1Mask)+" mod 5: "+itos(xkeyevent->state&Mod5Mask));
-
-	Ref<InputEventKey> k;
-	k.instance();
-
-	get_key_modifier_state(xkeyevent->state, k);
-
-	/* Phase 6, determine echo character */
-
-	// Echo characters in X11 are a keyrelease and a keypress
-	// one after the other with the (almot) same timestamp.
-	// To detect them, i use XPeekEvent and check that their
-	// difference in time is below a threshold.
-
-	if (xkeyevent->type != KeyPress) {
-
-		p_echo = false;
-
-		// make sure there are events pending,
-		// so this call won't block.
-		if (XPending(x11_display) > 0) {
-			XEvent peek_event;
-			XPeekEvent(x11_display, &peek_event);
-
-			// I'm using a threshold of 5 msecs,
-			// since sometimes there seems to be a little
-			// jitter. I'm still not convinced that all this approach
-			// is correct, but the xorg developers are
-			// not very helpful today.
-
-#define ABSDIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))
-			::Time threshold = ABSDIFF(peek_event.xkey.time, xkeyevent->time);
-#undef ABSDIFF
-			if (peek_event.type == KeyPress && threshold < 5) {
-				KeySym rk;
-				XLookupString((XKeyEvent *)&peek_event, str, 256, &rk, NULL);
-				if (rk == keysym_keycode) {
-					XEvent event;
-					XNextEvent(x11_display, &event); //erase next event
-					handle_key_event((XKeyEvent *)&event, true);
-					return; //ignore current, echo next
-				}
-			}
-
-			// use the time from peek_event so it always works
-		}
-
-		// save the time to check for echo when keypress happens
-	}
-
-	/* Phase 7, send event to Window */
-
-	k->set_pressed(keypress);
-
-	if (keycode >= 'a' && keycode <= 'z')
-		keycode -= 'a' - 'A';
-
-	k->set_keycode(keycode);
-	k->set_physical_keycode(physical_keycode);
-	k->set_unicode(unicode);
-	k->set_echo(p_echo);
-
-	if (k->get_keycode() == KEY_BACKTAB) {
-		//make it consistent across platforms.
-		k->set_keycode(KEY_TAB);
-		k->set_physical_keycode(KEY_TAB);
-		k->set_shift(true);
-	}
-
-	//don't set mod state if modifier keys are released by themselves
-	//else event.is_action() will not work correctly here
-	if (!k->is_pressed()) {
-		if (k->get_keycode() == KEY_SHIFT)
-			k->set_shift(false);
-		else if (k->get_keycode() == KEY_CONTROL)
-			k->set_control(false);
-		else if (k->get_keycode() == KEY_ALT)
-			k->set_alt(false);
-		else if (k->get_keycode() == KEY_META)
-			k->set_metakey(false);
-	}
-
-	bool last_is_pressed = Input::get_singleton()->is_key_pressed(k->get_keycode());
-	if (k->is_pressed()) {
-		if (last_is_pressed) {
-			k->set_echo(true);
-		}
-	}
-
-	//printf("key: %x\n",k->get_keycode());
-	input->accumulate_input_event(k);
-}
-
-struct Property {
-	unsigned char *data;
-	int format, nitems;
-	Atom type;
-};
-
-static Property read_property(Display *p_display, Window p_window, Atom p_property) {
-
-	Atom actual_type;
-	int actual_format;
-	unsigned long nitems;
-	unsigned long bytes_after;
-	unsigned char *ret = 0;
-
-	int read_bytes = 1024;
-
-	//Keep trying to read the property until there are no
-	//bytes unread.
-	do {
-		if (ret != 0)
-			XFree(ret);
-
-		XGetWindowProperty(p_display, p_window, p_property, 0, read_bytes, False, AnyPropertyType,
-				&actual_type, &actual_format, &nitems, &bytes_after,
-				&ret);
-
-		read_bytes *= 2;
-
-	} while (bytes_after != 0);
-
-	Property p = { ret, actual_format, (int)nitems, actual_type };
-
-	return p;
-}
-
-static Atom pick_target_from_list(Display *p_display, Atom *p_list, int p_count) {
-
-	static const char *target_type = "text/uri-list";
-
-	for (int i = 0; i < p_count; i++) {
-
-		Atom atom = p_list[i];
-
-		if (atom != None && String(XGetAtomName(p_display, atom)) == target_type)
-			return atom;
-	}
-	return None;
-}
-
-static Atom pick_target_from_atoms(Display *p_disp, Atom p_t1, Atom p_t2, Atom p_t3) {
-
-	static const char *target_type = "text/uri-list";
-	if (p_t1 != None && String(XGetAtomName(p_disp, p_t1)) == target_type)
-		return p_t1;
-
-	if (p_t2 != None && String(XGetAtomName(p_disp, p_t2)) == target_type)
-		return p_t2;
-
-	if (p_t3 != None && String(XGetAtomName(p_disp, p_t3)) == target_type)
-		return p_t3;
-
-	return None;
-}
-
-void OS_X11::_window_changed(XEvent *event) {
-
-	if (xic) {
-		//  Not portable.
-		set_ime_position(Point2(0, 1));
-	}
-	if ((event->xconfigure.width == current_videomode.width) &&
-			(event->xconfigure.height == current_videomode.height))
-		return;
-
-	current_videomode.width = event->xconfigure.width;
-	current_videomode.height = event->xconfigure.height;
-
-#if defined(VULKAN_ENABLED)
-	if (video_driver_index == VIDEO_DRIVER_VULKAN) {
-		context_vulkan->window_resize(0, current_videomode.width, current_videomode.height);
-	}
-#endif
-}
-
-void OS_X11::process_xevents() {
-
-	//printf("checking events %i\n", XPending(x11_display));
-
-	do_mouse_warp = false;
-
-	// Is the current mouse mode one where it needs to be grabbed.
-	bool mouse_mode_grab = mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED;
-
-	while (XPending(x11_display) > 0) {
-		XEvent event;
-		XNextEvent(x11_display, &event);
-
-		if (XFilterEvent(&event, None)) {
-			continue;
-		}
-
-		if (XGetEventData(x11_display, &event.xcookie)) {
-
-			if (event.xcookie.type == GenericEvent && event.xcookie.extension == xi.opcode) {
-
-				XIDeviceEvent *event_data = (XIDeviceEvent *)event.xcookie.data;
-				int index = event_data->detail;
-				Vector2 pos = Vector2(event_data->event_x, event_data->event_y);
-
-				switch (event_data->evtype) {
-					case XI_HierarchyChanged:
-					case XI_DeviceChanged: {
-						refresh_device_info();
-					} break;
-					case XI_RawMotion: {
-						XIRawEvent *raw_event = (XIRawEvent *)event_data;
-						int device_id = raw_event->deviceid;
-
-						// Determine the axis used (called valuators in XInput for some forsaken reason)
-						//  Mask is a bitmask indicating which axes are involved.
-						//  We are interested in the values of axes 0 and 1.
-						if (raw_event->valuators.mask_len <= 0) {
-							break;
-						}
-
-						const double *values = raw_event->raw_values;
-
-						double rel_x = 0.0;
-						double rel_y = 0.0;
-						double pressure = 0.0;
-						double tilt_x = 0.0;
-						double tilt_y = 0.0;
-
-						if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_ABSX)) {
-							rel_x = *values;
-							values++;
-						}
-
-						if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_ABSY)) {
-							rel_y = *values;
-							values++;
-						}
-
-						if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_PRESSURE)) {
-							pressure = *values;
-							values++;
-						}
-
-						if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_TILTX)) {
-							tilt_x = *values;
-							values++;
-						}
-
-						if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_TILTY)) {
-							tilt_y = *values;
-						}
-
-						Map<int, Vector3>::Element *pen_info = xi.pen_devices.find(device_id);
-						if (pen_info) {
-							Vector3 mult = pen_info->value();
-							if (mult.x != 0.0) xi.pressure = pressure / mult.x;
-							if ((mult.y != 0.0) && (mult.z != 0.0)) xi.tilt = Vector2(tilt_x / mult.y, tilt_y / mult.z);
-						}
-
-						// https://bugs.freedesktop.org/show_bug.cgi?id=71609
-						// http://lists.libsdl.org/pipermail/commits-libsdl.org/2015-June/000282.html
-						if (raw_event->time == xi.last_relative_time && rel_x == xi.relative_motion.x && rel_y == xi.relative_motion.y) {
-							break; // Flush duplicate to avoid overly fast motion
-						}
-
-						xi.old_raw_pos.x = xi.raw_pos.x;
-						xi.old_raw_pos.y = xi.raw_pos.y;
-						xi.raw_pos.x = rel_x;
-						xi.raw_pos.y = rel_y;
-
-						Map<int, Vector2>::Element *abs_info = xi.absolute_devices.find(device_id);
-
-						if (abs_info) {
-							// Absolute mode device
-							Vector2 mult = abs_info->value();
-
-							xi.relative_motion.x += (xi.raw_pos.x - xi.old_raw_pos.x) * mult.x;
-							xi.relative_motion.y += (xi.raw_pos.y - xi.old_raw_pos.y) * mult.y;
-						} else {
-							// Relative mode device
-							xi.relative_motion.x = xi.raw_pos.x;
-							xi.relative_motion.y = xi.raw_pos.y;
-						}
-
-						xi.last_relative_time = raw_event->time;
-					} break;
-#ifdef TOUCH_ENABLED
-					case XI_TouchBegin: // Fall-through
-							// Disabled hand-in-hand with the grabbing
-							//XIAllowTouchEvents(x11_display, event_data->deviceid, event_data->detail, x11_window, XIAcceptTouch);
-
-					case XI_TouchEnd: {
-
-						bool is_begin = event_data->evtype == XI_TouchBegin;
-
-						Ref<InputEventScreenTouch> st;
-						st.instance();
-						st->set_index(index);
-						st->set_position(pos);
-						st->set_pressed(is_begin);
-
-						if (is_begin) {
-							if (xi.state.has(index)) // Defensive
-								break;
-							xi.state[index] = pos;
-							if (xi.state.size() == 1) {
-								// X11 may send a motion event when a touch gesture begins, that would result
-								// in a spurious mouse motion event being sent to Godot; remember it to be able to filter it out
-								xi.mouse_pos_to_filter = pos;
-							}
-							input->accumulate_input_event(st);
-						} else {
-							if (!xi.state.has(index)) // Defensive
-								break;
-							xi.state.erase(index);
-							input->accumulate_input_event(st);
-						}
-					} break;
-
-					case XI_TouchUpdate: {
-
-						Map<int, Vector2>::Element *curr_pos_elem = xi.state.find(index);
-						if (!curr_pos_elem) { // Defensive
-							break;
-						}
-
-						if (curr_pos_elem->value() != pos) {
-
-							Ref<InputEventScreenDrag> sd;
-							sd.instance();
-							sd->set_index(index);
-							sd->set_position(pos);
-							sd->set_relative(pos - curr_pos_elem->value());
-							input->accumulate_input_event(sd);
-
-							curr_pos_elem->value() = pos;
-						}
-					} break;
-#endif
-				}
-			}
-		}
-		XFreeEventData(x11_display, &event.xcookie);
-
-		switch (event.type) {
-			case Expose:
-				Main::force_redraw();
-				break;
-
-			case NoExpose:
-				minimized = true;
-				break;
-
-			case VisibilityNotify: {
-				XVisibilityEvent *visibility = (XVisibilityEvent *)&event;
-				minimized = (visibility->state == VisibilityFullyObscured);
-			} break;
-			case LeaveNotify: {
-				if (main_loop && !mouse_mode_grab)
-					main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
-
-			} break;
-			case EnterNotify: {
-				if (main_loop && !mouse_mode_grab)
-					main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
-			} break;
-			case FocusIn:
-				minimized = false;
-				window_has_focus = true;
-				main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
-				window_focused = true;
-
-				if (mouse_mode_grab) {
-					// Show and update the cursor if confined and the window regained focus.
-					if (mouse_mode == MOUSE_MODE_CONFINED)
-						XUndefineCursor(x11_display, x11_window);
-					else if (mouse_mode == MOUSE_MODE_CAPTURED) // or re-hide it in captured mode
-						XDefineCursor(x11_display, x11_window, null_cursor);
-
-					XGrabPointer(
-							x11_display, x11_window, True,
-							ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
-							GrabModeAsync, GrabModeAsync, x11_window, None, CurrentTime);
-				}
-#ifdef TOUCH_ENABLED
-				// Grab touch devices to avoid OS gesture interference
-				/*for (int i = 0; i < xi.touch_devices.size(); ++i) {
-					XIGrabDevice(x11_display, xi.touch_devices[i], x11_window, CurrentTime, None, XIGrabModeAsync, XIGrabModeAsync, False, &xi.touch_event_mask);
-				}*/
-#endif
-				if (xic) {
-					XSetICFocus(xic);
-				}
-				break;
-
-			case FocusOut:
-				window_has_focus = false;
-				input->release_pressed_events();
-				main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
-				window_focused = false;
-
-				if (mouse_mode_grab) {
-					//dear X11, I try, I really try, but you never work, you do whathever you want.
-					if (mouse_mode == MOUSE_MODE_CAPTURED) {
-						// Show the cursor if we're in captured mode so it doesn't look weird.
-						XUndefineCursor(x11_display, x11_window);
-					}
-					XUngrabPointer(x11_display, CurrentTime);
-				}
-#ifdef TOUCH_ENABLED
-				// Ungrab touch devices so input works as usual while we are unfocused
-				/*for (int i = 0; i < xi.touch_devices.size(); ++i) {
-					XIUngrabDevice(x11_display, xi.touch_devices[i], CurrentTime);
-				}*/
-
-				// Release every pointer to avoid sticky points
-				for (Map<int, Vector2>::Element *E = xi.state.front(); E; E = E->next()) {
-
-					Ref<InputEventScreenTouch> st;
-					st.instance();
-					st->set_index(E->key());
-					st->set_position(E->get());
-					input->accumulate_input_event(st);
-				}
-				xi.state.clear();
-#endif
-				if (xic) {
-					XUnsetICFocus(xic);
-				}
-				break;
-
-			case ConfigureNotify:
-				_window_changed(&event);
-				break;
-			case ButtonPress:
-			case ButtonRelease: {
-
-				/* exit in case of a mouse button press */
-				last_timestamp = event.xbutton.time;
-				if (mouse_mode == MOUSE_MODE_CAPTURED) {
-					event.xbutton.x = last_mouse_pos.x;
-					event.xbutton.y = last_mouse_pos.y;
-				}
-
-				Ref<InputEventMouseButton> mb;
-				mb.instance();
-
-				get_key_modifier_state(event.xbutton.state, mb);
-				mb->set_button_index(event.xbutton.button);
-				if (mb->get_button_index() == 2)
-					mb->set_button_index(3);
-				else if (mb->get_button_index() == 3)
-					mb->set_button_index(2);
-				mb->set_button_mask(get_mouse_button_state(mb->get_button_index(), event.xbutton.type));
-				mb->set_position(Vector2(event.xbutton.x, event.xbutton.y));
-				mb->set_global_position(mb->get_position());
-
-				mb->set_pressed((event.type == ButtonPress));
-
-				if (event.type == ButtonPress) {
-
-					uint64_t diff = get_ticks_usec() / 1000 - last_click_ms;
-
-					if (mb->get_button_index() == last_click_button_index) {
-
-						if (diff < 400 && Point2(last_click_pos).distance_to(Point2(event.xbutton.x, event.xbutton.y)) < 5) {
-
-							last_click_ms = 0;
-							last_click_pos = Point2(-100, -100);
-							last_click_button_index = -1;
-							mb->set_doubleclick(true);
-						}
-
-					} else if (mb->get_button_index() < 4 || mb->get_button_index() > 7) {
-						last_click_button_index = mb->get_button_index();
-					}
-
-					if (!mb->is_doubleclick()) {
-						last_click_ms += diff;
-						last_click_pos = Point2(event.xbutton.x, event.xbutton.y);
-					}
-				}
-
-				input->accumulate_input_event(mb);
-
-			} break;
-			case MotionNotify: {
-
-				// The X11 API requires filtering one-by-one through the motion
-				// notify events, in order to figure out which event is the one
-				// generated by warping the mouse pointer.
-
-				while (true) {
-					if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == current_videomode.width / 2 && event.xmotion.y == current_videomode.height / 2) {
-						//this is likely the warp event since it was warped here
-						center = Vector2(event.xmotion.x, event.xmotion.y);
-						break;
-					}
-
-					if (XPending(x11_display) > 0) {
-						XEvent tevent;
-						XPeekEvent(x11_display, &tevent);
-						if (tevent.type == MotionNotify) {
-							XNextEvent(x11_display, &event);
-						} else {
-							break;
-						}
-					} else {
-						break;
-					}
-				}
-
-				last_timestamp = event.xmotion.time;
-
-				// Motion is also simple.
-				// A little hack is in order
-				// to be able to send relative motion events.
-				Point2 pos(event.xmotion.x, event.xmotion.y);
-
-				// Avoidance of spurious mouse motion (see handling of touch)
-				bool filter = false;
-				// Adding some tolerance to match better Point2i to Vector2
-				if (xi.state.size() && Vector2(pos).distance_squared_to(xi.mouse_pos_to_filter) < 2) {
-					filter = true;
-				}
-				// Invalidate to avoid filtering a possible legitimate similar event coming later
-				xi.mouse_pos_to_filter = Vector2(1e10, 1e10);
-				if (filter) {
-					break;
-				}
-
-				if (mouse_mode == MOUSE_MODE_CAPTURED) {
-					if (xi.relative_motion.x == 0 && xi.relative_motion.y == 0) {
-						break;
-					}
-
-					Point2i new_center = pos;
-					pos = last_mouse_pos + xi.relative_motion;
-					center = new_center;
-					do_mouse_warp = window_has_focus; // warp the cursor if we're focused in
-				}
-
-				if (!last_mouse_pos_valid) {
-
-					last_mouse_pos = pos;
-					last_mouse_pos_valid = true;
-				}
-
-				// Hackish but relative mouse motion is already handled in the RawMotion event.
-				//  RawMotion does not provide the absolute mouse position (whereas MotionNotify does).
-				//  Therefore, RawMotion cannot be the authority on absolute mouse position.
-				//  RawMotion provides more precision than MotionNotify, which doesn't sense subpixel motion.
-				//  Therefore, MotionNotify cannot be the authority on relative mouse motion.
-				//  This means we need to take a combined approach...
-				Point2 rel;
-
-				// Only use raw input if in capture mode. Otherwise use the classic behavior.
-				if (mouse_mode == MOUSE_MODE_CAPTURED) {
-					rel = xi.relative_motion;
-				} else {
-					rel = pos - last_mouse_pos;
-				}
-
-				// Reset to prevent lingering motion
-				xi.relative_motion.x = 0;
-				xi.relative_motion.y = 0;
-
-				if (mouse_mode == MOUSE_MODE_CAPTURED) {
-					pos = Point2i(current_videomode.width / 2, current_videomode.height / 2);
-				}
-
-				Ref<InputEventMouseMotion> mm;
-				mm.instance();
-
-				mm->set_pressure(xi.pressure);
-				mm->set_tilt(xi.tilt);
-
-				// Make the absolute position integral so it doesn't look _too_ weird :)
-				Point2i posi(pos);
-
-				get_key_modifier_state(event.xmotion.state, mm);
-				mm->set_button_mask(get_mouse_button_state());
-				mm->set_position(posi);
-				mm->set_global_position(posi);
-				input->set_mouse_position(posi);
-				mm->set_speed(input->get_last_mouse_speed());
-
-				mm->set_relative(rel);
-
-				last_mouse_pos = pos;
-
-				// printf("rel: %d,%d\n", rel.x, rel.y );
-				// Don't propagate the motion event unless we have focus
-				// this is so that the relative motion doesn't get messed up
-				// after we regain focus.
-				if (window_has_focus || !mouse_mode_grab)
-					input->accumulate_input_event(mm);
-
-			} break;
-			case KeyPress:
-			case KeyRelease: {
-
-				last_timestamp = event.xkey.time;
-
-				// key event is a little complex, so
-				// it will be handled in its own function.
-				handle_key_event((XKeyEvent *)&event);
-			} break;
-			case SelectionRequest: {
-
-				XSelectionRequestEvent *req;
-				XEvent e, respond;
-				e = event;
-
-				req = &(e.xselectionrequest);
-				if (req->target == XInternAtom(x11_display, "UTF8_STRING", 0) ||
-						req->target == XInternAtom(x11_display, "COMPOUND_TEXT", 0) ||
-						req->target == XInternAtom(x11_display, "TEXT", 0) ||
-						req->target == XA_STRING ||
-						req->target == XInternAtom(x11_display, "text/plain;charset=utf-8", 0) ||
-						req->target == XInternAtom(x11_display, "text/plain", 0)) {
-					CharString clip = OS::get_clipboard().utf8();
-					XChangeProperty(x11_display,
-							req->requestor,
-							req->property,
-							req->target,
-							8,
-							PropModeReplace,
-							(unsigned char *)clip.get_data(),
-							clip.length());
-					respond.xselection.property = req->property;
-				} else if (req->target == XInternAtom(x11_display, "TARGETS", 0)) {
-
-					Atom data[7];
-					data[0] = XInternAtom(x11_display, "TARGETS", 0);
-					data[1] = XInternAtom(x11_display, "UTF8_STRING", 0);
-					data[2] = XInternAtom(x11_display, "COMPOUND_TEXT", 0);
-					data[3] = XInternAtom(x11_display, "TEXT", 0);
-					data[4] = XA_STRING;
-					data[5] = XInternAtom(x11_display, "text/plain;charset=utf-8", 0);
-					data[6] = XInternAtom(x11_display, "text/plain", 0);
-
-					XChangeProperty(x11_display,
-							req->requestor,
-							req->property,
-							XA_ATOM,
-							32,
-							PropModeReplace,
-							(unsigned char *)&data,
-							sizeof(data) / sizeof(data[0]));
-					respond.xselection.property = req->property;
-
-				} else {
-					char *targetname = XGetAtomName(x11_display, req->target);
-					printf("No Target '%s'\n", targetname);
-					if (targetname)
-						XFree(targetname);
-					respond.xselection.property = None;
-				}
-
-				respond.xselection.type = SelectionNotify;
-				respond.xselection.display = req->display;
-				respond.xselection.requestor = req->requestor;
-				respond.xselection.selection = req->selection;
-				respond.xselection.target = req->target;
-				respond.xselection.time = req->time;
-				XSendEvent(x11_display, req->requestor, True, NoEventMask, &respond);
-				XFlush(x11_display);
-			} break;
-
-			case SelectionNotify:
-
-				if (event.xselection.target == requested) {
-
-					Property p = read_property(x11_display, x11_window, XInternAtom(x11_display, "PRIMARY", 0));
-
-					Vector<String> files = String((char *)p.data).split("\n", false);
-					for (int i = 0; i < files.size(); i++) {
-						files.write[i] = files[i].replace("file://", "").http_unescape().strip_edges();
-					}
-					main_loop->drop_files(files);
-
-					//Reply that all is well.
-					XClientMessageEvent m;
-					memset(&m, 0, sizeof(m));
-					m.type = ClientMessage;
-					m.display = x11_display;
-					m.window = xdnd_source_window;
-					m.message_type = xdnd_finished;
-					m.format = 32;
-					m.data.l[0] = x11_window;
-					m.data.l[1] = 1;
-					m.data.l[2] = xdnd_action_copy; //We only ever copy.
-
-					XSendEvent(x11_display, xdnd_source_window, False, NoEventMask, (XEvent *)&m);
-				}
-				break;
-
-			case ClientMessage:
-
-				if ((unsigned int)event.xclient.data.l[0] == (unsigned int)wm_delete)
-					main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
-
-				else if ((unsigned int)event.xclient.message_type == (unsigned int)xdnd_enter) {
-
-					//File(s) have been dragged over the window, check for supported target (text/uri-list)
-					xdnd_version = (event.xclient.data.l[1] >> 24);
-					Window source = event.xclient.data.l[0];
-					bool more_than_3 = event.xclient.data.l[1] & 1;
-					if (more_than_3) {
-						Property p = read_property(x11_display, source, XInternAtom(x11_display, "XdndTypeList", False));
-						requested = pick_target_from_list(x11_display, (Atom *)p.data, p.nitems);
-					} else
-						requested = pick_target_from_atoms(x11_display, event.xclient.data.l[2], event.xclient.data.l[3], event.xclient.data.l[4]);
-				} else if ((unsigned int)event.xclient.message_type == (unsigned int)xdnd_position) {
-
-					//xdnd position event, reply with an XDND status message
-					//just depending on type of data for now
-					XClientMessageEvent m;
-					memset(&m, 0, sizeof(m));
-					m.type = ClientMessage;
-					m.display = event.xclient.display;
-					m.window = event.xclient.data.l[0];
-					m.message_type = xdnd_status;
-					m.format = 32;
-					m.data.l[0] = x11_window;
-					m.data.l[1] = (requested != None);
-					m.data.l[2] = 0; //empty rectangle
-					m.data.l[3] = 0;
-					m.data.l[4] = xdnd_action_copy;
-
-					XSendEvent(x11_display, event.xclient.data.l[0], False, NoEventMask, (XEvent *)&m);
-					XFlush(x11_display);
-				} else if ((unsigned int)event.xclient.message_type == (unsigned int)xdnd_drop) {
-
-					if (requested != None) {
-						xdnd_source_window = event.xclient.data.l[0];
-						if (xdnd_version >= 1)
-							XConvertSelection(x11_display, xdnd_selection, requested, XInternAtom(x11_display, "PRIMARY", 0), x11_window, event.xclient.data.l[2]);
-						else
-							XConvertSelection(x11_display, xdnd_selection, requested, XInternAtom(x11_display, "PRIMARY", 0), x11_window, CurrentTime);
-					} else {
-						//Reply that we're not interested.
-						XClientMessageEvent m;
-						memset(&m, 0, sizeof(m));
-						m.type = ClientMessage;
-						m.display = event.xclient.display;
-						m.window = event.xclient.data.l[0];
-						m.message_type = xdnd_finished;
-						m.format = 32;
-						m.data.l[0] = x11_window;
-						m.data.l[1] = 0;
-						m.data.l[2] = None; //Failed.
-						XSendEvent(x11_display, event.xclient.data.l[0], False, NoEventMask, (XEvent *)&m);
-					}
-				}
-				break;
-			default:
-				break;
-		}
-	}
-
-	XFlush(x11_display);
-
-	if (do_mouse_warp) {
-
-		XWarpPointer(x11_display, None, x11_window,
-				0, 0, 0, 0, (int)current_videomode.width / 2, (int)current_videomode.height / 2);
-
-		/*
-		Window root, child;
-		int root_x, root_y;
-		int win_x, win_y;
-		unsigned int mask;
-		XQueryPointer( x11_display, x11_window, &root, &child, &root_x, &root_y, &win_x, &win_y, &mask );
-
-		printf("Root: %d,%d\n", root_x, root_y);
-		printf("Win: %d,%d\n", win_x, win_y);
-		*/
-	}
-
-	input->flush_accumulated_events();
-}
-
-MainLoop *OS_X11::get_main_loop() const {
-
-	return main_loop;
-}
-
-void OS_X11::delete_main_loop() {
-
-	if (main_loop)
-		memdelete(main_loop);
-	main_loop = NULL;
-}
-
-void OS_X11::set_main_loop(MainLoop *p_main_loop) {
-
-	main_loop = p_main_loop;
-	input->set_main_loop(p_main_loop);
-}
-
-bool OS_X11::can_draw() const {
-
-	return !minimized;
-};
-
-void OS_X11::set_clipboard(const String &p_text) {
-
-	OS::set_clipboard(p_text);
-
-	XSetSelectionOwner(x11_display, XA_PRIMARY, x11_window, CurrentTime);
-	XSetSelectionOwner(x11_display, XInternAtom(x11_display, "CLIPBOARD", 0), x11_window, CurrentTime);
-};
-
-static String _get_clipboard_impl(Atom p_source, Window x11_window, ::Display *x11_display, String p_internal_clipboard, Atom target) {
-
-	String ret;
-
-	Atom type;
-	Atom selection = XA_PRIMARY;
-	int format, result;
-	unsigned long len, bytes_left, dummy;
-	unsigned char *data;
-	Window Sown = XGetSelectionOwner(x11_display, p_source);
-
-	if (Sown == x11_window) {
-
-		return p_internal_clipboard;
-	};
-
-	if (Sown != None) {
-		XConvertSelection(x11_display, p_source, target, selection,
-				x11_window, CurrentTime);
-		XFlush(x11_display);
-		while (true) {
-			XEvent event;
-			XNextEvent(x11_display, &event);
-			if (event.type == SelectionNotify && event.xselection.requestor == x11_window) {
-				break;
-			};
-		};
-
-		//
-		// Do not get any data, see how much data is there
-		//
-		XGetWindowProperty(x11_display, x11_window,
-				selection, // Tricky..
-				0, 0, // offset - len
-				0, // Delete 0==FALSE
-				AnyPropertyType, //flag
-				&type, // return type
-				&format, // return format
-				&len, &bytes_left, //that
-				&data);
-		// DATA is There
-		if (bytes_left > 0) {
-			result = XGetWindowProperty(x11_display, x11_window,
-					selection, 0, bytes_left, 0,
-					AnyPropertyType, &type, &format,
-					&len, &dummy, &data);
-			if (result == Success) {
-				ret.parse_utf8((const char *)data);
-			} else
-				printf("FAIL\n");
-			XFree(data);
-		}
-	}
-
-	return ret;
-}
-
-static String _get_clipboard(Atom p_source, Window x11_window, ::Display *x11_display, String p_internal_clipboard) {
-	String ret;
-	Atom utf8_atom = XInternAtom(x11_display, "UTF8_STRING", True);
-	if (utf8_atom != None) {
-		ret = _get_clipboard_impl(p_source, x11_window, x11_display, p_internal_clipboard, utf8_atom);
-	}
-	if (ret == "") {
-		ret = _get_clipboard_impl(p_source, x11_window, x11_display, p_internal_clipboard, XA_STRING);
-	}
-	return ret;
-}
-
-String OS_X11::get_clipboard() const {
-
-	String ret;
-	ret = _get_clipboard(XInternAtom(x11_display, "CLIPBOARD", 0), x11_window, x11_display, OS::get_clipboard());
-
-	if (ret == "") {
-		ret = _get_clipboard(XA_PRIMARY, x11_window, x11_display, OS::get_clipboard());
-	};
-
-	return ret;
-}
-
-String OS_X11::get_name() const {
-
-	return "X11";
-}
-
-Error OS_X11::shell_open(String p_uri) {
-
-	Error ok;
-	List<String> args;
-	args.push_back(p_uri);
-	ok = execute("xdg-open", args, false);
-	if (ok == OK)
-		return OK;
-	ok = execute("gnome-open", args, false);
-	if (ok == OK)
-		return OK;
-	ok = execute("kde-open", args, false);
-	return ok;
-}
-
-bool OS_X11::_check_internal_feature_support(const String &p_feature) {
-
-	return p_feature == "pc";
-}
-
-String OS_X11::get_config_path() const {
-
-	if (has_environment("XDG_CONFIG_HOME")) {
-		return get_environment("XDG_CONFIG_HOME");
-	} else if (has_environment("HOME")) {
-		return get_environment("HOME").plus_file(".config");
-	} else {
-		return ".";
-	}
-}
-
-String OS_X11::get_data_path() const {
-
-	if (has_environment("XDG_DATA_HOME")) {
-		return get_environment("XDG_DATA_HOME");
-	} else if (has_environment("HOME")) {
-		return get_environment("HOME").plus_file(".local/share");
-	} else {
-		return get_config_path();
-	}
-}
-
-String OS_X11::get_cache_path() const {
-
-	if (has_environment("XDG_CACHE_HOME")) {
-		return get_environment("XDG_CACHE_HOME");
-	} else if (has_environment("HOME")) {
-		return get_environment("HOME").plus_file(".cache");
-	} else {
-		return get_config_path();
-	}
-}
-
-String OS_X11::get_system_dir(SystemDir p_dir) const {
-
-	String xdgparam;
-
-	switch (p_dir) {
-		case SYSTEM_DIR_DESKTOP: {
-
-			xdgparam = "DESKTOP";
-		} break;
-		case SYSTEM_DIR_DCIM: {
-
-			xdgparam = "PICTURES";
-
-		} break;
-		case SYSTEM_DIR_DOCUMENTS: {
-
-			xdgparam = "DOCUMENTS";
-
-		} break;
-		case SYSTEM_DIR_DOWNLOADS: {
-
-			xdgparam = "DOWNLOAD";
-
-		} break;
-		case SYSTEM_DIR_MOVIES: {
-
-			xdgparam = "VIDEOS";
-
-		} break;
-		case SYSTEM_DIR_MUSIC: {
-
-			xdgparam = "MUSIC";
-
-		} break;
-		case SYSTEM_DIR_PICTURES: {
-
-			xdgparam = "PICTURES";
-
-		} break;
-		case SYSTEM_DIR_RINGTONES: {
-
-			xdgparam = "MUSIC";
-
-		} break;
-	}
-
-	String pipe;
-	List<String> arg;
-	arg.push_back(xdgparam);
-	Error err = const_cast<OS_X11 *>(this)->execute("xdg-user-dir", arg, true, NULL, &pipe);
-	if (err != OK)
-		return ".";
-	return pipe.strip_edges();
-}
-
-void OS_X11::move_window_to_foreground() {
-
-	XEvent xev;
-	Atom net_active_window = XInternAtom(x11_display, "_NET_ACTIVE_WINDOW", False);
-
-	memset(&xev, 0, sizeof(xev));
-	xev.type = ClientMessage;
-	xev.xclient.window = x11_window;
-	xev.xclient.message_type = net_active_window;
-	xev.xclient.format = 32;
-	xev.xclient.data.l[0] = 1;
-	xev.xclient.data.l[1] = CurrentTime;
-
-	XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
-	XFlush(x11_display);
-}
-
-void OS_X11::set_cursor_shape(CursorShape p_shape) {
-
-	ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
-
-	if (p_shape == current_cursor) {
-		return;
-	}
-
-	if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
-		if (cursors[p_shape] != None) {
-			XDefineCursor(x11_display, x11_window, cursors[p_shape]);
-		} else if (cursors[CURSOR_ARROW] != None) {
-			XDefineCursor(x11_display, x11_window, cursors[CURSOR_ARROW]);
-		}
-	}
-
-	current_cursor = p_shape;
-}
-
-OS::CursorShape OS_X11::get_cursor_shape() const {
-
-	return current_cursor;
-}
-
-void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
-
-	if (p_cursor.is_valid()) {
-
-		Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape);
-
-		if (cursor_c) {
-			if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) {
-				set_cursor_shape(p_shape);
-				return;
-			}
-
-			cursors_cache.erase(p_shape);
-		}
-
-		Ref<Texture2D> texture = p_cursor;
-		Ref<AtlasTexture> atlas_texture = p_cursor;
-		Ref<Image> image;
-		Size2 texture_size;
-		Rect2 atlas_rect;
-
-		if (texture.is_valid()) {
-			image = texture->get_data();
-		}
-
-		if (!image.is_valid() && atlas_texture.is_valid()) {
-			texture = atlas_texture->get_atlas();
-
-			atlas_rect.size.width = texture->get_width();
-			atlas_rect.size.height = texture->get_height();
-			atlas_rect.position.x = atlas_texture->get_region().position.x;
-			atlas_rect.position.y = atlas_texture->get_region().position.y;
-
-			texture_size.width = atlas_texture->get_region().size.x;
-			texture_size.height = atlas_texture->get_region().size.y;
-		} else if (image.is_valid()) {
-			texture_size.width = texture->get_width();
-			texture_size.height = texture->get_height();
-		}
-
-		ERR_FAIL_COND(!texture.is_valid());
-		ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0);
-		ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256);
-		ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height);
-
-		image = texture->get_data();
-
-		ERR_FAIL_COND(!image.is_valid());
-
-		// Create the cursor structure
-		XcursorImage *cursor_image = XcursorImageCreate(texture_size.width, texture_size.height);
-		XcursorUInt image_size = texture_size.width * texture_size.height;
-		XcursorDim size = sizeof(XcursorPixel) * image_size;
-
-		cursor_image->version = 1;
-		cursor_image->size = size;
-		cursor_image->xhot = p_hotspot.x;
-		cursor_image->yhot = p_hotspot.y;
-
-		// allocate memory to contain the whole file
-		cursor_image->pixels = (XcursorPixel *)memalloc(size);
-
-		for (XcursorPixel index = 0; index < image_size; index++) {
-			int row_index = floor(index / texture_size.width) + atlas_rect.position.y;
-			int column_index = (index % int(texture_size.width)) + atlas_rect.position.x;
-
-			if (atlas_texture.is_valid()) {
-				column_index = MIN(column_index, atlas_rect.size.width - 1);
-				row_index = MIN(row_index, atlas_rect.size.height - 1);
-			}
-
-			*(cursor_image->pixels + index) = image->get_pixel(column_index, row_index).to_argb32();
-		}
-
-		ERR_FAIL_COND(cursor_image->pixels == NULL);
-
-		// Save it for a further usage
-		cursors[p_shape] = XcursorImageLoadCursor(x11_display, cursor_image);
-
-		Vector<Variant> params;
-		params.push_back(p_cursor);
-		params.push_back(p_hotspot);
-		cursors_cache.insert(p_shape, params);
-
-		if (p_shape == current_cursor) {
-			if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
-				XDefineCursor(x11_display, x11_window, cursors[p_shape]);
-			}
-		}
-
-		memfree(cursor_image->pixels);
-		XcursorImageDestroy(cursor_image);
-	} else {
-		// Reset to default system cursor
-		if (img[p_shape]) {
-			cursors[p_shape] = XcursorImageLoadCursor(x11_display, img[p_shape]);
-		}
-
-		CursorShape c = current_cursor;
-		current_cursor = CURSOR_MAX;
-		set_cursor_shape(c);
-
-		cursors_cache.erase(p_shape);
-	}
-}
-
-void OS_X11::release_rendering_thread() {
-#if defined(OPENGL_ENABLED)
-	if (video_driver_index == VIDEO_DRIVER_GLES2) {
-		context_gles2->release_current();
-	}
-#endif
-}
-
-void OS_X11::make_rendering_thread() {
-#if defined(OPENGL_ENABLED)
-	if (video_driver_index == VIDEO_DRIVER_GLES2) {
-		context_gles2->make_current();
-	}
-#endif
-}
-
-void OS_X11::swap_buffers() {
-#if defined(OPENGL_ENABLED)
-	if (video_driver_index == VIDEO_DRIVER_GLES2) {
-		context_gles2->swap_buffers();
-	}
-#endif
-	/* not needed for now
-#if defined(VULKAN_ENABLED)
-	if (video_driver_index == VIDEO_DRIVER_VULKAN) {
-		context_vulkan->swap_buffers();
-	}
-#endif*/
-}
-
-void OS_X11::alert(const String &p_alert, const String &p_title) {
-	const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
-
-	String path = get_environment("PATH");
-	Vector<String> path_elems = path.split(":", false);
-	String program;
-
-	for (int i = 0; i < path_elems.size(); i++) {
-		for (uint64_t k = 0; k < sizeof(message_programs) / sizeof(char *); k++) {
-			String tested_path = path_elems[i].plus_file(message_programs[k]);
-
-			if (FileAccess::exists(tested_path)) {
-				program = tested_path;
-				break;
-			}
-		}
-
-		if (program.length())
-			break;
-	}
-
-	List<String> args;
-
-	if (program.ends_with("zenity")) {
-		args.push_back("--error");
-		args.push_back("--width");
-		args.push_back("500");
-		args.push_back("--title");
-		args.push_back(p_title);
-		args.push_back("--text");
-		args.push_back(p_alert);
-	}
-
-	if (program.ends_with("kdialog")) {
-		args.push_back("--error");
-		args.push_back(p_alert);
-		args.push_back("--title");
-		args.push_back(p_title);
-	}
-
-	if (program.ends_with("Xdialog")) {
-		args.push_back("--title");
-		args.push_back(p_title);
-		args.push_back("--msgbox");
-		args.push_back(p_alert);
-		args.push_back("0");
-		args.push_back("0");
-	}
-
-	if (program.ends_with("xmessage")) {
-		args.push_back("-center");
-		args.push_back("-title");
-		args.push_back(p_title);
-		args.push_back(p_alert);
-	}
-
-	if (program.length()) {
-		execute(program, args, true);
-	} else {
-		print_line(p_alert);
-	}
-}
-
-bool g_set_icon_error = false;
-int set_icon_errorhandler(Display *dpy, XErrorEvent *ev) {
-	g_set_icon_error = true;
-	return 0;
-}
-
-void OS_X11::set_icon(const Ref<Image> &p_icon) {
-	int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&set_icon_errorhandler);
-
-	Atom net_wm_icon = XInternAtom(x11_display, "_NET_WM_ICON", False);
-
-	if (p_icon.is_valid()) {
-		Ref<Image> img = p_icon->duplicate();
-		img->convert(Image::FORMAT_RGBA8);
-
-		while (true) {
-			int w = img->get_width();
-			int h = img->get_height();
-
-			if (g_set_icon_error) {
-				g_set_icon_error = false;
-
-				WARN_PRINT("Icon too large, attempting to resize icon.");
-
-				int new_width, new_height;
-				if (w > h) {
-					new_width = w / 2;
-					new_height = h * new_width / w;
-				} else {
-					new_height = h / 2;
-					new_width = w * new_height / h;
-				}
-
-				w = new_width;
-				h = new_height;
-
-				if (!w || !h) {
-					WARN_PRINT("Unable to set icon.");
-					break;
-				}
-
-				img->resize(w, h, Image::INTERPOLATE_CUBIC);
-			}
-
-			// We're using long to have wordsize (32Bit build -> 32 Bits, 64 Bit build -> 64 Bits
-			Vector<long> pd;
-
-			pd.resize(2 + w * h);
-
-			pd.write[0] = w;
-			pd.write[1] = h;
-
-			const uint8_t *r = img->get_data().ptr();
-
-			long *wr = &pd.write[2];
-			uint8_t const *pr = r;
-
-			for (int i = 0; i < w * h; i++) {
-				long v = 0;
-				//    A             R             G            B
-				v |= pr[3] << 24 | pr[0] << 16 | pr[1] << 8 | pr[2];
-				*wr++ = v;
-				pr += 4;
-			}
-
-			XChangeProperty(x11_display, x11_window, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)pd.ptr(), pd.size());
-
-			if (!g_set_icon_error)
-				break;
-		}
-	} else {
-		XDeleteProperty(x11_display, x11_window, net_wm_icon);
-	}
-
-	XFlush(x11_display);
-	XSetErrorHandler(oldHandler);
-}
-
-void OS_X11::force_process_input() {
-	process_xevents(); // get rid of pending events
-#ifdef JOYDEV_ENABLED
-	joypad->process_joypads();
-#endif
-}
-
-void OS_X11::run() {
-
-	force_quit = false;
-
-	if (!main_loop)
-		return;
-
-	main_loop->init();
-
-	//uint64_t last_ticks=get_ticks_usec();
-
-	//int frames=0;
-	//uint64_t frame=0;
-
-	while (!force_quit) {
-
-		process_xevents(); // get rid of pending events
-#ifdef JOYDEV_ENABLED
-		joypad->process_joypads();
-#endif
-		if (Main::iteration())
-			break;
-	};
-
-	main_loop->finish();
-}
-
-bool OS_X11::is_joy_known(int p_device) {
-	return input->is_joy_mapped(p_device);
-}
-
-String OS_X11::get_joy_guid(int p_device) const {
-	return input->get_joy_guid_remapped(p_device);
-}
-
-void OS_X11::_set_use_vsync(bool p_enable) {
-#if defined(OPENGL_ENABLED)
-	if (video_driver_index == VIDEO_DRIVER_GLES2) {
-		if (context_gles2)
-			context_gles2->set_use_vsync(p_enable);
-	}
-#endif
-}
-
-void OS_X11::set_context(int p_context) {
-
-	XClassHint *classHint = XAllocClassHint();
-
-	if (classHint) {
-
-		CharString name_str;
-		switch (p_context) {
-			case CONTEXT_EDITOR:
-				name_str = "Godot_Editor";
-				break;
-			case CONTEXT_PROJECTMAN:
-				name_str = "Godot_ProjectList";
-				break;
-			case CONTEXT_ENGINE:
-				name_str = "Godot_Engine";
-				break;
-		}
-
-		CharString class_str;
-		if (p_context == CONTEXT_ENGINE) {
-			String config_name = GLOBAL_GET("application/config/name");
-			if (config_name.length() == 0) {
-				class_str = "Godot_Engine";
-			} else {
-				class_str = config_name.utf8();
-			}
-		} else {
-			class_str = "Godot";
-		}
-
-		classHint->res_class = class_str.ptrw();
-		classHint->res_name = name_str.ptrw();
-
-		XSetClassHint(x11_display, x11_window, classHint);
-		XFree(classHint);
-	}
-}
-
-void OS_X11::disable_crash_handler() {
-	crash_handler.disable();
-}
-
-bool OS_X11::is_disable_crash_handler() const {
-	return crash_handler.is_disabled();
-}
-
-static String get_mountpoint(const String &p_path) {
-	struct stat s;
-	if (stat(p_path.utf8().get_data(), &s)) {
-		return "";
-	}
-
-#ifdef HAVE_MNTENT
-	dev_t dev = s.st_dev;
-	FILE *fd = setmntent("/proc/mounts", "r");
-	if (!fd) {
-		return "";
-	}
-
-	struct mntent mnt;
-	char buf[1024];
-	size_t buflen = 1024;
-	while (getmntent_r(fd, &mnt, buf, buflen)) {
-		if (!stat(mnt.mnt_dir, &s) && s.st_dev == dev) {
-			endmntent(fd);
-			return String(mnt.mnt_dir);
-		}
-	}
-
-	endmntent(fd);
-#endif
-	return "";
-}
-
-Error OS_X11::move_to_trash(const String &p_path) {
-	String trash_can = "";
-	String mnt = get_mountpoint(p_path);
-
-	// If there is a directory "[Mountpoint]/.Trash-[UID]/files", use it as the trash can.
-	if (mnt != "") {
-		String path(mnt + "/.Trash-" + itos(getuid()) + "/files");
-		struct stat s;
-		if (!stat(path.utf8().get_data(), &s)) {
-			trash_can = path;
-		}
-	}
-
-	// Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash/files" as the trash can.
-	if (trash_can == "") {
-		char *dhome = getenv("XDG_DATA_HOME");
-		if (dhome) {
-			trash_can = String(dhome) + "/Trash/files";
-		}
-	}
-
-	// Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash/files" as the trash can.
-	if (trash_can == "") {
-		char *home = getenv("HOME");
-		if (home) {
-			trash_can = String(home) + "/.local/share/Trash/files";
-		}
-	}
-
-	// Issue an error if none of the previous locations is appropriate for the trash can.
-	if (trash_can == "") {
-		ERR_PRINT("move_to_trash: Could not determine the trash can location");
-		return FAILED;
-	}
-
-	// Create needed directories for decided trash can location.
-	DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-	Error err = dir_access->make_dir_recursive(trash_can);
-	memdelete(dir_access);
-
-	// Issue an error if trash can is not created proprely.
-	if (err != OK) {
-		ERR_PRINT("move_to_trash: Could not create the trash can \"" + trash_can + "\"");
-		return err;
-	}
-
-	// The trash can is successfully created, now move the given resource to it.
-	// Do not use DirAccess:rename() because it can't move files across multiple mountpoints.
-	List<String> mv_args;
-	mv_args.push_back(p_path);
-	mv_args.push_back(trash_can);
-	int retval;
-	err = execute("mv", mv_args, true, NULL, NULL, &retval);
-
-	// Issue an error if "mv" failed to move the given resource to the trash can.
-	if (err != OK || retval != 0) {
-		ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_can + "\"");
-		return FAILED;
-	}
-
-	return OK;
-}
-
-OS::LatinKeyboardVariant OS_X11::get_latin_keyboard_variant() const {
-
-	XkbDescRec *xkbdesc = XkbAllocKeyboard();
-	ERR_FAIL_COND_V(!xkbdesc, LATIN_KEYBOARD_QWERTY);
-
-	XkbGetNames(x11_display, XkbSymbolsNameMask, xkbdesc);
-	ERR_FAIL_COND_V(!xkbdesc->names, LATIN_KEYBOARD_QWERTY);
-	ERR_FAIL_COND_V(!xkbdesc->names->symbols, LATIN_KEYBOARD_QWERTY);
-
-	char *layout = XGetAtomName(x11_display, xkbdesc->names->symbols);
-	ERR_FAIL_COND_V(!layout, LATIN_KEYBOARD_QWERTY);
-
-	Vector<String> info = String(layout).split("+");
-	ERR_FAIL_INDEX_V(1, info.size(), LATIN_KEYBOARD_QWERTY);
-
-	if (info[1].find("colemak") != -1) {
-		return LATIN_KEYBOARD_COLEMAK;
-	} else if (info[1].find("qwertz") != -1) {
-		return LATIN_KEYBOARD_QWERTZ;
-	} else if (info[1].find("azerty") != -1) {
-		return LATIN_KEYBOARD_AZERTY;
-	} else if (info[1].find("qzerty") != -1) {
-		return LATIN_KEYBOARD_QZERTY;
-	} else if (info[1].find("dvorak") != -1) {
-		return LATIN_KEYBOARD_DVORAK;
-	} else if (info[1].find("neo") != -1) {
-		return LATIN_KEYBOARD_NEO;
-	}
-
-	return LATIN_KEYBOARD_QWERTY;
-}
-
-void OS_X11::update_real_mouse_position() {
-	Window root_return, child_return;
-	int root_x, root_y, win_x, win_y;
-	unsigned int mask_return;
-
-	Bool xquerypointer_result = XQueryPointer(x11_display, x11_window, &root_return, &child_return, &root_x, &root_y,
-			&win_x, &win_y, &mask_return);
-
-	if (xquerypointer_result) {
-		if (win_x > 0 && win_y > 0 && win_x <= current_videomode.width && win_y <= current_videomode.height) {
-
-			last_mouse_pos.x = win_x;
-			last_mouse_pos.y = win_y;
-			last_mouse_pos_valid = true;
-			input->set_mouse_position(last_mouse_pos);
-		}
-	}
-}
-
-OS_X11::OS_X11() {
-
-#ifdef PULSEAUDIO_ENABLED
-	AudioDriverManager::add_driver(&driver_pulseaudio);
-#endif
-
-#ifdef ALSA_ENABLED
-	AudioDriverManager::add_driver(&driver_alsa);
-#endif
-
-	xi.opcode = 0;
-	xi.last_relative_time = 0;
-	layered_window = false;
-	minimized = false;
-	window_focused = true;
-	xim_style = 0L;
-	mouse_mode = MOUSE_MODE_VISIBLE;
-	last_position_before_fs = Vector2();
-}

+ 0 - 338
platform/x11/os_x11.h

@@ -1,338 +0,0 @@
-/*************************************************************************/
-/*  os_x11.h                                                             */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the       */
-/* "Software"), to deal in the Software without restriction, including   */
-/* without limitation the rights to use, copy, modify, merge, publish,   */
-/* distribute, sublicense, and/or sell copies of the Software, and to    */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions:                                             */
-/*                                                                       */
-/* The above copyright notice and this permission notice shall be        */
-/* included in all copies or substantial portions of the Software.       */
-/*                                                                       */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
-/*************************************************************************/
-
-#ifndef OS_X11_H
-#define OS_X11_H
-
-#include "core/input/input.h"
-#include "crash_handler_x11.h"
-#include "drivers/alsa/audio_driver_alsa.h"
-#include "drivers/alsamidi/midi_driver_alsamidi.h"
-#include "drivers/pulseaudio/audio_driver_pulseaudio.h"
-#include "drivers/unix/os_unix.h"
-#include "joypad_linux.h"
-#include "servers/audio_server.h"
-#include "servers/visual/rasterizer.h"
-#include "servers/visual_server.h"
-
-#if defined(OPENGL_ENABLED)
-#include "context_gl_x11.h"
-#endif
-
-#if defined(VULKAN_ENABLED)
-#include "drivers/vulkan/rendering_device_vulkan.h"
-#include "platform/x11/vulkan_context_x11.h"
-#endif
-
-#include <X11/Xcursor/Xcursor.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/XInput2.h>
-#include <X11/extensions/Xrandr.h>
-#include <X11/keysym.h>
-
-// Hints for X11 fullscreen
-typedef struct {
-	unsigned long flags;
-	unsigned long functions;
-	unsigned long decorations;
-	long inputMode;
-	unsigned long status;
-} Hints;
-
-typedef struct _xrr_monitor_info {
-	Atom name;
-	Bool primary;
-	Bool automatic;
-	int noutput;
-	int x;
-	int y;
-	int width;
-	int height;
-	int mwidth;
-	int mheight;
-	RROutput *outputs;
-} xrr_monitor_info;
-
-#undef CursorShape
-
-class OS_X11 : public OS_Unix {
-
-	Atom wm_delete;
-	Atom xdnd_enter;
-	Atom xdnd_position;
-	Atom xdnd_status;
-	Atom xdnd_action_copy;
-	Atom xdnd_drop;
-	Atom xdnd_finished;
-	Atom xdnd_selection;
-	Atom requested;
-
-	int xdnd_version;
-
-#if defined(OPENGL_ENABLED)
-	ContextGL_X11 *context_gles2;
-#endif
-#if defined(VULKAN_ENABLED)
-	VulkanContextX11 *context_vulkan;
-	RenderingDeviceVulkan *rendering_device_vulkan;
-#endif
-
-	//Rasterizer *rasterizer;
-	VisualServer *visual_server;
-	VideoMode current_videomode;
-	List<String> args;
-	Window x11_window;
-	Window xdnd_source_window;
-	MainLoop *main_loop;
-	::Display *x11_display;
-	char *xmbstring;
-	int xmblen;
-	unsigned long last_timestamp;
-	::Time last_keyrelease_time;
-	::XIC xic;
-	::XIM xim;
-	::XIMStyle xim_style;
-	static void xim_destroy_callback(::XIM im, ::XPointer client_data,
-			::XPointer call_data);
-
-	// IME
-	bool im_active;
-	Vector2 im_position;
-	Vector2 last_position_before_fs;
-
-	Size2 min_size;
-	Size2 max_size;
-
-	Point2 last_mouse_pos;
-	bool last_mouse_pos_valid;
-	Point2i last_click_pos;
-	uint64_t last_click_ms;
-	int last_click_button_index;
-	uint32_t last_button_state;
-
-	struct {
-		int opcode;
-		Vector<int> touch_devices;
-		Map<int, Vector2> absolute_devices;
-		Map<int, Vector3> pen_devices;
-		XIEventMask all_event_mask;
-		XIEventMask all_master_event_mask;
-		Map<int, Vector2> state;
-		double pressure;
-		Vector2 tilt;
-		Vector2 mouse_pos_to_filter;
-		Vector2 relative_motion;
-		Vector2 raw_pos;
-		Vector2 old_raw_pos;
-		::Time last_relative_time;
-	} xi;
-
-	bool refresh_device_info();
-
-	unsigned int get_mouse_button_state(unsigned int p_x11_button, int p_x11_type);
-	void get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state);
-	void flush_mouse_motion();
-
-	MouseMode mouse_mode;
-	Point2i center;
-
-	void handle_key_event(XKeyEvent *p_event, bool p_echo = false);
-	void process_xevents();
-	virtual void delete_main_loop();
-
-	bool force_quit;
-	bool minimized;
-	bool window_has_focus;
-	bool do_mouse_warp;
-
-	const char *cursor_theme;
-	int cursor_size;
-	XcursorImage *img[CURSOR_MAX];
-	Cursor cursors[CURSOR_MAX];
-	Cursor null_cursor;
-	CursorShape current_cursor;
-	Map<CursorShape, Vector<Variant>> cursors_cache;
-
-	Input *input;
-
-#ifdef JOYDEV_ENABLED
-	JoypadLinux *joypad;
-#endif
-
-#ifdef ALSA_ENABLED
-	AudioDriverALSA driver_alsa;
-#endif
-
-#ifdef ALSAMIDI_ENABLED
-	MIDIDriverALSAMidi driver_alsamidi;
-#endif
-
-#ifdef PULSEAUDIO_ENABLED
-	AudioDriverPulseAudio driver_pulseaudio;
-#endif
-
-	bool layered_window;
-
-	CrashHandler crash_handler;
-
-	int video_driver_index;
-	bool maximized;
-	bool window_focused;
-	//void set_wm_border(bool p_enabled);
-	void set_wm_fullscreen(bool p_enabled);
-	void set_wm_above(bool p_enabled);
-
-	typedef xrr_monitor_info *(*xrr_get_monitors_t)(Display *dpy, Window window, Bool get_active, int *nmonitors);
-	typedef void (*xrr_free_monitors_t)(xrr_monitor_info *monitors);
-	xrr_get_monitors_t xrr_get_monitors;
-	xrr_free_monitors_t xrr_free_monitors;
-	void *xrandr_handle;
-	Bool xrandr_ext_ok;
-
-protected:
-	virtual int get_current_video_driver() const;
-
-	virtual void initialize_core();
-	virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
-	virtual void finalize();
-
-	virtual void set_main_loop(MainLoop *p_main_loop);
-
-	void _window_changed(XEvent *event);
-
-	bool is_window_maximize_allowed();
-
-public:
-	virtual String get_name() const;
-
-	virtual void set_cursor_shape(CursorShape p_shape);
-	virtual CursorShape get_cursor_shape() const;
-	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
-
-	void set_mouse_mode(MouseMode p_mode);
-	MouseMode get_mouse_mode() const;
-
-	virtual void warp_mouse_position(const Point2 &p_to);
-	virtual Point2 get_mouse_position() const;
-	virtual int get_mouse_button_state() const;
-	virtual void set_window_title(const String &p_title);
-
-	virtual void set_icon(const Ref<Image> &p_icon);
-
-	virtual MainLoop *get_main_loop() const;
-
-	virtual bool can_draw() const;
-
-	virtual void set_clipboard(const String &p_text);
-	virtual String get_clipboard() const;
-
-	virtual void release_rendering_thread();
-	virtual void make_rendering_thread();
-	virtual void swap_buffers();
-
-	virtual String get_config_path() const;
-	virtual String get_data_path() const;
-	virtual String get_cache_path() const;
-
-	virtual String get_system_dir(SystemDir p_dir) const;
-
-	virtual Error shell_open(String p_uri);
-
-	virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0);
-	virtual VideoMode get_video_mode(int p_screen = 0) const;
-	virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const;
-
-	virtual int get_screen_count() const;
-	virtual int get_current_screen() const;
-	virtual void set_current_screen(int p_screen);
-	virtual Point2 get_screen_position(int p_screen = -1) const;
-	virtual Size2 get_screen_size(int p_screen = -1) const;
-	virtual int get_screen_dpi(int p_screen = -1) const;
-	virtual Point2 get_window_position() const;
-	virtual void set_window_position(const Point2 &p_position);
-	virtual Size2 get_window_size() const;
-	virtual Size2 get_real_window_size() const;
-	virtual Size2 get_max_window_size() const;
-	virtual Size2 get_min_window_size() const;
-	virtual void set_min_window_size(const Size2 p_size);
-	virtual void set_max_window_size(const Size2 p_size);
-	virtual void set_window_size(const Size2 p_size);
-	virtual void set_window_fullscreen(bool p_enabled);
-	virtual bool is_window_fullscreen() const;
-	virtual void set_window_resizable(bool p_enabled);
-	virtual bool is_window_resizable() const;
-	virtual void set_window_minimized(bool p_enabled);
-	virtual bool is_window_minimized() const;
-	virtual void set_window_maximized(bool p_enabled);
-	virtual bool is_window_maximized() const;
-	virtual void set_window_always_on_top(bool p_enabled);
-	virtual bool is_window_always_on_top() const;
-	virtual bool is_window_focused() const;
-	virtual void request_attention();
-
-	virtual void set_borderless_window(bool p_borderless);
-	virtual bool get_borderless_window();
-
-	virtual bool get_window_per_pixel_transparency_enabled() const;
-	virtual void set_window_per_pixel_transparency_enabled(bool p_enabled);
-
-	virtual void set_ime_active(const bool p_active);
-	virtual void set_ime_position(const Point2 &p_pos);
-
-	virtual String get_unique_id() const;
-
-	virtual void move_window_to_foreground();
-	virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
-
-	virtual bool is_joy_known(int p_device);
-	virtual String get_joy_guid(int p_device) const;
-
-	virtual void set_context(int p_context);
-
-	virtual void _set_use_vsync(bool p_enable);
-	//virtual bool is_vsync_enabled() const;
-
-	virtual bool _check_internal_feature_support(const String &p_feature);
-
-	virtual void force_process_input();
-	void run();
-
-	void disable_crash_handler();
-	bool is_disable_crash_handler() const;
-
-	virtual Error move_to_trash(const String &p_path);
-
-	virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
-
-	void update_real_mouse_position();
-	OS_X11();
-};
-
-#endif

+ 1 - 1
scene/2d/particles_2d.cpp

@@ -228,7 +228,7 @@ bool Particles2D::get_fractional_delta() const {
 
 String Particles2D::get_configuration_warning() const {
 
-	if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
+	if (VisualServer::get_singleton()->is_low_end()) {
 		return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles\" option for this purpose.");
 	}
 

+ 3 - 2
scene/2d/touch_screen_button.cpp

@@ -33,6 +33,7 @@
 #include "core/input/input.h"
 #include "core/input/input_map.h"
 #include "core/os/os.h"
+#include "scene/main/viewport.h"
 
 void TouchScreenButton::set_texture(const Ref<Texture2D> &p_texture) {
 
@@ -114,7 +115,7 @@ void TouchScreenButton::_notification(int p_what) {
 
 			if (!is_inside_tree())
 				return;
-			if (!Engine::get_singleton()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility == VISIBILITY_TOUCHSCREEN_ONLY)
+			if (!Engine::get_singleton()->is_editor_hint() && !!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())) && visibility == VISIBILITY_TOUCHSCREEN_ONLY)
 				return;
 
 			if (finger_pressed != -1) {
@@ -145,7 +146,7 @@ void TouchScreenButton::_notification(int p_what) {
 		} break;
 		case NOTIFICATION_ENTER_TREE: {
 
-			if (!Engine::get_singleton()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility == VISIBILITY_TOUCHSCREEN_ONLY)
+			if (!Engine::get_singleton()->is_editor_hint() && !!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())) && visibility == VISIBILITY_TOUCHSCREEN_ONLY)
 				return;
 			update();
 

+ 1 - 1
scene/3d/gi_probe.cpp

@@ -526,7 +526,7 @@ Vector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
 
 String GIProbe::get_configuration_warning() const {
 
-	if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
+	if (VisualServer::get_singleton()->is_low_end()) {
 		return TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead.");
 	}
 	return String();

+ 1 - 1
scene/3d/particles.cpp

@@ -240,7 +240,7 @@ bool Particles::get_fractional_delta() const {
 
 String Particles::get_configuration_warning() const {
 
-	if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
+	if (VisualServer::get_singleton()->is_low_end()) {
 		return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles node instead. You can use the \"Convert to CPUParticles\" option for this purpose.");
 	}
 

+ 21 - 21
scene/gui/line_edit.cpp

@@ -36,12 +36,12 @@
 #include "core/print_string.h"
 #include "core/translation.h"
 #include "label.h"
-
+#include "servers/display_server.h"
 #ifdef TOOLS_ENABLED
 #include "editor/editor_scale.h"
 #include "editor/editor_settings.h"
 #endif
-
+#include "scene/main/viewport.h"
 static bool _is_text_char(CharType c) {
 
 	return !is_symbol(c);
@@ -127,8 +127,8 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
 			selection.creating = false;
 			selection.doubleclick = false;
 
-			if (OS::get_singleton()->has_virtual_keyboard())
-				OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), max_length);
+			if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+				DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length);
 		}
 
 		update();
@@ -304,8 +304,8 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
 				case KEY_ENTER: {
 
 					emit_signal("text_entered", text);
-					if (OS::get_singleton()->has_virtual_keyboard())
-						OS::get_singleton()->hide_virtual_keyboard();
+					if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+						DisplayServer::get_singleton()->virtual_keyboard_hide();
 
 				} break;
 
@@ -914,8 +914,8 @@ void LineEdit::_notification(int p_what) {
 
 			if (has_focus()) {
 
-				OS::get_singleton()->set_ime_active(true);
-				OS::get_singleton()->set_ime_position(get_global_position() + Point2(using_placeholder ? 0 : x_ofs, y_ofs + caret_height));
+				DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
+				DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + Point2(using_placeholder ? 0 : x_ofs, y_ofs + caret_height), get_viewport()->get_window_id());
 			}
 		} break;
 		case NOTIFICATION_FOCUS_ENTER: {
@@ -926,12 +926,12 @@ void LineEdit::_notification(int p_what) {
 				draw_caret = true;
 			}
 
-			OS::get_singleton()->set_ime_active(true);
+			DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
 			Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height;
-			OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos);
+			DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos, get_viewport()->get_window_id());
 
-			if (OS::get_singleton()->has_virtual_keyboard())
-				OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), max_length);
+			if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+				DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length);
 
 		} break;
 		case NOTIFICATION_FOCUS_EXIT: {
@@ -940,20 +940,20 @@ void LineEdit::_notification(int p_what) {
 				caret_blink_timer->stop();
 			}
 
-			OS::get_singleton()->set_ime_position(Point2());
-			OS::get_singleton()->set_ime_active(false);
+			DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id());
+			DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id());
 			ime_text = "";
 			ime_selection = Point2();
 
-			if (OS::get_singleton()->has_virtual_keyboard())
-				OS::get_singleton()->hide_virtual_keyboard();
+			if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+				DisplayServer::get_singleton()->virtual_keyboard_hide();
 
 		} break;
 		case MainLoop::NOTIFICATION_OS_IME_UPDATE: {
 
 			if (has_focus()) {
-				ime_text = OS::get_singleton()->get_ime_text();
-				ime_selection = OS::get_singleton()->get_ime_selection();
+				ime_text = DisplayServer::get_singleton()->ime_get_text();
+				ime_selection = DisplayServer::get_singleton()->ime_get_selection();
 				update();
 			}
 		} break;
@@ -963,14 +963,14 @@ void LineEdit::_notification(int p_what) {
 void LineEdit::copy_text() {
 
 	if (selection.enabled && !pass) {
-		OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin));
+		DisplayServer::get_singleton()->clipboard_set(text.substr(selection.begin, selection.end - selection.begin));
 	}
 }
 
 void LineEdit::cut_text() {
 
 	if (selection.enabled && !pass) {
-		OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin));
+		DisplayServer::get_singleton()->clipboard_set(text.substr(selection.begin, selection.end - selection.begin));
 		selection_delete();
 	}
 }
@@ -978,7 +978,7 @@ void LineEdit::cut_text() {
 void LineEdit::paste_text() {
 
 	// Strip escape characters like \n and \t as they can't be displayed on LineEdit.
-	String paste_buffer = OS::get_singleton()->get_clipboard().strip_escapes();
+	String paste_buffer = DisplayServer::get_singleton()->clipboard_get().strip_escapes();
 
 	if (paste_buffer != "") {
 

+ 2 - 1
scene/gui/rich_text_label.cpp

@@ -34,6 +34,7 @@
 #include "core/os/keyboard.h"
 #include "core/os/os.h"
 #include "scene/scene_string_names.h"
+#include "servers/display_server.h"
 
 #include "modules/modules_enabled.gen.h"
 #ifdef MODULE_REGEX_ENABLED
@@ -2584,7 +2585,7 @@ void RichTextLabel::selection_copy() {
 	}
 
 	if (text != "") {
-		OS::get_singleton()->set_clipboard(text);
+		DisplayServer::get_singleton()->clipboard_set(text);
 	}
 }
 

+ 2 - 2
scene/gui/scroll_bar.cpp

@@ -33,6 +33,7 @@
 #include "core/os/keyboard.h"
 #include "core/os/os.h"
 #include "core/print_string.h"
+#include "scene/main/viewport.h"
 
 bool ScrollBar::focus_by_default = false;
 
@@ -559,8 +560,7 @@ void ScrollBar::_drag_node_input(const Ref<InputEvent> &p_input) {
 			drag_node_accum = Vector2();
 			last_drag_node_accum = Vector2();
 			drag_node_from = Vector2(orientation == HORIZONTAL ? get_value() : 0, orientation == VERTICAL ? get_value() : 0);
-
-			drag_node_touching = OS::get_singleton()->has_touchscreen_ui_hint();
+			drag_node_touching = !DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
 			drag_node_touching_deaccel = false;
 			time_since_motion = 0;
 

+ 2 - 2
scene/gui/scroll_container.cpp

@@ -129,7 +129,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
 		if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll)
 			accept_event(); //accept event if scroll changed
 
-		if (!OS::get_singleton()->has_touchscreen_ui_hint())
+		if (!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())))
 			return;
 
 		if (mb->get_button_index() != BUTTON_LEFT)
@@ -145,7 +145,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			drag_accum = Vector2();
 			last_drag_accum = Vector2();
 			drag_from = Vector2(h_scroll->get_value(), v_scroll->get_value());
-			drag_touching = OS::get_singleton()->has_touchscreen_ui_hint();
+			drag_touching = !DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
 			drag_touching_deaccel = false;
 			beyond_deadzone = false;
 			time_since_motion = 0;

+ 17 - 17
scene/gui/text_edit.cpp

@@ -1754,8 +1754,8 @@ void TextEdit::_notification(int p_what) {
 			}
 
 			if (has_focus()) {
-				OS::get_singleton()->set_ime_active(true);
-				OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height()));
+				DisplayServer::get_singleton()->window_set_ime_active(true);
+				DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height()));
 			}
 		} break;
 		case NOTIFICATION_FOCUS_ENTER: {
@@ -1766,12 +1766,12 @@ void TextEdit::_notification(int p_what) {
 				draw_caret = true;
 			}
 
-			OS::get_singleton()->set_ime_active(true);
+			DisplayServer::get_singleton()->window_set_ime_active(true);
 			Point2 cursor_pos = Point2(cursor_get_column(), cursor_get_line()) * get_row_height();
-			OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos);
+			DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos);
 
-			if (OS::get_singleton()->has_virtual_keyboard())
-				OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect());
+			if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+				DisplayServer::get_singleton()->virtual_keyboard_show(get_text(), get_global_rect());
 		} break;
 		case NOTIFICATION_FOCUS_EXIT: {
 
@@ -1779,19 +1779,19 @@ void TextEdit::_notification(int p_what) {
 				caret_blink_timer->stop();
 			}
 
-			OS::get_singleton()->set_ime_position(Point2());
-			OS::get_singleton()->set_ime_active(false);
+			DisplayServer::get_singleton()->window_set_ime_position(Point2());
+			DisplayServer::get_singleton()->window_set_ime_active(false);
 			ime_text = "";
 			ime_selection = Point2();
 
-			if (OS::get_singleton()->has_virtual_keyboard())
-				OS::get_singleton()->hide_virtual_keyboard();
+			if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+				DisplayServer::get_singleton()->virtual_keyboard_hide();
 		} break;
 		case MainLoop::NOTIFICATION_OS_IME_UPDATE: {
 
 			if (has_focus()) {
-				ime_text = OS::get_singleton()->get_ime_text();
-				ime_selection = OS::get_singleton()->get_ime_selection();
+				ime_text = DisplayServer::get_singleton()->ime_get_text();
+				ime_selection = DisplayServer::get_singleton()->ime_get_selection();
 				update();
 			}
 		} break;
@@ -5226,7 +5226,7 @@ void TextEdit::cut() {
 	if (!selection.active) {
 
 		String clipboard = text[cursor.line];
-		OS::get_singleton()->set_clipboard(clipboard);
+		DisplayServer::get_singleton()->clipboard_set(clipboard);
 		cursor_set_line(cursor.line);
 		cursor_set_column(0);
 
@@ -5244,7 +5244,7 @@ void TextEdit::cut() {
 	} else {
 
 		String clipboard = _base_get_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
-		OS::get_singleton()->set_clipboard(clipboard);
+		DisplayServer::get_singleton()->clipboard_set(clipboard);
 
 		_remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
 		cursor_set_line(selection.from_line); // Set afterwards else it causes the view to be offset.
@@ -5264,19 +5264,19 @@ void TextEdit::copy() {
 		if (text[cursor.line].length() != 0) {
 
 			String clipboard = _base_get_text(cursor.line, 0, cursor.line, text[cursor.line].length());
-			OS::get_singleton()->set_clipboard(clipboard);
+			DisplayServer::get_singleton()->clipboard_set(clipboard);
 			cut_copy_line = clipboard;
 		}
 	} else {
 		String clipboard = _base_get_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
-		OS::get_singleton()->set_clipboard(clipboard);
+		DisplayServer::get_singleton()->clipboard_set(clipboard);
 		cut_copy_line = "";
 	}
 }
 
 void TextEdit::paste() {
 
-	String clipboard = OS::get_singleton()->get_clipboard();
+	String clipboard = DisplayServer::get_singleton()->clipboard_get();
 
 	begin_complex_operation();
 	if (selection.active) {

+ 1 - 1
scene/gui/tree.cpp

@@ -2703,7 +2703,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
 					drag_accum = 0;
 					//last_drag_accum=0;
 					drag_from = v_scroll->get_value();
-					drag_touching = OS::get_singleton()->has_touchscreen_ui_hint();
+					drag_touching = !DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
 					drag_touching_deaccel = false;
 					if (drag_touching) {
 						set_physics_process_internal(true);

+ 4 - 3
scene/main/scene_tree.cpp

@@ -47,6 +47,7 @@
 #include "scene/resources/mesh.h"
 #include "scene/resources/packed_scene.h"
 #include "scene/scene_string_names.h"
+#include "servers/display_server.h"
 #include "servers/navigation_server.h"
 #include "servers/physics_2d_server.h"
 #include "servers/physics_server.h"
@@ -526,7 +527,7 @@ bool SceneTree::idle(float p_time) {
 	_notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS);
 	_notify_group_pause("idle_process", Node::NOTIFICATION_PROCESS);
 
-	Size2 win_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
+	Size2 win_size = Size2(DisplayServer::get_singleton()->window_get_size().width, DisplayServer::get_singleton()->window_get_size().height);
 
 	if (win_size != last_screen_size) {
 
@@ -1143,7 +1144,7 @@ void SceneTree::_update_root_rect() {
 	}
 
 	//actual screen video mode
-	Size2 video_mode = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
+	Size2 video_mode = Size2(DisplayServer::get_singleton()->window_get_size().width, DisplayServer::get_singleton()->window_get_size().height);
 	Size2 desired_res = stretch_min;
 
 	Size2 viewport_size;
@@ -1734,7 +1735,7 @@ SceneTree::SceneTree() {
 	stretch_aspect = STRETCH_ASPECT_IGNORE;
 	stretch_shrink = 1;
 
-	last_screen_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
+	last_screen_size = Size2(DisplayServer::get_singleton()->window_get_size().width, DisplayServer::get_singleton()->window_get_size().height);
 	_update_root_rect();
 
 	root->set_physics_object_picking(GLOBAL_DEF("physics/common/enable_object_picking", true));

+ 10 - 5
scene/main/viewport.cpp

@@ -51,6 +51,7 @@
 #include "scene/main/timer.h"
 #include "scene/resources/mesh.h"
 #include "scene/scene_string_names.h"
+#include "servers/display_server.h"
 #include "servers/physics_2d_server.h"
 
 void ViewportTexture::setup_local_to_scene() {
@@ -732,7 +733,7 @@ Rect2 Viewport::get_visible_rect() const {
 	Rect2 r;
 
 	if (size == Size2()) {
-		r = Rect2(Point2(), OS::get_singleton()->get_window_size());
+		r = Rect2(Point2(), DisplayServer::get_singleton()->window_get_size());
 	} else {
 		r = Rect2(Point2(), size);
 	}
@@ -2172,7 +2173,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
 		}
 
 		if (!over) {
-			OS::get_singleton()->set_cursor_shape((OS::CursorShape)Input::get_singleton()->get_default_cursor_shape());
+			DisplayServer::get_singleton()->cursor_set_shape((DisplayServer::CursorShape)Input::get_singleton()->get_default_cursor_shape());
 			return;
 		}
 
@@ -2245,7 +2246,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
 			}
 		}
 
-		OS::get_singleton()->set_cursor_shape((OS::CursorShape)cursor_shape);
+		DisplayServer::get_singleton()->cursor_set_shape((DisplayServer::CursorShape)cursor_shape);
 
 		if (over && over->can_process()) {
 			_gui_call_input(over, mm);
@@ -2258,9 +2259,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
 			bool can_drop = _gui_drop(over, pos, true);
 
 			if (!can_drop) {
-				OS::get_singleton()->set_cursor_shape(OS::CURSOR_FORBIDDEN);
+				DisplayServer::get_singleton()->cursor_set_shape(DisplayServer::CURSOR_FORBIDDEN);
 			} else {
-				OS::get_singleton()->set_cursor_shape(OS::CURSOR_CAN_DROP);
+				DisplayServer::get_singleton()->cursor_set_shape(DisplayServer::CURSOR_CAN_DROP);
 			}
 			//change mouse accordingly i guess
 		}
@@ -3086,6 +3087,10 @@ void Viewport::_propagate_update_default_repeat(Node *p_node) {
 	}
 }
 
+DisplayServer::WindowID Viewport::get_window_id() const {
+	return DisplayServer::MAIN_WINDOW_ID;
+}
+
 void Viewport::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("set_use_arvr", "use"), &Viewport::set_use_arvr);

+ 3 - 0
scene/main/viewport.h

@@ -35,6 +35,7 @@
 #include "scene/main/node.h"
 #include "scene/resources/texture.h"
 #include "scene/resources/world_2d.h"
+#include "servers/display_server.h"
 #include "servers/visual_server.h"
 
 class Camera;
@@ -560,6 +561,8 @@ public:
 	void set_default_canvas_item_texture_repeat(DefaultCanvasItemTextureRepeat p_repeat);
 	DefaultCanvasItemTextureRepeat get_default_canvas_item_texture_repeat() const;
 
+	DisplayServer::WindowID get_window_id() const;
+
 	Viewport();
 	~Viewport();
 };

+ 1 - 1
scene/register_scene_types.cpp

@@ -480,7 +480,7 @@ void register_scene_types() {
 #endif
 	ClassDB::register_class<NavigationMesh>();
 
-	AcceptDialog::set_swap_ok_cancel(GLOBAL_DEF("gui/common/swap_ok_cancel", bool(OS::get_singleton()->get_swap_ok_cancel())));
+	AcceptDialog::set_swap_ok_cancel(GLOBAL_DEF("gui/common/swap_ok_cancel", bool(DisplayServer::get_singleton()->get_swap_ok_cancel())));
 
 	ClassDB::register_class<Shader>();
 	ClassDB::register_class<VisualShader>();

+ 103 - 4
servers/display_server.cpp

@@ -29,8 +29,13 @@
 /*************************************************************************/
 
 #include "display_server.h"
+#include "core/input/input.h"
 
 DisplayServer *DisplayServer::singleton = nullptr;
+DisplayServer::SwitchVSyncCallbackInThread DisplayServer::switch_vsync_function = nullptr;
+
+DisplayServer::DisplayServerCreate DisplayServer::server_create_functions[DisplayServer::MAX_SERVERS];
+int DisplayServer::server_create_count = 0;
 
 void DisplayServer::global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta) {
 	WARN_PRINT("Global menus not supported by this display server.");
@@ -76,6 +81,18 @@ DisplayServer::ScreenOrientation DisplayServer::screen_get_orientation(int p_scr
 	return SCREEN_LANDSCAPE;
 }
 
+bool DisplayServer::screen_is_touchscreen(int p_screen) const {
+	//return false;
+	return Input::get_singleton() && Input::get_singleton()->is_emulating_touch_from_mouse();
+}
+
+void DisplayServer::screen_set_keep_on(bool p_enable) {
+	WARN_PRINT("Keeping screen on not supported by this display server.");
+}
+bool DisplayServer::screen_is_kept_on() const {
+	return false;
+}
+
 DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i) {
 	ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server.");
 }
@@ -104,7 +121,7 @@ bool DisplayServer::is_console_visible() const {
 	return false;
 }
 
-void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect) {
+void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_legth) {
 	WARN_PRINT("Virtual keyboard not supported by this display server.");
 }
 void DisplayServer::virtual_keyboard_hide() {
@@ -180,7 +197,32 @@ void DisplayServer::set_native_icon(const String &p_filename) {
 	WARN_PRINT("Native icon not supported by this display server.");
 }
 void DisplayServer::set_icon(const Ref<Image> &p_icon) {
-	WARN_PRINT("Iconnot supported by this display server.");
+	WARN_PRINT("Icon not supported by this display server.");
+}
+
+void DisplayServer::_set_use_vsync(bool p_enable) {
+	WARN_PRINT("VSync not supported by this display server.");
+}
+void DisplayServer::vsync_set_enabled(bool p_enable) {
+	vsync_enabled = p_enable;
+	if (switch_vsync_function) { //if a function was set, use function
+		switch_vsync_function(p_enable);
+	} else { //otherwise just call here
+		_set_use_vsync(p_enable);
+	}
+}
+bool DisplayServer::vsync_is_enabled() const {
+	return vsync_enabled;
+}
+
+void DisplayServer::vsync_set_use_via_compositor(bool p_enable) {
+	WARN_PRINT("VSync via compositor not supported by this display server.");
+}
+bool DisplayServer::vsync_is_using_via_compositor() const {
+	return false;
+}
+
+void DisplayServer::set_context(Context p_context) {
 }
 
 void DisplayServer::_bind_methods() {
@@ -214,6 +256,9 @@ void DisplayServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("screen_set_orientation", "orientation", "screen"), &DisplayServer::screen_set_orientation, DEFVAL(SCREEN_OF_MAIN_WINDOW));
 	ClassDB::bind_method(D_METHOD("screen_get_orientation", "screen"), &DisplayServer::screen_get_orientation, DEFVAL(SCREEN_OF_MAIN_WINDOW));
 
+	ClassDB::bind_method(D_METHOD("screen_set_keep_on", "enable"), &DisplayServer::screen_set_keep_on);
+	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("create_sub_window", "mode", "rect"), &DisplayServer::create_sub_window, DEFVAL(Rect2i()));
@@ -258,14 +303,14 @@ void DisplayServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("console_set_visible", "console_visible"), &DisplayServer::console_set_visible);
 	ClassDB::bind_method(D_METHOD("is_console_visible"), &DisplayServer::is_console_visible);
 
-	ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2i()));
+	ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "max_length"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2i()), DEFVAL(-1));
 	ClassDB::bind_method(D_METHOD("virtual_keyboard_hide"), &DisplayServer::virtual_keyboard_hide);
 
 	ClassDB::bind_method(D_METHOD("virtual_keyboard_get_height"), &DisplayServer::virtual_keyboard_get_height);
 
 	ClassDB::bind_method(D_METHOD("cursor_set_shape", "shape"), &DisplayServer::cursor_set_shape);
 	ClassDB::bind_method(D_METHOD("cursor_get_shape"), &DisplayServer::cursor_get_shape);
-	ClassDB::bind_method(D_METHOD("cursor_set_custom_image", "cursor", "shape", "hotspot"), &DisplayServer::cursor_set_custom_image);
+	ClassDB::bind_method(D_METHOD("cursor_set_custom_image", "cursor", "shape", "hotspot"), &DisplayServer::cursor_set_custom_image, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2()));
 
 	ClassDB::bind_method(D_METHOD("get_swap_ok_cancel"), &DisplayServer::get_swap_ok_cancel);
 
@@ -285,6 +330,12 @@ void DisplayServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("process_events"), &DisplayServer::process_events);
 	ClassDB::bind_method(D_METHOD("force_process_and_drop_events"), &DisplayServer::force_process_and_drop_events);
 
+	ClassDB::bind_method(D_METHOD("vsync_set_enabled", "enabled"), &DisplayServer::vsync_set_enabled);
+	ClassDB::bind_method(D_METHOD("vsync_is_enabled"), &DisplayServer::vsync_is_enabled);
+
+	ClassDB::bind_method(D_METHOD("vsync_set_use_via_compositor", "enabled"), &DisplayServer::vsync_set_use_via_compositor);
+	ClassDB::bind_method(D_METHOD("vsync_is_using_via_compositor"), &DisplayServer::vsync_is_using_via_compositor);
+
 	ClassDB::bind_method(D_METHOD("set_native_icon", "filename"), &DisplayServer::set_native_icon);
 	ClassDB::bind_method(D_METHOD("set_icon", "image"), &DisplayServer::set_icon);
 
@@ -367,8 +418,56 @@ void DisplayServer::_bind_methods() {
 	BIND_ENUM_CONSTANT(LATIN_KEYBOARD_NEO);
 	BIND_ENUM_CONSTANT(LATIN_KEYBOARD_COLEMAK);
 }
+
+void DisplayServer::register_create_function(const char *p_name, CreateFunction p_function, GetVideoDriversFunction p_get_drivers) {
+	ERR_FAIL_COND(server_create_count == MAX_SERVERS);
+	server_create_functions[server_create_count].create_function = p_function;
+	server_create_functions[server_create_count].name = p_name;
+	server_create_count++;
+}
+int DisplayServer::get_create_function_count() {
+	return server_create_count;
+}
+const char *DisplayServer::get_create_function_name(int p_index) {
+	ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr);
+	return server_create_functions[p_index].name;
+}
+
+Vector<String> DisplayServer::get_create_function_rendering_drivers(int p_index) {
+	ERR_FAIL_INDEX_V(p_index, server_create_count, Vector<String>());
+	return server_create_functions[p_index].get_rendering_drivers_function();
+}
+
+DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+	ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr);
+	return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_flags, p_resolution, r_error);
+}
+
+void DisplayServer::_input_set_mouse_mode(Input::MouseMode p_mode) {
+	singleton->mouse_set_mode(MouseMode(p_mode));
+}
+Input::MouseMode DisplayServer::_input_get_mouse_mode() {
+	return Input::MouseMode(singleton->mouse_get_mode());
+}
+
+void DisplayServer::_input_warp(const Vector2 &p_to_pos) {
+	singleton->mouse_warp_to_position(p_to_pos);
+}
+
+Input::CursorShape DisplayServer::_input_get_current_cursor_shape() {
+	return (Input::CursorShape)singleton->cursor_get_shape();
+}
+void DisplayServer::_input_set_custom_mouse_cursor_func(const RES &p_image, Input::CursorShape p_shape, const Vector2 &p_hostspot) {
+	singleton->cursor_set_custom_image(p_image, (CursorShape)p_shape, p_hostspot);
+}
+
 DisplayServer::DisplayServer() {
 	singleton = this;
+	Input::set_mouse_mode_func = _input_set_mouse_mode;
+	Input::get_mouse_mode_func = _input_get_mouse_mode;
+	Input::warp_mouse_func = _input_warp;
+	Input::get_current_cursor_shape_func = _input_get_current_cursor_shape;
+	Input::set_custom_mouse_cursor_func = _input_set_custom_mouse_cursor_func;
 }
 DisplayServer::~DisplayServer() {
 }

+ 71 - 14
servers/display_server.h

@@ -31,6 +31,7 @@
 #ifndef DISPLAY_SERVER_H
 #define DISPLAY_SERVER_H
 
+#include "core/input/input.h"
 #include "core/os/os.h"
 #include "core/resource.h"
 
@@ -38,9 +39,45 @@ class DisplayServer : public Object {
 	GDCLASS(DisplayServer, Object)
 
 	static DisplayServer *singleton;
+	bool vsync_enabled = true;
+
+public:
+	_FORCE_INLINE_ static DisplayServer *get_singleton() {
+		return singleton;
+	}
+	enum WindowMode {
+		WINDOW_MODE_WINDOWED,
+		WINDOW_MODE_MINIMIZED,
+		WINDOW_MODE_MAXIMIZED,
+		WINDOW_MODE_FULLSCREEN
+	};
+
+	typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, uint32_t, const Size2i &, Error &r_error); //video driver, window mode, resolution
+	typedef Vector<String> (*GetVideoDriversFunction)(); //video driver, window mode, resolution
+private:
+	static void _input_set_mouse_mode(Input::MouseMode p_mode);
+	static Input::MouseMode _input_get_mouse_mode();
+	static void _input_warp(const Vector2 &p_to_pos);
+	static Input::CursorShape _input_get_current_cursor_shape();
+	static void _input_set_custom_mouse_cursor_func(const RES &, Input::CursorShape, const Vector2 &p_hostspot);
 
 protected:
 	static void _bind_methods();
+	enum {
+		MAX_SERVERS = 64
+	};
+
+	struct DisplayServerCreate {
+		const char *name;
+		GetVideoDriversFunction get_rendering_drivers_function;
+		CreateFunction create_function;
+	};
+
+	static DisplayServerCreate server_create_functions[MAX_SERVERS];
+	static int server_create_count;
+
+	friend class VisualServerRaster;
+	virtual void _set_use_vsync(bool p_enable);
 
 public:
 	enum Feature {
@@ -62,7 +99,8 @@ public:
 		FEATURE_ICON,
 		FEATURE_NATIVE_ICON,
 		FEATURE_ORIENTATION,
-		FEATURE_SWAP_BUFFERS
+		FEATURE_SWAP_BUFFERS,
+		FEATURE_KEEP_SCREEN_ON,
 
 	};
 
@@ -101,8 +139,7 @@ public:
 	virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
 	virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
 	virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
-	virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
-
+	virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
 	enum ScreenOrientation {
 
 		SCREEN_LANDSCAPE,
@@ -117,6 +154,8 @@ public:
 	virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW);
 	ScreenOrientation screen_get_orientation(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
 
+	virtual void screen_set_keep_on(bool p_enable); //disable screensaver
+	virtual bool screen_is_kept_on() const;
 	enum {
 		MAIN_WINDOW_ID = 0,
 		INVALID_WINDOW_ID = -1
@@ -126,13 +165,6 @@ public:
 
 	virtual Vector<int> get_window_list() const = 0;
 
-	enum WindowMode {
-		WINDOW_MODE_WINDOWED,
-		WINDOW_MODE_MINIMIZED,
-		WINDOW_MODE_MAXIMIZED,
-		WINDOW_MODE_FULLSCREEN
-	};
-
 	enum WindowFlags {
 		WINDOW_FLAG_RESIZE_DISABLED,
 		WINDOW_FLAG_BORDERLESS,
@@ -179,6 +211,8 @@ public:
 
 	virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const = 0;
 
+	virtual bool can_any_window_draw() const = 0;
+
 	virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
 	virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
 
@@ -188,7 +222,7 @@ public:
 	virtual void console_set_visible(bool p_enabled);
 	virtual bool is_console_visible() const;
 
-	virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2());
+	virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_legth = -1);
 	virtual void virtual_keyboard_hide();
 
 	// returns height of the currently shown virtual keyboard (0 if keyboard is hidden)
@@ -216,7 +250,7 @@ public:
 	};
 	virtual void cursor_set_shape(CursorShape p_shape);
 	virtual CursorShape cursor_get_shape() const;
-	virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
+	virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
 
 	virtual bool get_swap_ok_cancel();
 
@@ -255,8 +289,31 @@ public:
 	virtual void set_native_icon(const String &p_filename);
 	virtual void set_icon(const Ref<Image> &p_icon);
 
-	typedef Vector<String> *(*GetSupportedVideoDriversFunction)();
-	typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, uint32_t, const Size2i &, Error &r_error); //video driver, window mode, resolution
+	typedef void (*SwitchVSyncCallbackInThread)(bool);
+
+	static SwitchVSyncCallbackInThread switch_vsync_function;
+
+	void vsync_set_enabled(bool p_enable);
+	bool vsync_is_enabled() const;
+
+	virtual void vsync_set_use_via_compositor(bool p_enable);
+	virtual bool vsync_is_using_via_compositor() const;
+
+	//real, actual overridable function to switch vsync, which needs to be called from graphics thread if needed
+
+	enum Context {
+		CONTEXT_EDITOR,
+		CONTEXT_PROJECTMAN,
+		CONTEXT_ENGINE,
+	};
+
+	virtual void set_context(Context p_context);
+
+	static void register_create_function(const char *p_name, CreateFunction p_function, GetVideoDriversFunction p_get_drivers);
+	static int get_create_function_count();
+	static const char *get_create_function_name(int p_index);
+	static Vector<String> get_create_function_rendering_drivers(int p_index);
+	static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
 
 	DisplayServer();
 	~DisplayServer();

+ 1 - 1
servers/visual/visual_server_raster.cpp

@@ -234,7 +234,7 @@ void VisualServerRaster::set_debug_generate_wireframes(bool p_generate) {
 }
 
 void VisualServerRaster::call_set_use_vsync(bool p_enable) {
-	OS::get_singleton()->_set_use_vsync(p_enable);
+	DisplayServer::get_singleton()->_set_use_vsync(p_enable);
 }
 
 bool VisualServerRaster::is_low_end() const {

+ 4 - 3
servers/visual/visual_server_wrap_mt.cpp

@@ -31,6 +31,7 @@
 #include "visual_server_wrap_mt.h"
 #include "core/os/os.h"
 #include "core/project_settings.h"
+#include "servers/display_server.h"
 
 void VisualServerWrapMT::thread_exit() {
 
@@ -61,7 +62,7 @@ void VisualServerWrapMT::thread_loop() {
 
 	server_thread = Thread::get_caller_id();
 
-	OS::get_singleton()->make_rendering_thread();
+	DisplayServer::get_singleton()->make_rendering_thread();
 
 	visual_server->init();
 
@@ -108,7 +109,7 @@ void VisualServerWrapMT::init() {
 	if (create_thread) {
 
 		print_verbose("VisualServerWrapMT: Creating render thread");
-		OS::get_singleton()->release_rendering_thread();
+		DisplayServer::get_singleton()->release_rendering_thread();
 		if (create_thread) {
 			thread = Thread::create(_thread_callback, this);
 			print_verbose("VisualServerWrapMT: Starting render thread");
@@ -173,7 +174,7 @@ VisualServerWrapMT::VisualServerWrapMT(VisualServer *p_contained, bool p_create_
 		command_queue(p_create_thread) {
 
 	singleton_mt = this;
-	OS::switch_vsync_function = set_use_vsync_callback; //as this goes to another thread, make sure it goes properly
+	DisplayServer::switch_vsync_function = set_use_vsync_callback; //as this goes to another thread, make sure it goes properly
 
 	visual_server = p_contained;
 	create_thread = p_create_thread;