diff options
Diffstat (limited to 'Telegram/SourceFiles/platform')
11 files changed, 118 insertions, 545 deletions
diff --git a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp index 08b1fad2fc..e7440da764 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "platform/linux/linux_gdk_helper.h" +#include "base/platform/linux/base_linux_gtk_integration_p.h" #include "platform/linux/linux_gtk_integration_p.h" extern "C" { diff --git a/Telegram/SourceFiles/platform/linux/linux_gtk_file_dialog.cpp b/Telegram/SourceFiles/platform/linux/linux_gtk_file_dialog.cpp index be65f7af64..96c725c7ba 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gtk_file_dialog.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_gtk_file_dialog.cpp @@ -642,7 +642,7 @@ bool Supported() { } bool Use(Type type) { - return IsGtkIntegrationForced() + return qEnvironmentVariableIsSet("TDESKTOP_USE_GTK_FILE_DIALOG") || DesktopEnvironment::IsGtkBased() // use as a fallback for portal dialog || UseXDGDesktopPortal(); diff --git a/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp b/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp index 59fcd12d9a..75b2cd18e0 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp @@ -7,149 +7,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "platform/linux/linux_gtk_integration.h" +#include "base/platform/linux/base_linux_gtk_integration.h" +#include "base/platform/linux/base_linux_gtk_integration_p.h" #include "platform/linux/linux_gtk_integration_p.h" -#include "base/platform/base_platform_info.h" -#include "platform/linux/linux_xlib_helper.h" #include "platform/linux/linux_gdk_helper.h" #include "platform/linux/linux_gtk_file_dialog.h" #include "platform/linux/linux_open_with_dialog.h" #include "platform/linux/specific_linux.h" +#include "ui/platform/ui_platform_utility.h" #include "core/sandbox.h" #include "core/core_settings.h" #include "core/application.h" -#include "main/main_domain.h" -#include "mainwindow.h" namespace Platform { namespace internal { using namespace Platform::Gtk; +using BaseGtkIntegration = base::Platform::GtkIntegration; namespace { -bool GtkTriedToInit = false; -bool GtkLoaded = false; - -bool LoadLibrary(QLibrary &lib, const char *name, int version) { -#ifdef LINK_TO_GTK - return true; -#else // LINK_TO_GTK - DEBUG_LOG(("Loading '%1' with version %2...").arg( - QLatin1String(name)).arg(version)); - lib.setFileNameAndVersion(QLatin1String(name), version); - if (lib.load()) { - DEBUG_LOG(("Loaded '%1' with version %2!").arg( - QLatin1String(name)).arg(version)); - return true; - } - lib.setFileNameAndVersion(QLatin1String(name), QString()); - if (lib.load()) { - DEBUG_LOG(("Loaded '%1' without version!").arg(QLatin1String(name))); - return true; - } - LOG(("Could not load '%1' with version %2 :(").arg( - QLatin1String(name)).arg(version)); - return false; -#endif // !LINK_TO_GTK -} +bool Loaded = false; -void GtkMessageHandler( - const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer unused_data) { - // Silence false-positive Gtk warnings (we are using Xlib to set - // the WM_TRANSIENT_FOR hint). - if (message != qstr("GtkDialog mapped without a transient parent. " - "This is discouraged.")) { - // For other messages, call the default handler. - g_log_default_handler(log_domain, log_level, message, unused_data); - } -} - -bool SetupGtkBase(QLibrary &lib_gtk) { - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_init_check", gtk_init_check)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_check_version", gtk_check_version)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_settings_get_default", gtk_settings_get_default)) return false; - - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_widget_hide", gtk_widget_hide)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_widget_get_window", gtk_widget_get_window)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_widget_realize", gtk_widget_realize)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_widget_hide_on_delete", gtk_widget_hide_on_delete)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_widget_destroy", gtk_widget_destroy)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_clipboard_get", gtk_clipboard_get)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_clipboard_store", gtk_clipboard_store)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_clipboard_wait_for_contents", gtk_clipboard_wait_for_contents)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_clipboard_wait_for_image", gtk_clipboard_wait_for_image)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_selection_data_targets_include_image", gtk_selection_data_targets_include_image)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_selection_data_free", gtk_selection_data_free)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_dialog_new", gtk_file_chooser_dialog_new)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_get_type", gtk_file_chooser_get_type)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_image_get_type", gtk_image_get_type)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_set_current_folder", gtk_file_chooser_set_current_folder)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_get_current_folder", gtk_file_chooser_get_current_folder)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_set_current_name", gtk_file_chooser_set_current_name)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_select_filename", gtk_file_chooser_select_filename)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_get_filenames", gtk_file_chooser_get_filenames)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_set_filter", gtk_file_chooser_set_filter)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_get_filter", gtk_file_chooser_get_filter)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_window_get_type", gtk_window_get_type)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_window_set_title", gtk_window_set_title)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_set_local_only", gtk_file_chooser_set_local_only)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_set_action", gtk_file_chooser_set_action)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_set_select_multiple", gtk_file_chooser_set_select_multiple)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_set_do_overwrite_confirmation", gtk_file_chooser_set_do_overwrite_confirmation)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_remove_filter", gtk_file_chooser_remove_filter)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_filter_set_name", gtk_file_filter_set_name)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_filter_add_pattern", gtk_file_filter_add_pattern)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_add_filter", gtk_file_chooser_add_filter)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_set_preview_widget", gtk_file_chooser_set_preview_widget)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_get_preview_filename", gtk_file_chooser_get_preview_filename)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_chooser_set_preview_widget_active", gtk_file_chooser_set_preview_widget_active)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_file_filter_new", gtk_file_filter_new)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_image_new", gtk_image_new)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_image_set_from_pixbuf", gtk_image_set_from_pixbuf)) return false; - - if (!LOAD_GTK_SYMBOL(lib_gtk, "gdk_window_set_modal_hint", gdk_window_set_modal_hint)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gdk_window_focus", gdk_window_focus)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_dialog_get_type", gtk_dialog_get_type)) return false; - if (!LOAD_GTK_SYMBOL(lib_gtk, "gtk_dialog_run", gtk_dialog_run)) return false; - - if (!LOAD_GTK_SYMBOL(lib_gtk, "gdk_atom_intern", gdk_atom_intern)) return false; - - if (LOAD_GTK_SYMBOL(lib_gtk, "gdk_set_allowed_backends", gdk_set_allowed_backends)) { - // We work only with Wayland and X11 GDK backends. - // Otherwise we get segfault in Ubuntu 17.04 in gtk_init_check() call. - // See https://github.com/telegramdesktop/tdesktop/issues/3176 - // See https://github.com/telegramdesktop/tdesktop/issues/3162 - if(IsWayland()) { - DEBUG_LOG(("Limit allowed GDK backends to wayland,x11")); - gdk_set_allowed_backends("wayland,x11"); - } else { - DEBUG_LOG(("Limit allowed GDK backends to x11,wayland")); - gdk_set_allowed_backends("x11,wayland"); - } - } - - // gtk_init will reset the Xlib error handler, - // and that causes Qt applications to quit on X errors. - // Therefore, we need to manually restore it. - XErrorHandlerRestorer handlerRestorer; - - DEBUG_LOG(("Library gtk functions loaded!")); - GtkTriedToInit = true; - if (!gtk_init_check(0, 0)) { - gtk_init_check = nullptr; - DEBUG_LOG(("Failed to gtk_init_check(0, 0)!")); - return false; - } - DEBUG_LOG(("Checked gtk with gtk_init_check!")); - - // Use our custom log handler. - g_log_set_handler("Gtk", G_LOG_LEVEL_MESSAGE, GtkMessageHandler, nullptr); - - return true; +QLibrary &Library() { + return BaseGtkIntegration::Instance()->library(); } bool GetImageFromClipboardSupported() { @@ -166,47 +47,6 @@ bool GetImageFromClipboardSupported() { && (gdk_atom_intern != nullptr); } -template <typename T> -std::optional<T> GtkSetting(const QString &propertyName) { - const auto integration = GtkIntegration::Instance(); - if (!integration - || !integration->loaded() - || gtk_settings_get_default == nullptr) { - return std::nullopt; - } - auto settings = gtk_settings_get_default(); - T value; - g_object_get(settings, propertyName.toUtf8(), &value, nullptr); - return value; -} - -bool IconThemeShouldBeSet() { - // change the icon theme only if - // it isn't already set by a platformtheme plugin - // if QT_QPA_PLATFORMTHEME=(gtk2|gtk3), then force-apply the icon theme - static const auto Result = - // QGenericUnixTheme - (QIcon::themeName() == qstr("hicolor") - && QIcon::fallbackThemeName() == qstr("hicolor")) - // QGnomeTheme - || (QIcon::themeName() == qstr("Adwaita") - && QIcon::fallbackThemeName() == qstr("gnome")) - // qt5ct - || (QIcon::themeName().isEmpty() - && QIcon::fallbackThemeName().isEmpty()) - || IsGtkIntegrationForced(); - - return Result; -} - -bool CursorSizeShouldBeSet() { - // change the cursor size only on Wayland and if it wasn't already set - static const auto Result = IsWayland() - && qEnvironmentVariableIsEmpty("XCURSOR_SIZE"); - - return Result; -} - void SetScaleFactor() { Core::Sandbox::Instance().customEnterFromEventLoop([] { const auto integration = GtkIntegration::Instance(); @@ -225,61 +65,6 @@ void SetScaleFactor() { }); } -void SetIconTheme() { - Core::Sandbox::Instance().customEnterFromEventLoop([] { - const auto integration = GtkIntegration::Instance(); - if (!integration || !IconThemeShouldBeSet()) { - return; - } - - const auto themeName = integration->getStringSetting( - qsl("gtk-icon-theme-name")); - - const auto fallbackThemeName = integration->getStringSetting( - qsl("gtk-fallback-icon-theme")); - - if (!themeName.has_value() || !fallbackThemeName.has_value()) { - return; - } - - DEBUG_LOG(("Setting GTK icon theme")); - - QIcon::setThemeName(*themeName); - QIcon::setFallbackThemeName(*fallbackThemeName); - - DEBUG_LOG(("New icon theme: %1").arg(QIcon::themeName())); - DEBUG_LOG(("New fallback icon theme: %1").arg( - QIcon::fallbackThemeName())); - - SetApplicationIcon(Window::CreateIcon()); - if (App::wnd()) { - App::wnd()->setWindowIcon(Window::CreateIcon()); - } - - Core::App().domain().notifyUnreadBadgeChanged(); - }); -} - -void SetCursorSize() { - Core::Sandbox::Instance().customEnterFromEventLoop([] { - const auto integration = GtkIntegration::Instance(); - if (!integration || !CursorSizeShouldBeSet()) { - return; - } - - const auto newCursorSize = integration->getIntSetting( - qsl("gtk-cursor-theme-size")); - - if (!newCursorSize.has_value()) { - return; - } - - DEBUG_LOG(("Setting GTK cursor size")); - qputenv("XCURSOR_SIZE", QByteArray::number(*newCursorSize)); - DEBUG_LOG(("New cursor size: %1").arg(*newCursorSize)); - }); -} - void DarkModeChanged() { Core::Sandbox::Instance().customEnterFromEventLoop([] { Core::App().settings().setSystemDarkMode(IsDarkMode()); @@ -299,10 +84,7 @@ GtkIntegration::GtkIntegration() { } GtkIntegration *GtkIntegration::Instance() { - static const auto useGtkIntegration = !qEnvironmentVariableIsSet( - kDisableGtkIntegration.utf8()); - - if (!useGtkIntegration) { + if (!BaseGtkIntegration::Instance()) { return nullptr; } @@ -311,131 +93,107 @@ GtkIntegration *GtkIntegration::Instance() { } void GtkIntegration::load() { - Expects(!GtkLoaded); - DEBUG_LOG(("Loading GTK")); + Expects(!loaded()); - QLibrary lib_gtk; - lib_gtk.setLoadHints(QLibrary::DeepBindHint); - - if (LoadLibrary(lib_gtk, "gtk-3", 0)) { - GtkLoaded = SetupGtkBase(lib_gtk); - } - if (!GtkLoaded - && !GtkTriedToInit - && LoadLibrary(lib_gtk, "gtk-x11-2.0", 0)) { - GtkLoaded = SetupGtkBase(lib_gtk); + if (!BaseGtkIntegration::Instance()->loaded()) { + return; } - if (GtkLoaded) { - LOAD_GTK_SYMBOL(lib_gtk, "gdk_display_get_default", gdk_display_get_default); - LOAD_GTK_SYMBOL(lib_gtk, "gdk_display_get_monitor", gdk_display_get_monitor); - LOAD_GTK_SYMBOL(lib_gtk, "gdk_display_get_primary_monitor", gdk_display_get_primary_monitor); - LOAD_GTK_SYMBOL(lib_gtk, "gdk_monitor_get_scale_factor", gdk_monitor_get_scale_factor); - - LOAD_GTK_SYMBOL(lib_gtk, "gdk_pixbuf_new_from_file_at_size", gdk_pixbuf_new_from_file_at_size); - LOAD_GTK_SYMBOL(lib_gtk, "gdk_pixbuf_get_has_alpha", gdk_pixbuf_get_has_alpha); - LOAD_GTK_SYMBOL(lib_gtk, "gdk_pixbuf_get_pixels", gdk_pixbuf_get_pixels); - LOAD_GTK_SYMBOL(lib_gtk, "gdk_pixbuf_get_width", gdk_pixbuf_get_width); - LOAD_GTK_SYMBOL(lib_gtk, "gdk_pixbuf_get_height", gdk_pixbuf_get_height); - LOAD_GTK_SYMBOL(lib_gtk, "gdk_pixbuf_get_rowstride", gdk_pixbuf_get_rowstride); - - GdkHelperLoad(lib_gtk); - - LOAD_GTK_SYMBOL(lib_gtk, "gtk_dialog_get_widget_for_response", gtk_dialog_get_widget_for_response); - LOAD_GTK_SYMBOL(lib_gtk, "gtk_button_set_label", gtk_button_set_label); - LOAD_GTK_SYMBOL(lib_gtk, "gtk_button_get_type", gtk_button_get_type); - - LOAD_GTK_SYMBOL(lib_gtk, "gtk_app_chooser_dialog_new", gtk_app_chooser_dialog_new); - LOAD_GTK_SYMBOL(lib_gtk, "gtk_app_chooser_get_app_info", gtk_app_chooser_get_app_info); - LOAD_GTK_SYMBOL(lib_gtk, "gtk_app_chooser_get_type", gtk_app_chooser_get_type); - - SetScaleFactor(); - SetIconTheme(); - SetCursorSize(); - - const auto settings = gtk_settings_get_default(); - - g_signal_connect( - settings, - "notify::gtk-icon-theme-name", - G_CALLBACK(SetIconTheme), - nullptr); - - g_signal_connect( - settings, - "notify::gtk-theme-name", - G_CALLBACK(DarkModeChanged), - nullptr); - - g_signal_connect( - settings, - "notify::gtk-cursor-theme-size", - G_CALLBACK(SetCursorSize), - nullptr); - - if (checkVersion(3, 0, 0)) { - g_signal_connect( - settings, - "notify::gtk-application-prefer-dark-theme", - G_CALLBACK(DarkModeChanged), - nullptr); - } - - if (checkVersion(3, 12, 0)) { - g_signal_connect( - settings, - "notify::gtk-decoration-layout", - G_CALLBACK(DecorationLayoutChanged), - nullptr); - } - } else { - LOG(("Could not load gtk-3 or gtk-x11-2.0!")); + LOAD_GTK_SYMBOL(Library(), "gtk_widget_show", gtk_widget_show); + LOAD_GTK_SYMBOL(Library(), "gtk_widget_hide", gtk_widget_hide); + LOAD_GTK_SYMBOL(Library(), "gtk_widget_get_window", gtk_widget_get_window); + LOAD_GTK_SYMBOL(Library(), "gtk_widget_realize", gtk_widget_realize); + LOAD_GTK_SYMBOL(Library(), "gtk_widget_hide_on_delete", gtk_widget_hide_on_delete); + LOAD_GTK_SYMBOL(Library(), "gtk_widget_destroy", gtk_widget_destroy); + LOAD_GTK_SYMBOL(Library(), "gtk_clipboard_get", gtk_clipboard_get); + LOAD_GTK_SYMBOL(Library(), "gtk_clipboard_store", gtk_clipboard_store); + LOAD_GTK_SYMBOL(Library(), "gtk_clipboard_wait_for_contents", gtk_clipboard_wait_for_contents); + LOAD_GTK_SYMBOL(Library(), "gtk_clipboard_wait_for_image", gtk_clipboard_wait_for_image); + LOAD_GTK_SYMBOL(Library(), "gtk_selection_data_targets_include_image", gtk_selection_data_targets_include_image); + LOAD_GTK_SYMBOL(Library(), "gtk_selection_data_free", gtk_selection_data_free); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_dialog_new", gtk_file_chooser_dialog_new); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_get_type", gtk_file_chooser_get_type); + LOAD_GTK_SYMBOL(Library(), "gtk_image_get_type", gtk_image_get_type); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_set_current_folder", gtk_file_chooser_set_current_folder); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_get_current_folder", gtk_file_chooser_get_current_folder); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_set_current_name", gtk_file_chooser_set_current_name); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_select_filename", gtk_file_chooser_select_filename); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_get_filenames", gtk_file_chooser_get_filenames); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_set_filter", gtk_file_chooser_set_filter); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_get_filter", gtk_file_chooser_get_filter); + LOAD_GTK_SYMBOL(Library(), "gtk_window_get_type", gtk_window_get_type); + LOAD_GTK_SYMBOL(Library(), "gtk_window_set_title", gtk_window_set_title); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_set_local_only", gtk_file_chooser_set_local_only); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_set_action", gtk_file_chooser_set_action); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_set_select_multiple", gtk_file_chooser_set_select_multiple); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_set_do_overwrite_confirmation", gtk_file_chooser_set_do_overwrite_confirmation); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_remove_filter", gtk_file_chooser_remove_filter); + LOAD_GTK_SYMBOL(Library(), "gtk_file_filter_set_name", gtk_file_filter_set_name); + LOAD_GTK_SYMBOL(Library(), "gtk_file_filter_add_pattern", gtk_file_filter_add_pattern); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_add_filter", gtk_file_chooser_add_filter); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_set_preview_widget", gtk_file_chooser_set_preview_widget); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_get_preview_filename", gtk_file_chooser_get_preview_filename); + LOAD_GTK_SYMBOL(Library(), "gtk_file_chooser_set_preview_widget_active", gtk_file_chooser_set_preview_widget_active); + LOAD_GTK_SYMBOL(Library(), "gtk_file_filter_new", gtk_file_filter_new); + LOAD_GTK_SYMBOL(Library(), "gtk_image_new", gtk_image_new); + LOAD_GTK_SYMBOL(Library(), "gtk_image_set_from_pixbuf", gtk_image_set_from_pixbuf); + + LOAD_GTK_SYMBOL(Library(), "gdk_window_set_modal_hint", gdk_window_set_modal_hint); + LOAD_GTK_SYMBOL(Library(), "gdk_window_focus", gdk_window_focus); + LOAD_GTK_SYMBOL(Library(), "gtk_dialog_get_type", gtk_dialog_get_type); + LOAD_GTK_SYMBOL(Library(), "gtk_dialog_run", gtk_dialog_run); + + LOAD_GTK_SYMBOL(Library(), "gdk_atom_intern", gdk_atom_intern); + + LOAD_GTK_SYMBOL(Library(), "gdk_display_get_default", gdk_display_get_default); + LOAD_GTK_SYMBOL(Library(), "gdk_display_get_monitor", gdk_display_get_monitor); + LOAD_GTK_SYMBOL(Library(), "gdk_display_get_primary_monitor", gdk_display_get_primary_monitor); + LOAD_GTK_SYMBOL(Library(), "gdk_monitor_get_scale_factor", gdk_monitor_get_scale_factor); + + LOAD_GTK_SYMBOL(Library(), "gdk_pixbuf_new_from_file_at_size", gdk_pixbuf_new_from_file_at_size); + LOAD_GTK_SYMBOL(Library(), "gdk_pixbuf_get_has_alpha", gdk_pixbuf_get_has_alpha); + LOAD_GTK_SYMBOL(Library(), "gdk_pixbuf_get_pixels", gdk_pixbuf_get_pixels); + LOAD_GTK_SYMBOL(Library(), "gdk_pixbuf_get_width", gdk_pixbuf_get_width); + LOAD_GTK_SYMBOL(Library(), "gdk_pixbuf_get_height", gdk_pixbuf_get_height); + LOAD_GTK_SYMBOL(Library(), "gdk_pixbuf_get_rowstride", gdk_pixbuf_get_rowstride); + + GdkHelperLoad(Library()); + + LOAD_GTK_SYMBOL(Library(), "gtk_dialog_get_widget_for_response", gtk_dialog_get_widget_for_response); + LOAD_GTK_SYMBOL(Library(), "gtk_button_set_label", gtk_button_set_label); + LOAD_GTK_SYMBOL(Library(), "gtk_button_get_type", gtk_button_get_type); + + LOAD_GTK_SYMBOL(Library(), "gtk_app_chooser_dialog_new", gtk_app_chooser_dialog_new); + LOAD_GTK_SYMBOL(Library(), "gtk_app_chooser_get_app_info", gtk_app_chooser_get_app_info); + LOAD_GTK_SYMBOL(Library(), "gtk_app_chooser_get_type", gtk_app_chooser_get_type); + + Loaded = true; + + SetScaleFactor(); + + BaseGtkIntegration::Instance()->connectToSetting( + "gtk-theme-name", + DarkModeChanged); + + if (BaseGtkIntegration::Instance()->checkVersion(3, 0, 0)) { + BaseGtkIntegration::Instance()->connectToSetting( + "gtk-application-prefer-dark-theme", + DarkModeChanged); } -} -bool GtkIntegration::loaded() const { - return GtkLoaded; -} + if (BaseGtkIntegration::Instance()->checkVersion(3, 12, 0)) { + BaseGtkIntegration::Instance()->connectToSetting( + "gtk-decoration-layout", + DecorationLayoutChanged); -bool GtkIntegration::checkVersion(uint major, uint minor, uint micro) const { - return (loaded() && gtk_check_version != nullptr) - ? !gtk_check_version(major, minor, micro) - : false; -} - -std::optional<bool> GtkIntegration::getBoolSetting( - const QString &propertyName) const { - const auto value = GtkSetting<gboolean>(propertyName); - if (!value.has_value()) { - return std::nullopt; - } - DEBUG_LOG(("Getting GTK setting, %1: %2") - .arg(propertyName) - .arg(Logs::b(*value))); - return *value; -} - -std::optional<int> GtkIntegration::getIntSetting( - const QString &propertyName) const { - const auto value = GtkSetting<gint>(propertyName); - if (value.has_value()) { - DEBUG_LOG(("Getting GTK setting, %1: %2") - .arg(propertyName) - .arg(*value)); + BaseGtkIntegration::Instance()->connectToSetting( + "gtk-decoration-layout", + Ui::Platform::NotifyTitleControlsLayoutChanged); } - return value; } -std::optional<QString> GtkIntegration::getStringSetting( - const QString &propertyName) const { - auto value = GtkSetting<gchararray>(propertyName); - if (!value.has_value()) { - return std::nullopt; - } - const auto str = QString::fromUtf8(*value); - g_free(*value); - DEBUG_LOG(("Getting GTK setting, %1: '%2'").arg(propertyName).arg(str)); - return str; +bool GtkIntegration::loaded() const { + return Loaded; } std::optional<int> GtkIntegration::scaleFactor() const { diff --git a/Telegram/SourceFiles/platform/linux/linux_gtk_integration.h b/Telegram/SourceFiles/platform/linux/linux_gtk_integration.h index 25774161b1..4a24bd3882 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gtk_integration.h +++ b/Telegram/SourceFiles/platform/linux/linux_gtk_integration.h @@ -12,27 +12,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Platform { namespace internal { -inline constexpr auto kDisableGtkIntegration = "TDESKTOP_DISABLE_GTK_INTEGRATION"_cs; - class GtkIntegration { public: static GtkIntegration *Instance(); void load(); [[nodiscard]] bool loaded() const; - [[nodiscard]] bool checkVersion( - uint major, - uint minor, - uint micro) const; - - [[nodiscard]] std::optional<bool> getBoolSetting( - const QString &propertyName) const; - - [[nodiscard]] std::optional<int> getIntSetting( - const QString &propertyName) const; - - [[nodiscard]] std::optional<QString> getStringSetting( - const QString &propertyName) const; [[nodiscard]] std::optional<int> scaleFactor() const; diff --git a/Telegram/SourceFiles/platform/linux/linux_gtk_integration_dummy.cpp b/Telegram/SourceFiles/platform/linux/linux_gtk_integration_dummy.cpp index 59225e9475..e27184daa0 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gtk_integration_dummy.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_gtk_integration_dummy.cpp @@ -24,25 +24,6 @@ bool GtkIntegration::loaded() const { return false; } -bool GtkIntegration::checkVersion(uint major, uint minor, uint micro) const { - return false; -} - -std::optional<bool> GtkIntegration::getBoolSetting( - const QString &propertyName) const { - return std::nullopt; -} - -std::optional<int> GtkIntegration::getIntSetting( - const QString &propertyName) const { - return std::nullopt; -} - -std::optional<QString> GtkIntegration::getStringSetting( - const QString &propertyName) const { - return std::nullopt; -} - std::optional<int> GtkIntegration::scaleFactor() const { return std::nullopt; } diff --git a/Telegram/SourceFiles/platform/linux/linux_gtk_integration_p.h b/Telegram/SourceFiles/platform/linux/linux_gtk_integration_p.h index b0b60e6bcf..d2c9e92076 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gtk_integration_p.h +++ b/Telegram/SourceFiles/platform/linux/linux_gtk_integration_p.h @@ -7,8 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include <QtCore/QLibrary> - extern "C" { #undef signals #include <gtk/gtk.h> @@ -16,16 +14,6 @@ extern "C" { #define signals public } // extern "C" -#if defined DESKTOP_APP_USE_PACKAGED && !defined DESKTOP_APP_USE_PACKAGED_LAZY -#define LINK_TO_GTK -#endif // DESKTOP_APP_USE_PACKAGED && !DESKTOP_APP_USE_PACKAGED_LAZY - -#ifdef LINK_TO_GTK -#define LOAD_GTK_SYMBOL(lib, name, func) (func = ::func) -#else // LINK_TO_GTK -#define LOAD_GTK_SYMBOL Platform::Gtk::LoadSymbol -#endif // !LINK_TO_GTK - // To be able to compile with gtk-2.0 headers as well typedef struct _GdkMonitor GdkMonitor; typedef struct _GtkAppChooser GtkAppChooser; @@ -33,24 +21,6 @@ typedef struct _GtkAppChooser GtkAppChooser; namespace Platform { namespace Gtk { -template <typename Function> -bool LoadSymbol(QLibrary &lib, const char *name, Function &func) { - func = nullptr; - if (!lib.isLoaded()) { - return false; - } - - func = reinterpret_cast<Function>(lib.resolve(name)); - if (func) { - return true; - } - LOG(("Error: failed to load '%1' function!").arg(name)); - return false; -} - -inline gboolean (*gtk_init_check)(int *argc, char ***argv) = nullptr; -inline const gchar* (*gtk_check_version)(guint required_major, guint required_minor, guint required_micro) = nullptr; -inline GtkSettings* (*gtk_settings_get_default)(void) = nullptr; inline void (*gtk_widget_show)(GtkWidget *widget) = nullptr; inline void (*gtk_widget_hide)(GtkWidget *widget) = nullptr; inline GdkWindow* (*gtk_widget_get_window)(GtkWidget *widget) = nullptr; @@ -90,7 +60,6 @@ inline GtkWidget* (*gtk_image_new)(void) = nullptr; inline void (*gtk_image_set_from_pixbuf)(GtkImage *image, GdkPixbuf *pixbuf) = nullptr; inline GtkWidget* (*gtk_app_chooser_dialog_new)(GtkWindow *parent, GtkDialogFlags flags, GFile *file) = nullptr; inline GAppInfo* (*gtk_app_chooser_get_app_info)(GtkAppChooser *self) = nullptr; -inline void (*gdk_set_allowed_backends)(const gchar *backends) = nullptr; inline void (*gdk_window_set_modal_hint)(GdkWindow *window, gboolean modal) = nullptr; inline void (*gdk_window_focus)(GdkWindow *window, guint32 timestamp) = nullptr; diff --git a/Telegram/SourceFiles/platform/linux/linux_xlib_helper.cpp b/Telegram/SourceFiles/platform/linux/linux_xlib_helper.cpp deleted file mode 100644 index 270f0ae8f8..0000000000 --- a/Telegram/SourceFiles/platform/linux/linux_xlib_helper.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "platform/linux/linux_xlib_helper.h" - -extern "C" { -#include <X11/Xlib.h> -} - -namespace Platform { -namespace internal { - -class XErrorHandlerRestorer::Private { -public: - Private() - : _oldErrorHandler(XSetErrorHandler(nullptr)) { - } - - ~Private() { - XSetErrorHandler(_oldErrorHandler); - } - -private: - int (*_oldErrorHandler)(Display *, XErrorEvent *); -}; - -XErrorHandlerRestorer::XErrorHandlerRestorer() -: _private(std::make_unique<Private>()) { -} - -XErrorHandlerRestorer::~XErrorHandlerRestorer() = default; - -} // namespace internal -} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_xlib_helper.h b/Telegram/SourceFiles/platform/linux/linux_xlib_helper.h deleted file mode 100644 index abd1720663..0000000000 --- a/Telegram/SourceFiles/platform/linux/linux_xlib_helper.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace Platform { -namespace internal { - -class XErrorHandlerRestorer { -public: - XErrorHandlerRestorer(); - ~XErrorHandlerRestorer(); - -private: - class Private; - const std::unique_ptr<Private> _private; -}; - -} // namespace internal -} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index 5f5a94bfb0..c5349ed8f2 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -24,7 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_controller.h" #include "window/window_session_controller.h" #include "base/platform/base_platform_info.h" -#include "base/platform/linux/base_xcb_utilities_linux.h" +#include "base/platform/linux/base_linux_xcb_utilities.h" #include "base/call_delayed.h" #include "ui/widgets/popup_menu.h" #include "ui/widgets/input_fields.h" diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 12e98b37f4..6fab06580c 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -8,7 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/linux/specific_linux.h" #include "base/platform/base_platform_info.h" -#include "base/platform/linux/base_xcb_utilities_linux.h" +#include "base/platform/linux/base_linux_xcb_utilities.h" +#include "base/platform/linux/base_linux_gtk_integration.h" #include "platform/linux/linux_desktop_environment.h" #include "platform/linux/linux_gtk_integration.h" #include "platform/linux/linux_wayland_integration.h" @@ -60,6 +61,7 @@ extern "C" { #include <iostream> using namespace Platform; +using BaseGtkIntegration = base::Platform::GtkIntegration; using Platform::internal::WaylandIntegration; using Platform::internal::GtkIntegration; @@ -68,8 +70,6 @@ Q_DECLARE_METATYPE(QMargins); namespace Platform { namespace { -constexpr auto kIgnoreGtkIncompatibility = "TDESKTOP_I_KNOW_ABOUT_GTK_INCOMPATIBILITY"_cs; - constexpr auto kDesktopFile = ":/misc/telegramdesktop.desktop"_cs; constexpr auto kIconName = "telegram"_cs; constexpr auto kHandlerTypeName = "x-scheme-handler/tg"_cs; @@ -80,8 +80,6 @@ constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs; constexpr auto kXCBFrameExtentsAtomName = "_GTK_FRAME_EXTENTS"_cs; -QStringList PlatformThemes; - #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION std::unique_ptr<internal::NotificationServiceWatcher> NSWInstance; @@ -562,27 +560,6 @@ bool InSnap() { return Result; } -bool IsStaticBinary() { -#ifdef DESKTOP_APP_USE_PACKAGED - return false; -#else // DESKTOP_APP_USE_PACKAGED - return true; -#endif // !DESKTOP_APP_USE_PACKAGED -} - -bool IsGtkIntegrationForced() { - static const auto Result = [&] { - if (!GtkIntegration::Instance()) { - return false; - } - - return PlatformThemes.contains(qstr("gtk3"), Qt::CaseInsensitive) - || PlatformThemes.contains(qstr("gtk2"), Qt::CaseInsensitive); - }(); - - return Result; -} - bool AreQtPluginsBundled() { #if !defined DESKTOP_APP_USE_PACKAGED || defined DESKTOP_APP_USE_PACKAGED_LAZY return true; @@ -719,7 +696,7 @@ QImage GetImageFromClipboard() { } std::optional<bool> IsDarkMode() { - const auto integration = GtkIntegration::Instance(); + const auto integration = BaseGtkIntegration::Instance(); if (!integration) { return std::nullopt; } @@ -832,7 +809,7 @@ bool WindowsNeedShadow() { Window::ControlsLayout WindowControlsLayout() { const auto gtkResult = []() -> std::optional<Window::ControlsLayout> { - const auto integration = GtkIntegration::Instance(); + const auto integration = BaseGtkIntegration::Instance(); if (!integration || !integration->checkVersion(3, 12, 0)) { return std::nullopt; } @@ -962,53 +939,15 @@ int psFixPrevious() { namespace Platform { void start() { - PlatformThemes = QString::fromUtf8(qgetenv("QT_QPA_PLATFORMTHEME")) - .split(':', base::QStringSkipEmptyParts); - LOG(("Launcher filename: %1").arg(GetLauncherFilename())); qputenv("PULSE_PROP_application.name", AppName.utf8()); qputenv("PULSE_PROP_application.icon_name", GetIconName().toLatin1()); - // if gtk integration and qgtk3/qgtk2 platformtheme (or qgtk2 style) - // is used at the same time, the app will crash - if (GtkIntegration::Instance() - && !IsStaticBinary() |