mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 10:50:00 +00:00
C++ Pointer dispatch API
This commit is contained in:
parent
aebaa7d6c9
commit
3a2359f107
8 changed files with 175 additions and 124 deletions
|
@ -256,6 +256,7 @@ endforeach()
|
|||
set(generated_headers
|
||||
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_internal.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_enums_internal.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_enums.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_string_internal.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_brush_internal.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_sharedvector_internal.h
|
||||
|
|
|
@ -9,26 +9,43 @@ use std::path::{Path, PathBuf};
|
|||
// cSpell: ignore compat constexpr corelib deps sharedvector pathdata
|
||||
|
||||
fn enums(path: &Path) -> anyhow::Result<()> {
|
||||
let mut enums =
|
||||
std::fs::File::create(path).context("Error creating slint_internal_enums.h file")?;
|
||||
writeln!(enums, "#pragma once")?;
|
||||
writeln!(enums, "// This file is auto-generated from {}", file!())?;
|
||||
writeln!(enums, "namespace slint::cbindgen_private {{")?;
|
||||
let mut enums_priv = std::fs::File::create(path.join("slint_enums_internal.h"))
|
||||
.context("Error creating slint_internal_enums.h file")?;
|
||||
writeln!(enums_priv, "#pragma once")?;
|
||||
writeln!(enums_priv, "// This file is auto-generated from {}", file!())?;
|
||||
writeln!(enums_priv, "#include \"slint_enums.h\"")?;
|
||||
writeln!(enums_priv, "namespace slint::cbindgen_private {{")?;
|
||||
let mut enums_pub = std::fs::File::create(path.join("slint_enums.h"))
|
||||
.context("Error creating slint_enums.h file")?;
|
||||
writeln!(enums_pub, "#pragma once")?;
|
||||
writeln!(enums_pub, "// This file is auto-generated from {}", file!())?;
|
||||
writeln!(enums_pub, "namespace slint {{")?;
|
||||
macro_rules! enum_file {
|
||||
(PointerEventButton) => {{
|
||||
writeln!(enums_priv, "using slint::PointerEventButton;")?;
|
||||
&mut enums_pub
|
||||
}};
|
||||
($_:ident) => {
|
||||
&mut enums_priv
|
||||
};
|
||||
}
|
||||
macro_rules! print_enums {
|
||||
($( $(#[doc = $enum_doc:literal])* $(#[non_exhaustive])? enum $Name:ident { $( $(#[doc = $value_doc:literal])* $Value:ident,)* })*) => {
|
||||
$(
|
||||
$(writeln!(enums, "///{}", $enum_doc)?;)*
|
||||
writeln!(enums, "enum class {} {{", stringify!($Name))?;
|
||||
let file = enum_file!($Name);
|
||||
$(writeln!(file, "///{}", $enum_doc)?;)*
|
||||
writeln!(file, "enum class {} {{", stringify!($Name))?;
|
||||
$(
|
||||
$(writeln!(enums, " ///{}", $value_doc)?;)*
|
||||
writeln!(enums, " {},", stringify!($Value).trim_start_matches("r#"))?;
|
||||
$(writeln!(file, " ///{}", $value_doc)?;)*
|
||||
writeln!(file, " {},", stringify!($Value).trim_start_matches("r#"))?;
|
||||
)*
|
||||
writeln!(enums, "}};")?;
|
||||
writeln!(file, "}};")?;
|
||||
)*
|
||||
}
|
||||
}
|
||||
i_slint_common::for_each_enums!(print_enums);
|
||||
writeln!(enums, "}}")?;
|
||||
writeln!(enums_pub, "}}")?;
|
||||
writeln!(enums_priv, "}}")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -743,7 +760,7 @@ pub fn gen_all(
|
|||
proc_macro2::fallback::force(); // avoid a abort if panic=abort is set
|
||||
std::fs::create_dir_all(include_dir).context("Could not create the include directory")?;
|
||||
let mut deps = Vec::new();
|
||||
enums(&include_dir.join("slint_enums_internal.h"))?;
|
||||
enums(include_dir)?;
|
||||
gen_corelib(root_dir, include_dir, &mut deps, enabled_features)?;
|
||||
gen_backend_qt(root_dir, include_dir, &mut deps)?;
|
||||
gen_backend(root_dir, include_dir, &mut deps)?;
|
||||
|
|
|
@ -233,6 +233,13 @@ public:
|
|||
cbindgen_private::slint_windowrc_dispatch_key_event(&inner, &event);
|
||||
}
|
||||
|
||||
/// Send a pointer event to this window
|
||||
void dispatch_pointer_event(const cbindgen_private::MouseEvent &event)
|
||||
{
|
||||
private_api::assert_main_thread();
|
||||
cbindgen_private::slint_windowrc_dispatch_pointer_event(&inner, event);
|
||||
}
|
||||
|
||||
/// Registers a font by the specified path. The path must refer to an existing
|
||||
/// TrueType font.
|
||||
/// \returns an empty optional on success, otherwise an error string
|
||||
|
@ -523,6 +530,83 @@ public:
|
|||
inner.dispatch_key_event(event);
|
||||
}
|
||||
|
||||
/// Dispatches a pointer or mouse press event to the scene.
|
||||
///
|
||||
/// Use this function when you're implementing your own backend and want to forward user
|
||||
/// pointer/mouse events.
|
||||
///
|
||||
/// \a pos represents the logical position of the pointer relative to the window.
|
||||
/// \a button is the button that was pressed.
|
||||
void dispatch_pointer_press_event(LogicalPosition pos, PointerEventButton button)
|
||||
{
|
||||
using slint::cbindgen_private::MouseEvent;
|
||||
MouseEvent event { .tag = MouseEvent::Tag::Pressed,
|
||||
.pressed = MouseEvent::Pressed_Body { .position = { pos.x, pos.y },
|
||||
.button = button,
|
||||
.click_count = 0 } };
|
||||
inner.dispatch_pointer_event(event);
|
||||
}
|
||||
/// Dispatches a pointer or mouse release event to the scene.
|
||||
///
|
||||
/// Use this function when you're implementing your own backend and want to forward user
|
||||
/// pointer/mouse events.
|
||||
///
|
||||
/// \a pos represents the logical position of the pointer relative to the window.
|
||||
/// \a button is the button that was released.
|
||||
void dispatch_pointer_release_event(LogicalPosition pos, PointerEventButton button)
|
||||
{
|
||||
using slint::cbindgen_private::MouseEvent;
|
||||
MouseEvent event { .tag = MouseEvent::Tag::Released,
|
||||
.released = MouseEvent::Released_Body { .position = { pos.x, pos.y },
|
||||
.button = button,
|
||||
.click_count = 0 } };
|
||||
inner.dispatch_pointer_event(event);
|
||||
}
|
||||
/// Dispatches a pointer exit event to the scene.
|
||||
///
|
||||
/// Use this function when you're implementing your own backend and want to forward user
|
||||
/// pointer/mouse events.
|
||||
///
|
||||
/// This event is triggered when the pointer exits the window.
|
||||
void dispatch_pointer_exit_event()
|
||||
{
|
||||
using slint::cbindgen_private::MouseEvent;
|
||||
MouseEvent event { .tag = MouseEvent::Tag::Exit, .moved = {} };
|
||||
inner.dispatch_pointer_event(event);
|
||||
}
|
||||
|
||||
/// Dispatches a pointer move event to the scene.
|
||||
///
|
||||
/// Use this function when you're implementing your own backend and want to forward user
|
||||
/// pointer/mouse events.
|
||||
///
|
||||
/// \a pos represents the logical position of the pointer relative to the window.
|
||||
void dispatch_pointer_move_event(LogicalPosition pos)
|
||||
{
|
||||
using slint::cbindgen_private::MouseEvent;
|
||||
MouseEvent event { .tag = MouseEvent::Tag::Moved,
|
||||
.moved = MouseEvent::Moved_Body { .position = { pos.x, pos.y } } };
|
||||
inner.dispatch_pointer_event(event);
|
||||
}
|
||||
|
||||
/// Dispatches a scroll (or wheel) event to the scene.
|
||||
///
|
||||
/// Use this function when you're implementing your own backend and want to forward user wheel
|
||||
/// events.
|
||||
///
|
||||
/// \a parameter represents the logical position of the pointer relative to the window.
|
||||
/// \a delta_x and \a delta_y represent the scroll delta values in the X and Y
|
||||
/// directions in logical pixels.
|
||||
void dispatch_pointer_scroll_event(LogicalPosition pos, float delta_x, float delta_y)
|
||||
{
|
||||
using slint::cbindgen_private::MouseEvent;
|
||||
MouseEvent event { .tag = MouseEvent::Tag::Wheel,
|
||||
.wheel = MouseEvent::Wheel_Body { .position = { pos.x, pos.y },
|
||||
.delta_x = delta_x,
|
||||
.delta_y = delta_y } };
|
||||
inner.dispatch_pointer_event(event);
|
||||
}
|
||||
|
||||
/// \private
|
||||
private_api::WindowAdapterRc &window_handle() { return inner; }
|
||||
/// \private
|
||||
|
|
|
@ -121,16 +121,6 @@ public:
|
|||
return *reinterpret_cast<Window *>(&self);
|
||||
}
|
||||
|
||||
/// Send a pointer event to this window
|
||||
// Note: in rust, this is on the Window. FIXME: use a public event type
|
||||
void dispatch_pointer_event(const cbindgen_private::MouseEvent &event)
|
||||
{
|
||||
private_api::assert_main_thread();
|
||||
if (was_initialized) {
|
||||
cbindgen_private::slint_windowrc_dispatch_pointer_event(&self, event);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the logical size of this window after a resize event
|
||||
// Note: in rust, this is an event on the Window
|
||||
void dispatch_resize_event(slint::LogicalSize s)
|
||||
|
|
|
@ -104,90 +104,42 @@ struct MyWindowAdapter : public slint_platform::WindowAdapter
|
|||
SetWindowPos(hwnd, nullptr, x, y, width, height, 0);
|
||||
}
|
||||
|
||||
std::optional<slint::cbindgen_private::MouseEvent> mouseEventForMessage(UINT uMsg,
|
||||
LPARAM lParam)
|
||||
{
|
||||
float x = float(LOWORD(lParam));
|
||||
float y = float(HIWORD(lParam));
|
||||
|
||||
auto makePressEvent = [=](UINT uMsg) {
|
||||
slint::cbindgen_private::PointerEventButton button;
|
||||
switch (uMsg) {
|
||||
case WM_LBUTTONDOWN:
|
||||
button = slint::cbindgen_private::PointerEventButton::Left;
|
||||
break;
|
||||
case WM_MBUTTONDOWN:
|
||||
button = slint::cbindgen_private::PointerEventButton::Middle;
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
button = slint::cbindgen_private::PointerEventButton::Right;
|
||||
break;
|
||||
default:
|
||||
assert(!"not implemented");
|
||||
}
|
||||
return slint::cbindgen_private::MouseEvent {
|
||||
.tag = slint::cbindgen_private::MouseEvent::Tag::Pressed,
|
||||
.pressed =
|
||||
slint::cbindgen_private::MouseEvent::Pressed_Body {
|
||||
.position = { x, y },
|
||||
.button = button,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
auto makeReleaseEvent = [=](UINT uMsg) {
|
||||
slint::cbindgen_private::PointerEventButton button;
|
||||
switch (uMsg) {
|
||||
case WM_LBUTTONUP:
|
||||
button = slint::cbindgen_private::PointerEventButton::Left;
|
||||
break;
|
||||
case WM_MBUTTONUP:
|
||||
button = slint::cbindgen_private::PointerEventButton::Middle;
|
||||
break;
|
||||
case WM_RBUTTONUP:
|
||||
button = slint::cbindgen_private::PointerEventButton::Right;
|
||||
break;
|
||||
default:
|
||||
assert(!"not implemented");
|
||||
}
|
||||
return slint::cbindgen_private::MouseEvent {
|
||||
.tag = slint::cbindgen_private::MouseEvent::Tag::Released,
|
||||
.released =
|
||||
slint::cbindgen_private::MouseEvent::Released_Body {
|
||||
.position = { x, y },
|
||||
.button = button,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
switch (uMsg) {
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
return makeReleaseEvent(uMsg);
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
return makePressEvent(uMsg);
|
||||
case WM_MOUSEMOVE:
|
||||
return slint::cbindgen_private::MouseEvent {
|
||||
.tag = slint::cbindgen_private::MouseEvent::Tag::Moved,
|
||||
.moved =
|
||||
slint::cbindgen_private::MouseEvent::Moved_Body {
|
||||
.position = { x, y },
|
||||
}
|
||||
};
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void mouse_event(UINT uMsg, LPARAM lParam)
|
||||
{
|
||||
if (auto event = mouseEventForMessage(uMsg, lParam)) {
|
||||
dispatch_pointer_event(*event);
|
||||
using slint::LogicalPosition;
|
||||
using slint::PointerEventButton;
|
||||
float x = float(LOWORD(lParam));
|
||||
float y = float(HIWORD(lParam));
|
||||
switch (uMsg) {
|
||||
case WM_LBUTTONUP:
|
||||
window().dispatch_pointer_release_event(LogicalPosition({ x, y }),
|
||||
PointerEventButton::Left);
|
||||
break;
|
||||
case WM_MBUTTONUP:
|
||||
window().dispatch_pointer_release_event(LogicalPosition({ x, y }),
|
||||
PointerEventButton::Middle);
|
||||
break;
|
||||
case WM_RBUTTONUP:
|
||||
window().dispatch_pointer_release_event(LogicalPosition({ x, y }),
|
||||
PointerEventButton::Right);
|
||||
break;
|
||||
case WM_LBUTTONDOWN:
|
||||
window().dispatch_pointer_press_event(LogicalPosition({ x, y }),
|
||||
PointerEventButton::Left);
|
||||
break;
|
||||
case WM_MBUTTONDOWN:
|
||||
window().dispatch_pointer_press_event(LogicalPosition({ x, y }),
|
||||
PointerEventButton::Middle);
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
window().dispatch_pointer_press_event(LogicalPosition({ x, y }),
|
||||
PointerEventButton::Right);
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
window().dispatch_pointer_move_event(LogicalPosition({ x, y }));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,17 +11,17 @@
|
|||
|
||||
namespace slint_platform = slint::experimental::platform;
|
||||
|
||||
slint::cbindgen_private::PointerEventButton convert_button(Qt::MouseButtons b)
|
||||
slint::PointerEventButton convert_button(Qt::MouseButtons b)
|
||||
{
|
||||
switch (b) {
|
||||
case Qt::LeftButton:
|
||||
return slint::cbindgen_private::PointerEventButton::Left;
|
||||
return slint::PointerEventButton::Left;
|
||||
case Qt::RightButton:
|
||||
return slint::cbindgen_private::PointerEventButton::Right;
|
||||
return slint::PointerEventButton::Right;
|
||||
case Qt::MiddleButton:
|
||||
return slint::cbindgen_private::PointerEventButton::Middle;
|
||||
return slint::PointerEventButton::Middle;
|
||||
default:
|
||||
return slint::cbindgen_private::PointerEventButton::Other;
|
||||
return slint::PointerEventButton::Other;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,29 +134,22 @@ public:
|
|||
void mousePressEvent(QMouseEvent *event) override
|
||||
{
|
||||
slint_platform::update_timers_and_animations();
|
||||
dispatch_pointer_event(slint::cbindgen_private::MouseEvent {
|
||||
.tag = slint::cbindgen_private::MouseEvent::Tag::Pressed,
|
||||
.pressed = slint::cbindgen_private::MouseEvent::Pressed_Body {
|
||||
.position = { float(event->pos().x()), float(event->pos().y()) },
|
||||
.button = convert_button(event->button()) } });
|
||||
window().dispatch_pointer_press_event(
|
||||
slint::LogicalPosition({ float(event->pos().x()), float(event->pos().y()) }),
|
||||
convert_button(event->button()));
|
||||
}
|
||||
void mouseReleaseEvent(QMouseEvent *event) override
|
||||
{
|
||||
slint_platform::update_timers_and_animations();
|
||||
dispatch_pointer_event(slint::cbindgen_private::MouseEvent {
|
||||
.tag = slint::cbindgen_private::MouseEvent::Tag::Released,
|
||||
.released = slint::cbindgen_private::MouseEvent::Released_Body {
|
||||
.position = { float(event->pos().x()), float(event->pos().y()) },
|
||||
.button = convert_button(event->button()) } });
|
||||
window().dispatch_pointer_release_event(
|
||||
slint::LogicalPosition({ float(event->pos().x()), float(event->pos().y()) }),
|
||||
convert_button(event->button()));
|
||||
}
|
||||
void mouseMoveEvent(QMouseEvent *event) override
|
||||
{
|
||||
slint_platform::update_timers_and_animations();
|
||||
dispatch_pointer_event(slint::cbindgen_private::MouseEvent {
|
||||
.tag = slint::cbindgen_private::MouseEvent::Tag::Moved,
|
||||
.moved = slint::cbindgen_private::MouseEvent::Moved_Body {
|
||||
.position = { float(event->pos().x()), float(event->pos().y()) },
|
||||
} });
|
||||
window().dispatch_pointer_move_event(
|
||||
slint::LogicalPosition({ float(event->pos().x()), float(event->pos().y()) }));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue