mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-31 15:47:26 +00:00
Remove the WindowAdapter from the renderer constructor
This allows disentangling the native window creation from the renderer creation, which is rather ugly and complicated on the C++ side.
This commit is contained in:
parent
dd5ef9993f
commit
fe4a434ce4
13 changed files with 170 additions and 173 deletions
|
@ -256,6 +256,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const cbindgen_private::WindowAdapterRcOpaque &handle() const { return inner; }
|
||||
|
||||
private:
|
||||
cbindgen_private::WindowAdapterRcOpaque inner;
|
||||
};
|
||||
|
|
|
@ -31,7 +31,6 @@ namespace platform {
|
|||
template<typename R>
|
||||
concept Renderer = requires(R r)
|
||||
{
|
||||
r.init(static_cast<const cbindgen_private::WindowAdapterRcOpaque *>(nullptr));
|
||||
cbindgen_private::RendererPtr { r.renderer_handle() };
|
||||
};
|
||||
|
||||
|
@ -82,8 +81,8 @@ class WindowAdapter : public AbstractWindowAdapter
|
|||
// Note that we do not have ownership (there is no reference increase for this)
|
||||
// because it would otherwise be a reference loop
|
||||
cbindgen_private::WindowAdapterRcOpaque self {};
|
||||
std::unique_ptr<R> m_renderer;
|
||||
// Whether this WindowAdapter was already given to the slint runtime
|
||||
const R m_renderer;
|
||||
bool was_initialized = false;
|
||||
|
||||
private:
|
||||
|
@ -93,7 +92,7 @@ private:
|
|||
cbindgen_private::slint_window_adapter_new(
|
||||
this, [](void *wa) { delete reinterpret_cast<const WA *>(wa); },
|
||||
[](void *wa) {
|
||||
return reinterpret_cast<const WA *>(wa)->m_renderer.renderer_handle();
|
||||
return reinterpret_cast<const WA *>(wa)->m_renderer->renderer_handle();
|
||||
},
|
||||
[](void *wa) { reinterpret_cast<const WA *>(wa)->show(); },
|
||||
[](void *wa) { reinterpret_cast<const WA *>(wa)->hide(); },
|
||||
|
@ -102,20 +101,18 @@ private:
|
|||
return reinterpret_cast<const WA *>(wa)->physical_size();
|
||||
},
|
||||
&self);
|
||||
m_renderer.init(&self);
|
||||
was_initialized = true;
|
||||
return self;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Construct a WindowAdapter. The arguments are forwarded to initialize the renderer
|
||||
template<typename... Args>
|
||||
explicit WindowAdapter(Args... a) : m_renderer(std::forward<Args>(a)...)
|
||||
{
|
||||
}
|
||||
/// Construct a WindowAdapter
|
||||
explicit WindowAdapter() { }
|
||||
|
||||
void set_renderer(std::unique_ptr<R> renderer) { m_renderer = std::move(renderer); }
|
||||
|
||||
/// Return a reference to the renderer that can be used to do the rendering.
|
||||
const R &renderer() const { return m_renderer; }
|
||||
const R &renderer() const { return *m_renderer; }
|
||||
|
||||
/// Return the slint::Window associated with this window.
|
||||
///
|
||||
|
@ -207,23 +204,12 @@ class SoftwareRenderer
|
|||
mutable cbindgen_private::SoftwareRendererOpaque inner;
|
||||
|
||||
public:
|
||||
virtual ~SoftwareRenderer()
|
||||
{
|
||||
if (inner) {
|
||||
cbindgen_private::slint_software_renderer_drop(inner);
|
||||
}
|
||||
};
|
||||
virtual ~SoftwareRenderer() { cbindgen_private::slint_software_renderer_drop(inner); };
|
||||
SoftwareRenderer(const SoftwareRenderer &) = delete;
|
||||
SoftwareRenderer &operator=(const SoftwareRenderer &) = delete;
|
||||
SoftwareRenderer() = default;
|
||||
|
||||
/// \private
|
||||
void init(const cbindgen_private::WindowAdapterRcOpaque *win, int max_buffer_age) const
|
||||
SoftwareRenderer(int max_buffer_age)
|
||||
{
|
||||
if (inner) {
|
||||
cbindgen_private::slint_software_renderer_drop(inner);
|
||||
}
|
||||
inner = cbindgen_private::slint_software_renderer_new(max_buffer_age, win);
|
||||
inner = cbindgen_private::slint_software_renderer_new(max_buffer_age);
|
||||
}
|
||||
|
||||
/// \private
|
||||
|
@ -238,10 +224,12 @@ public:
|
|||
///
|
||||
/// The stride is the amount of pixels between two lines in the buffer.
|
||||
/// It is must be at least as large as the width of the window.
|
||||
void render(std::span<slint::Rgb8Pixel> buffer, std::size_t pixel_stride) const
|
||||
void render(const Window &window, std::span<slint::Rgb8Pixel> buffer,
|
||||
std::size_t pixel_stride) const
|
||||
{
|
||||
cbindgen_private::slint_software_renderer_render_rgb8(inner, buffer.data(), buffer.size(),
|
||||
pixel_stride);
|
||||
cbindgen_private::slint_software_renderer_render_rgb8(
|
||||
inner, &window.window_handle().handle(), buffer.data(), buffer.size(),
|
||||
pixel_stride);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -325,33 +313,17 @@ public:
|
|||
/// Use render to perform the rendering.
|
||||
class SkiaRenderer
|
||||
{
|
||||
mutable cbindgen_private::SkiaRendererOpaque inner = nullptr;
|
||||
NativeWindowHandle window_handle;
|
||||
PhysicalSize initial_size;
|
||||
mutable cbindgen_private::SkiaRendererOpaque inner;
|
||||
|
||||
public:
|
||||
virtual ~SkiaRenderer()
|
||||
{
|
||||
if (inner) {
|
||||
cbindgen_private::slint_skia_renderer_drop(inner);
|
||||
}
|
||||
};
|
||||
virtual ~SkiaRenderer() { cbindgen_private::slint_skia_renderer_drop(inner); }
|
||||
SkiaRenderer(const SkiaRenderer &) = delete;
|
||||
SkiaRenderer &operator=(const SkiaRenderer &) = delete;
|
||||
/// Constructs a new Skia renderer for the given window - referenced by the provided
|
||||
/// WindowHandle - and the specified initial size.
|
||||
SkiaRenderer(NativeWindowHandle &&window_handle, PhysicalSize initial_size)
|
||||
: window_handle(std::move(window_handle)), initial_size(initial_size)
|
||||
SkiaRenderer(const NativeWindowHandle &window_handle, PhysicalSize initial_size)
|
||||
{
|
||||
}
|
||||
|
||||
/// \private
|
||||
void init(const cbindgen_private::WindowAdapterRcOpaque *win) const
|
||||
{
|
||||
if (inner) {
|
||||
cbindgen_private::slint_skia_renderer_drop(inner);
|
||||
}
|
||||
inner = cbindgen_private::slint_skia_renderer_new(win, window_handle.inner, initial_size);
|
||||
inner = cbindgen_private::slint_skia_renderer_new(window_handle.inner, initial_size);
|
||||
}
|
||||
|
||||
/// \private
|
||||
|
@ -360,9 +332,9 @@ public:
|
|||
return cbindgen_private::slint_skia_renderer_handle(inner);
|
||||
}
|
||||
|
||||
void render(PhysicalSize size) const
|
||||
void render(const Window &window, PhysicalSize size) const
|
||||
{
|
||||
cbindgen_private::slint_skia_renderer_render(inner, size);
|
||||
cbindgen_private::slint_skia_renderer_render(inner, &window.window_handle().handle(), size);
|
||||
}
|
||||
|
||||
void resize(PhysicalSize size) const
|
||||
|
|
|
@ -160,19 +160,14 @@ pub extern "C" fn slint_platform_update_timers_and_animations() {
|
|||
type SoftwareRendererOpaque = *const c_void;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_software_renderer_new(
|
||||
buffer_age: u32,
|
||||
window: &WindowAdapterRcOpaque,
|
||||
) -> SoftwareRendererOpaque {
|
||||
let window = core::mem::transmute::<&WindowAdapterRcOpaque, &Rc<dyn WindowAdapter>>(window);
|
||||
let weak = Rc::downgrade(window);
|
||||
pub unsafe extern "C" fn slint_software_renderer_new(buffer_age: u32) -> SoftwareRendererOpaque {
|
||||
let repaint_buffer_type = match buffer_age {
|
||||
0 => RepaintBufferType::NewBuffer,
|
||||
1 => RepaintBufferType::ReusedBuffer,
|
||||
2 => RepaintBufferType::SwappedBuffers,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Box::into_raw(Box::new(SoftwareRenderer::new(repaint_buffer_type, weak)))
|
||||
Box::into_raw(Box::new(SoftwareRenderer::new_without_window(repaint_buffer_type)))
|
||||
as SoftwareRendererOpaque
|
||||
}
|
||||
|
||||
|
@ -184,12 +179,16 @@ pub unsafe extern "C" fn slint_software_renderer_drop(r: SoftwareRendererOpaque)
|
|||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_software_renderer_render_rgb8(
|
||||
r: SoftwareRendererOpaque,
|
||||
window_adapter: *const WindowAdapterRcOpaque,
|
||||
buffer: *mut Rgb8Pixel,
|
||||
buffer_len: usize,
|
||||
pixel_stride: usize,
|
||||
) {
|
||||
let buffer = core::slice::from_raw_parts_mut(buffer, buffer_len);
|
||||
(*(r as *const SoftwareRenderer)).render(buffer, pixel_stride);
|
||||
let renderer = &*(r as *const SoftwareRenderer);
|
||||
let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
|
||||
renderer.set_window(window_adapter.window());
|
||||
renderer.render(buffer, pixel_stride);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -288,16 +287,11 @@ pub unsafe extern "C" fn slint_raw_window_handle_drop(handle: CppRawHandleOpaque
|
|||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_skia_renderer_new(
|
||||
window_adapter: &WindowAdapterRcOpaque,
|
||||
handle_opaque: CppRawHandleOpaque,
|
||||
size: IntSize,
|
||||
) -> SkiaRendererOpaque {
|
||||
let window_adapter =
|
||||
core::mem::transmute::<&WindowAdapterRcOpaque, &Rc<dyn WindowAdapter>>(window_adapter);
|
||||
let weak = Rc::downgrade(window_adapter);
|
||||
let boxed_renderer: Box<SkiaRenderer> = Box::new(
|
||||
SkiaRenderer::new(
|
||||
weak,
|
||||
&*(handle_opaque as *const CppRawHandle),
|
||||
&*(handle_opaque as *const CppRawHandle),
|
||||
PhysicalSize { width: size.width, height: size.height },
|
||||
|
@ -331,9 +325,15 @@ pub unsafe extern "C" fn slint_skia_renderer_resize(r: SkiaRendererOpaque, size:
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_skia_renderer_render(r: SkiaRendererOpaque, size: IntSize) {
|
||||
pub unsafe extern "C" fn slint_skia_renderer_render(
|
||||
r: SkiaRendererOpaque,
|
||||
window: *const WindowAdapterRcOpaque,
|
||||
size: IntSize,
|
||||
) {
|
||||
let window_adapter = &*(window as *const Rc<dyn WindowAdapter>);
|
||||
let r = &*(r as *const SkiaRenderer);
|
||||
r.render(PhysicalSize { width: size.width, height: size.height }).unwrap();
|
||||
r.render(window_adapter.window(), PhysicalSize { width: size.width, height: size.height })
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -19,22 +19,46 @@ struct Geometry
|
|||
uint32_t height = 0;
|
||||
};
|
||||
|
||||
struct NativeWindowHandle
|
||||
struct MyWindowAdapter : public slint_platform::WindowAdapter<slint_platform::SkiaRenderer>
|
||||
{
|
||||
HWND hwnd;
|
||||
};
|
||||
|
||||
struct MyWindowAdapter : NativeWindowHandle,
|
||||
public slint_platform::WindowAdapter<slint_platform::SkiaRenderer>
|
||||
{
|
||||
Geometry geometry = { 0, 0, 600, 300 };
|
||||
|
||||
MyWindowAdapter(HWND winId)
|
||||
: NativeWindowHandle { MyWindowAdapter::create_window(winId) },
|
||||
slint_platform::WindowAdapter<slint_platform::SkiaRenderer>(
|
||||
slint_platform::NativeWindowHandle::from_win32(hwnd, GetModuleHandleW(nullptr)),
|
||||
slint::PhysicalSize({ 600, 300 }))
|
||||
{
|
||||
HINSTANCE hInstance = GetModuleHandleW(nullptr);
|
||||
|
||||
// Register the window class.
|
||||
const wchar_t CLASS_NAME[] = L"Sample Window Class";
|
||||
|
||||
WNDCLASS wc = {};
|
||||
|
||||
wc.lpfnWndProc = MyWindowAdapter::windowProc;
|
||||
wc.hInstance = hInstance;
|
||||
wc.lpszClassName = CLASS_NAME;
|
||||
|
||||
RegisterClass(&wc);
|
||||
|
||||
// Create the window.
|
||||
|
||||
hwnd = CreateWindowEx(0, // Optional window styles.
|
||||
CLASS_NAME, // Window class
|
||||
L"Learn to Program Windows", // Window text
|
||||
WS_CHILDWINDOW, // Window style
|
||||
|
||||
// Size and position
|
||||
0, 0, 600, 300,
|
||||
|
||||
winId,
|
||||
NULL, // Menu
|
||||
hInstance, // Instance handle
|
||||
NULL // Additional application data
|
||||
);
|
||||
|
||||
set_renderer(std::make_unique<slint_platform::SkiaRenderer>(
|
||||
slint_platform::NativeWindowHandle::from_win32(hwnd, hInstance),
|
||||
slint::PhysicalSize({ 600, 300 })));
|
||||
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
}
|
||||
|
||||
|
@ -61,7 +85,7 @@ struct MyWindowAdapter : NativeWindowHandle,
|
|||
|
||||
void render()
|
||||
{
|
||||
renderer().render(physical_size());
|
||||
renderer().render(window(), physical_size());
|
||||
if (has_active_animations())
|
||||
request_redraw();
|
||||
}
|
||||
|
@ -205,37 +229,4 @@ struct MyWindowAdapter : NativeWindowHandle,
|
|||
}
|
||||
|
||||
private:
|
||||
static HWND create_window(HWND parentWindow)
|
||||
{
|
||||
HINSTANCE hInstance = GetModuleHandleW(nullptr);
|
||||
|
||||
// Register the window class.
|
||||
const wchar_t CLASS_NAME[] = L"Sample Window Class";
|
||||
|
||||
WNDCLASS wc = {};
|
||||
|
||||
wc.lpfnWndProc = MyWindowAdapter::windowProc;
|
||||
wc.hInstance = hInstance;
|
||||
wc.lpszClassName = CLASS_NAME;
|
||||
|
||||
RegisterClass(&wc);
|
||||
|
||||
// Create the window.
|
||||
|
||||
HWND hwnd = CreateWindowEx(0, // Optional window styles.
|
||||
CLASS_NAME, // Window class
|
||||
L"Learn to Program Windows", // Window text
|
||||
WS_CHILDWINDOW, // Window style
|
||||
|
||||
// Size and position
|
||||
0, 0, 600, 300,
|
||||
|
||||
parentWindow,
|
||||
NULL, // Menu
|
||||
hInstance, // Instance handle
|
||||
NULL // Additional application data
|
||||
);
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -54,11 +54,11 @@ class MyWindow : public QWindow, public slint_platform::WindowAdapter<slint_plat
|
|||
|
||||
public:
|
||||
MyWindow(QWindow *parentWindow = nullptr)
|
||||
: QWindow(parentWindow),
|
||||
slint_platform::WindowAdapter<slint_platform::SkiaRenderer>(
|
||||
window_handle_for_qt_window(this),
|
||||
slint::PhysicalSize({ uint32_t(width()), uint32_t(height()) }))
|
||||
: QWindow(parentWindow), slint_platform::WindowAdapter<slint_platform::SkiaRenderer>()
|
||||
{
|
||||
set_renderer(std::make_unique<slint_platform::SkiaRenderer>(
|
||||
window_handle_for_qt_window(this),
|
||||
slint::PhysicalSize({ uint32_t(width()), uint32_t(height()) })));
|
||||
}
|
||||
|
||||
/*void keyEvent(QKeyEvent *event) override
|
||||
|
@ -71,7 +71,7 @@ public:
|
|||
slint_platform::update_timers_and_animations();
|
||||
|
||||
auto windowSize = slint::PhysicalSize({ uint32_t(width()), uint32_t(height()) });
|
||||
renderer().render(windowSize);
|
||||
renderer().render(window(), windowSize);
|
||||
|
||||
if (has_active_animations()) {
|
||||
requestUpdate();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue