##### Is your feature request related to a problem? Please describe <!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
The proposal is simple, improve Dark Mode. For example, the fact that on Windows Geany's Dark Mode does not change the color of the TitleBar is something that frustrates me
##### Describe the solution you'd like <!-- A clear and concise description of what you want to happen -->
For me, implementing [this would be enough](https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/ui/apply-wi...).
Since you are using GTK and not WinAPI to program windows (a pretty obvious choice since this project is not focused on Windows), the [`DwmSetWindowAttribute`](https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetw...) function will only work with the window handle. In other words, if you get the window handle using specific GTK functions, you can change the color of the Title Bar. You can also see what the system Color Mode is using the `ShouldAppsUseDarkMode` and `ShouldSystemUseDarkMode` functions.
[Geting Window Handler using GTK](https://stackoverflow.com/questions/9259731/getting-gtk-gdk-window-handle-on...) for exemple...
##### Describe alternatives you've considered <!-- A clear and concise description of any alternative solutions or features you've considered -->
I've already used the method of changing the color of the system's Title Bars, but it's not very cool or interesting as a solution... (but yes, it works)
##### Additional context <!-- Add any other context or screenshots about the feature request here -->
I already made a [similar issue](https://github.com/geany/geany/issues/4036), and it has already been resolved. But it is not the same issue. The big difference is that I would like the problem to be solved with code, within the project, and not on each user's computer (let's face it, having to change a part of the system for each installation just because of 1 application is not very cool...).
@GabrielFrigo4 I've just tried what you suggested in #4201. I don't have access to a Windows machine where I could try the result at the moment. Could you test the artifact at the bottom of
https://github.com/geany/geany/actions/runs/12727914414 ?
@GabrielFrigo4 I've just tried what you suggested in #4201. I don't have access to a Windows machine where I could try the result at the moment. Could you test the artifact at the bottom of
Sure, I can test it. But I'm away from the computer right now, so I'll test it in a few hours. How do I test it?
How do I test it?
Download the installer at the bottom of the page I linked, install Geany from it, and check if the title bar is dark when using the dark Windows theme.
@GabrielFrigo4 I've just tried what you suggested in #4201. I don't have access to a Windows machine where I could try the result at the moment. Could you test the artifact at the bottom of
The Title Bar remained White even with Dark Mode turned on (it kept the same behavior as the previous Geany version)
Well, no idea then. Maybe I did something wrong or something else happens in GTK that prevents setting the titlebar color. I'm not planning to spend more time on this.
Well, no idea then. Maybe I did something wrong or something else happens in GTK that prevents setting the titlebar color. I'm not planning to spend more time on this.
Well, I found a function that can help [`gdk_win32_window_get_handle`](https://discourse.gnome.org/t/getting-a-win32-window-handle-from-a-gtkwindow...). But if it doesn't work then I'll have to test and look deeper how to do it in GTK...
Apparently the macro GDK_WINDOW_HWND use [gdk_win32_window_get_handle](https://discourse.gnome.org/t/getting-a-win32-window-handle-from-a-gtkwindow...).
This is what I did in #4201 - the `GDK_WINDOW_HWND()` macro expands to `gdk_win32_window_get_handle()`.
@GabrielFrigo4 I've just tried what you suggested in #4201. I don't have access to a Windows machine where I could try the result at the moment. Could you test the artifact at the bottom of
I think I found the error I made two small codes, Code1 and Code2. Code1 worked and Code2 gave `Failed to get GdkWindow from GtkWidget.``
### Code1 (Ok) ```c #include <gtk/gtk.h> #include <windows.h> #include <dwmapi.h> #include <gdk/gdkwin32.h>
void enable_dark_titlebar(GtkWidget *window) { GdkWindow *gdk_window = gtk_widget_get_window(window); if (gdk_window) { HWND hwnd = (HWND)gdk_win32_window_get_handle(gdk_window); if (hwnd) { BOOL use_dark_mode = TRUE; DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &use_dark_mode, sizeof(use_dark_mode)); } else { g_warning("Failed to get HWND from GdkWindow."); } } else { g_warning("Failed to get GdkWindow from GtkWidget."); } }
int main(int argc, char *argv[]) { GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Dark Mode Title Bar"); gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
// After *gtk_widget_show_all(window);* enable_dark_titlebar(window);
gtk_main();
return 0; } ```
### Code2 (Failed) ```c #include <gtk/gtk.h> #include <windows.h> #include <dwmapi.h> #include <gdk/gdkwin32.h>
void enable_dark_titlebar(GtkWidget *window) { GdkWindow *gdk_window = gtk_widget_get_window(window); if (gdk_window) { HWND hwnd = (HWND)gdk_win32_window_get_handle(gdk_window); if (hwnd) { BOOL use_dark_mode = TRUE; DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &use_dark_mode, sizeof(use_dark_mode)); } else { g_warning("Failed to get HWND from GdkWindow."); } } else { g_warning("Failed to get GdkWindow from GtkWidget."); } }
int main(int argc, char *argv[]) { GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Dark Mode Title Bar"); gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
// Before *gtk_widget_show_all(window);* enable_dark_titlebar(window);
gtk_widget_show_all(window);
gtk_main();
return 0; } ```
### Change only when it is Dark Theme
However, Code1 has an error: It will always leave the Title Bar in Dark Mode, regardless of the theme that the User left in Windows.
To do this, we simply use the functions `RegOpenKeyA` (Since this type of information is saved in the Windows registry... And functions like `ShouldAppsUseDarkMode` and `ShouldSystemUseDarkMode` are not documented and may change location in memory and ruin the program's startup later...)
### Code3 (Completely OK) ```c #include <gtk/gtk.h> #include <windows.h> #include <dwmapi.h> #include <gdk/gdkwin32.h>
BOOL ShouldAppsUseDarkMode() { BOOL isLight = TRUE; DWORD val, dataSize = sizeof(val); if (RegGetValueA(HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", RRF_RT_DWORD, NULL, &val, &dataSize) == ERROR_SUCCESS) { isLight = val; } else { g_warning("Failed to get AppsUseLightTheme from Reg."); } return !isLight; }
void enable_dark_titlebar(GtkWidget *window) { GdkWindow *gdk_window = gtk_widget_get_window(window); if (gdk_window) { HWND hwnd = (HWND)gdk_win32_window_get_handle(gdk_window); if (hwnd) { BOOL use_dark_mode = ShouldAppsUseDarkMode(); DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &use_dark_mode, sizeof(use_dark_mode)); } else { g_warning("Failed to get HWND from GdkWindow."); } } else { g_warning("Failed to get GdkWindow from GtkWidget."); } }
int main(int argc, char *argv[]) { GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Dark Mode Title Bar"); gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
enable_dark_titlebar(window);
gtk_main();
return 0; } ```
@GabrielFrigo4 Thanks! I thought that the window titlebar color update has to be performed before the window is shown - I was apparently wrong.
Based on your experiments, I've just created
https://github.com/geany/geany/pull/4205
Could you test it? I've written it completely in linux so no idea if it works.
Forgot to mention, the artifact to test is here: https://github.com/geany/geany/actions/runs/12777183780/
Forgot to mention, the artifact to test is here: https://github.com/geany/geany/actions/runs/12777183780/
It worked perfectly :) But I think there is one more adjustment, which is to make the Title Bar change to Dark Mode work before calling the GTK Show function. Since calling it afterwards causes a small (really small) transition period between Light Mode and Dark Mode in the Title Bar (yes, the previous error was exactly calling the function before calling the GTK Show function). If this is not possible, then we are already at the best level.
I found the reason why it didn't work before the `gtk_widget_show_all` call
Basically, the `gtk_widget_show_all` function creates the `GdkWindow`, since to create the `GdkWindow` you need to realize the `GtkWindow`, which the `gtk_widget_show_all` function does. But there are other functions that realize the `GtkWindow`, one of them is `gtk_widget_realize`, which only realize the `GtkWindow`, without showing the window or anything else. So if we call `gtk_widget_realize` before the `gtk_widget_get_window` function, we can get the `GdkWindow`.
So the __Perfect Code__ is
### Perfect Code ```c #include <gtk/gtk.h> #include <windows.h> #include <dwmapi.h> #include <gdk/gdkwin32.h>
BOOL ShouldAppsUseDarkMode() { BOOL isLight = TRUE; DWORD val, dataSize = sizeof(val); const char *REG_PATH = "Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"; const char *REG_VAR = "AppsUseLightTheme"; if (RegGetValueA(HKEY_CURRENT_USER, REG_PATH, REG_VAR, RRF_RT_DWORD, NULL, &val, &dataSize) == ERROR_SUCCESS) { isLight = val; } else { g_warning("Failed to get AppsUseLightTheme from Reg."); } return !isLight; }
void current_mode_titlebar(GtkWidget *window) { GdkWindow *gdk_window = gtk_widget_get_window(window); if (gdk_window) { HWND hwnd = (HWND)gdk_win32_window_get_handle(gdk_window); if (hwnd) { BOOL use_dark_mode = ShouldAppsUseDarkMode(); DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &use_dark_mode, sizeof(use_dark_mode)); } else { g_warning("Failed to get HWND from GdkWindow."); } } else { g_warning("Failed to get GdkWindow from GtkWidget."); } }
int main(int argc, char *argv[]) { GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Dark Mode Title Bar"); gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_realize(window); current_mode_titlebar(window);
gtk_widget_show_all(window);
gtk_main();
return 0; } ```
Thanks. I tried to implement what you suggest, the build to test is here:
https://github.com/geany/geany/actions/runs/12790085866
Thanks. I tried to implement what you suggest, the build to test is here:
It is working perfectly. Thank you :)
Closed #4200 as completed.
Reopened #4200.
Reopening since the PR is not merged yet. I'll wait for what others think about it.
github-comments@lists.geany.org