aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2023-01-12 15:30:44 -0500
committerDavid Robillard <d@drobilla.net>2023-01-14 11:53:28 -0500
commit1e48f8bbfdb0f1ce2f9132d604405fb72d160d9d (patch)
tree2fbb2e70f5bf5e7f7e021dafb51dd508944426f2
parentbd4f79646f623e929e6aa22bea028952b515aeef (diff)
downloadpugl-1e48f8bbfdb0f1ce2f9132d604405fb72d160d9d.tar.gz
pugl-1e48f8bbfdb0f1ce2f9132d604405fb72d160d9d.tar.bz2
pugl-1e48f8bbfdb0f1ce2f9132d604405fb72d160d9d.zip
Windows: Add PUGL_DARK_FRAME hint
This allows dark applications to visually integrate more nicely in Windows 10. A little thing, but it really goes a long way to make programs not look out of place and half-baked.
-rw-r--r--bindings/cpp/include/pugl/pugl.hpp4
-rw-r--r--examples/pugl_management_demo.c11
-rw-r--r--examples/pugl_shader_demo.c1
-rw-r--r--examples/pugl_vulkan_cpp_demo.cpp1
-rw-r--r--include/pugl/pugl.h3
-rw-r--r--meson.build3
-rw-r--r--src/win.c20
-rw-r--r--test/test_utils.h2
8 files changed, 38 insertions, 7 deletions
diff --git a/bindings/cpp/include/pugl/pugl.hpp b/bindings/cpp/include/pugl/pugl.hpp
index 90c5de6..257ccd2 100644
--- a/bindings/cpp/include/pugl/pugl.hpp
+++ b/bindings/cpp/include/pugl/pugl.hpp
@@ -378,9 +378,11 @@ enum class ViewHint {
ignoreKeyRepeat, ///< @copydoc PUGL_IGNORE_KEY_REPEAT
refreshRate, ///< @copydoc PUGL_REFRESH_RATE
viewType, ///< @copydoc PUGL_VIEW_TYPE
+ darkFrame, ///< @copydoc PUGL_DARK_FRAME
};
-static_assert(static_cast<ViewHint>(PUGL_VIEW_TYPE) == ViewHint::viewType, "");
+static_assert(static_cast<ViewHint>(PUGL_DARK_FRAME) == ViewHint::darkFrame,
+ "");
using ViewHintValue = PuglViewHintValue; ///< @copydoc PuglViewHintValue
diff --git a/examples/pugl_management_demo.c b/examples/pugl_management_demo.c
index 30a026e..766bee1 100644
--- a/examples/pugl_management_demo.c
+++ b/examples/pugl_management_demo.c
@@ -50,20 +50,20 @@ onExpose(PuglView* const view, const PuglExposeEvent* const event)
cairo_clip_preserve(cr);
// Draw background
- cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
+ cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
cairo_set_line_width(cr, 4.0);
cairo_fill(cr);
// Set up text renering
char buf[128] = {0};
cairo_text_extents_t extents = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
- cairo_set_font_size(cr, 32.0);
+ cairo_set_font_size(cr, 30.0);
// Draw time label
snprintf(buf, sizeof(buf), "Draw time: %g", puglGetTime(world));
cairo_text_extents(cr, buf, &extents);
cairo_move_to(cr, cx - extents.width / 2.0, cy + extents.height / 2.0 - 48.0);
- cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+ cairo_set_source_rgb(cr, 0.9, 0.9, 0.9);
cairo_show_text(cr, buf);
// Draw style label
@@ -112,13 +112,15 @@ toggleDialog(DemoApp* const app)
puglSetHandle(app->dialogView.view, &app->dialogView);
puglSetTransientParent(app->dialogView.view,
puglGetNativeView(app->mainView.view));
+
+ puglSetViewString(app->dialogView.view, PUGL_WINDOW_TITLE, "Dialog");
+ puglSetViewHint(app->dialogView.view, PUGL_DARK_FRAME, PUGL_TRUE);
puglSetSizeHint(app->dialogView.view, PUGL_DEFAULT_SIZE, 320, 240);
puglSetSizeHint(app->dialogView.view, PUGL_MIN_SIZE, 160, 120);
puglSetViewHint(app->dialogView.view, PUGL_IGNORE_KEY_REPEAT, true);
puglSetViewHint(app->dialogView.view, PUGL_RESIZABLE, true);
puglSetViewHint(
app->dialogView.view, PUGL_VIEW_TYPE, PUGL_VIEW_TYPE_DIALOG);
- puglSetViewString(app->dialogView.view, PUGL_WINDOW_TITLE, "Dialog");
}
return puglShow(app->dialogView.view, PUGL_SHOW_RAISE);
@@ -240,6 +242,7 @@ main(int argc, char** argv)
puglSetHandle(app.mainView.view, &app.mainView);
puglSetSizeHint(app.mainView.view, PUGL_DEFAULT_SIZE, 640, 480);
puglSetSizeHint(app.mainView.view, PUGL_MIN_SIZE, 320, 240);
+ puglSetViewHint(app.mainView.view, PUGL_DARK_FRAME, PUGL_TRUE);
puglSetViewHint(app.mainView.view, PUGL_IGNORE_KEY_REPEAT, true);
puglSetViewHint(app.mainView.view, PUGL_RESIZABLE, true);
puglSetViewHint(app.mainView.view, PUGL_VIEW_TYPE, PUGL_VIEW_TYPE_NORMAL);
diff --git a/examples/pugl_shader_demo.c b/examples/pugl_shader_demo.c
index 5773a9d..5cd9c7c 100644
--- a/examples/pugl_shader_demo.c
+++ b/examples/pugl_shader_demo.c
@@ -265,6 +265,7 @@ setupPugl(PuglTestApp* app)
puglSetViewHint(app->view, PUGL_DOUBLE_BUFFER, app->opts.doubleBuffer);
puglSetViewHint(app->view, PUGL_SWAP_INTERVAL, app->opts.sync);
puglSetViewHint(app->view, PUGL_IGNORE_KEY_REPEAT, PUGL_TRUE);
+ puglSetViewHint(app->view, PUGL_DARK_FRAME, PUGL_TRUE);
puglSetHandle(app->view, app);
puglSetEventFunc(app->view, onEvent);
}
diff --git a/examples/pugl_vulkan_cpp_demo.cpp b/examples/pugl_vulkan_cpp_demo.cpp
index 7e652a5..2cfb1e8 100644
--- a/examples/pugl_vulkan_cpp_demo.cpp
+++ b/examples/pugl_vulkan_cpp_demo.cpp
@@ -1719,6 +1719,7 @@ run(const char* const programPath,
app.view.setSizeHint(pugl::SizeHint::minSize, width / 4U, height / 4U);
app.view.setBackend(pugl::vulkanBackend());
app.view.setHint(pugl::ViewHint::resizable, opts.resizable);
+ app.view.setHint(pugl::ViewHint::darkFrame, true);
const pugl::Status st = app.view.realize();
if (st != pugl::Status::success) {
return logError("Failed to create window (%s)\n", pugl::strerror(st));
diff --git a/include/pugl/pugl.h b/include/pugl/pugl.h
index 4427c5a..801ae3c 100644
--- a/include/pugl/pugl.h
+++ b/include/pugl/pugl.h
@@ -923,10 +923,11 @@ typedef enum {
PUGL_IGNORE_KEY_REPEAT, ///< True if key repeat events are ignored
PUGL_REFRESH_RATE, ///< Refresh rate in Hz
PUGL_VIEW_TYPE, ///< View type (a #PuglViewType)
+ PUGL_DARK_FRAME, ///< True if window frame should be dark
} PuglViewHint;
/// The number of #PuglViewHint values
-#define PUGL_NUM_VIEW_HINTS ((unsigned)PUGL_VIEW_TYPE + 1U)
+#define PUGL_NUM_VIEW_HINTS ((unsigned)PUGL_DARK_FRAME + 1U)
/// A special view hint value
typedef enum {
diff --git a/meson.build b/meson.build
index 652cd77..63f14bb 100644
--- a/meson.build
+++ b/meson.build
@@ -99,10 +99,11 @@ elif host_machine.system() == 'windows'
user32_dep = cc.find_library('user32')
shlwapi_dep = cc.find_library('shlwapi')
+ dwmapi_dep = cc.find_library('dwmapi')
platform = 'win'
platform_sources = files('src/win.c')
- core_deps = [user32_dep, shlwapi_dep]
+ core_deps = [user32_dep, shlwapi_dep, dwmapi_dep]
extension = '.c'
else # X11
diff --git a/src/win.c b/src/win.c
index db3f98c..e9c621e 100644
--- a/src/win.c
+++ b/src/win.c
@@ -8,6 +8,7 @@
#include "pugl/pugl.h"
+#include <dwmapi.h>
#include <windows.h>
#include <windowsx.h>
@@ -30,6 +31,11 @@
# define GWLP_USERDATA (-21)
#endif
+#define PRE_20H1_DWMWA_USE_IMMERSIVE_DARK_MODE 19
+#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
+# define DWMWA_USE_IMMERSIVE_DARK_MODE 20
+#endif
+
#define PUGL_LOCAL_CLOSE_MSG (WM_USER + 50)
#define PUGL_LOCAL_MARK_MSG (WM_USER + 51)
#define PUGL_LOCAL_CLIENT_MSG (WM_USER + 52)
@@ -280,12 +286,26 @@ puglRealize(PuglView* view)
}
// Set basic window hints and attributes
+
puglSetViewString(view, PUGL_WINDOW_TITLE, view->strings[PUGL_WINDOW_TITLE]);
puglSetTransientParent(view, view->transientParent);
view->impl->scaleFactor = puglWinGetViewScaleFactor(view);
view->impl->cursor = LoadCursor(NULL, IDC_ARROW);
+ if (view->hints[PUGL_DARK_FRAME]) {
+ const BOOL useDarkMode = TRUE;
+ if ((DwmSetWindowAttribute(view->impl->hwnd,
+ DWMWA_USE_IMMERSIVE_DARK_MODE,
+ &useDarkMode,
+ sizeof(useDarkMode)) != S_OK)) {
+ DwmSetWindowAttribute(view->impl->hwnd,
+ PRE_20H1_DWMWA_USE_IMMERSIVE_DARK_MODE,
+ &useDarkMode,
+ sizeof(useDarkMode));
+ }
+ }
+
SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);
return puglDispatchSimpleEvent(view, PUGL_REALIZE);
diff --git a/test/test_utils.h b/test/test_utils.h
index e26e970..785c8c7 100644
--- a/test/test_utils.h
+++ b/test/test_utils.h
@@ -296,6 +296,8 @@ puglViewHintString(const PuglViewHint hint)
return "Refresh rate";
case PUGL_VIEW_TYPE:
return "View type";
+ case PUGL_DARK_FRAME:
+ return "Dark frame";
}
return "Unknown";