diff options
-rw-r--r-- | doc/classes/DisplayServer.xml | 12 | ||||
-rw-r--r-- | doc/classes/EditorPaths.xml | 4 | ||||
-rw-r--r-- | editor/editor_paths.cpp | 14 | ||||
-rw-r--r-- | editor/renames_map_3_to_4.cpp | 3 | ||||
-rw-r--r-- | modules/gltf/editor/editor_scene_importer_blend.cpp | 5 | ||||
-rw-r--r-- | modules/mono/godotsharp_dirs.cpp | 22 | ||||
-rw-r--r-- | modules/text_server_adv/text_server_adv.cpp | 23 | ||||
-rw-r--r-- | modules/text_server_fb/text_server_fb.cpp | 6 | ||||
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.cpp | 24 | ||||
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.h | 1 | ||||
-rw-r--r-- | platform/macos/display_server_macos.h | 1 | ||||
-rw-r--r-- | platform/macos/display_server_macos.mm | 30 | ||||
-rw-r--r-- | platform/windows/display_server_windows.cpp | 24 | ||||
-rw-r--r-- | platform/windows/display_server_windows.h | 5 | ||||
-rw-r--r-- | scene/gui/code_edit.cpp | 6 | ||||
-rw-r--r-- | servers/display_server.cpp | 2 | ||||
-rw-r--r-- | servers/display_server.h | 2 |
17 files changed, 159 insertions, 25 deletions
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 4c2200ae9a..8bf58d5cd3 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -865,6 +865,15 @@ [b]Note:[/b] This method is implemented on Android and iOS. </description> </method> + <method name="screen_get_pixel" qualifiers="const"> + <return type="Color" /> + <param index="0" name="position" type="Vector2i" /> + <description> + Returns color of the display pixel at the [param position]. + [b]Note:[/b] This method is implemented on Linux (X11), macOS, and Windows. + [b]Note:[/b] On macOS, this method requires "Screen Recording" permission, if permission is not granted it will return desktop wallpaper color. + </description> + </method> <method name="screen_get_position" qualifiers="const"> <return type="Vector2i" /> <param index="0" name="screen" type="int" default="-1" /> @@ -1543,6 +1552,9 @@ <constant name="FEATURE_EXTEND_TO_TITLE" value="20" enum="Feature"> Display server supports expanding window content to the title. See [constant WINDOW_FLAG_EXTEND_TO_TITLE]. [b]macOS[/b] </constant> + <constant name="FEATURE_SCREEN_CAPTURE" value="21" enum="Feature"> + Display server supports reading screen pixels. See [method screen_get_pixel]. + </constant> <constant name="MOUSE_MODE_VISIBLE" value="0" enum="MouseMode"> Makes the mouse cursor visible if it is hidden. </constant> diff --git a/doc/classes/EditorPaths.xml b/doc/classes/EditorPaths.xml index eacb366d84..c4b9eda24c 100644 --- a/doc/classes/EditorPaths.xml +++ b/doc/classes/EditorPaths.xml @@ -64,7 +64,9 @@ <return type="bool" /> <description> Returns [code]true[/code] if the editor is marked as self-contained, [code]false[/code] otherwise. When self-contained mode is enabled, user configuration, data and cache files are saved in an [code]editor_data/[/code] folder next to the editor binary. This makes portable usage easier and ensures the Godot editor minimizes file writes outside its own folder. Self-contained mode is not available for exported projects. - Self-contained mode can be enabled by creating a file named [code]._sc_[/code] or [code]_sc_[/code] in the same folder as the editor binary while the editor is not running. See also [method get_self_contained_file]. + Self-contained mode can be enabled by creating a file named [code]._sc_[/code] or [code]_sc_[/code] in the same folder as the editor binary or macOS .app bundle while the editor is not running. See also [method get_self_contained_file]. + [b]Note:[/b] On macOS, quarantine flag should be manually removed before using self-contained mode, see [url=https://docs.godotengine.org/en/stable/tutorials/export/running_on_macos.html]Running on macOS[/url]. + [b]Note:[/b] On macOS, placing [code]_sc_[/code] or any other file inside .app bundle will break digital signature and make it non-portable, consider placing it in the same folder as the .app bundle instead. [b]Note:[/b] The Steam release of Godot uses self-contained mode by default. </description> </method> diff --git a/editor/editor_paths.cpp b/editor/editor_paths.cpp index 389c16fd66..d5ba841801 100644 --- a/editor/editor_paths.cpp +++ b/editor/editor_paths.cpp @@ -117,14 +117,20 @@ EditorPaths::EditorPaths() { // Self-contained mode if a `._sc_` or `_sc_` file is present in executable dir. String exe_path = OS::get_singleton()->get_executable_path().get_base_dir(); + Ref<DirAccess> d = DirAccess::create_for_path(exe_path); + if (d->file_exists(exe_path + "/._sc_")) { + self_contained = true; + self_contained_file = exe_path + "/._sc_"; + } else if (d->file_exists(exe_path + "/_sc_")) { + self_contained = true; + self_contained_file = exe_path + "/_sc_"; + } // On macOS, look outside .app bundle, since .app bundle is read-only. + // Note: This will not work if Gatekeeper path randomization is active. if (OS::get_singleton()->has_feature("macos") && exe_path.ends_with("MacOS") && exe_path.path_join("..").simplify_path().ends_with("Contents")) { exe_path = exe_path.path_join("../../..").simplify_path(); - } - { - Ref<DirAccess> d = DirAccess::create_for_path(exe_path); - + d = DirAccess::create_for_path(exe_path); if (d->file_exists(exe_path + "/._sc_")) { self_contained = true; self_contained_file = exe_path + "/._sc_"; diff --git a/editor/renames_map_3_to_4.cpp b/editor/renames_map_3_to_4.cpp index ef348e538f..359b18591b 100644 --- a/editor/renames_map_3_to_4.cpp +++ b/editor/renames_map_3_to_4.cpp @@ -1095,6 +1095,7 @@ const char *RenamesMap3To4::gdscript_properties_renames[][2] = { { "margin_top", "offset_top" }, // Control -- Breaks NinePatchRect, StyleBox. { "mid_height", "height" }, // CapsuleMesh { "neighbor_dist", "neighbor_distance" }, // NavigationAgent2D, NavigationAgent3D + { "octaves", "fractal_octaves" }, // OpenSimplexNoise -> FastNoiseLite { "offset_h", "drag_horizontal_offset" }, // Camera2D { "offset_v", "drag_vertical_offset" }, // Camera2D { "off_disabled", "unchecked_disabled" }, // Theme @@ -1189,6 +1190,7 @@ const char *RenamesMap3To4::csharp_properties_renames[][2] = { { "MarginTop", "OffsetTop" }, // Control -- Breaks NinePatchRect, StyleBox. { "MidHeight", "Height" }, // CapsuleMesh { "NeighborDist", "NeighborDistance" }, // NavigationAgent2D, NavigationAgent3D + { "Octaves", "FractalOctaves" }, // OpenSimplexNoise -> FastNoiseLite { "OffsetH", "DragHorizontalOffset" }, // Camera2D { "OffsetV", "DragVerticalOffset" }, // Camera2D { "OffDisabled", "UncheckedDisabled" }, // Theme @@ -1525,6 +1527,7 @@ const char *RenamesMap3To4::class_renames[][2] = { { "NetworkedMultiplayerPeer", "MultiplayerPeer" }, { "Occluder", "OccluderInstance3D" }, { "OmniLight", "OmniLight3D" }, + { "OpenSimplexNoise", "FastNoiseLite" }, { "PHashTranslation", "OptimizedTranslation" }, { "PacketPeerGDNative", "PacketPeerExtension" }, { "PanoramaSky", "Sky" }, diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 7dcdc8e7cf..a736e36c6a 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -297,13 +297,14 @@ static bool _test_blender_path(const String &p_path, String *r_err = nullptr) { } return false; } - - if (pipe.find("Blender ") != 0) { + int bl = pipe.find("Blender "); + if (bl == -1) { if (r_err) { *r_err = vformat(TTR("Unexpected --version output from Blender binary at: %s"), path); } return false; } + pipe = pipe.substr(bl); pipe = pipe.replace_first("Blender ", ""); int pp = pipe.find("."); if (pp == -1) { diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index d08dedcfcb..bff7d04b55 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -66,23 +66,25 @@ String _get_mono_user_dir() { if (EditorPaths::get_singleton()) { return EditorPaths::get_singleton()->get_data_dir().path_join("mono"); } else { - String settings_path; + String settings_path = OS::get_singleton()->get_data_path().path_join(OS::get_singleton()->get_godot_dir_name()); // Self-contained mode if a `._sc_` or `_sc_` file is present in executable dir. String exe_dir = OS::get_singleton()->get_executable_path().get_base_dir(); - - // On macOS, look outside .app bundle, since .app bundle is read-only. - if (OS::get_singleton()->has_feature("macos") && exe_dir.ends_with("MacOS") && exe_dir.path_join("..").simplify_path().ends_with("Contents")) { - exe_dir = exe_dir.path_join("../../..").simplify_path(); - } - Ref<DirAccess> d = DirAccess::create_for_path(exe_dir); - if (d->file_exists("._sc_") || d->file_exists("_sc_")) { // contain yourself settings_path = exe_dir.path_join("editor_data"); - } else { - settings_path = OS::get_singleton()->get_data_path().path_join(OS::get_singleton()->get_godot_dir_name()); + } + + // On macOS, look outside .app bundle, since .app bundle is read-only. + // Note: This will not work if Gatekeeper path randomization is active. + if (OS::get_singleton()->has_feature("macos") && exe_dir.ends_with("MacOS") && exe_dir.path_join("..").simplify_path().ends_with("Contents")) { + exe_dir = exe_dir.path_join("../../..").simplify_path(); + d = DirAccess::create_for_path(exe_dir); + if (d->file_exists("._sc_") || d->file_exists("_sc_")) { + // contain yourself + settings_path = exe_dir.path_join("editor_data"); + } } return settings_path.path_join("mono"); diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 2a29d86ec6..79c007ace6 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -4322,7 +4322,7 @@ double TextServerAdvanced::_shaped_text_fit_to_width(const RID &p_shaped, double elongation_count++; } } - if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { + if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE && (gl.flags & GRAPHEME_IS_PUNCTUATION) != GRAPHEME_IS_PUNCTUATION) { space_count++; } } @@ -4339,9 +4339,9 @@ double TextServerAdvanced::_shaped_text_fit_to_width(const RID &p_shaped, double int count = delta_width_per_kashida / gl.advance; int prev_count = gl.repeat; if ((gl.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) { - gl.repeat = MAX(count, 0); + gl.repeat = CLAMP(count, 0, 255); } else { - gl.repeat = MAX(count + 1, 1); + gl.repeat = CLAMP(count + 1, 1, 255); } justification_width += (gl.repeat - prev_count) * gl.advance; } @@ -4355,7 +4355,7 @@ double TextServerAdvanced::_shaped_text_fit_to_width(const RID &p_shaped, double for (int i = start_pos; i <= end_pos; i++) { Glyph &gl = sd->glyphs.write[i]; if (gl.count > 0) { - if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { + if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE && (gl.flags & GRAPHEME_IS_PUNCTUATION) != GRAPHEME_IS_PUNCTUATION) { double old_adv = gl.advance; double new_advance; if ((gl.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) { @@ -4791,6 +4791,19 @@ bool TextServerAdvanced::_shaped_text_update_breaks(const RID &p_shaped) { gl.font_rid = sd_glyphs[i].font_rid; gl.font_size = sd_glyphs[i].font_size; gl.flags = GRAPHEME_IS_BREAK_SOFT | GRAPHEME_IS_VIRTUAL | GRAPHEME_IS_SPACE; + // Mark virtual space after punctuation as punctuation to avoid justification at this point. + if (c_punct_size == 0) { + if (u_ispunct(c) && c != 0x005f) { + gl.flags |= GRAPHEME_IS_PUNCTUATION; + } + } else { + for (int j = 0; j < c_punct_size; j++) { + if (c_punct[j] == c) { + gl.flags |= GRAPHEME_IS_PUNCTUATION; + break; + } + } + } if (sd_glyphs[i].flags & GRAPHEME_IS_RTL) { gl.flags |= GRAPHEME_IS_RTL; for (int j = sd_glyphs[i].count - 1; j >= 0; j--) { @@ -5002,7 +5015,7 @@ bool TextServerAdvanced::_shaped_text_update_justification_ops(const RID &p_shap } } } - } else if ((sd_glyphs[i].flags & GRAPHEME_IS_SPACE) != GRAPHEME_IS_SPACE) { + } else if ((sd_glyphs[i].flags & GRAPHEME_IS_SPACE) != GRAPHEME_IS_SPACE && (sd_glyphs[i].flags & GRAPHEME_IS_PUNCTUATION) != GRAPHEME_IS_PUNCTUATION) { int count = sd_glyphs[i].count; // Do not add extra spaces at the end of the line. if (sd_glyphs[i].end == sd->end) { diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index e94b330d33..9a9dcb3a31 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -3271,7 +3271,7 @@ double TextServerFallback::_shaped_text_fit_to_width(const RID &p_shaped, double for (int i = start_pos; i <= end_pos; i++) { const Glyph &gl = sd->glyphs[i]; if (gl.count > 0) { - if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { + if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE && (gl.flags & GRAPHEME_IS_PUNCTUATION) != GRAPHEME_IS_PUNCTUATION) { space_count++; } } @@ -3282,7 +3282,7 @@ double TextServerFallback::_shaped_text_fit_to_width(const RID &p_shaped, double for (int i = start_pos; i <= end_pos; i++) { Glyph &gl = sd->glyphs.write[i]; if (gl.count > 0) { - if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { + if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE && (gl.flags & GRAPHEME_IS_PUNCTUATION) != GRAPHEME_IS_PUNCTUATION) { double old_adv = gl.advance; gl.advance = MAX(gl.advance + delta_width_per_space, Math::round(0.1 * gl.font_size)); justification_width += (gl.advance - old_adv); @@ -3381,7 +3381,7 @@ bool TextServerFallback::_shaped_text_update_breaks(const RID &p_shaped) { if (sd_glyphs[i].count > 0) { char32_t c = sd->text[sd_glyphs[i].start - sd->start]; if (c_punct_size == 0) { - if (is_punct(c) && c != 0x005F) { + if (is_punct(c) && c != 0x005F && c != ' ') { sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION; } } else { diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index d1f1115aad..70e5ac8561 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -128,6 +128,7 @@ bool DisplayServerX11::has_feature(Feature p_feature) const { #endif case FEATURE_CLIPBOARD_PRIMARY: case FEATURE_TEXT_TO_SPEECH: + case FEATURE_SCREEN_CAPTURE: return true; default: { } @@ -1169,6 +1170,29 @@ int DisplayServerX11::screen_get_dpi(int p_screen) const { return 96; } +Color DisplayServerX11::screen_get_pixel(const Point2i &p_position) const { + Point2i pos = p_position; + + int number_of_screens = XScreenCount(x11_display); + for (int i = 0; i < number_of_screens; i++) { + Window root = XRootWindow(x11_display, i); + XWindowAttributes root_attrs; + XGetWindowAttributes(x11_display, root, &root_attrs); + if ((pos.x >= root_attrs.x) && (pos.x <= root_attrs.x + root_attrs.width) && (pos.y >= root_attrs.y) && (pos.y <= root_attrs.y + root_attrs.height)) { + XImage *image = XGetImage(x11_display, root, pos.x, pos.y, 1, 1, AllPlanes, XYPixmap); + if (image) { + XColor c; + c.pixel = XGetPixel(image, 0, 0); + XFree(image); + XQueryColor(x11_display, XDefaultColormap(x11_display, i), &c); + return Color(float(c.red) / 65535.0, float(c.green) / 65535.0, float(c.blue) / 65535.0, 1.0); + } + } + } + + return Color(); +} + float DisplayServerX11::screen_get_refresh_rate(int p_screen) const { _THREAD_SAFE_METHOD_ diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index dbe8a0ce2b..c98409253e 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -409,6 +409,7 @@ public: virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + virtual Color screen_get_pixel(const Point2i &p_position) const override; #if defined(DBUS_ENABLED) virtual void screen_set_keep_on(bool p_enable) override; diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index fb9bcdfe56..f7c5b0b847 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -334,6 +334,7 @@ public: virtual float screen_get_max_scale() const override; virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + virtual Color screen_get_pixel(const Point2i &p_position) const override; virtual void screen_set_keep_on(bool p_enable) override; virtual bool screen_is_kept_on() const override; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index e8eb5b419b..eba69f8954 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -765,6 +765,7 @@ bool DisplayServerMacOS::has_feature(Feature p_feature) const { case FEATURE_SWAP_BUFFERS: case FEATURE_TEXT_TO_SPEECH: case FEATURE_EXTEND_TO_TITLE: + case FEATURE_SCREEN_CAPTURE: return true; default: { } @@ -2249,6 +2250,35 @@ Rect2i DisplayServerMacOS::screen_get_usable_rect(int p_screen) const { return Rect2i(); } +Color DisplayServerMacOS::screen_get_pixel(const Point2i &p_position) const { + Point2i position = p_position; + // OS X native y-coordinate relative to _get_screens_origin() is negative, + // Godot passes a positive value. + position.y *= -1; + position += _get_screens_origin(); + position /= screen_get_max_scale(); + + for (NSScreen *screen in [NSScreen screens]) { + NSRect frame = [screen frame]; + if (NSMouseInRect(NSMakePoint(position.x, position.y), frame, NO)) { + NSDictionary *screenDescription = [screen deviceDescription]; + CGDirectDisplayID display_id = [[screenDescription objectForKey:@"NSScreenNumber"] unsignedIntValue]; + CGImageRef image = CGDisplayCreateImageForRect(display_id, CGRectMake(position.x - frame.origin.x, frame.size.height - (position.y - frame.origin.y), 1, 1)); + if (image) { + NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCGImage:image]; + CGImageRelease(image); + NSColor *color = [bitmap colorAtX:0 y:0]; + if (color) { + CGFloat components[4]; + [color getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]]; + return Color(components[0], components[1], components[2], components[3]); + } + } + } + } + return Color(); +} + float DisplayServerMacOS::screen_get_refresh_rate(int p_screen) const { _THREAD_SAFE_METHOD_ diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 360e446de7..ad96a82df7 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -90,6 +90,7 @@ bool DisplayServerWindows::has_feature(Feature p_feature) const { case FEATURE_SWAP_BUFFERS: case FEATURE_KEEP_SCREEN_ON: case FEATURE_TEXT_TO_SPEECH: + case FEATURE_SCREEN_CAPTURE: return true; default: return false; @@ -631,6 +632,26 @@ int DisplayServerWindows::screen_get_dpi(int p_screen) const { EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcDpi, (LPARAM)&data); return data.dpi; } + +Color DisplayServerWindows::screen_get_pixel(const Point2i &p_position) const { + Point2i pos = p_position + _get_screens_origin(); + + POINT p; + p.x = pos.x; + p.y = pos.y; + if (win81p_LogicalToPhysicalPointForPerMonitorDPI) { + win81p_LogicalToPhysicalPointForPerMonitorDPI(0, &p); + } + HDC dc = GetDC(0); + COLORREF col = GetPixel(dc, p.x, p.y); + if (col != CLR_INVALID) { + return Color(float(col & 0x000000FF) / 256.0, float((col & 0x0000FF00) >> 8) / 256.0, float((col & 0x00FF0000) >> 16) / 256.0, 1.0); + } + ReleaseDC(NULL, dc); + + return Color(); +} + float DisplayServerWindows::screen_get_refresh_rate(int p_screen) const { _THREAD_SAFE_METHOD_ @@ -4023,6 +4044,7 @@ GetImmersiveUserColorSetPreferencePtr DisplayServerWindows::GetImmersiveUserColo bool DisplayServerWindows::winink_available = false; GetPointerTypePtr DisplayServerWindows::win8p_GetPointerType = nullptr; GetPointerPenInfoPtr DisplayServerWindows::win8p_GetPointerPenInfo = nullptr; +LogicalToPhysicalPointForPerMonitorDPIPtr DisplayServerWindows::win81p_LogicalToPhysicalPointForPerMonitorDPI = nullptr; typedef enum _SHC_PROCESS_DPI_AWARENESS { SHC_PROCESS_DPI_UNAWARE = 0, @@ -4151,10 +4173,12 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } // Note: Windows Ink API for pen input, available on Windows 8+ only. + // Note: DPI conversion API, available on Windows 8.1+ only. HMODULE user32_lib = LoadLibraryW(L"user32.dll"); if (user32_lib) { win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType"); win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo"); + win81p_LogicalToPhysicalPointForPerMonitorDPI = (LogicalToPhysicalPointForPerMonitorDPIPtr)GetProcAddress(user32_lib, "LogicalToPhysicalPointForPerMonitorDPI"); winink_available = win8p_GetPointerType && win8p_GetPointerPenInfo; } diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 0d2137d048..1b36b0951e 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -259,6 +259,7 @@ typedef struct tagPOINTER_PEN_INFO { typedef BOOL(WINAPI *GetPointerTypePtr)(uint32_t p_id, POINTER_INPUT_TYPE *p_type); typedef BOOL(WINAPI *GetPointerPenInfoPtr)(uint32_t p_id, POINTER_PEN_INFO *p_pen_info); +typedef BOOL(WINAPI *LogicalToPhysicalPointForPerMonitorDPIPtr)(HWND hwnd, LPPOINT lpPoint); typedef struct { BYTE bWidth; // Width, in pixels, of the image @@ -305,6 +306,9 @@ class DisplayServerWindows : public DisplayServer { static GetPointerTypePtr win8p_GetPointerType; static GetPointerPenInfoPtr win8p_GetPointerPenInfo; + // DPI conversion API + static LogicalToPhysicalPointForPerMonitorDPIPtr win81p_LogicalToPhysicalPointForPerMonitorDPI; + void _update_tablet_ctx(const String &p_old_driver, const String &p_new_driver); String tablet_driver; Vector<String> tablet_drivers; @@ -524,6 +528,7 @@ public: virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + virtual Color screen_get_pixel(const Point2i &p_position) const override; virtual void screen_set_keep_on(bool p_enable) override; //disable screensaver virtual bool screen_is_kept_on() const override; diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index ee39327d4d..91c4fa3761 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -2926,6 +2926,12 @@ void CodeEdit::_filter_code_completion_candidates_impl() { code_completion_options.clear(); code_completion_base = string_to_complete; + /* Don't autocomplete setting numerical values. */ + if (code_completion_base.is_numeric()) { + cancel_code_completion(); + return; + } + Vector<ScriptLanguage::CodeCompletionOption> completion_options_casei; Vector<ScriptLanguage::CodeCompletionOption> completion_options_substr; Vector<ScriptLanguage::CodeCompletionOption> completion_options_substr_casei; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 2d65cea432..1e60094106 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -658,6 +658,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("is_touchscreen_available"), &DisplayServer::is_touchscreen_available, DEFVAL(SCREEN_OF_MAIN_WINDOW)); ClassDB::bind_method(D_METHOD("screen_get_max_scale"), &DisplayServer::screen_get_max_scale); ClassDB::bind_method(D_METHOD("screen_get_refresh_rate", "screen"), &DisplayServer::screen_get_refresh_rate, DEFVAL(SCREEN_OF_MAIN_WINDOW)); + ClassDB::bind_method(D_METHOD("screen_get_pixel", "position"), &DisplayServer::screen_get_pixel); 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)); @@ -785,6 +786,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_CLIPBOARD_PRIMARY); BIND_ENUM_CONSTANT(FEATURE_TEXT_TO_SPEECH); BIND_ENUM_CONSTANT(FEATURE_EXTEND_TO_TITLE); + BIND_ENUM_CONSTANT(FEATURE_SCREEN_CAPTURE); BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); diff --git a/servers/display_server.h b/servers/display_server.h index aa30b25b65..fa37a694e6 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -124,6 +124,7 @@ public: FEATURE_CLIPBOARD_PRIMARY, FEATURE_TEXT_TO_SPEECH, FEATURE_EXTEND_TO_TITLE, + FEATURE_SCREEN_CAPTURE, }; virtual bool has_feature(Feature p_feature) const = 0; @@ -275,6 +276,7 @@ public: return scale; } virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0; + virtual Color screen_get_pixel(const Point2i &p_position) const { return Color(); }; virtual bool is_touchscreen_available() const; // Keep the ScreenOrientation enum values in sync with the `display/window/handheld/orientation` |