Skip to content

Commit 0f5b956

Browse files
committed
C++: Expose raw window handle API
We had the raw_window_handle_06 feature and functions in Rust, but there wasn't an easy way to do the same in C++. This is especially useful for embedding windows (such as browsers, 3D views, etc.) or just wanting to access the platform's handles for other reasons. Similar to Rust, you need to enable a specific non-default feature for this API. I re-used the existing NativeWindowHandle struct for this, moving it out of slint-platform.h and adding getters to it.
1 parent 1f8ef60 commit 0f5b956

File tree

8 files changed

+493
-291
lines changed

8 files changed

+493
-291
lines changed

api/cpp/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ define_cargo_dependent_feature(accessibility "Enable integration with operating
119119
define_cargo_dependent_feature(testing "Enable support for testing API (experimental)" ON "NOT SLINT_FEATURE_FREESTANDING")
120120
define_cargo_feature(experimental "Enable experimental features. (No backward compatibility guarantees)" OFF)
121121
define_cargo_dependent_feature(system-testing "Enable system testing support (experimental)" OFF "SLINT_FEATURE_EXPERIMENTAL AND NOT SLINT_FEATURE_FREESTANDING")
122+
define_cargo_feature(raw-window-handle-06 "Enable integration with raw-window-handle." OFF)
122123

123124
if (SLINT_BUILD_RUNTIME)
124125
if(SLINT_FEATURE_COMPILER AND NOT SLINT_COMPILER)

api/cpp/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,14 @@ backend-linuxkms = ["i-slint-backend-selector/backend-linuxkms", "std"]
3838
backend-linuxkms-noseat = ["i-slint-backend-selector/backend-linuxkms-noseat", "std"]
3939
renderer-femtovg = ["i-slint-backend-selector/renderer-femtovg"]
4040
renderer-femtovg-wgpu = ["i-slint-backend-selector/renderer-femtovg-wgpu"]
41-
renderer-skia = ["i-slint-backend-selector/renderer-skia", "i-slint-renderer-skia", "raw-window-handle"]
41+
renderer-skia = ["i-slint-backend-selector/renderer-skia", "i-slint-renderer-skia", "raw-window-handle-06"]
4242
renderer-skia-opengl = ["i-slint-backend-selector/renderer-skia-opengl", "renderer-skia"]
4343
renderer-skia-vulkan = ["i-slint-backend-selector/renderer-skia-vulkan", "renderer-skia"]
4444
renderer-software = ["i-slint-backend-selector/renderer-software"]
4545
gettext = ["i-slint-core/gettext-rs"]
4646
accessibility = ["i-slint-backend-selector/accessibility"]
4747
system-testing = ["i-slint-backend-selector/system-testing"]
48+
raw-window-handle-06 = ["i-slint-core/raw-window-handle-06", "i-slint-backend-selector/raw-window-handle-06"]
4849

4950
std = ["i-slint-core/default", "i-slint-core/image-default-formats", "i-slint-backend-selector"]
5051
freestanding = ["i-slint-core/libm", "i-slint-core/unsafe-single-threaded"]

api/cpp/cbindgen.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ fn gen_corelib(
580580
"slint_windowrc_is_minimized",
581581
"slint_windowrc_is_maximized",
582582
"slint_windowrc_take_snapshot",
583+
"slint_windowrc_window_handle",
583584
"GradientStop",
584585
"ConicGradientBrush",
585586
"slint_conic_gradient_normalize_stops",
@@ -1015,6 +1016,7 @@ declare_features! {
10151016
system_testing
10161017
freestanding
10171018
experimental
1019+
raw_window_handle_06
10181020
}
10191021

10201022
/// Generate the headers.

api/cpp/include/slint-platform.h

Lines changed: 0 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,8 @@
77

88
#include <cassert>
99
#include <cstdint>
10-
#include <utility>
1110
#include <ranges>
1211

13-
struct xcb_connection_t;
14-
struct wl_surface;
15-
struct wl_display;
16-
17-
#if defined(__APPLE__) && !defined(_WIN32) && !defined(_WIN64)
18-
# ifdef __OBJC__
19-
@class NSView;
20-
@class NSWindow;
21-
# else
22-
typedef struct objc_object NSView;
23-
typedef struct objc_object NSWindow;
24-
# endif
25-
#endif
26-
2712
namespace slint {
2813

2914
/// Use the types in this namespace when implementing a custom Slint platform.
@@ -873,99 +858,6 @@ class SoftwareRenderer : public AbstractRenderer
873858
#endif
874859

875860
#ifdef SLINT_FEATURE_RENDERER_SKIA
876-
/// An opaque, low-level window handle that internalizes everything necessary to exchange messages
877-
/// with the windowing system. This includes the connection to the display server, if necessary.
878-
///
879-
/// Note that this class does not provide any kind of ownership. The caller is responsible for
880-
/// ensuring that the pointers supplied to the constructor are valid throughout the lifetime of the
881-
/// NativeWindowHandle.
882-
class NativeWindowHandle
883-
{
884-
cbindgen_private::CppRawHandleOpaque inner;
885-
friend class SkiaRenderer;
886-
887-
NativeWindowHandle(cbindgen_private::CppRawHandleOpaque inner) : inner(inner) { }
888-
889-
public:
890-
NativeWindowHandle() = delete;
891-
NativeWindowHandle(const NativeWindowHandle &) = delete;
892-
NativeWindowHandle &operator=(const NativeWindowHandle &) = delete;
893-
/// Creates a new NativeWindowHandle by moving the handle data from \a other into this
894-
/// NativeWindowHandle.
895-
NativeWindowHandle(NativeWindowHandle &&other) { inner = std::exchange(other.inner, nullptr); }
896-
/// Creates a new NativeWindowHandle by moving the handle data from \a other into this
897-
/// NativeWindowHandle.
898-
NativeWindowHandle &operator=(NativeWindowHandle &&other)
899-
{
900-
if (this == &other) {
901-
return *this;
902-
}
903-
if (inner) {
904-
cbindgen_private::slint_raw_window_handle_drop(inner);
905-
}
906-
inner = std::exchange(other.inner, nullptr);
907-
return *this;
908-
}
909-
910-
# if (!defined(__APPLE__) && !defined(_WIN32) && !defined(_WIN64)) || defined(DOXYGEN)
911-
/// Creates a new NativeWindowHandle from the given xcb_window_t \a window,
912-
/// xcb_visualid_t \a visual_id, XCB \a connection, and \a screen number.
913-
static NativeWindowHandle from_x11_xcb(uint32_t /*xcb_window_t*/ window,
914-
uint32_t /*xcb_visualid_t*/ visual_id,
915-
xcb_connection_t *connection, int screen)
916-
{
917-
918-
return { cbindgen_private::slint_new_raw_window_handle_x11_xcb(window, visual_id,
919-
connection, screen) };
920-
}
921-
922-
/// Creates a new NativeWindowHandle from the given XLib \a window,
923-
/// VisualID \a visual_id, Display \a display, and \a screen number.
924-
static NativeWindowHandle from_x11_xlib(uint32_t /*Window*/ window,
925-
unsigned long /*VisualID*/ visual_id,
926-
void /*Display*/ *display, int screen)
927-
{
928-
929-
return { cbindgen_private::slint_new_raw_window_handle_x11_xlib(window, visual_id, display,
930-
screen) };
931-
}
932-
933-
/// Creates a new NativeWindowHandle from the given wayland \a surface,
934-
/// and \a display.
935-
static NativeWindowHandle from_wayland(wl_surface *surface, wl_display *display)
936-
{
937-
938-
return { cbindgen_private::slint_new_raw_window_handle_wayland(surface, display) };
939-
}
940-
941-
# endif
942-
# if (defined(__APPLE__) && !defined(_WIN32) && !defined(_WIN64)) || defined(DOXYGEN)
943-
944-
/// Creates a new NativeWindowHandle from the given \a nsview, and \a nswindow.
945-
static NativeWindowHandle from_appkit(NSView *nsview, NSWindow *nswindow)
946-
{
947-
948-
return { cbindgen_private::slint_new_raw_window_handle_appkit(nsview, nswindow) };
949-
}
950-
951-
# endif
952-
# if (!defined(__APPLE__) && (defined(_WIN32) || !defined(_WIN64))) || defined(DOXYGEN)
953-
954-
/// Creates a new NativeWindowHandle from the given HWND \a hwnd, and HINSTANCE \a hinstance.
955-
static NativeWindowHandle from_win32(void *hwnd, void *hinstance)
956-
{
957-
return { cbindgen_private::slint_new_raw_window_handle_win32(hwnd, hinstance) };
958-
}
959-
# endif
960-
/// Destroys the NativeWindowHandle.
961-
~NativeWindowHandle()
962-
{
963-
if (inner) {
964-
cbindgen_private::slint_raw_window_handle_drop(inner);
965-
}
966-
}
967-
};
968-
969861
/// Slint's Skia renderer.
970862
///
971863
/// Create the renderer when you have created a native window with a non-zero size.

api/cpp/include/slint_window.h

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@
55

66
#include "slint_internal.h"
77

8+
#include <utility>
9+
10+
struct xcb_connection_t;
11+
struct wl_surface;
12+
struct wl_display;
13+
14+
#if defined(__APPLE__) && !defined(_WIN32) && !defined(_WIN64)
15+
# ifdef __OBJC__
16+
@class NSView;
17+
@class NSWindow;
18+
# else
19+
typedef struct objc_object NSView;
20+
typedef struct objc_object NSWindow;
21+
# endif
22+
#endif
23+
824
namespace slint {
925
#if !defined(DOXYGEN)
1026
namespace platform {
@@ -281,6 +297,151 @@ class WindowAdapterRc
281297

282298
}
283299

300+
#ifdef SLINT_FEATURE_RAW_WINDOW_HANDLE_06
301+
/// An opaque, low-level window handle that internalizes everything necessary to exchange messages
302+
/// with the windowing system. This includes the connection to the display server, if necessary.
303+
///
304+
/// Note that this class does not provide any kind of ownership. The caller is responsible for
305+
/// ensuring that the pointers supplied to the constructor are valid throughout the lifetime of the
306+
/// NativeWindowHandle.
307+
class NativeWindowHandle
308+
{
309+
cbindgen_private::CppRawHandleOpaque inner;
310+
friend class SkiaRenderer;
311+
312+
public:
313+
NativeWindowHandle() = delete;
314+
NativeWindowHandle(const NativeWindowHandle &) = delete;
315+
NativeWindowHandle &operator=(const NativeWindowHandle &) = delete;
316+
/// Creates a new NativeWindowHandle by moving the handle data from \a other into this
317+
/// NativeWindowHandle.
318+
NativeWindowHandle(NativeWindowHandle &&other) { inner = std::exchange(other.inner, nullptr); }
319+
/// Creates a new NativeWindowHandle by moving the handle data from \a other into this
320+
/// NativeWindowHandle.
321+
NativeWindowHandle &operator=(NativeWindowHandle &&other)
322+
{
323+
if (this == &other) {
324+
return *this;
325+
}
326+
if (inner) {
327+
cbindgen_private::slint_raw_window_handle_drop(inner);
328+
}
329+
inner = std::exchange(other.inner, nullptr);
330+
return *this;
331+
}
332+
333+
# if (!defined(__APPLE__) && !defined(_WIN32) && !defined(_WIN64)) || defined(DOXYGEN)
334+
335+
/// Creates a new NativeWindowHandle from the given xcb_window_t \a window,
336+
/// xcb_visualid_t \a visual_id, XCB \a connection, and \a screen number.
337+
static NativeWindowHandle from_x11_xcb(uint32_t /*xcb_window_t*/ window,
338+
uint32_t /*xcb_visualid_t*/ visual_id,
339+
xcb_connection_t *connection, int screen)
340+
{
341+
342+
return { cbindgen_private::slint_new_raw_window_handle_x11_xcb(window, visual_id,
343+
connection, screen) };
344+
}
345+
346+
/// Creates a new NativeWindowHandle from the given XLib \a window,
347+
/// VisualID \a visual_id, Display \a display, and \a screen number.
348+
static NativeWindowHandle from_x11_xlib(uint32_t /*Window*/ window,
349+
unsigned long /*VisualID*/ visual_id,
350+
void /*Display*/ *display, int screen)
351+
{
352+
353+
return { cbindgen_private::slint_new_raw_window_handle_x11_xlib(window, visual_id, display,
354+
screen) };
355+
}
356+
357+
/// Creates a new NativeWindowHandle from the given wayland \a surface,
358+
/// and \a display.
359+
static NativeWindowHandle from_wayland(wl_surface *surface, wl_display *display)
360+
{
361+
362+
return { cbindgen_private::slint_new_raw_window_handle_wayland(surface, display) };
363+
}
364+
365+
/// Returns the wl_surface from this NativeWindowHandle.
366+
wl_surface *wayland_surface() const
367+
{
368+
if (inner) {
369+
return static_cast<wl_surface *>(cbindgen_private::slint_raw_window_handle_wayland(inner));
370+
}
371+
return nullptr;
372+
}
373+
374+
/// Returns the wl_display from this NativeWindowHandle.
375+
wl_display *wayland_display() const
376+
{
377+
if (inner) {
378+
return static_cast<wl_display *>(cbindgen_private::slint_raw_display_handle_wayland(inner));
379+
}
380+
return nullptr;
381+
}
382+
383+
# endif
384+
# if (defined(__APPLE__) && !defined(_WIN32) && !defined(_WIN64)) || defined(DOXYGEN)
385+
386+
/// Creates a new NativeWindowHandle from the given \a nsview, and \a nswindow.
387+
static NativeWindowHandle from_appkit(NSView *nsview, NSWindow *nswindow)
388+
{
389+
390+
return { cbindgen_private::slint_new_raw_window_handle_appkit(nsview, nswindow) };
391+
}
392+
393+
/// Returns the NSView from this NativeWindowHandle.
394+
NSView *appkit_view() const
395+
{
396+
if (inner) {
397+
return static_cast<NSView *>(cbindgen_private::slint_raw_view_handle_appkit(inner));
398+
}
399+
return nullptr;
400+
}
401+
402+
# endif
403+
# if (!defined(__APPLE__) && (defined(_WIN32) || !defined(_WIN64))) || defined(DOXYGEN)
404+
405+
/// Creates a new NativeWindowHandle from the given HWND \a hwnd, and HINSTANCE \a hinstance.
406+
static NativeWindowHandle from_win32(void *hwnd, void *hinstance)
407+
{
408+
return { cbindgen_private::slint_new_raw_window_handle_win32(hwnd, hinstance) };
409+
}
410+
411+
/// Returns the HWND from this NativeWindowHandle.
412+
void const*win32_hwnd() const
413+
{
414+
if (inner) {
415+
return cbindgen_private::slint_raw_hwnd_handle_win32(inner);
416+
}
417+
return nullptr;
418+
}
419+
420+
/// Returns the HINSTANCE from this NativeWindowHandle.
421+
void const*win32_instance() const
422+
{
423+
if (inner) {
424+
return cbindgen_private::slint_raw_hinstance_handle_win32(inner);
425+
}
426+
return nullptr;
427+
}
428+
429+
# endif
430+
/// Destroys the NativeWindowHandle.
431+
~NativeWindowHandle()
432+
{
433+
if (inner) {
434+
cbindgen_private::slint_raw_window_handle_drop(inner);
435+
}
436+
}
437+
438+
protected:
439+
NativeWindowHandle(cbindgen_private::CppRawHandleOpaque inner) : inner(inner) { }
440+
441+
friend class Window;
442+
};
443+
#endif
444+
284445
/// This class represents a window towards the windowing system, that's used to render the
285446
/// scene of a component. It provides API to control windowing system specific aspects such
286447
/// as the position on the screen.
@@ -637,6 +798,11 @@ class Window
637798
}
638799
}
639800

801+
NativeWindowHandle native_window_handle() const
802+
{
803+
return cbindgen_private::slint_windowrc_window_handle(&inner.handle());
804+
}
805+
640806
/// \private
641807
private_api::WindowAdapterRc &window_handle() { return inner; }
642808
/// \private

0 commit comments

Comments
 (0)