mirror of https://github.com/GNOME/gimp.git
gui: Change Windows title bar based on theme
On Windows, the title bar can be set to light or dark mode via DwmSetWindowAttribute (). This adds code to update the main title bar and dialogue title bars based on the current theme. The main title bar uses "prefer-dark-theme", while the dialogue title bars uses the color of the widget background to assume the correct color.
This commit is contained in:
parent
bf8ee69570
commit
ad8b47bff7
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include "config/gimpcoreconfig.h"
|
||||
|
||||
#include "widgets/gimpwidgets-utils.h"
|
||||
|
||||
#include "about.h"
|
||||
#include "git-version.h"
|
||||
|
||||
|
@ -50,23 +52,25 @@
|
|||
|
||||
typedef struct
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *dialog;
|
||||
|
||||
Gimp *gimp;
|
||||
|
||||
GtkWidget *update_frame;
|
||||
GimpCoreConfig *config;
|
||||
|
||||
GtkWidget *anim_area;
|
||||
PangoLayout *layout;
|
||||
GtkWidget *anim_area;
|
||||
PangoLayout *layout;
|
||||
|
||||
gint n_authors;
|
||||
gint shuffle[G_N_ELEMENTS (authors) - 1]; /* NULL terminated */
|
||||
gint n_authors;
|
||||
gint shuffle[G_N_ELEMENTS (authors) - 1]; /* NULL terminated */
|
||||
|
||||
guint timer;
|
||||
guint timer;
|
||||
|
||||
gint index;
|
||||
gint animstep;
|
||||
gint state;
|
||||
gboolean visible;
|
||||
gint index;
|
||||
gint animstep;
|
||||
gint state;
|
||||
gboolean visible;
|
||||
} GimpAboutDialog;
|
||||
|
||||
|
||||
|
@ -99,7 +103,8 @@ static void about_dialog_download_clicked
|
|||
const gchar *link);
|
||||
|
||||
GtkWidget *
|
||||
about_dialog_create (GimpCoreConfig *config)
|
||||
about_dialog_create (Gimp *gimp,
|
||||
GimpCoreConfig *config)
|
||||
{
|
||||
static GimpAboutDialog dialog;
|
||||
|
||||
|
@ -112,6 +117,7 @@ about_dialog_create (GimpCoreConfig *config)
|
|||
gchar *copyright;
|
||||
gchar *version;
|
||||
|
||||
dialog.gimp = gimp;
|
||||
dialog.n_authors = G_N_ELEMENTS (authors) - 1;
|
||||
dialog.config = config;
|
||||
|
||||
|
@ -206,6 +212,10 @@ about_dialog_map (GtkWidget *widget,
|
|||
|
||||
dialog->timer = g_timeout_add (800, about_dialog_timer, dialog);
|
||||
}
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
gimp_window_set_title_bar_theme (dialog->gimp, widget, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
#define __ABOUT_DIALOG_H__
|
||||
|
||||
|
||||
GtkWidget * about_dialog_create (GimpCoreConfig *config);
|
||||
GtkWidget * about_dialog_create (Gimp *gimp,
|
||||
GimpCoreConfig *config);
|
||||
|
||||
|
||||
#endif /* __ABOUT_DIALOG_H__ */
|
||||
|
|
|
@ -217,7 +217,7 @@ dialogs_about_get (GimpDialogFactory *factory,
|
|||
GimpUIManager *ui_manager,
|
||||
gint view_size)
|
||||
{
|
||||
return about_dialog_create (context->gimp->edit_config);
|
||||
return about_dialog_create (context->gimp, context->gimp->edit_config);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
|
|
|
@ -435,14 +435,18 @@ gimp_update_about_dialog (GimpCoreConfig *config,
|
|||
const GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
#ifndef GIMP_CONSOLE_COMPILATION
|
||||
Gimp *gimp = user_data;
|
||||
#endif
|
||||
|
||||
g_signal_handlers_disconnect_by_func (config,
|
||||
(GCallback) gimp_update_about_dialog,
|
||||
NULL);
|
||||
user_data);
|
||||
|
||||
if (config->last_known_release != NULL)
|
||||
{
|
||||
#ifndef GIMP_CONSOLE_COMPILATION
|
||||
gtk_widget_show (about_dialog_create (config));
|
||||
gtk_widget_show (about_dialog_create (gimp, config));
|
||||
#else
|
||||
g_printerr (_("A new version of GIMP (%s) was released.\n"
|
||||
"It is recommended to update."),
|
||||
|
@ -639,7 +643,7 @@ gimp_update_auto_check (GimpCoreConfig *config,
|
|||
|
||||
g_signal_connect (config, "notify::last-known-release",
|
||||
(GCallback) gimp_update_about_dialog,
|
||||
NULL);
|
||||
gimp);
|
||||
|
||||
gimp_update_check (config);
|
||||
|
||||
|
|
|
@ -617,6 +617,10 @@ gui_restore_after_callback (Gimp *gimp,
|
|||
|
||||
shell = gimp_display_get_shell (display);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
themes_set_title_bar (gimp);
|
||||
#endif
|
||||
|
||||
if (gui_config->restore_session)
|
||||
session_restore (gimp, initial_monitor);
|
||||
|
||||
|
@ -624,7 +628,7 @@ gui_restore_after_callback (Gimp *gimp,
|
|||
|
||||
#ifdef G_OS_WIN32
|
||||
/* Prevents window from reappearing on start-up if the user
|
||||
* requested it to be minimized via window hints
|
||||
* requested it to be minimized via window hints
|
||||
*/
|
||||
if (StartupInfo.wShowWindow != SW_SHOWMINIMIZED &&
|
||||
StartupInfo.wShowWindow != SW_SHOWMINNOACTIVE &&
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
|
||||
#include "core/gimp.h"
|
||||
|
||||
#include "display/gimpimagewindow.h"
|
||||
|
||||
#include "widgets/gimpwidgets-utils.h"
|
||||
|
||||
#include "themes.h"
|
||||
|
||||
#include "gimp-intl.h"
|
||||
|
@ -105,6 +109,10 @@ themes_init (Gimp *gimp)
|
|||
gimp);
|
||||
|
||||
themes_theme_change_notify (config, NULL, gimp);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
themes_set_title_bar (gimp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -469,6 +477,10 @@ themes_theme_change_notify (GimpGuiConfig *config,
|
|||
g_object_unref (theme_css);
|
||||
|
||||
gtk_style_context_reset_widgets (gdk_screen_get_default ());
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
themes_set_title_bar (gimp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -549,3 +561,22 @@ themes_theme_paths_notify (GimpExtensionManager *manager,
|
|||
g_list_free_full (path, (GDestroyNotify) g_object_unref);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
themes_set_title_bar (Gimp *gimp)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
GList *windows = gimp_get_image_windows (gimp);
|
||||
GList *iter;
|
||||
|
||||
for (iter = windows; iter; iter = g_list_next (iter))
|
||||
{
|
||||
GtkWidget *window = GTK_WIDGET (windows->data);
|
||||
|
||||
gimp_window_set_title_bar_theme (gimp, window, TRUE);
|
||||
}
|
||||
|
||||
if (windows)
|
||||
g_list_free (windows);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -30,5 +30,6 @@ GFile * themes_get_theme_file (Gimp *gimp,
|
|||
const gchar *first_component,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
void themes_set_title_bar (Gimp *gimp);
|
||||
|
||||
#endif /* __THEMES_H__ */
|
||||
|
|
|
@ -86,6 +86,8 @@ static gboolean gimp_file_dialog_delete_event (GtkWidget *w
|
|||
GdkEventAny *event);
|
||||
static void gimp_file_dialog_response (GtkDialog *dialog,
|
||||
gint response_id);
|
||||
static void gimp_file_dialog_map (GimpFileDialog *dialog,
|
||||
gpointer data);
|
||||
static GFile * gimp_file_dialog_real_get_default_folder (GimpFileDialog *dialog);
|
||||
static void gimp_file_dialog_real_save_state (GimpFileDialog *dialog,
|
||||
const gchar *state_name);
|
||||
|
@ -225,6 +227,11 @@ gimp_file_dialog_class_init (GimpFileDialogClass *klass)
|
|||
static void
|
||||
gimp_file_dialog_init (GimpFileDialog *dialog)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
g_signal_connect (dialog, "map",
|
||||
G_CALLBACK (gimp_file_dialog_map),
|
||||
NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -420,6 +427,15 @@ gimp_file_dialog_response (GtkDialog *dialog,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_file_dialog_map (GimpFileDialog *dialog,
|
||||
gpointer data)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
gimp_window_set_title_bar_theme (dialog->gimp, GTK_WIDGET (dialog), FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static GFile *
|
||||
gimp_file_dialog_real_get_default_folder (GimpFileDialog *dialog)
|
||||
{
|
||||
|
|
|
@ -26,7 +26,12 @@
|
|||
#include <gtk/gtk.h>
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <dwmapi.h>
|
||||
#include <gdk/gdkwin32.h>
|
||||
|
||||
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
||||
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
|
@ -51,6 +56,8 @@
|
|||
|
||||
#include "gegl/gimp-babl.h"
|
||||
|
||||
#include "config/gimpguiconfig.h"
|
||||
|
||||
#include "core/gimp.h"
|
||||
#include "core/gimpprogress.h"
|
||||
#include "core/gimptoolinfo.h"
|
||||
|
@ -2616,3 +2623,59 @@ gimp_window_set_transient_cb (GtkWidget *window,
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
gimp_window_set_title_bar_theme (Gimp *gimp,
|
||||
GtkWidget *dialog,
|
||||
gboolean is_main_window)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
HWND hwnd;
|
||||
GdkWindow *window = NULL;
|
||||
gboolean use_dark_mode = FALSE;
|
||||
|
||||
window = gtk_widget_get_window (GTK_WIDGET (dialog));
|
||||
if (window)
|
||||
{
|
||||
if (gimp)
|
||||
{
|
||||
GimpGuiConfig *config;
|
||||
|
||||
config = GIMP_GUI_CONFIG (gimp->config);
|
||||
use_dark_mode = config->prefer_dark_theme;
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkStyleContext *style;
|
||||
GdkRGBA *color = NULL;
|
||||
|
||||
/* Workaround if we don't have access to GimpGuiConfig.
|
||||
* If the background color is below the threshold, then we're
|
||||
* likely in dark mode.
|
||||
*/
|
||||
style = gtk_widget_get_style_context (dialog);
|
||||
gtk_style_context_get (style, gtk_style_context_get_state (style),
|
||||
GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &color,
|
||||
NULL);
|
||||
if (color)
|
||||
{
|
||||
if (color->red < 0.5 && color->green < 0.5 && color->blue < 0.5)
|
||||
use_dark_mode = TRUE;
|
||||
|
||||
gdk_rgba_free (color);
|
||||
}
|
||||
}
|
||||
|
||||
hwnd = (HWND) gdk_win32_window_get_handle (window);
|
||||
DwmSetWindowAttribute (hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE,
|
||||
&use_dark_mode, sizeof (use_dark_mode));
|
||||
|
||||
if (! is_main_window)
|
||||
{
|
||||
/* Toggle the window's visibility so the title bar change appears */
|
||||
gdk_window_hide (window);
|
||||
gdk_window_show (window);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -165,5 +165,9 @@ gboolean gimp_utils_are_menu_path_identical (const gchar *path1
|
|||
gchar **mnemonic_path1,
|
||||
gchar **path1_section_name);
|
||||
|
||||
void gimp_window_set_title_bar_theme (Gimp *gimp,
|
||||
GtkWidget *dialog,
|
||||
gboolean is_main_window);
|
||||
|
||||
|
||||
#endif /* __APP_GIMP_WIDGETS_UTILS_H__ */
|
||||
|
|
|
@ -34,6 +34,14 @@
|
|||
|
||||
#include "libgimp/libgimp-intl.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <dwmapi.h>
|
||||
#include <gdk/gdkwin32.h>
|
||||
|
||||
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
||||
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION: gimpdialog
|
||||
|
@ -67,27 +75,28 @@ struct _GimpDialogPrivate
|
|||
#define GET_PRIVATE(obj) (((GimpDialog *) (obj))->priv)
|
||||
|
||||
|
||||
static void gimp_dialog_constructed (GObject *object);
|
||||
static void gimp_dialog_dispose (GObject *object);
|
||||
static void gimp_dialog_finalize (GObject *object);
|
||||
static void gimp_dialog_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gimp_dialog_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gimp_dialog_constructed (GObject *object);
|
||||
static void gimp_dialog_dispose (GObject *object);
|
||||
static void gimp_dialog_finalize (GObject *object);
|
||||
static void gimp_dialog_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gimp_dialog_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void gimp_dialog_hide (GtkWidget *widget);
|
||||
static gboolean gimp_dialog_delete_event (GtkWidget *widget,
|
||||
GdkEventAny *event);
|
||||
static void gimp_dialog_hide (GtkWidget *widget);
|
||||
static gboolean gimp_dialog_delete_event (GtkWidget *widget,
|
||||
GdkEventAny *event);
|
||||
|
||||
static void gimp_dialog_close (GtkDialog *dialog);
|
||||
static void gimp_dialog_close (GtkDialog *dialog);
|
||||
|
||||
static void gimp_dialog_response (GtkDialog *dialog,
|
||||
gint response_id);
|
||||
static void gimp_dialog_response (GtkDialog *dialog,
|
||||
gint response_id);
|
||||
|
||||
static void gimp_dialog_set_title_bar_theme (GtkWidget *dialog);
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GimpDialog, gimp_dialog, GTK_TYPE_DIALOG)
|
||||
|
||||
|
@ -161,6 +170,12 @@ gimp_dialog_init (GimpDialog *dialog)
|
|||
g_signal_connect (dialog, "response",
|
||||
G_CALLBACK (gimp_dialog_response),
|
||||
NULL);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
g_signal_connect (GTK_WIDGET (dialog), "map",
|
||||
G_CALLBACK (gimp_dialog_set_title_bar_theme),
|
||||
NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -656,6 +671,10 @@ gimp_dialog_run (GimpDialog *dialog)
|
|||
|
||||
gtk_window_present (GTK_WINDOW (dialog));
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
gimp_dialog_set_title_bar_theme (GTK_WIDGET (dialog));
|
||||
#endif
|
||||
|
||||
response_handler = g_signal_connect (dialog, "response",
|
||||
G_CALLBACK (run_response_handler),
|
||||
&ri);
|
||||
|
@ -750,3 +769,46 @@ gimp_dialogs_show_help_button (gboolean show)
|
|||
{
|
||||
show_help_button = show ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_dialog_set_title_bar_theme (GtkWidget *dialog)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
HWND hwnd;
|
||||
gboolean use_dark_mode = FALSE;
|
||||
GdkWindow *window = NULL;
|
||||
|
||||
window = gtk_widget_get_window (GTK_WIDGET (dialog));
|
||||
if (window)
|
||||
{
|
||||
GtkStyleContext *style;
|
||||
GdkRGBA *color = NULL;
|
||||
|
||||
hwnd = (HWND) gdk_win32_window_get_handle (window);
|
||||
/* Workaround since we don't have access to GimpGuiConfig.
|
||||
* If the background color is below the threshold, then we're
|
||||
* likely in dark mode.
|
||||
*/
|
||||
style = gtk_widget_get_style_context (GTK_WIDGET (dialog));
|
||||
gtk_style_context_get (style, gtk_style_context_get_state (style),
|
||||
GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &color,
|
||||
NULL);
|
||||
if (color)
|
||||
{
|
||||
if (color->red < 0.5 && color->green < 0.5 && color->blue < 0.5)
|
||||
use_dark_mode = TRUE;
|
||||
|
||||
gdk_rgba_free (color);
|
||||
}
|
||||
|
||||
DwmSetWindowAttribute (hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE,
|
||||
&use_dark_mode, sizeof (use_dark_mode));
|
||||
UpdateWindow (hwnd);
|
||||
ShowWindow (hwnd, 5);
|
||||
|
||||
/* Toggle the window's visibility so the title bar change appears */
|
||||
gdk_window_hide (window);
|
||||
gdk_window_show (window);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue