Merge pull request #87384 from bruvzg/sys_base_color
Add method to get "base" system UI color and system theme change callback.
This commit is contained in:
commit
b6dee8850b
|
@ -136,7 +136,7 @@
|
||||||
<description>
|
<description>
|
||||||
Displays OS native dialog for selecting files or directories in the file system.
|
Displays OS native dialog for selecting files or directories in the file system.
|
||||||
Callbacks have the following arguments: [code]status: bool, selected_paths: PackedStringArray, selected_filter_index: int[/code].
|
Callbacks have the following arguments: [code]status: bool, selected_paths: PackedStringArray, selected_filter_index: int[/code].
|
||||||
[b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG] feature. Supported platforms include Linux (X11 and Wayland), Windows, and macOS.
|
[b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG] feature. Supported platforms include Linux (X11/Wayland), Windows, and macOS.
|
||||||
[b]Note:[/b] [param current_directory] might be ignored.
|
[b]Note:[/b] [param current_directory] might be ignored.
|
||||||
[b]Note:[/b] On Linux, [param show_hidden] is ignored.
|
[b]Note:[/b] On Linux, [param show_hidden] is ignored.
|
||||||
[b]Note:[/b] On macOS, native file dialogs have no title.
|
[b]Note:[/b] On macOS, native file dialogs have no title.
|
||||||
|
@ -161,7 +161,7 @@
|
||||||
- [code]"values"[/code] - [PackedStringArray] of values. If empty, boolean option (check box) is used.
|
- [code]"values"[/code] - [PackedStringArray] of values. If empty, boolean option (check box) is used.
|
||||||
- [code]"default"[/code] - default selected option index ([int]) or default boolean value ([bool]).
|
- [code]"default"[/code] - default selected option index ([int]) or default boolean value ([bool]).
|
||||||
Callbacks have the following arguments: [code]status: bool, selected_paths: PackedStringArray, selected_filter_index: int, selected_option: Dictionary[/code].
|
Callbacks have the following arguments: [code]status: bool, selected_paths: PackedStringArray, selected_filter_index: int, selected_option: Dictionary[/code].
|
||||||
[b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG] feature. Supported platforms include Linux (X11 and Wayland), Windows, and macOS.
|
[b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG] feature. Supported platforms include Linux (X11/Wayland), Windows, and macOS.
|
||||||
[b]Note:[/b] [param current_directory] might be ignored.
|
[b]Note:[/b] [param current_directory] might be ignored.
|
||||||
[b]Note:[/b] On Linux (X11), [param show_hidden] is ignored.
|
[b]Note:[/b] On Linux (X11), [param show_hidden] is ignored.
|
||||||
[b]Note:[/b] On macOS, native file dialogs have no title.
|
[b]Note:[/b] On macOS, native file dialogs have no title.
|
||||||
|
@ -182,6 +182,13 @@
|
||||||
[b]Note:[/b] This method is implemented on macOS and Windows.
|
[b]Note:[/b] This method is implemented on macOS and Windows.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="get_base_color" qualifiers="const">
|
||||||
|
<return type="Color" />
|
||||||
|
<description>
|
||||||
|
Returns the OS theme base color (default control background). Returns [code]Color(0, 0, 0, 0)[/code] if the base color is unknown.
|
||||||
|
[b]Note:[/b] This method is implemented on macOS and Windows.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="get_display_cutouts" qualifiers="const">
|
<method name="get_display_cutouts" qualifiers="const">
|
||||||
<return type="Rect2[]" />
|
<return type="Rect2[]" />
|
||||||
<description>
|
<description>
|
||||||
|
@ -1147,6 +1154,14 @@
|
||||||
Sets the window icon (usually displayed in the top-left corner) in the operating system's [i]native[/i] format. The file at [param filename] must be in [code].ico[/code] format on Windows or [code].icns[/code] on macOS. By using specially crafted [code].ico[/code] or [code].icns[/code] icons, [method set_native_icon] allows specifying different icons depending on the size the icon is displayed at. This size is determined by the operating system and user preferences (including the display scale factor). To use icons in other formats, use [method set_icon] instead.
|
Sets the window icon (usually displayed in the top-left corner) in the operating system's [i]native[/i] format. The file at [param filename] must be in [code].ico[/code] format on Windows or [code].icns[/code] on macOS. By using specially crafted [code].ico[/code] or [code].icns[/code] icons, [method set_native_icon] allows specifying different icons depending on the size the icon is displayed at. This size is determined by the operating system and user preferences (including the display scale factor). To use icons in other formats, use [method set_icon] instead.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="set_system_theme_change_callback">
|
||||||
|
<return type="void" />
|
||||||
|
<param index="0" name="callable" type="Callable" />
|
||||||
|
<description>
|
||||||
|
Sets the [param callable] that should be called when system theme settings are changed. Callback method should have zero arguments.
|
||||||
|
[b]Note:[/b] This method is implemented on Android, iOS, macOS, Windows, and Linux (X11/Wayland).
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="status_indicator_set_callback">
|
<method name="status_indicator_set_callback">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<param index="0" name="id" type="int" />
|
<param index="0" name="id" type="int" />
|
||||||
|
|
|
@ -127,6 +127,16 @@ bool DisplayServerAndroid::is_dark_mode() const {
|
||||||
return godot_java->is_dark_mode();
|
return godot_java->is_dark_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisplayServerAndroid::set_system_theme_change_callback(const Callable &p_callable) {
|
||||||
|
system_theme_changed = p_callable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayServerAndroid::emit_system_theme_changed() {
|
||||||
|
if (system_theme_changed.is_valid()) {
|
||||||
|
system_theme_changed.call_deferred();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DisplayServerAndroid::clipboard_set(const String &p_text) {
|
void DisplayServerAndroid::clipboard_set(const String &p_text) {
|
||||||
GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();
|
GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();
|
||||||
ERR_FAIL_NULL(godot_java);
|
ERR_FAIL_NULL(godot_java);
|
||||||
|
|
|
@ -84,6 +84,8 @@ class DisplayServerAndroid : public DisplayServer {
|
||||||
Callable input_text_callback;
|
Callable input_text_callback;
|
||||||
Callable rect_changed_callback;
|
Callable rect_changed_callback;
|
||||||
|
|
||||||
|
Callable system_theme_changed;
|
||||||
|
|
||||||
void _window_callback(const Callable &p_callable, const Variant &p_arg, bool p_deferred = false) const;
|
void _window_callback(const Callable &p_callable, const Variant &p_arg, bool p_deferred = false) const;
|
||||||
|
|
||||||
static void _dispatch_input_events(const Ref<InputEvent> &p_event);
|
static void _dispatch_input_events(const Ref<InputEvent> &p_event);
|
||||||
|
@ -103,8 +105,11 @@ public:
|
||||||
virtual void tts_resume() override;
|
virtual void tts_resume() override;
|
||||||
virtual void tts_stop() override;
|
virtual void tts_stop() override;
|
||||||
|
|
||||||
|
void emit_system_theme_changed();
|
||||||
|
|
||||||
virtual bool is_dark_mode_supported() const override;
|
virtual bool is_dark_mode_supported() const override;
|
||||||
virtual bool is_dark_mode() const override;
|
virtual bool is_dark_mode() const override;
|
||||||
|
virtual void set_system_theme_change_callback(const Callable &p_callable) override;
|
||||||
|
|
||||||
virtual void clipboard_set(const String &p_text) override;
|
virtual void clipboard_set(const String &p_text) override;
|
||||||
virtual String clipboard_get() const override;
|
virtual String clipboard_get() const override;
|
||||||
|
|
|
@ -149,6 +149,7 @@ class Godot(private val context: Context) : SensorEventListener {
|
||||||
private var useApkExpansion = false
|
private var useApkExpansion = false
|
||||||
private var useImmersive = false
|
private var useImmersive = false
|
||||||
private var useDebugOpengl = false
|
private var useDebugOpengl = false
|
||||||
|
private var darkMode = false;
|
||||||
|
|
||||||
private var containerLayout: FrameLayout? = null
|
private var containerLayout: FrameLayout? = null
|
||||||
var renderView: GodotRenderView? = null
|
var renderView: GodotRenderView? = null
|
||||||
|
@ -184,6 +185,8 @@ class Godot(private val context: Context) : SensorEventListener {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
darkMode = context.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
|
||||||
|
|
||||||
beginBenchmarkMeasure("Startup", "Godot::onCreate")
|
beginBenchmarkMeasure("Startup", "Godot::onCreate")
|
||||||
try {
|
try {
|
||||||
this.primaryHost = primaryHost
|
this.primaryHost = primaryHost
|
||||||
|
@ -559,6 +562,17 @@ class Godot(private val context: Context) : SensorEventListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration change callback
|
||||||
|
*/
|
||||||
|
fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
|
var newDarkMode = newConfig.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
|
||||||
|
if (darkMode != newDarkMode) {
|
||||||
|
darkMode = newDarkMode
|
||||||
|
GodotLib.onNightModeChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity result callback
|
* Activity result callback
|
||||||
*/
|
*/
|
||||||
|
@ -731,7 +745,7 @@ class Godot(private val context: Context) : SensorEventListener {
|
||||||
*/
|
*/
|
||||||
@Keep
|
@Keep
|
||||||
private fun isDarkModeSupported(): Boolean {
|
private fun isDarkModeSupported(): Boolean {
|
||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
|
return context.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_UNDEFINED
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -739,10 +753,7 @@ class Godot(private val context: Context) : SensorEventListener {
|
||||||
*/
|
*/
|
||||||
@Keep
|
@Keep
|
||||||
private fun isDarkMode(): Boolean {
|
private fun isDarkMode(): Boolean {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
return darkMode
|
||||||
return context.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasClipboard(): Boolean {
|
fun hasClipboard(): Boolean {
|
||||||
|
|
|
@ -38,6 +38,7 @@ import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
|
@ -145,6 +146,13 @@ public class GodotFragment extends Fragment implements IDownloaderClient, GodotH
|
||||||
parentHost = null;
|
parentHost = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CallSuper
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
|
super.onConfigurationChanged(newConfig);
|
||||||
|
godot.onConfigurationChanged(newConfig);
|
||||||
|
}
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
|
|
@ -219,6 +219,11 @@ public class GodotLib {
|
||||||
*/
|
*/
|
||||||
public static native void requestPermissionResult(String p_permission, boolean p_result);
|
public static native void requestPermissionResult(String p_permission, boolean p_result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked on the theme light/dark mode change.
|
||||||
|
*/
|
||||||
|
public static native void onNightModeChanged();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked on the GL thread to configure the height of the virtual keyboard.
|
* Invoked on the GL thread to configure the height of the virtual keyboard.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -487,6 +487,13 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *
|
||||||
Callable(obj, str_method).call_deferredp(argptrs, count);
|
Callable(obj, str_method).call_deferredp(argptrs, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onNightModeChanged(JNIEnv *env, jclass clazz) {
|
||||||
|
DisplayServerAndroid *ds = (DisplayServerAndroid *)DisplayServer::get_singleton();
|
||||||
|
if (ds) {
|
||||||
|
ds->emit_system_theme_changed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result) {
|
||||||
String permission = jstring_to_string(p_permission, env);
|
String permission = jstring_to_string(p_permission, env);
|
||||||
if (permission == "android.permission.RECORD_AUDIO" && p_result) {
|
if (permission == "android.permission.RECORD_AUDIO" && p_result) {
|
||||||
|
|
|
@ -66,6 +66,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *en
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jclass clazz, jlong ID, jstring method, jobjectArray params);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jclass clazz, jlong ID, jstring method, jobjectArray params);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jclass clazz, jint p_height);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jclass clazz, jint p_height);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result);
|
||||||
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onNightModeChanged(JNIEnv *env, jclass clazz);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz);
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,8 @@ class DisplayServerIOS : public DisplayServer {
|
||||||
Callable input_event_callback;
|
Callable input_event_callback;
|
||||||
Callable input_text_callback;
|
Callable input_text_callback;
|
||||||
|
|
||||||
|
Callable system_theme_changed;
|
||||||
|
|
||||||
int virtual_keyboard_height = 0;
|
int virtual_keyboard_height = 0;
|
||||||
|
|
||||||
void perform_event(const Ref<InputEvent> &p_event);
|
void perform_event(const Ref<InputEvent> &p_event);
|
||||||
|
@ -109,6 +111,8 @@ public:
|
||||||
void send_window_event(DisplayServer::WindowEvent p_event) const;
|
void send_window_event(DisplayServer::WindowEvent p_event) const;
|
||||||
void _window_callback(const Callable &p_callable, const Variant &p_arg) const;
|
void _window_callback(const Callable &p_callable, const Variant &p_arg) const;
|
||||||
|
|
||||||
|
void emit_system_theme_changed();
|
||||||
|
|
||||||
// MARK: - Input
|
// MARK: - Input
|
||||||
|
|
||||||
// MARK: Touches and Apple Pencil
|
// MARK: Touches and Apple Pencil
|
||||||
|
@ -145,6 +149,7 @@ public:
|
||||||
|
|
||||||
virtual bool is_dark_mode_supported() const override;
|
virtual bool is_dark_mode_supported() const override;
|
||||||
virtual bool is_dark_mode() const override;
|
virtual bool is_dark_mode() const override;
|
||||||
|
virtual void set_system_theme_change_callback(const Callable &p_callable) override;
|
||||||
|
|
||||||
virtual Rect2i get_display_safe_area() const override;
|
virtual Rect2i get_display_safe_area() const override;
|
||||||
|
|
||||||
|
@ -159,8 +164,7 @@ public:
|
||||||
|
|
||||||
virtual Vector<DisplayServer::WindowID> get_window_list() const override;
|
virtual Vector<DisplayServer::WindowID> get_window_list() const override;
|
||||||
|
|
||||||
virtual WindowID
|
virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override;
|
||||||
get_window_at_screen_position(const Point2i &p_position) const override;
|
|
||||||
|
|
||||||
virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override;
|
virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
|
|
||||||
|
|
|
@ -387,6 +387,16 @@ bool DisplayServerIOS::is_dark_mode() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisplayServerIOS::set_system_theme_change_callback(const Callable &p_callable) {
|
||||||
|
system_theme_changed = p_callable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayServerIOS::emit_system_theme_changed() {
|
||||||
|
if (system_theme_changed.is_valid()) {
|
||||||
|
system_theme_changed.call();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rect2i DisplayServerIOS::get_display_safe_area() const {
|
Rect2i DisplayServerIOS::get_display_safe_area() const {
|
||||||
UIEdgeInsets insets = UIEdgeInsetsZero;
|
UIEdgeInsets insets = UIEdgeInsetsZero;
|
||||||
UIView *view = AppDelegate.viewController.godotView;
|
UIView *view = AppDelegate.viewController.godotView;
|
||||||
|
|
|
@ -167,6 +167,23 @@ static const float earth_gravity = 9.80665;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)system_theme_changed {
|
||||||
|
DisplayServerIOS *ds = (DisplayServerIOS *)DisplayServer::get_singleton();
|
||||||
|
if (ds) {
|
||||||
|
ds->emit_system_theme_changed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
|
||||||
|
if (@available(iOS 13.0, *)) {
|
||||||
|
[super traitCollectionDidChange:previousTraitCollection];
|
||||||
|
|
||||||
|
if ([UITraitCollection currentTraitCollection].userInterfaceStyle != previousTraitCollection.userInterfaceStyle) {
|
||||||
|
[self system_theme_changed];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)stopRendering {
|
- (void)stopRendering {
|
||||||
if (!self.isActive) {
|
if (!self.isActive) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -528,10 +528,10 @@ void FreeDesktopPortalDesktop::_file_dialog_callback(const Callable &p_callable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeDesktopPortalDesktop::_thread_file_dialog_monitor(void *p_ud) {
|
void FreeDesktopPortalDesktop::_thread_monitor(void *p_ud) {
|
||||||
FreeDesktopPortalDesktop *portal = (FreeDesktopPortalDesktop *)p_ud;
|
FreeDesktopPortalDesktop *portal = (FreeDesktopPortalDesktop *)p_ud;
|
||||||
|
|
||||||
while (!portal->file_dialog_thread_abort.is_set()) {
|
while (!portal->monitor_thread_abort.is_set()) {
|
||||||
{
|
{
|
||||||
MutexLock lock(portal->file_dialog_mutex);
|
MutexLock lock(portal->file_dialog_mutex);
|
||||||
for (int i = portal->file_dialogs.size() - 1; i >= 0; i--) {
|
for (int i = portal->file_dialogs.size() - 1; i >= 0; i--) {
|
||||||
|
@ -579,10 +579,44 @@ void FreeDesktopPortalDesktop::_thread_file_dialog_monitor(void *p_ud) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (portal->theme_connection) {
|
||||||
|
while (true) {
|
||||||
|
DBusMessage *msg = dbus_connection_pop_message(portal->theme_connection);
|
||||||
|
if (!msg) {
|
||||||
|
break;
|
||||||
|
} else if (dbus_message_is_signal(msg, "org.freedesktop.portal.Settings", "SettingChanged")) {
|
||||||
|
DBusMessageIter iter;
|
||||||
|
if (dbus_message_iter_init(msg, &iter)) {
|
||||||
|
const char *value;
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
String name_space = String::utf8(value);
|
||||||
|
dbus_message_iter_next(&iter);
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
String key = String::utf8(value);
|
||||||
|
|
||||||
|
if (name_space == "org.freedesktop.appearance" && key == "color-scheme") {
|
||||||
|
callable_mp(portal, &FreeDesktopPortalDesktop::_system_theme_changed_callback).call_deferred();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbus_message_unref(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dbus_message_unref(msg);
|
||||||
|
}
|
||||||
|
dbus_connection_read_write(portal->theme_connection, 0);
|
||||||
|
}
|
||||||
|
|
||||||
usleep(50000);
|
usleep(50000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FreeDesktopPortalDesktop::_system_theme_changed_callback() {
|
||||||
|
if (system_theme_changed.is_valid()) {
|
||||||
|
system_theme_changed.call();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FreeDesktopPortalDesktop::FreeDesktopPortalDesktop() {
|
FreeDesktopPortalDesktop::FreeDesktopPortalDesktop() {
|
||||||
#ifdef SOWRAP_ENABLED
|
#ifdef SOWRAP_ENABLED
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
@ -611,17 +645,34 @@ FreeDesktopPortalDesktop::FreeDesktopPortalDesktop() {
|
||||||
unsupported = true;
|
unsupported = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBusError err;
|
||||||
|
dbus_error_init(&err);
|
||||||
|
theme_connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
|
||||||
|
if (dbus_error_is_set(&err)) {
|
||||||
|
dbus_error_free(&err);
|
||||||
|
} else {
|
||||||
|
theme_path = "type='signal',sender='org.freedesktop.portal.Desktop',interface='org.freedesktop.portal.Settings',member='SettingChanged'";
|
||||||
|
dbus_bus_add_match(theme_connection, theme_path.utf8().get_data(), &err);
|
||||||
|
if (dbus_error_is_set(&err)) {
|
||||||
|
dbus_error_free(&err);
|
||||||
|
dbus_connection_unref(theme_connection);
|
||||||
|
theme_connection = nullptr;
|
||||||
|
}
|
||||||
|
dbus_connection_read_write(theme_connection, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (!unsupported) {
|
if (!unsupported) {
|
||||||
file_dialog_thread_abort.clear();
|
monitor_thread_abort.clear();
|
||||||
file_dialog_thread.start(FreeDesktopPortalDesktop::_thread_file_dialog_monitor, this);
|
monitor_thread.start(FreeDesktopPortalDesktop::_thread_monitor, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeDesktopPortalDesktop::~FreeDesktopPortalDesktop() {
|
FreeDesktopPortalDesktop::~FreeDesktopPortalDesktop() {
|
||||||
file_dialog_thread_abort.set();
|
monitor_thread_abort.set();
|
||||||
if (file_dialog_thread.is_started()) {
|
if (monitor_thread.is_started()) {
|
||||||
file_dialog_thread.wait_to_finish();
|
monitor_thread.wait_to_finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FreeDesktopPortalDesktop::FileDialogData &fd : file_dialogs) {
|
for (FreeDesktopPortalDesktop::FileDialogData &fd : file_dialogs) {
|
||||||
if (fd.connection) {
|
if (fd.connection) {
|
||||||
DBusError err;
|
DBusError err;
|
||||||
|
@ -631,6 +682,13 @@ FreeDesktopPortalDesktop::~FreeDesktopPortalDesktop() {
|
||||||
dbus_connection_unref(fd.connection);
|
dbus_connection_unref(fd.connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (theme_connection) {
|
||||||
|
DBusError err;
|
||||||
|
dbus_error_init(&err);
|
||||||
|
dbus_bus_remove_match(theme_connection, theme_path.utf8().get_data(), &err);
|
||||||
|
dbus_error_free(&err);
|
||||||
|
dbus_connection_unref(theme_connection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // DBUS_ENABLED
|
#endif // DBUS_ENABLED
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#ifdef DBUS_ENABLED
|
#ifdef DBUS_ENABLED
|
||||||
|
|
||||||
#include "core/os/thread.h"
|
#include "core/os/thread.h"
|
||||||
|
#include "core/os/thread_safe.h"
|
||||||
#include "servers/display_server.h"
|
#include "servers/display_server.h"
|
||||||
|
|
||||||
struct DBusMessage;
|
struct DBusMessage;
|
||||||
|
@ -68,10 +69,15 @@ private:
|
||||||
|
|
||||||
Mutex file_dialog_mutex;
|
Mutex file_dialog_mutex;
|
||||||
Vector<FileDialogData> file_dialogs;
|
Vector<FileDialogData> file_dialogs;
|
||||||
Thread file_dialog_thread;
|
Thread monitor_thread;
|
||||||
SafeFlag file_dialog_thread_abort;
|
SafeFlag monitor_thread_abort;
|
||||||
|
|
||||||
static void _thread_file_dialog_monitor(void *p_ud);
|
DBusConnection *theme_connection = nullptr;
|
||||||
|
String theme_path;
|
||||||
|
Callable system_theme_changed;
|
||||||
|
void _system_theme_changed_callback();
|
||||||
|
|
||||||
|
static void _thread_monitor(void *p_ud);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FreeDesktopPortalDesktop();
|
FreeDesktopPortalDesktop();
|
||||||
|
@ -86,6 +92,9 @@ public:
|
||||||
// 1: Prefer dark appearance.
|
// 1: Prefer dark appearance.
|
||||||
// 2: Prefer light appearance.
|
// 2: Prefer light appearance.
|
||||||
uint32_t get_appearance_color_scheme();
|
uint32_t get_appearance_color_scheme();
|
||||||
|
void set_system_theme_change_callback(const Callable &p_system_theme_changed) {
|
||||||
|
system_theme_changed = p_system_theme_changed;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DBUS_ENABLED
|
#endif // DBUS_ENABLED
|
||||||
|
|
|
@ -275,6 +275,10 @@ bool DisplayServerWayland::is_dark_mode() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisplayServerWayland::set_system_theme_change_callback(const Callable &p_callable) {
|
||||||
|
portal_desktop->set_system_theme_change_callback(p_callable);
|
||||||
|
}
|
||||||
|
|
||||||
Error DisplayServerWayland::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) {
|
Error DisplayServerWayland::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) {
|
||||||
WindowID window_id = MAIN_WINDOW_ID;
|
WindowID window_id = MAIN_WINDOW_ID;
|
||||||
// TODO: Use window IDs for multiwindow support.
|
// TODO: Use window IDs for multiwindow support.
|
||||||
|
|
|
@ -171,6 +171,7 @@ public:
|
||||||
#ifdef DBUS_ENABLED
|
#ifdef DBUS_ENABLED
|
||||||
virtual bool is_dark_mode_supported() const override;
|
virtual bool is_dark_mode_supported() const override;
|
||||||
virtual bool is_dark_mode() const override;
|
virtual bool is_dark_mode() const override;
|
||||||
|
virtual void set_system_theme_change_callback(const Callable &p_callable) override;
|
||||||
|
|
||||||
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override;
|
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override;
|
||||||
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override;
|
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override;
|
||||||
|
|
|
@ -364,6 +364,10 @@ bool DisplayServerX11::is_dark_mode() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisplayServerX11::set_system_theme_change_callback(const Callable &p_callable) {
|
||||||
|
portal_desktop->set_system_theme_change_callback(p_callable);
|
||||||
|
}
|
||||||
|
|
||||||
Error DisplayServerX11::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) {
|
Error DisplayServerX11::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) {
|
||||||
WindowID window_id = last_focused_window;
|
WindowID window_id = last_focused_window;
|
||||||
|
|
||||||
|
|
|
@ -400,6 +400,7 @@ public:
|
||||||
#if defined(DBUS_ENABLED)
|
#if defined(DBUS_ENABLED)
|
||||||
virtual bool is_dark_mode_supported() const override;
|
virtual bool is_dark_mode_supported() const override;
|
||||||
virtual bool is_dark_mode() const override;
|
virtual bool is_dark_mode() const override;
|
||||||
|
virtual void set_system_theme_change_callback(const Callable &p_callable) override;
|
||||||
|
|
||||||
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override;
|
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override;
|
||||||
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override;
|
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override;
|
||||||
|
|
|
@ -220,6 +220,8 @@ private:
|
||||||
};
|
};
|
||||||
List<MenuCall> deferred_menu_calls;
|
List<MenuCall> deferred_menu_calls;
|
||||||
|
|
||||||
|
Callable system_theme_changed;
|
||||||
|
|
||||||
const NSMenu *_get_menu_root(const String &p_menu_root) const;
|
const NSMenu *_get_menu_root(const String &p_menu_root) const;
|
||||||
NSMenu *_get_menu_root(const String &p_menu_root);
|
NSMenu *_get_menu_root(const String &p_menu_root);
|
||||||
bool _is_menu_opened(NSMenu *p_menu) const;
|
bool _is_menu_opened(NSMenu *p_menu) const;
|
||||||
|
@ -254,6 +256,8 @@ public:
|
||||||
void menu_open(NSMenu *p_menu);
|
void menu_open(NSMenu *p_menu);
|
||||||
void menu_close(NSMenu *p_menu);
|
void menu_close(NSMenu *p_menu);
|
||||||
|
|
||||||
|
void emit_system_theme_changed();
|
||||||
|
|
||||||
bool has_window(WindowID p_window) const;
|
bool has_window(WindowID p_window) const;
|
||||||
WindowData &get_window(WindowID p_window);
|
WindowData &get_window(WindowID p_window);
|
||||||
|
|
||||||
|
@ -358,6 +362,8 @@ public:
|
||||||
virtual bool is_dark_mode_supported() const override;
|
virtual bool is_dark_mode_supported() const override;
|
||||||
virtual bool is_dark_mode() const override;
|
virtual bool is_dark_mode() const override;
|
||||||
virtual Color get_accent_color() const override;
|
virtual Color get_accent_color() const override;
|
||||||
|
virtual Color get_base_color() const override;
|
||||||
|
virtual void set_system_theme_change_callback(const Callable &p_callable) override;
|
||||||
|
|
||||||
virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override;
|
virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override;
|
||||||
virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override;
|
virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override;
|
||||||
|
|
|
@ -2051,7 +2051,17 @@ bool DisplayServerMacOS::is_dark_mode() const {
|
||||||
|
|
||||||
Color DisplayServerMacOS::get_accent_color() const {
|
Color DisplayServerMacOS::get_accent_color() const {
|
||||||
if (@available(macOS 10.14, *)) {
|
if (@available(macOS 10.14, *)) {
|
||||||
NSColor *color = [[NSColor controlAccentColor] colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]];
|
__block NSColor *color = nullptr;
|
||||||
|
if (@available(macOS 11.0, *)) {
|
||||||
|
[NSApp.effectiveAppearance performAsCurrentDrawingAppearance:^{
|
||||||
|
color = [[NSColor controlAccentColor] colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]];
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
NSAppearance *saved_appearance = [NSAppearance currentAppearance];
|
||||||
|
[NSAppearance setCurrentAppearance:[NSApp effectiveAppearance]];
|
||||||
|
color = [[NSColor controlAccentColor] colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]];
|
||||||
|
[NSAppearance setCurrentAppearance:saved_appearance];
|
||||||
|
}
|
||||||
if (color) {
|
if (color) {
|
||||||
CGFloat components[4];
|
CGFloat components[4];
|
||||||
[color getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
|
[color getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
|
||||||
|
@ -2064,6 +2074,41 @@ Color DisplayServerMacOS::get_accent_color() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color DisplayServerMacOS::get_base_color() const {
|
||||||
|
if (@available(macOS 10.14, *)) {
|
||||||
|
__block NSColor *color = nullptr;
|
||||||
|
if (@available(macOS 11.0, *)) {
|
||||||
|
[NSApp.effectiveAppearance performAsCurrentDrawingAppearance:^{
|
||||||
|
color = [[NSColor controlColor] colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]];
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
NSAppearance *saved_appearance = [NSAppearance currentAppearance];
|
||||||
|
[NSAppearance setCurrentAppearance:[NSApp effectiveAppearance]];
|
||||||
|
color = [[NSColor controlColor] colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]];
|
||||||
|
[NSAppearance setCurrentAppearance:saved_appearance];
|
||||||
|
}
|
||||||
|
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]);
|
||||||
|
} else {
|
||||||
|
return Color(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Color(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayServerMacOS::set_system_theme_change_callback(const Callable &p_callable) {
|
||||||
|
system_theme_changed = p_callable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayServerMacOS::emit_system_theme_changed() {
|
||||||
|
if (system_theme_changed.is_valid()) {
|
||||||
|
system_theme_changed.call();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Error DisplayServerMacOS::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) {
|
Error DisplayServerMacOS::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) {
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,13 @@
|
||||||
[[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
|
[[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)system_theme_changed:(NSNotification *)notification {
|
||||||
|
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
|
||||||
|
if (ds) {
|
||||||
|
ds->emit_system_theme_changed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)notice {
|
- (void)applicationDidFinishLaunching:(NSNotification *)notice {
|
||||||
NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
|
NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
|
||||||
NSString *nsbundleid_env = [NSString stringWithUTF8String:getenv("__CFBundleIdentifier")];
|
NSString *nsbundleid_env = [NSString stringWithUTF8String:getenv("__CFBundleIdentifier")];
|
||||||
|
@ -124,6 +131,8 @@
|
||||||
// If the executable is started from terminal or is not bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored).
|
// If the executable is started from terminal or is not bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored).
|
||||||
[self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02];
|
[self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02];
|
||||||
}
|
}
|
||||||
|
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(system_theme_changed:) name:@"AppleInterfaceThemeChangedNotification" object:nil];
|
||||||
|
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(system_theme_changed:) name:@"AppleColorPreferencesChangedNotification" object:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init {
|
- (id)init {
|
||||||
|
@ -136,6 +145,11 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:@"AppleInterfaceThemeChangedNotification" object:nil];
|
||||||
|
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:@"AppleColorPreferencesChangedNotification" object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
|
- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
|
||||||
OS_MacOS *os = (OS_MacOS *)OS::get_singleton();
|
OS_MacOS *os = (OS_MacOS *)OS::get_singleton();
|
||||||
if (!event || !os) {
|
if (!event || !os) {
|
||||||
|
|
|
@ -3494,13 +3494,17 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
||||||
case WM_PAINT: {
|
case WM_PAINT: {
|
||||||
Main::force_redraw();
|
Main::force_redraw();
|
||||||
} break;
|
} break;
|
||||||
case WM_SETTINGCHANGE: {
|
case WM_SETTINGCHANGE:
|
||||||
|
case WM_SYSCOLORCHANGE: {
|
||||||
if (lParam && CompareStringOrdinal(reinterpret_cast<LPCWCH>(lParam), -1, L"ImmersiveColorSet", -1, true) == CSTR_EQUAL) {
|
if (lParam && CompareStringOrdinal(reinterpret_cast<LPCWCH>(lParam), -1, L"ImmersiveColorSet", -1, true) == CSTR_EQUAL) {
|
||||||
if (is_dark_mode_supported() && dark_title_available) {
|
if (is_dark_mode_supported() && dark_title_available) {
|
||||||
BOOL value = is_dark_mode();
|
BOOL value = is_dark_mode();
|
||||||
::DwmSetWindowAttribute(windows[window_id].hWnd, use_legacy_dark_mode_before_20H1 ? DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 : DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
|
::DwmSetWindowAttribute(windows[window_id].hWnd, use_legacy_dark_mode_before_20H1 ? DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 : DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (system_theme_changed.is_valid()) {
|
||||||
|
system_theme_changed.call();
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case WM_THEMECHANGED: {
|
case WM_THEMECHANGED: {
|
||||||
if (is_dark_mode_supported() && dark_title_available) {
|
if (is_dark_mode_supported() && dark_title_available) {
|
||||||
|
@ -5058,6 +5062,19 @@ Color DisplayServerWindows::get_accent_color() const {
|
||||||
return Color((argb & 0xFF) / 255.f, ((argb & 0xFF00) >> 8) / 255.f, ((argb & 0xFF0000) >> 16) / 255.f, ((argb & 0xFF000000) >> 24) / 255.f);
|
return Color((argb & 0xFF) / 255.f, ((argb & 0xFF00) >> 8) / 255.f, ((argb & 0xFF0000) >> 16) / 255.f, ((argb & 0xFF000000) >> 24) / 255.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color DisplayServerWindows::get_base_color() const {
|
||||||
|
if (!ux_theme_available) {
|
||||||
|
return Color(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int argb = GetImmersiveColorFromColorSetEx((UINT)GetImmersiveUserColorSetPreference(false, false), GetImmersiveColorTypeFromName(ShouldAppsUseDarkMode() ? L"ImmersiveDarkChromeMediumLow" : L"ImmersiveLightChromeMediumLow"), false, 0);
|
||||||
|
return Color((argb & 0xFF) / 255.f, ((argb & 0xFF00) >> 8) / 255.f, ((argb & 0xFF0000) >> 16) / 255.f, ((argb & 0xFF000000) >> 24) / 255.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayServerWindows::set_system_theme_change_callback(const Callable &p_callable) {
|
||||||
|
system_theme_changed = p_callable;
|
||||||
|
}
|
||||||
|
|
||||||
int DisplayServerWindows::tablet_get_driver_count() const {
|
int DisplayServerWindows::tablet_get_driver_count() const {
|
||||||
return tablet_drivers.size();
|
return tablet_drivers.size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -477,6 +477,8 @@ class DisplayServerWindows : public DisplayServer {
|
||||||
CursorShape cursor_shape = CursorShape::CURSOR_ARROW;
|
CursorShape cursor_shape = CursorShape::CURSOR_ARROW;
|
||||||
RBMap<CursorShape, Vector<Variant>> cursors_cache;
|
RBMap<CursorShape, Vector<Variant>> cursors_cache;
|
||||||
|
|
||||||
|
Callable system_theme_changed;
|
||||||
|
|
||||||
void _drag_event(WindowID p_window, float p_x, float p_y, int idx);
|
void _drag_event(WindowID p_window, float p_x, float p_y, int idx);
|
||||||
void _touch_event(WindowID p_window, bool p_pressed, float p_x, float p_y, int idx);
|
void _touch_event(WindowID p_window, bool p_pressed, float p_x, float p_y, int idx);
|
||||||
|
|
||||||
|
@ -522,6 +524,8 @@ public:
|
||||||
virtual bool is_dark_mode_supported() const override;
|
virtual bool is_dark_mode_supported() const override;
|
||||||
virtual bool is_dark_mode() const override;
|
virtual bool is_dark_mode() const override;
|
||||||
virtual Color get_accent_color() const override;
|
virtual Color get_accent_color() const override;
|
||||||
|
virtual Color get_base_color() const override;
|
||||||
|
virtual void set_system_theme_change_callback(const Callable &p_callable) override;
|
||||||
|
|
||||||
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override;
|
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override;
|
||||||
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override;
|
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override;
|
||||||
|
|
|
@ -711,6 +711,8 @@ void DisplayServer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("is_dark_mode_supported"), &DisplayServer::is_dark_mode_supported);
|
ClassDB::bind_method(D_METHOD("is_dark_mode_supported"), &DisplayServer::is_dark_mode_supported);
|
||||||
ClassDB::bind_method(D_METHOD("is_dark_mode"), &DisplayServer::is_dark_mode);
|
ClassDB::bind_method(D_METHOD("is_dark_mode"), &DisplayServer::is_dark_mode);
|
||||||
ClassDB::bind_method(D_METHOD("get_accent_color"), &DisplayServer::get_accent_color);
|
ClassDB::bind_method(D_METHOD("get_accent_color"), &DisplayServer::get_accent_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_base_color"), &DisplayServer::get_base_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_system_theme_change_callback", "callable"), &DisplayServer::set_system_theme_change_callback);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("mouse_set_mode", "mouse_mode"), &DisplayServer::mouse_set_mode);
|
ClassDB::bind_method(D_METHOD("mouse_set_mode", "mouse_mode"), &DisplayServer::mouse_set_mode);
|
||||||
ClassDB::bind_method(D_METHOD("mouse_get_mode"), &DisplayServer::mouse_get_mode);
|
ClassDB::bind_method(D_METHOD("mouse_get_mode"), &DisplayServer::mouse_get_mode);
|
||||||
|
|
|
@ -227,7 +227,9 @@ public:
|
||||||
|
|
||||||
virtual bool is_dark_mode_supported() const { return false; };
|
virtual bool is_dark_mode_supported() const { return false; };
|
||||||
virtual bool is_dark_mode() const { return false; };
|
virtual bool is_dark_mode() const { return false; };
|
||||||
virtual Color get_accent_color() const { return Color(0, 0, 0, 0); };
|
virtual Color get_accent_color() const { return Color(0, 0, 0, 0); }
|
||||||
|
virtual Color get_base_color() const { return Color(0, 0, 0, 0); }
|
||||||
|
virtual void set_system_theme_change_callback(const Callable &p_callable) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool window_early_clear_override_enabled;
|
static bool window_early_clear_override_enabled;
|
||||||
|
|
Loading…
Reference in New Issue