mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-09 18:11:42 +01:00
JBR-6376: implement detecting of OS theme on linux
This commit is contained in:
55
make/autoconf/lib-dbus.m4
Normal file
55
make/autoconf/lib-dbus.m4
Normal file
@@ -0,0 +1,55 @@
|
||||
#
|
||||
# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2024, JetBrains s.r.o.. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
################################################################################
|
||||
# Check if a potential dbus library match is correct and usable
|
||||
################################################################################
|
||||
AC_DEFUN_ONCE([LIB_SETUP_DBUS],
|
||||
[
|
||||
AC_ARG_WITH(dbus-includes, [AS_HELP_STRING([--with-dbus-includes],
|
||||
[specify include directories for the dbus files as list separated by space])])
|
||||
|
||||
if test "x$NEEDS_LIB_DBUS" = xfalse; then
|
||||
DBUS_CFLAGS=
|
||||
DBUS_FOUND=false
|
||||
else
|
||||
if test "x${with_dbus_includes}" != x; then
|
||||
DBUS_FOUND=true
|
||||
DBUS_CFLAGS=""
|
||||
for include in $with_dbus_includes; do
|
||||
DBUS_CFLAGS="${DBUS_CFLAGS}-I${include} "
|
||||
done
|
||||
else
|
||||
PKG_CHECK_MODULES(DBUS, dbus-1, [DBUS_FOUND=true], [
|
||||
DBUS_FOUND=false
|
||||
AC_MSG_NOTICE([Can't find dbus-1 library. This library is needed to use some features. You can install dbus-1 library or specify include directories manually by giving --with-dbus-includes option.])
|
||||
])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(DBUS_CFLAGS)
|
||||
AC_SUBST(DBUS_FOUND)
|
||||
])
|
||||
@@ -36,6 +36,7 @@ m4_include([lib-x11.m4])
|
||||
m4_include([lib-fontconfig.m4])
|
||||
m4_include([lib-speechd.m4])
|
||||
m4_include([lib-nvdacontrollerclient.m4])
|
||||
m4_include([lib-dbus.m4])
|
||||
m4_include([lib-tests.m4])
|
||||
|
||||
################################################################################
|
||||
@@ -82,11 +83,13 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES],
|
||||
NEEDS_LIB_FREETYPE=true
|
||||
fi
|
||||
|
||||
# Check if alsa is needed
|
||||
# Check if alsa and dbus is needed
|
||||
if test "x$OPENJDK_TARGET_OS" = xlinux; then
|
||||
NEEDS_LIB_ALSA=true
|
||||
NEEDS_LIB_DBUS=true
|
||||
else
|
||||
NEEDS_LIB_ALSA=false
|
||||
NEEDS_LIB_DBUS=false
|
||||
fi
|
||||
|
||||
# Check if ffi is needed
|
||||
@@ -143,6 +146,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
|
||||
LIB_SETUP_X11
|
||||
LIB_SETUP_SPEECHD
|
||||
LIB_SETUP_NVDACONTROLLERCLIENT
|
||||
LIB_SETUP_DBUS
|
||||
LIB_TESTS_SETUP_GTEST
|
||||
|
||||
# Math library
|
||||
|
||||
@@ -470,6 +470,10 @@ UBSAN_LDFLAGS := @UBSAN_LDFLAGS@
|
||||
X_CFLAGS := @X_CFLAGS@
|
||||
X_LIBS := @X_LIBS@
|
||||
|
||||
# Necessary additional compiler flags to compile dbus
|
||||
DBUS_CFLAGS := @DBUS_CFLAGS@
|
||||
DBUS_FOUND := @DBUS_FOUND@
|
||||
|
||||
# Linux speechd a11y announcer
|
||||
A11Y_SPEECHD_ANNOUNCING_ENABLED:=@A11Y_SPEECHD_ANNOUNCING_ENABLED@
|
||||
SPEECHD_CFLAGS:=@SPEECHD_CFLAGS@
|
||||
|
||||
@@ -58,6 +58,10 @@ ifeq ($(call isTargetOs, windows), true)
|
||||
#
|
||||
endif
|
||||
|
||||
ifeq ($(DBUS_FOUND), false)
|
||||
LIBAWT_EXCLUDE_FILES += dbus_interface.c dbus_interface.h
|
||||
endif
|
||||
|
||||
ifeq ($(call isTargetOs, linux macosx aix), true)
|
||||
LIBAWT_EXCLUDE_FILES += awt_Font.c CUPSfuncs.c fontpath.c X11Color.c
|
||||
endif
|
||||
@@ -85,6 +89,10 @@ LIBAWT_EXTRA_HEADER_DIRS := \
|
||||
|
||||
LIBAWT_CFLAGS := -D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES -DMLIB_NO_LIBSUNMATH
|
||||
|
||||
ifeq ($(DBUS_FOUND), true)
|
||||
LIBAWT_CFLAGS += -DDBUS_FOUND
|
||||
endif
|
||||
|
||||
ifeq ($(call isTargetOs, windows), true)
|
||||
LIBAWT_CFLAGS += -EHsc -DUNICODE -D_UNICODE
|
||||
ifeq ($(call isTargetCpuBits, 64), true)
|
||||
@@ -133,7 +141,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \
|
||||
EXTRA_SRC := $(LIBAWT_EXTRA_SRC), \
|
||||
EXCLUDE_FILES := $(LIBAWT_EXCLUDE_FILES), \
|
||||
OPTIMIZATION := HIGHEST, \
|
||||
CFLAGS := $(LIBAWT_CFLAGS) $(X_CFLAGS), \
|
||||
CFLAGS := $(LIBAWT_CFLAGS) $(X_CFLAGS) $(DBUS_CFLAGS), \
|
||||
CXXFLAGS := $(LIBAWT_CFLAGS) $(X_CFLAGS), \
|
||||
CFLAGS_gcc := -fgcse-after-reload, \
|
||||
EXTRA_HEADER_DIRS := $(LIBAWT_EXTRA_HEADER_DIRS), \
|
||||
@@ -149,6 +157,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \
|
||||
DISABLED_WARNINGS_clang_debug_trace.c := format-nonliteral, \
|
||||
DISABLED_WARNINGS_clang_Trace.c := format-nonliteral, \
|
||||
DISABLED_WARNINGS_clang_TransformHelper.c := sign-compare, \
|
||||
DISABLED_WARNINGS_clang_system_properties.c := format-nonliteral, \
|
||||
DISABLED_WARNINGS_microsoft := 4244 4996, \
|
||||
DISABLED_WARNINGS_microsoft_awt_Toolkit.cpp := 4267, \
|
||||
LDFLAGS_windows := -delayload:comctl32.dll -delayload:comdlg32.dll \
|
||||
@@ -221,7 +230,7 @@ ifeq ($(call isTargetOs, windows macosx), false)
|
||||
EXCLUDES := medialib, \
|
||||
OPTIMIZATION := LOW, \
|
||||
CFLAGS := -DHEADLESS=true $(CUPS_CFLAGS) $(FONTCONFIG_CFLAGS) \
|
||||
$(X_CFLAGS), \
|
||||
$(X_CFLAGS) $(DBUS_CFLAGS), \
|
||||
EXTRA_HEADER_DIRS := $(LIBAWT_HEADLESS_EXTRA_HEADER_DIRS), \
|
||||
DISABLED_WARNINGS_gcc := unused-variable, \
|
||||
DISABLED_WARNINGS_clang := unused-variable, \
|
||||
@@ -295,7 +304,7 @@ ifeq ($(call isTargetOs, windows macosx)+$(ENABLE_HEADLESS_ONLY), false+false)
|
||||
EXTRA_HEADER_DIRS := $(LIBAWT_XAWT_EXTRA_HEADER_DIRS), \
|
||||
EXCLUDES := medialib debug, \
|
||||
OPTIMIZATION := LOW, \
|
||||
CFLAGS := -DXAWT -DXAWT_HACK $(LIBAWT_XAWT_CFLAGS) \
|
||||
CFLAGS := -DXAWT -DXAWT_HACK $(LIBAWT_XAWT_CFLAGS) $(DBUS_CFLAGS) \
|
||||
$(FONTCONFIG_CFLAGS) $(CUPS_CFLAGS) $(X_CFLAGS), \
|
||||
DISABLED_WARNINGS_gcc := int-to-pointer-cast unused-variable, \
|
||||
DISABLED_WARNINGS_clang := unused-variable, \
|
||||
@@ -395,6 +404,8 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
DISABLED_WARNINGS_clang_OGLBufImgOps.c := format-nonliteral, \
|
||||
DISABLED_WARNINGS_clang_OGLPaints.c := format-nonliteral, \
|
||||
DISABLED_WARNINGS_clang_PrinterView.m := enum-conversion, \
|
||||
DISABLED_WARNINGS_clang_SystemHotkey.m := format-nonliteral, \
|
||||
DISABLED_WARNINGS_clang_system_properties.c := format-nonliteral, \
|
||||
JDK_LIBS := libawt java.base:libjava libosxapp, \
|
||||
LIBS_macosx := $(LIBM) \
|
||||
-framework Accelerate \
|
||||
|
||||
101
src/java.desktop/linux/native/libawt/awt/dbus_interface.c
Normal file
101
src/java.desktop/linux/native/libawt/awt/dbus_interface.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, JetBrains s.r.o.. All rights reserved.
|
||||
*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
#include "dbus_interface.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "jvm_md.h"
|
||||
|
||||
#define DBUS_LIB JNI_LIB_NAME("dbus-1")
|
||||
#define DBUS_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("dbus-1", "3")
|
||||
|
||||
static bool isCurrentVersionSupported(DBusApi* dBusApi) {
|
||||
int major = 0, minor = 0, micro = 0;
|
||||
dBusApi->dbus_get_version(&major, &minor, µ);
|
||||
return major == 1;
|
||||
}
|
||||
|
||||
static bool DBusApi_init(DBusApi* dBusApi, void *libhandle) {
|
||||
dBusApi->dbus_get_version = dlsym(libhandle, "dbus_get_version");
|
||||
if (dBusApi->dbus_get_version == NULL || !isCurrentVersionSupported(dBusApi)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dBusApi->dbus_error_init = dlsym(libhandle, "dbus_error_init");
|
||||
dBusApi->dbus_bus_get = dlsym(libhandle, "dbus_bus_get");
|
||||
dBusApi->dbus_error_is_set = dlsym(libhandle, "dbus_error_is_set");
|
||||
dBusApi->dbus_bus_request_name = dlsym(libhandle, "dbus_bus_request_name");
|
||||
dBusApi->dbus_connection_flush = dlsym(libhandle, "dbus_connection_flush");
|
||||
dBusApi->dbus_message_new_method_call = dlsym(libhandle, "dbus_message_new_method_call");
|
||||
dBusApi->dbus_message_set_destination = dlsym(libhandle, "dbus_message_set_destination");
|
||||
dBusApi->dbus_message_iter_init_append = dlsym(libhandle, "dbus_message_iter_init_append");
|
||||
dBusApi->dbus_message_iter_append_basic = dlsym(libhandle, "dbus_message_iter_append_basic");
|
||||
dBusApi->dbus_connection_send_with_reply_and_block = dlsym(libhandle, "dbus_connection_send_with_reply_and_block");
|
||||
dBusApi->dbus_message_iter_init = dlsym(libhandle, "dbus_message_iter_init");
|
||||
dBusApi->dbus_message_iter_get_arg_type = dlsym(libhandle, "dbus_message_iter_get_arg_type");
|
||||
dBusApi->dbus_message_iter_get_basic = dlsym(libhandle, "dbus_message_iter_get_basic");
|
||||
dBusApi->dbus_message_iter_recurse = dlsym(libhandle, "dbus_message_iter_recurse");
|
||||
dBusApi->dbus_message_iter_next = dlsym(libhandle, "dbus_message_iter_next");
|
||||
dBusApi->dbus_message_unref = dlsym(libhandle, "dbus_message_unref");
|
||||
dBusApi->dbus_error_free = dlsym(libhandle, "dbus_error_free");
|
||||
|
||||
return dBusApi->dbus_error_init != NULL && dBusApi->dbus_bus_get != NULL && dBusApi->dbus_error_is_set != NULL &&
|
||||
dBusApi->dbus_bus_request_name != NULL && dBusApi->dbus_connection_flush != NULL &&
|
||||
dBusApi->dbus_message_set_destination != NULL && dBusApi->dbus_message_iter_init_append != NULL &&
|
||||
dBusApi->dbus_message_iter_append_basic != NULL && dBusApi->dbus_connection_send_with_reply_and_block != NULL &&
|
||||
dBusApi->dbus_message_iter_init != NULL && dBusApi->dbus_message_iter_get_arg_type != NULL &&
|
||||
dBusApi->dbus_message_iter_get_basic != NULL && dBusApi->dbus_message_iter_recurse != NULL &&
|
||||
dBusApi->dbus_message_iter_next != NULL && dBusApi->dbus_message_unref != NULL &&
|
||||
dBusApi->dbus_message_new_method_call != NULL && dBusApi->dbus_error_free != NULL;
|
||||
}
|
||||
|
||||
DBusApi* DBusApi_setupDBus(void *libhandle) {
|
||||
DBusApi *dBusApi = (DBusApi*)malloc(sizeof(DBusApi));
|
||||
if (dBusApi == NULL || !DBusApi_init(dBusApi, libhandle)) {
|
||||
free(dBusApi);
|
||||
dBusApi = NULL;
|
||||
}
|
||||
|
||||
return dBusApi;
|
||||
}
|
||||
|
||||
DBusApi* DBusApi_setupDBusDefault() {
|
||||
void *dbus_libhandle = dlopen(DBUS_LIB, RTLD_LAZY | RTLD_LOCAL);
|
||||
if (dbus_libhandle == NULL) {
|
||||
dbus_libhandle = dlopen(DBUS_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
|
||||
if (dbus_libhandle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return DBusApi_setupDBus(dbus_libhandle);
|
||||
}
|
||||
76
src/java.desktop/linux/native/libawt/awt/dbus_interface.h
Normal file
76
src/java.desktop/linux/native/libawt/awt/dbus_interface.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, JetBrains s.r.o.. All rights reserved.
|
||||
*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef JETBRAINSRUNTIME_DBUS_INTERFACE_H
|
||||
#define JETBRAINSRUNTIME_DBUS_INTERFACE_H
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
typedef struct DBusApi {
|
||||
void (*dbus_get_version)(int *major_version_p, int *minor_version_p, int *micro_version_p);
|
||||
|
||||
void (*dbus_error_init)(DBusError *error);
|
||||
|
||||
DBusConnection *(*dbus_bus_get)(DBusBusType type, DBusError *error);
|
||||
|
||||
dbus_bool_t (*dbus_error_is_set)(const DBusError *error);
|
||||
|
||||
void (*dbus_error_free)(DBusError *error);
|
||||
|
||||
int (*dbus_bus_request_name)(DBusConnection *connection, const char *name, unsigned int flags, DBusError *error);
|
||||
|
||||
void (*dbus_connection_flush)(DBusConnection *connection);
|
||||
|
||||
DBusMessage* (*dbus_message_new_method_call)(const char *bus_name, const char *path,
|
||||
const char *iface, const char *method);
|
||||
|
||||
dbus_bool_t (*dbus_message_set_destination)(DBusMessage *message, const char *destination);
|
||||
|
||||
void (*dbus_message_iter_init_append)(DBusMessage *message, DBusMessageIter *iter);
|
||||
|
||||
dbus_bool_t (*dbus_message_iter_append_basic)(DBusMessageIter *iter, int type, const void *value);
|
||||
|
||||
DBusMessage *(*dbus_connection_send_with_reply_and_block)(DBusConnection *connection, DBusMessage *message,
|
||||
int timeout_milliseconds, DBusError *error);
|
||||
|
||||
dbus_bool_t (*dbus_message_iter_init)(DBusMessage *message, DBusMessageIter *iter);
|
||||
|
||||
int (*dbus_message_iter_get_arg_type)(DBusMessageIter *iter);
|
||||
|
||||
void (*dbus_message_iter_get_basic)(DBusMessageIter *iter, void *value);
|
||||
|
||||
void (*dbus_message_iter_recurse)(DBusMessageIter *iter, DBusMessageIter *sub);
|
||||
|
||||
dbus_bool_t (*dbus_message_iter_next)(DBusMessageIter *iter);
|
||||
|
||||
void (*dbus_message_unref)(DBusMessage *message);
|
||||
} DBusApi;
|
||||
|
||||
DBusApi* DBusApi_setupDBus(void *libhandle);
|
||||
DBusApi* DBusApi_setupDBusDefault();
|
||||
|
||||
#endif //JETBRAINSRUNTIME_DBUS_INTERFACE_H
|
||||
262
src/java.desktop/linux/native/libawt/awt/system_properties.c
Normal file
262
src/java.desktop/linux/native/libawt/awt/system_properties.c
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, JetBrains s.r.o.. All rights reserved.
|
||||
*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "system_properties.h"
|
||||
|
||||
#ifdef DBUS_FOUND
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define UNKNOWN_RESULT -1
|
||||
#define SETTING_INTERFACE "org.freedesktop.portal.Settings"
|
||||
#define SETTING_INTERFACE_METHOD "Read"
|
||||
#define DESKTOP_DESTINATION "org.freedesktop.portal.Desktop"
|
||||
#define DESKTOP_PATH "/org/freedesktop/portal/desktop"
|
||||
#define REPLY_TIMEOUT 150
|
||||
|
||||
static DBusConnection *connection = NULL;
|
||||
static JNIEnv *env = NULL;
|
||||
static DBusApi *dBus = NULL;
|
||||
static DBusMessage *msg_freedesktop_appearance = NULL;
|
||||
static DBusMessage *msg_gnome_desktop = NULL;
|
||||
static bool initialized = false;
|
||||
static bool logEnabled = true;
|
||||
extern JavaVM *jvm;
|
||||
|
||||
static void printError(const char* fmt, ...) {
|
||||
if (!logEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
char* buf = (char*)malloc(1024);
|
||||
|
||||
if (env && buf) {
|
||||
va_list vargs;
|
||||
va_start(vargs, fmt);
|
||||
vsnprintf(buf, 1024, fmt, vargs);
|
||||
jstring text = JNU_NewStringPlatform(env, buf);
|
||||
free(buf);
|
||||
va_end(vargs);
|
||||
|
||||
jboolean ignoreException;
|
||||
JNU_CallStaticMethodByName(env, &ignoreException, "sun/awt/UNIXToolkit", "printError",
|
||||
"(Ljava/lang/String;)V", text);
|
||||
}
|
||||
}
|
||||
|
||||
static bool dbusCheckError(DBusError *err, const char *msg) {
|
||||
bool is_error_set = dBus->dbus_error_is_set(err);
|
||||
if (is_error_set) {
|
||||
printError("DBus error: %s. %s\n", msg, err->message);
|
||||
dBus->dbus_error_free(err);
|
||||
}
|
||||
return is_error_set;
|
||||
}
|
||||
|
||||
// current implementation of object decomposition supports only
|
||||
// primitive types (including a recursive type wrapper)
|
||||
static bool decomposeDBusReply(void *val, DBusMessageIter *iter, int demand_type) {
|
||||
int cur_type = dBus->dbus_message_iter_get_arg_type(iter);
|
||||
switch (cur_type)
|
||||
{
|
||||
case DBUS_TYPE_INT16:
|
||||
case DBUS_TYPE_UINT16:
|
||||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT32:
|
||||
case DBUS_TYPE_INT64:
|
||||
case DBUS_TYPE_UINT64:
|
||||
case DBUS_TYPE_STRING:
|
||||
{
|
||||
if (cur_type != demand_type) {
|
||||
return false;
|
||||
}
|
||||
dBus->dbus_message_iter_get_basic(iter, val);
|
||||
return true;
|
||||
}
|
||||
case DBUS_TYPE_VARIANT:
|
||||
{
|
||||
DBusMessageIter unwrap_iter;
|
||||
dBus->dbus_message_iter_recurse(iter, &unwrap_iter);
|
||||
bool res = decomposeDBusReply(val, &unwrap_iter, demand_type);
|
||||
// current implementation doesn't support types with multiple fields
|
||||
if (dBus->dbus_message_iter_next(iter)) {
|
||||
return false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
case DBUS_TYPE_INVALID:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static DBusMessage *createDBusMessage(const char *messages[], int message_count) {
|
||||
DBusMessage *msg = NULL;
|
||||
DBusMessageIter msg_iter;
|
||||
|
||||
if ((msg = dBus->dbus_message_new_method_call(NULL, DESKTOP_PATH, SETTING_INTERFACE, SETTING_INTERFACE_METHOD)) == NULL) {
|
||||
printError("DBus error: cannot allocate message\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!dBus->dbus_message_set_destination(msg, DESKTOP_DESTINATION)) {
|
||||
printError("DBus error: cannot set destination\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dBus->dbus_message_iter_init_append(msg, &msg_iter);
|
||||
|
||||
for (int i = 0; i < message_count; i++) {
|
||||
if (!dBus->dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &messages[i])) {
|
||||
printError("DBus error: cannot append to message\n");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
return msg;
|
||||
cleanup:
|
||||
if (msg) {
|
||||
dBus->dbus_message_unref(msg);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool sendDBusMessageWithReply(DBusMessage *msg, void *val, int demand_type) {
|
||||
DBusError error;
|
||||
DBusMessage *msg_reply = NULL;
|
||||
DBusMessageIter msg_iter;
|
||||
bool res = false;
|
||||
|
||||
dBus->dbus_error_init(&error);
|
||||
if ((msg_reply = dBus->dbus_connection_send_with_reply_and_block(connection, msg, REPLY_TIMEOUT, &error)) == NULL) {
|
||||
printError("DBus error: cannot get msg_reply or sent message. %s\n", dBus->dbus_error_is_set(&error) ? error.message : "");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!dBus->dbus_message_iter_init(msg_reply, &msg_iter)) {
|
||||
printError("DBus error: cannot process message\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
res = decomposeDBusReply(val, &msg_iter, demand_type);
|
||||
cleanup:
|
||||
if (msg_reply) {
|
||||
dBus->dbus_message_unref(msg_reply);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_sun_awt_UNIXToolkit_isSystemDarkColorScheme() {
|
||||
static int use_freedesktop_appearance = -1;
|
||||
if (!initialized) {
|
||||
return UNKNOWN_RESULT;
|
||||
}
|
||||
|
||||
if (use_freedesktop_appearance == -1) {
|
||||
unsigned int res = 0;
|
||||
logEnabled = false;
|
||||
use_freedesktop_appearance =
|
||||
sendDBusMessageWithReply(msg_freedesktop_appearance, &res, DBUS_TYPE_UINT32);
|
||||
logEnabled = true;
|
||||
}
|
||||
|
||||
if (use_freedesktop_appearance) {
|
||||
unsigned int res = 0;
|
||||
if (!sendDBusMessageWithReply(msg_freedesktop_appearance, &res, DBUS_TYPE_UINT32)) {
|
||||
return UNKNOWN_RESULT;
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
char *res = NULL;
|
||||
if (!sendDBusMessageWithReply(msg_gnome_desktop, &res, DBUS_TYPE_STRING)) {
|
||||
return UNKNOWN_RESULT;
|
||||
}
|
||||
return (res != NULL) ? strstr(res, "dark") != NULL : UNKNOWN_RESULT;
|
||||
}
|
||||
}
|
||||
|
||||
jboolean SystemProperties_setup(DBusApi *dBus_, JNIEnv *env_) {
|
||||
env = env_;
|
||||
dBus = dBus_;
|
||||
DBusError err;
|
||||
int ret;
|
||||
|
||||
dBus->dbus_error_init(&err);
|
||||
if ((connection = dBus->dbus_bus_get(DBUS_BUS_SESSION, &err)) == NULL) {
|
||||
printError("DBus error: connection is Null\n");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
if (dbusCheckError(&err, "connection error")) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
ret = dBus->dbus_bus_request_name(connection, "dbus.JBR.server", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
|
||||
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER && ret != DBUS_REQUEST_NAME_REPLY_IN_QUEUE) {
|
||||
printError("DBus error: Failed to acquire service name \n");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
if (dbusCheckError(&err, "error request 'dbus.JBR.server' name on the bus")) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
dBus->dbus_connection_flush(connection);
|
||||
|
||||
const char *freedesktop_appearance_messages[] = {"org.freedesktop.appearance", "color-scheme"};
|
||||
const char *gnome_desktop_messages[] = {"org.gnome.desktop.interface", "gtk-theme"};
|
||||
msg_freedesktop_appearance = createDBusMessage(freedesktop_appearance_messages, 2);
|
||||
msg_gnome_desktop = createDBusMessage(gnome_desktop_messages, 2);
|
||||
if (msg_freedesktop_appearance == NULL || msg_gnome_desktop == NULL) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_sun_awt_UNIXToolkit_dbusInit() {
|
||||
DBusApi *dBus = DBusApi_setupDBusDefault();
|
||||
if (dBus) {
|
||||
return SystemProperties_setup(dBus, env);
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
JNIEXPORT jint JNICALL Java_sun_awt_UNIXToolkit_isSystemDarkColorScheme() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_sun_awt_UNIXToolkit_dbusInit() {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
44
src/java.desktop/linux/native/libawt/awt/system_properties.h
Normal file
44
src/java.desktop/linux/native/libawt/awt/system_properties.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, JetBrains s.r.o.. All rights reserved.
|
||||
*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef JETBRAINSRUNTIME_SYSTEM_PROPERTIES_H
|
||||
#define JETBRAINSRUNTIME_SYSTEM_PROPERTIES_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <jni.h>
|
||||
#include <jni_util.h>
|
||||
|
||||
#ifdef DBUS_FOUND
|
||||
|
||||
#include "dbus_interface.h"
|
||||
|
||||
jboolean SystemProperties_setup(DBusApi *dBus_, JNIEnv *env_);
|
||||
void SystemProperties_pullEvent(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif //JETBRAINSRUNTIME_SYSTEM_PROPERTIES_H
|
||||
@@ -55,11 +55,13 @@ import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
|
||||
import jdk.internal.misc.InnocuousThread;
|
||||
import sun.awt.X11.XBaseWindow;
|
||||
import sun.security.action.GetIntegerAction;
|
||||
import com.sun.java.swing.plaf.gtk.GTKConstants.TextDirection;
|
||||
import sun.java2d.opengl.OGLRenderQueue;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
public abstract class UNIXToolkit extends SunToolkit
|
||||
{
|
||||
@@ -103,6 +105,16 @@ public abstract class UNIXToolkit extends SunToolkit
|
||||
private Boolean nativeGTKAvailable;
|
||||
private Boolean nativeGTKLoaded;
|
||||
private BufferedImage tmpImage = null;
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.UNIXToolkit");
|
||||
|
||||
private static void printError(String str) {
|
||||
log.fine(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeDesktopProperties() {
|
||||
initSystemPropertyWatcher();
|
||||
}
|
||||
|
||||
public static int getDatatransferTimeout() {
|
||||
@SuppressWarnings("removal")
|
||||
@@ -531,6 +543,8 @@ public abstract class UNIXToolkit extends SunToolkit
|
||||
return result;
|
||||
}
|
||||
|
||||
private static native int isSystemDarkColorScheme();
|
||||
|
||||
@Override
|
||||
public boolean isRunningOnWayland() {
|
||||
return isOnWayland();
|
||||
@@ -549,6 +563,43 @@ public abstract class UNIXToolkit extends SunToolkit
|
||||
// application icons).
|
||||
private static final WindowFocusListener waylandWindowFocusListener;
|
||||
|
||||
private static final String OS_THEME_IS_DARK = "awt.os.theme.isDark";
|
||||
|
||||
private static Thread systemPropertyWatcher = null;
|
||||
|
||||
private static native boolean dbusInit();
|
||||
|
||||
private void initSystemPropertyWatcher() {
|
||||
@SuppressWarnings("removal")
|
||||
String dbusEnabled = AccessController.doPrivileged(
|
||||
new GetPropertyAction("jbr.dbus.enabled", "true")).toLowerCase();
|
||||
if (!"true".equals(dbusEnabled) || !dbusInit()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int initialSystemDarkColorScheme = isSystemDarkColorScheme();
|
||||
if (initialSystemDarkColorScheme >= 0) {
|
||||
setDesktopProperty(OS_THEME_IS_DARK, initialSystemDarkColorScheme != 0);
|
||||
|
||||
systemPropertyWatcher = InnocuousThread.newThread("SystemPropertyWatcher",
|
||||
() -> {
|
||||
while (true) {
|
||||
try {
|
||||
int isSystemDarkColorScheme = isSystemDarkColorScheme();
|
||||
if (isSystemDarkColorScheme >= 0) {
|
||||
setDesktopProperty(OS_THEME_IS_DARK, isSystemDarkColorScheme != 0);
|
||||
}
|
||||
|
||||
Thread.sleep(1000);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
systemPropertyWatcher.setDaemon(true);
|
||||
systemPropertyWatcher.start();
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
if (isOnWayland()) {
|
||||
waylandWindowFocusListener = new WindowAdapter() {
|
||||
|
||||
@@ -1924,6 +1924,7 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
|
||||
localEnv.displayChanged());
|
||||
}
|
||||
}
|
||||
super.initializeDesktopProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
97
test/jdk/jb/java/awt/Toolkit/DetectingOSThemeTest.java
Normal file
97
test/jdk/jb/java/awt/Toolkit/DetectingOSThemeTest.java
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2000-2024 JetBrains s.r.o.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary DetectingOSThemeTest checks that JBR could correctly detect OS theme and notify about theme changing in time
|
||||
* @run main DetectingOSThemeTest
|
||||
* @requires (os.family == "linux")
|
||||
*/
|
||||
public class DetectingOSThemeTest {
|
||||
private static final int TIME_TO_WAIT = 2000;
|
||||
private static final String LIGHT_THEME_NAME = "Light";
|
||||
private static final String DARK_THEME_NAME = "Dark";
|
||||
private static final String UNDEFINED_THEME_NAME = "Undefined";
|
||||
|
||||
private static String currentTheme() {
|
||||
Boolean val = (Boolean) Toolkit.getDefaultToolkit().getDesktopProperty("awt.os.theme.isDark");
|
||||
if (val == null) {
|
||||
return UNDEFINED_THEME_NAME;
|
||||
}
|
||||
return (val) ? DARK_THEME_NAME : LIGHT_THEME_NAME;
|
||||
}
|
||||
|
||||
private static void setOsDarkTheme(String val) {
|
||||
try {
|
||||
if (val.equals(DARK_THEME_NAME)) {
|
||||
Runtime.getRuntime().exec("gsettings set org.gnome.desktop.interface gtk-theme 'Adwaita-dark'");
|
||||
Runtime.getRuntime().exec("gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark'");
|
||||
} else {
|
||||
Runtime.getRuntime().exec("gsettings set org.gnome.desktop.interface gtk-theme 'Adwaita'");
|
||||
Runtime.getRuntime().exec("gsettings set org.gnome.desktop.interface color-scheme 'default'");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String currentTheme = null;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
currentTheme = currentTheme();
|
||||
if (currentTheme.equals(UNDEFINED_THEME_NAME)) {
|
||||
throw new RuntimeException("Test Failed! Cannot detect current OS theme");
|
||||
}
|
||||
|
||||
String initialTheme = currentTheme;
|
||||
try {
|
||||
setOsDarkTheme(LIGHT_THEME_NAME);
|
||||
Thread.sleep(TIME_TO_WAIT);
|
||||
if (!currentTheme().equals(LIGHT_THEME_NAME)) {
|
||||
throw new RuntimeException("Test Failed! Initial OS theme supposed to be Light");
|
||||
}
|
||||
|
||||
String[] themesOrder = {DARK_THEME_NAME, LIGHT_THEME_NAME, DARK_THEME_NAME};
|
||||
Toolkit.getDefaultToolkit().addPropertyChangeListener("awt.os.theme.isDark", evt -> {
|
||||
currentTheme = currentTheme();
|
||||
});
|
||||
|
||||
for (String nextTheme : themesOrder) {
|
||||
setOsDarkTheme(nextTheme);
|
||||
Thread.sleep(TIME_TO_WAIT);
|
||||
|
||||
if (!currentTheme().equals(nextTheme)) {
|
||||
throw new RuntimeException("Test Failed! OS theme which was set doesn't match with detected");
|
||||
}
|
||||
if (!currentTheme.equals(nextTheme)) {
|
||||
throw new RuntimeException("Test Failed! Changing OS theme was not detected");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
setOsDarkTheme(initialTheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user