/*****************************************************************************
* Copyright (C) 2022 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* ( at your option ) any later version.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <QColor>
#include <QPalette>
#include <QApplication>
#undef signals
#include <vlc_common.h>
#include <vlc_plugin.h>
#include "../qtthemeprovider.hpp"
#include <mutex>
#include <functional>
#include "nav_button_provider_gtk.h"
#include "gtk_util.h"
using namespace gtk;
class GtkPrivateThemeProvider {
public:
bool windowMaximized = false;
bool windowActive = false;
int bannerHeight = -1;
NavButtonProviderGtk navButtons;
//Metrics
int interNavButtonSpacing = 0;
int csdFrameMarginLeft = 0;
int csdFrameMarginRight = 0;
int csdFrameMarginTop = 0;
int csdFrameMarginBottom = 0;
};
static bool isThemeDark( vlc_qt_theme_provider_t*)
{
GdkRGBA colBg = GetBgColor("");
GdkRGBA colText = GetFgColor("GtkLabel#label");
return GdkRBGALightness(colBg) < GdkRBGALightness(colText);
}
static void setGtkColor(vlc_qt_theme_provider_t* obj,
vlc_qt_theme_color_set set, vlc_qt_theme_color_section section,
vlc_qt_theme_color_name name, vlc_qt_theme_color_state state,
const GdkRGBA& gColor)
{
obj->setColorF(obj, set, section, name, state, gColor.red, gColor.green, gColor.blue, gColor.alpha);
}
static void setGtkColorSet(vlc_qt_theme_provider_t* obj,
vlc_qt_theme_color_set set, vlc_qt_theme_color_section section,
vlc_qt_theme_color_name name,
std::function<GdkRGBA (const std::string&)> getter, const std::string &selector)
{
setGtkColor(obj, set, section, name, VQTC_STATE_NORMAL, getter(selector));
setGtkColor(obj, set, section, name, VQTC_STATE_DISABLED, getter(selector + ":disabled"));
setGtkColor(obj, set, section, name, VQTC_STATE_HOVERED, getter(selector + ":hover"));
setGtkColor(obj, set, section, name, VQTC_STATE_PRESSED, getter(selector + ":hover:active"));
setGtkColor(obj, set, section, name, VQTC_STATE_FOCUSED, getter(selector + ":focus"));
}
static void setGtkColorSetBg(vlc_qt_theme_provider_t* obj,
vlc_qt_theme_color_set set, vlc_qt_theme_color_name name,
const std::string &selector)
{
setGtkColorSet(obj, set, VQTC_SECTION_BG, name, GetBgColor, selector);
}
static void setGtkColorSetFg(vlc_qt_theme_provider_t* obj,
vlc_qt_theme_color_set set, vlc_qt_theme_color_name name,
const std::string &selector)
{
setGtkColorSet(obj, set, VQTC_SECTION_FG, name, GetFgColor, selector);
}
static void setGtkColorSetFgFromBg(vlc_qt_theme_provider_t* obj,
vlc_qt_theme_color_set set, vlc_qt_theme_color_name name,
const std::string &selector)
{
setGtkColorSet(obj, set, VQTC_SECTION_FG, name, GetBgColor, selector);
}
static void setGtkColorSetBorder(vlc_qt_theme_provider_t* obj, vlc_qt_theme_color_set set, const std::string &selector)
{
setGtkColorSet(obj, set, VQTC_SECTION_DECORATION, VQTC_NAME_BORDER, GetBorderColor, selector);
}
static void setGtkColorSetHighlight(vlc_qt_theme_provider_t* obj, vlc_qt_theme_color_set set, const std::string &selector)
{
auto setFgBg = [obj, set, &selector](vlc_qt_theme_color_state state, std::string stateStr)
{
setGtkColor(obj, set, VQTC_SECTION_BG, VQTC_NAME_HIGHLIGHT, state, GetBgColor(selector + stateStr));
setGtkColor(obj, set, VQTC_SECTION_FG, VQTC_NAME_HIGHLIGHT, state, GetFgColor(selector + stateStr + " GtkLabel#label"));
};
setFgBg(VQTC_STATE_NORMAL, ":selected");
setFgBg(VQTC_STATE_DISABLED, ":selected:disabled");
setFgBg(VQTC_STATE_HOVERED, ":selected:hover");
setFgBg(VQTC_STATE_PRESSED, ":selected:hover:active");
setFgBg(VQTC_STATE_FOCUSED, ":selected:focus");
}
picture_t* getThemeImage(vlc_qt_theme_provider_t* obj, vlc_qt_theme_image_type type, const vlc_qt_theme_image_setting* settings)
{
auto sys = static_cast<GtkPrivateThemeProvider*>(obj->p_sys);
if (type == VLC_QT_THEME_IMAGE_TYPE_CSD_BUTTON)
{
SetDeviceScaleFactor(settings->windowScaleFactor);
bool windowMaximized = settings->u.csdButton.maximized;
bool windowActive = settings->u.csdButton.active;
int bannerHeight = settings->u.csdButton.bannerHeight;
vlc_qt_theme_csd_button_state state = settings->u.csdButton.state;
vlc_qt_theme_csd_button_type buttonType = settings->u.csdButton.buttonType;
if (buttonType == VLC_QT_THEME_BUTTON_MAXIMIZE && windowMaximized)
buttonType = VLC_QT_THEME_BUTTON_RESTORE;
else if (buttonType == VLC_QT_THEME_BUTTON_RESTORE && !windowMaximized)
buttonType = VLC_QT_THEME_BUTTON_MAXIMIZE;
if (windowActive != sys->windowActive
|| windowMaximized != sys->windowMaximized
|| bannerHeight != sys->bannerHeight)
{
sys->navButtons.RedrawImages(bannerHeight, windowMaximized, windowActive);
sys->bannerHeight = bannerHeight;
sys->windowMaximized = windowMaximized;
sys->windowActive = windowActive;
sys->interNavButtonSpacing = sys->navButtons.GetInterNavButtonSpacing();
MyInset frameMargin = sys->navButtons.GetTopAreaSpacing();
sys->csdFrameMarginLeft = frameMargin.left();
sys->csdFrameMarginRight = frameMargin.right();
sys->csdFrameMarginTop = frameMargin.top();
sys->csdFrameMarginBottom = frameMargin.bottom();
if (obj->metricsUpdated)
obj->metricsUpdated(obj, VLC_QT_THEME_IMAGE_TYPE_CSD_BUTTON, obj->metricsUpdatedData);
}
picture_t* pic = sys->navButtons.GetImage(buttonType, state).get();
if (pic)
picture_Hold(pic);
return pic;
}
return nullptr;
}
static bool getThemeMetrics(vlc_qt_theme_provider_t* obj, vlc_qt_theme_image_type type, struct vlc_qt_theme_metrics* metrics)
{
auto sys = static_cast<GtkPrivateThemeProvider*>(obj->p_sys);
if (type != VLC_QT_THEME_IMAGE_TYPE_CSD_BUTTON)
return false;
metrics->u.csd.interNavButtonSpacing = sys->interNavButtonSpacing;
metrics->u.csd.csdFrameMarginLeft = sys->csdFrameMarginLeft;
metrics->u.csd.csdFrameMarginRight = sys->csdFrameMarginRight;
metrics->u.csd.csdFrameMarginTop = sys->csdFrameMarginTop;
metrics->u.csd.csdFrameMarginBottom = sys->csdFrameMarginBottom;
return true;
}
bool supportThemeImage(vlc_qt_theme_provider_t*, vlc_qt_theme_image_type type)
{
if (type == VLC_QT_THEME_IMAGE_TYPE_CSD_BUTTON)
return true;
return false;
}
static int updatePalette(vlc_qt_theme_provider_t* obj)
{
bool isDark = isThemeDark(obj);
GdkRGBA accent;
{
QColor qcAccent;
char* accentColor = var_InheritString(obj, "qt-accent-color");
assert(accentColor);
if (!strcmp(accentColor, "default"))
{
qcAccent = QColor( isDark ? "#FF8800" : "#FF610A" );
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
else if (!strcmp(accentColor, "system"))
{
assert(qApp);
const auto palette = qApp->palette();
qcAccent = palette.color(QPalette::Normal, QPalette::Accent);
}
#endif
else
{
qcAccent = QColor(accentColor);
}
free(accentColor);
gdk_rgba_parse(&accent, qcAccent.name(QColor::HexRgb).toLatin1().constData());
}
//IDK how to retrieve the shadow color from GTK, using a black like in our theme is good enough
GdkRGBA shadow;
shadow.red = shadow.green = shadow.blue = 0.f;
shadow.alpha = 0.22;
#define VIEW_SELECTOR "GtkListBox#list"
{
auto CS = VQTC_SET_VIEW;
std::string seletor = "GtkListBox#list";
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, VIEW_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_PRIMARY, VIEW_SELECTOR);
setGtkColorSetBg(obj, CS, VQTC_NAME_SECONDARY, VIEW_SELECTOR); //use same color
setGtkColorSetFg(obj, CS, VQTC_NAME_SECONDARY, VIEW_SELECTOR "GtkLabel#label.dim-label");
setGtkColorSetBorder(obj, CS, VIEW_SELECTOR);
setGtkColor(obj, CS, VQTC_SECTION_DECORATION, VQTC_NAME_ACCENT, VQTC_STATE_NORMAL, accent);
setGtkColor(obj, CS, VQTC_SECTION_DECORATION, VQTC_NAME_VISUAL_FOCUS, VQTC_STATE_NORMAL, GetFocusColor(VIEW_SELECTOR " GtkLabel#label"));
setGtkColor(obj, CS, VQTC_SECTION_DECORATION, VQTC_NAME_SEPARATOR, VQTC_STATE_NORMAL, GetSeparatorColor(VIEW_SELECTOR " GtkSeparator#separator.horizontal"));
setGtkColor(obj, CS, VQTC_SECTION_DECORATION, VQTC_NAME_SHADOW, VQTC_STATE_NORMAL, shadow);
}
#define POPUP_SELECTOR "GtkInfoBar#infobar"
{
auto CS = VQTC_SET_WINDOW;
setGtkColorSetBg(obj, CS, VQTC_NAME_NEGATIVE, POPUP_SELECTOR ".error #revealer #box");
setGtkColorSetFg(obj, CS, VQTC_NAME_NEGATIVE, POPUP_SELECTOR ".error #revealer #box");
setGtkColorSetBg(obj, CS, VQTC_NAME_NEUTRAL, POPUP_SELECTOR ".warning #revealer #box");
setGtkColorSetFg(obj, CS, VQTC_NAME_NEUTRAL, POPUP_SELECTOR ".warning #revealer #box");
setGtkColorSetBg(obj, CS, VQTC_NAME_POSITIVE, POPUP_SELECTOR ".success #revealer #box");
setGtkColorSetFg(obj, CS, VQTC_NAME_POSITIVE, POPUP_SELECTOR ".success #revealer #box");
#define TITLEBAR_SELECTOR "#window.background.csd GtkHeaderBar#headerbar.header-bar.titlebar"
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, TITLEBAR_SELECTOR);
setGtkColorSetBg(obj, CS, VQTC_NAME_SECONDARY, TITLEBAR_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_PRIMARY, TITLEBAR_SELECTOR);
setGtkColorSetBorder(obj, CS, TITLEBAR_SELECTOR);
setGtkColor(obj, CS, VQTC_SECTION_DECORATION, VQTC_NAME_SEPARATOR, VQTC_STATE_NORMAL, GetSeparatorColor(VIEW_SELECTOR " GtkSeparator#separator.horizontal"));
}
#define MENUBAR_SELECTOR TITLEBAR_SELECTOR " GtkMenuBar#menubar"
{
auto CS = VQTC_SET_MENUBAR;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, MENUBAR_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_PRIMARY, MENUBAR_SELECTOR " GtkLabel#menuitem");
GdkRGBA menubarbg = GetBgColor(MENUBAR_SELECTOR);
menubarbg.alpha = 0.0;
setGtkColor(obj, CS, VQTC_SECTION_BG, VQTC_NAME_PRIMARY, VQTC_STATE_NORMAL, menubarbg);
}
#define TOOLBUTTON_SELECTOR TITLEBAR_SELECTOR " GtkButton#button.toggle"
{
auto CS = VQTC_SET_TOOL_BUTTON;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, TOOLBUTTON_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_PRIMARY, TOOLBUTTON_SELECTOR);
setGtkColorSetBorder(obj, CS, TOOLBUTTON_SELECTOR);
setGtkColorSetBg(obj, CS, VQTC_NAME_NEGATIVE, TOOLBUTTON_SELECTOR ".error.destructive-action");
setGtkColorSetFg(obj, CS, VQTC_NAME_NEGATIVE, TOOLBUTTON_SELECTOR ".error.destructive-action");
setGtkColorSetBg(obj, CS, VQTC_NAME_NEUTRAL, TOOLBUTTON_SELECTOR ".warning");
setGtkColorSetFg(obj, CS, VQTC_NAME_NEUTRAL, TOOLBUTTON_SELECTOR ".warning");
setGtkColorSetBg(obj, CS, VQTC_NAME_POSITIVE, TOOLBUTTON_SELECTOR ".success");
setGtkColorSetFg(obj, CS, VQTC_NAME_POSITIVE, TOOLBUTTON_SELECTOR ".success");
}
#define TABBUTTON_SELECTOR TITLEBAR_SELECTOR " GtkBox#box.linked.stack-switcher.horizontal GtkButton#button.text-button"
{
auto CS = VQTC_SET_TAB_BUTTON;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, TABBUTTON_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_SECONDARY, TABBUTTON_SELECTOR ":checked");
setGtkColorSetBorder(obj, CS, TABBUTTON_SELECTOR);
//keep the background transparent in the tabbar in normal state, they look weird otherwise
GdkRGBA tabButtonNormalBg = GetBgColor(TITLEBAR_SELECTOR);
tabButtonNormalBg.alpha = 1.f;
setGtkColor(obj, CS, VQTC_SECTION_BG, VQTC_NAME_PRIMARY, VQTC_STATE_NORMAL, tabButtonNormalBg);
}
#define BUTTON_STANDARD_SELECTOR VIEW_SELECTOR " GtkButton#button.flat"
{
auto CS = VQTC_SET_BUTTON_STANDARD;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, BUTTON_STANDARD_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_PRIMARY, BUTTON_STANDARD_SELECTOR);
setGtkColorSetBorder(obj, CS, BUTTON_STANDARD_SELECTOR);
}
#define BUTTON_ACCENT_SELECTOR VIEW_SELECTOR " GtkButton#button.suggested-action"
{
auto CS = VQTC_SET_BUTTON_ACCENT;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, BUTTON_ACCENT_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_PRIMARY, BUTTON_ACCENT_SELECTOR);
setGtkColorSetBorder(obj, CS, BUTTON_ACCENT_SELECTOR);
}
#define TEXTFIELD_SELECTOR TITLEBAR_SELECTOR " GtkEntry#entry"
{
auto CS = VQTC_SET_TEXTFIELD;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, TEXTFIELD_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_PRIMARY, TEXTFIELD_SELECTOR);
setGtkColorSetBorder(obj, CS, TEXTFIELD_SELECTOR);
std::string textfield_hightlight_selector = std::string{TEXTFIELD_SELECTOR}
+ (GtkCheckVersion(3, 20) ? " GtkLabel#label #selection" : " GtkLabel#label:selected");
setGtkColor(obj, CS, VQTC_SECTION_BG, VQTC_NAME_HIGHLIGHT, VQTC_STATE_NORMAL,
GetSelectionBgColor(textfield_hightlight_selector));
setGtkColor(obj, CS, VQTC_SECTION_FG, VQTC_NAME_HIGHLIGHT, VQTC_STATE_NORMAL,
GetFgColor(textfield_hightlight_selector));
setGtkColorSetBg(obj, CS, VQTC_NAME_NEGATIVE, TEXTFIELD_SELECTOR ".error");
setGtkColorSetFg(obj, CS, VQTC_NAME_NEGATIVE, TEXTFIELD_SELECTOR ".error");
setGtkColorSetBg(obj, CS, VQTC_NAME_NEUTRAL, TEXTFIELD_SELECTOR ".warning");
setGtkColorSetFg(obj, CS, VQTC_NAME_NEUTRAL, TEXTFIELD_SELECTOR ".warning");
setGtkColorSetBg(obj, CS, VQTC_NAME_POSITIVE, TEXTFIELD_SELECTOR ".success");
setGtkColorSetFg(obj, CS, VQTC_NAME_POSITIVE, TEXTFIELD_SELECTOR ".success");
}
//use the .osd class as it will remove the transparency effect on the slider
#define SLIDER_SELECTOR "GtkProgressBar#progressbar.osd"
{
auto CS = VQTC_SET_SLIDER;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, SLIDER_SELECTOR);
#define SLIDER_PROGRESS_SELECTOR SLIDER_SELECTOR " #trough #progress"
setGtkColorSetFgFromBg(obj, CS, VQTC_NAME_PRIMARY, SLIDER_PROGRESS_SELECTOR);
setGtkColorSetBorder(obj, CS, SLIDER_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_NEUTRAL, SLIDER_PROGRESS_SELECTOR ".pulse ");
//use the destructive action button background color which should always be red
setGtkColor(obj, CS, VQTC_SECTION_FG, VQTC_NAME_NEGATIVE, VQTC_STATE_NORMAL, GetBgColor(TOOLBUTTON_SELECTOR ".error.destructive-action"));
}
//we may ask for accent variant but as far as I can tell, themes won't provide the variant
#define BADGE_SELECTOR VIEW_SELECTOR " GtkFrame#frame.osd"
{
auto CS = VQTC_SET_BADGE;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, BADGE_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_PRIMARY, BADGE_SELECTOR);
setGtkColorSetBorder(obj, CS, BADGE_SELECTOR);
}
{
auto CS = VQTC_SET_TOOLTIP;
std::string tooltipSelector = GtkCheckVersion(3, 20) ? "#tooltip.background"
: "GtkWindow#window.background.tooltip";
setGtkColor(obj, CS, VQTC_SECTION_BG, VQTC_NAME_PRIMARY, VQTC_STATE_NORMAL, GetBgColor(tooltipSelector));
setGtkColor(obj, CS, VQTC_SECTION_DECORATION, VQTC_NAME_BORDER, VQTC_STATE_NORMAL, GetBorderColor(tooltipSelector));
tooltipSelector += " GtkLabel#label";
setGtkColor(obj, CS, VQTC_SECTION_FG, VQTC_NAME_PRIMARY, VQTC_STATE_NORMAL, GetFgColor(tooltipSelector));
}
#define ITEM_SELECTOR VIEW_SELECTOR " GtkListBoxRow#row.activatable"
{
auto CS = VQTC_SET_ITEM;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, ITEM_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_PRIMARY, ITEM_SELECTOR);
setGtkColorSetBorder(obj, CS, ITEM_SELECTOR);
setGtkColorSetHighlight(obj, CS, ITEM_SELECTOR);
const auto separator = GetSeparatorColor(" GtkListBoxRow#separator.horizontal");
setGtkColor(obj, CS, VQTC_SECTION_DECORATION, VQTC_NAME_INDICATOR, VQTC_STATE_NORMAL, separator);
}
#define COMBOBOX_SELECTOR VIEW_SELECTOR " GtkComboBoxText#combobox #box.linked #entry.combo"
{
auto CS = VQTC_SET_COMBOBOX;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, COMBOBOX_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_PRIMARY, COMBOBOX_SELECTOR);
setGtkColorSetBorder(obj, CS, COMBOBOX_SELECTOR);
}
#define SPINBOX_SELECTOR VIEW_SELECTOR " GtkSpinButton#spinbutton.vertical"
{
auto CS = VQTC_SET_COMBOBOX;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, SPINBOX_SELECTOR);
setGtkColorSetFg(obj, CS, VQTC_NAME_PRIMARY, SPINBOX_SELECTOR);
setGtkColorSetBorder(obj, CS, SPINBOX_SELECTOR);
}
#define SWITCH_SELECTOR VIEW_SELECTOR " GtkSwitch#switch"
{
auto CS = VQTC_SET_SWITCH;
setGtkColorSetBg(obj, CS, VQTC_NAME_PRIMARY, SWITCH_SELECTOR);
setGtkColorSetFgFromBg(obj, CS, VQTC_NAME_PRIMARY, SWITCH_SELECTOR " #slider");
setGtkColorSetBg(obj, CS, VQTC_NAME_SECONDARY, SWITCH_SELECTOR ":checked");
setGtkColorSetFgFromBg(obj, CS, VQTC_NAME_SECONDARY, SWITCH_SELECTOR ":checked #slider");
setGtkColorSetBorder(obj, CS, SWITCH_SELECTOR);
}
return VLC_SUCCESS;
}
static void Close(vlc_qt_theme_provider_t* obj)
{
auto sys = static_cast<GtkPrivateThemeProvider*>(obj->p_sys);
delete sys;
}
static int Open(vlc_object_t* p_this)
{
vlc_qt_theme_provider_t* obj = (vlc_qt_theme_provider_t*)p_this;
std::once_flag flag;
std::call_once(flag, [](){
int argc = 0;
char** argv = nullptr;
gtk_init(&argc, &argv);
gdk_init(&argc, &argv);
//register types needed by g_type_from_name
g_type_class_unref(g_type_class_ref(gtk_button_get_type()));
g_type_class_unref(g_type_class_ref(gtk_entry_get_type()));
g_type_class_unref(g_type_class_ref(gtk_frame_get_type()));
g_type_class_unref(g_type_class_ref(gtk_header_bar_get_type()));
g_type_class_unref(g_type_class_ref(gtk_image_get_type()));
g_type_class_unref(g_type_class_ref(gtk_info_bar_get_type()));
g_type_class_unref(g_type_class_ref(gtk_label_get_type()));
g_type_class_unref(g_type_class_ref(gtk_menu_get_type()));
g_type_class_unref(g_type_class_ref(gtk_menu_bar_get_type()));
g_type_class_unref(g_type_class_ref(gtk_menu_item_get_type()));
g_type_class_unref(g_type_class_ref(gtk_range_get_type()));
g_type_class_unref(g_type_class_ref(gtk_scrollbar_get_type()));
g_type_class_unref(g_type_class_ref(gtk_scrolled_window_get_type()));
g_type_class_unref(g_type_class_ref(gtk_separator_get_type()));
g_type_class_unref(g_type_class_ref(gtk_spinner_get_type()));
g_type_class_unref(g_type_class_ref(gtk_text_view_get_type()));
g_type_class_unref(g_type_class_ref(gtk_toggle_button_get_type()));
g_type_class_unref(g_type_class_ref(gtk_tree_view_get_type()));
g_type_class_unref(g_type_class_ref(gtk_window_get_type()));
g_type_class_unref(g_type_class_ref(gtk_combo_box_text_get_type()));
g_type_class_unref(g_type_class_ref(gtk_cell_view_get_type()));
g_type_class_unref(g_type_class_ref(gtk_scale_get_type()));
g_type_class_unref(g_type_class_ref(gtk_progress_bar_get_type()));
g_type_class_unref(g_type_class_ref(gtk_overlay_get_type()));
g_type_class_unref(g_type_class_ref(gtk_list_box_get_type()));
g_type_class_unref(g_type_class_ref(gtk_list_box_row_get_type()));
g_type_class_unref(g_type_class_ref(gtk_spin_button_get_type()));
g_type_class_unref(g_type_class_ref(gtk_switch_get_type()));
});
auto sys = new (std::nothrow) GtkPrivateThemeProvider();
if (!sys)
return VLC_EGENERIC;
obj->p_sys = sys;
obj->close = Close;
obj->isThemeDark = isThemeDark;
obj->updatePalette = updatePalette;
obj->supportThemeImage = supportThemeImage;
obj->getThemeImage = getThemeImage;
obj->getThemeMetrics = getThemeMetrics;
return VLC_SUCCESS;
}
vlc_module_begin()
add_shortcut("qt-themeprovider-gtk")
set_description( "Qt GTK system theme" )
set_capability("qt theme provider", 0)
set_callback(Open)
vlc_module_end()
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet am 2026-11-04)
¤
*© Formatika GbR, Deutschland
|
|