实现键盘事件

This commit is contained in:
2025-06-24 17:40:38 +08:00
parent 3004bf1f00
commit 193b355e6e
13 changed files with 448 additions and 158 deletions

View File

@@ -161,6 +161,20 @@ enum class key_code : uint16_t {
max_key_value = 0xFF
};
/**
* @enum key_action
* @brief 键盘按键的动作
*
* 定义键盘按键的动作类型,用于描述按键事件的状态。
*/
enum class key_action {
none, ///< 无动作
press, ///< 按下
release, ///< 释放
repeat, ///< 重复按下(长按)
double_press ///< 双击
};
/**
* @enum mouse_button
* @brief 鼠标按钮的位标志
@@ -270,6 +284,12 @@ struct wheel_event {
*/
key_code platform_key_to_key_code(int32_t native_key); // 在平台特定代码中实现
/**
*
*
*/
key_action platform_event_to_key_action(uint32_t native_event, uintptr_t native_param); // 在平台特定代码中实现
/**
* @brief 将平台特定的鼠标事件转换为统一的mouse_button
* @param native_event 平台原生事件类型

View File

@@ -6,136 +6,277 @@
key_code platform_key_to_key_code(int32_t native_key) {
switch (native_key) {
// 字母键 (A-Z)
case 'A': return key_code::a;
case 'B': return key_code::b;
case 'C': return key_code::c;
case 'D': return key_code::d;
case 'E': return key_code::e;
case 'F': return key_code::f;
case 'G': return key_code::g;
case 'H': return key_code::h;
case 'I': return key_code::i;
case 'J': return key_code::j;
case 'K': return key_code::k;
case 'L': return key_code::l;
case 'M': return key_code::m;
case 'N': return key_code::n;
case 'O': return key_code::o;
case 'P': return key_code::p;
case 'Q': return key_code::q;
case 'R': return key_code::r;
case 'S': return key_code::s;
case 'T': return key_code::t;
case 'U': return key_code::u;
case 'V': return key_code::v;
case 'W': return key_code::w;
case 'X': return key_code::x;
case 'Y': return key_code::y;
case 'Z': return key_code::z;
case 'A':
return key_code::a;
case 'B':
return key_code::b;
case 'C':
return key_code::c;
case 'D':
return key_code::d;
case 'E':
return key_code::e;
case 'F':
return key_code::f;
case 'G':
return key_code::g;
case 'H':
return key_code::h;
case 'I':
return key_code::i;
case 'J':
return key_code::j;
case 'K':
return key_code::k;
case 'L':
return key_code::l;
case 'M':
return key_code::m;
case 'N':
return key_code::n;
case 'O':
return key_code::o;
case 'P':
return key_code::p;
case 'Q':
return key_code::q;
case 'R':
return key_code::r;
case 'S':
return key_code::s;
case 'T':
return key_code::t;
case 'U':
return key_code::u;
case 'V':
return key_code::v;
case 'W':
return key_code::w;
case 'X':
return key_code::x;
case 'Y':
return key_code::y;
case 'Z':
return key_code::z;
// 数字键 (0-9)
case '0': return key_code::num_0;
case '1': return key_code::num_1;
case '2': return key_code::num_2;
case '3': return key_code::num_3;
case '4': return key_code::num_4;
case '5': return key_code::num_5;
case '6': return key_code::num_6;
case '7': return key_code::num_7;
case '8': return key_code::num_8;
case '9': return key_code::num_9;
case '0':
return key_code::num_0;
case '1':
return key_code::num_1;
case '2':
return key_code::num_2;
case '3':
return key_code::num_3;
case '4':
return key_code::num_4;
case '5':
return key_code::num_5;
case '6':
return key_code::num_6;
case '7':
return key_code::num_7;
case '8':
return key_code::num_8;
case '9':
return key_code::num_9;
// 功能键 (F1-F12)
case VK_F1: return key_code::f1;
case VK_F2: return key_code::f2;
case VK_F3: return key_code::f3;
case VK_F4: return key_code::f4;
case VK_F5: return key_code::f5;
case VK_F6: return key_code::f6;
case VK_F7: return key_code::f7;
case VK_F8: return key_code::f8;
case VK_F9: return key_code::f9;
case VK_F10: return key_code::f10;
case VK_F11: return key_code::f11;
case VK_F12: return key_code::f12;
case VK_F1:
return key_code::f1;
case VK_F2:
return key_code::f2;
case VK_F3:
return key_code::f3;
case VK_F4:
return key_code::f4;
case VK_F5:
return key_code::f5;
case VK_F6:
return key_code::f6;
case VK_F7:
return key_code::f7;
case VK_F8:
return key_code::f8;
case VK_F9:
return key_code::f9;
case VK_F10:
return key_code::f10;
case VK_F11:
return key_code::f11;
case VK_F12:
return key_code::f12;
// 特殊键
case VK_ESCAPE: return key_code::escape;
case VK_TAB: return key_code::tab;
case VK_CAPITAL: return key_code::caps_lock;
case VK_SHIFT: return key_code::left_shift;
case VK_LSHIFT: return key_code::left_shift;
case VK_RSHIFT: return key_code::right_shift;
case VK_CONTROL: return key_code::left_control;
case VK_LCONTROL: return key_code::left_control;
case VK_RCONTROL: return key_code::right_control;
case VK_MENU: return key_code::left_alt;
case VK_LMENU: return key_code::left_alt;
case VK_RMENU: return key_code::right_alt;
case VK_LWIN: return key_code::left_meta;
case VK_RWIN: return key_code::right_meta;
case VK_APPS: return key_code::context_menu;
case VK_SPACE: return key_code::space;
case VK_RETURN: return key_code::enter;
case VK_BACK: return key_code::backspace;
case VK_DELETE: return key_code::delete_key;
case VK_ESCAPE:
return key_code::escape;
case VK_TAB:
return key_code::tab;
case VK_CAPITAL:
return key_code::caps_lock;
case VK_SHIFT:
return key_code::left_shift;
case VK_LSHIFT:
return key_code::left_shift;
case VK_RSHIFT:
return key_code::right_shift;
case VK_CONTROL:
return key_code::left_control;
case VK_LCONTROL:
return key_code::left_control;
case VK_RCONTROL:
return key_code::right_control;
case VK_MENU:
return key_code::left_alt;
case VK_LMENU:
return key_code::left_alt;
case VK_RMENU:
return key_code::right_alt;
case VK_LWIN:
return key_code::left_meta;
case VK_RWIN:
return key_code::right_meta;
case VK_APPS:
return key_code::context_menu;
case VK_SPACE:
return key_code::space;
case VK_RETURN:
return key_code::enter;
case VK_BACK:
return key_code::backspace;
case VK_DELETE:
return key_code::delete_key;
// 导航键
case VK_INSERT: return key_code::insert;
case VK_HOME: return key_code::home;
case VK_END: return key_code::end;
case VK_PRIOR: return key_code::page_up;
case VK_NEXT: return key_code::page_down;
case VK_UP: return key_code::up;
case VK_DOWN: return key_code::down;
case VK_LEFT: return key_code::left;
case VK_RIGHT: return key_code::right;
case VK_INSERT:
return key_code::insert;
case VK_HOME:
return key_code::home;
case VK_END:
return key_code::end;
case VK_PRIOR:
return key_code::page_up;
case VK_NEXT:
return key_code::page_down;
case VK_UP:
return key_code::up;
case VK_DOWN:
return key_code::down;
case VK_LEFT:
return key_code::left;
case VK_RIGHT:
return key_code::right;
// 符号键
case VK_OEM_3: return key_code::back_quote; // `
case VK_OEM_MINUS: return key_code::minus; // -
case VK_OEM_PLUS: return key_code::equals; // =
case VK_OEM_4: return key_code::left_bracket; // [
case VK_OEM_6: return key_code::right_bracket; // ]
case VK_OEM_5: return key_code::backslash; // 左斜杠
case VK_OEM_1: return key_code::semicolon; // ;
case VK_OEM_7: return key_code::apostrophe; // '
case VK_OEM_COMMA: return key_code::comma; // ,
case VK_OEM_PERIOD: return key_code::period; // .
case VK_OEM_2: return key_code::slash; // /
case VK_OEM_3:
return key_code::back_quote; // `
case VK_OEM_MINUS:
return key_code::minus; // -
case VK_OEM_PLUS:
return key_code::equals; // =
case VK_OEM_4:
return key_code::left_bracket; // [
case VK_OEM_6:
return key_code::right_bracket; // ]
case VK_OEM_5:
return key_code::backslash; // 左斜杠
case VK_OEM_1:
return key_code::semicolon; // ;
case VK_OEM_7:
return key_code::apostrophe; // '
case VK_OEM_COMMA:
return key_code::comma; // ,
case VK_OEM_PERIOD:
return key_code::period; // .
case VK_OEM_2:
return key_code::slash; // /
// 小键盘
case VK_NUMLOCK: return key_code::num_lock;
case VK_NUMPAD0: return key_code::numpad_0;
case VK_NUMPAD1: return key_code::numpad_1;
case VK_NUMPAD2: return key_code::numpad_2;
case VK_NUMPAD3: return key_code::numpad_3;
case VK_NUMPAD4: return key_code::numpad_4;
case VK_NUMPAD5: return key_code::numpad_5;
case VK_NUMPAD6: return key_code::numpad_6;
case VK_NUMPAD7: return key_code::numpad_7;
case VK_NUMPAD8: return key_code::numpad_8;
case VK_NUMPAD9: return key_code::numpad_9;
case VK_MULTIPLY: return key_code::numpad_multiply;
case VK_ADD: return key_code::numpad_add;
case VK_SUBTRACT: return key_code::numpad_subtract;
case VK_DECIMAL: return key_code::numpad_decimal;
case VK_DIVIDE: return key_code::numpad_divide;
case VK_NUMLOCK:
return key_code::num_lock;
case VK_NUMPAD0:
return key_code::numpad_0;
case VK_NUMPAD1:
return key_code::numpad_1;
case VK_NUMPAD2:
return key_code::numpad_2;
case VK_NUMPAD3:
return key_code::numpad_3;
case VK_NUMPAD4:
return key_code::numpad_4;
case VK_NUMPAD5:
return key_code::numpad_5;
case VK_NUMPAD6:
return key_code::numpad_6;
case VK_NUMPAD7:
return key_code::numpad_7;
case VK_NUMPAD8:
return key_code::numpad_8;
case VK_NUMPAD9:
return key_code::numpad_9;
case VK_MULTIPLY:
return key_code::numpad_multiply;
case VK_ADD:
return key_code::numpad_add;
case VK_SUBTRACT:
return key_code::numpad_subtract;
case VK_DECIMAL:
return key_code::numpad_decimal;
case VK_DIVIDE:
return key_code::numpad_divide;
// 系统/媒体键
case VK_SNAPSHOT: return key_code::print_screen;
case VK_SCROLL: return key_code::scroll_lock;
case VK_PAUSE: return key_code::pause;
case VK_VOLUME_MUTE: return key_code::volume_mute;
case VK_VOLUME_DOWN: return key_code::volume_down;
case VK_VOLUME_UP: return key_code::volume_up;
case VK_MEDIA_PLAY_PAUSE: return key_code::media_play;
case VK_MEDIA_STOP: return key_code::media_stop;
case VK_MEDIA_PREV_TRACK: return key_code::media_prev;
case VK_MEDIA_NEXT_TRACK: return key_code::media_next;
case VK_SNAPSHOT:
return key_code::print_screen;
case VK_SCROLL:
return key_code::scroll_lock;
case VK_PAUSE:
return key_code::pause;
case VK_VOLUME_MUTE:
return key_code::volume_mute;
case VK_VOLUME_DOWN:
return key_code::volume_down;
case VK_VOLUME_UP:
return key_code::volume_up;
case VK_MEDIA_PLAY_PAUSE:
return key_code::media_play;
case VK_MEDIA_STOP:
return key_code::media_stop;
case VK_MEDIA_PREV_TRACK:
return key_code::media_prev;
case VK_MEDIA_NEXT_TRACK:
return key_code::media_next;
// 未识别的键
default: return key_code::unknown;
default:
return key_code::unknown;
}
}
key_action platform_event_to_key_action(uint32_t native_event, uintptr_t native_param) {
switch (native_event) {
case WM_KEYDOWN:
if (native_param & 0x40000000) { // 如果是重复按下
return key_action::repeat;
}
return key_action::press;
case WM_KEYUP:
return key_action::release;
case WM_SYSKEYDOWN:
if (native_param & 0x40000000) { // 如果是重复按下
return key_action::repeat;
}
return key_action::press;
case WM_SYSKEYUP:
return key_action::release;
case WM_CHAR:
return key_action::press; // 字符输入事件
default:
return key_action::none;
}
}

View File

@@ -15,12 +15,10 @@ namespace text_layout_impl {
pending.metrics.rect.size().y() - static_cast<float>(pending.region.rect.size().y());
auto& glyph = layout.glyphs.emplace_back();
glyph.is_emoji = pending.is_emoji;
glyph.glyph_index = pending.glyph_index;
glyph.position = { pending.start_x + pending.metrics.offset.x(),
baseline_y + pending.metrics.offset.y() + size_y_diff };
glyph.size = pending.metrics.rect.size();
glyph.region = pending.region;
glyph.is_emoji = pending.is_emoji;
glyph.position = { pending.start_x + pending.metrics.offset.x(),
baseline_y + pending.metrics.offset.y() + size_y_diff };
glyph.region = pending.region;
}
}
void update_line_metrics(text_layout_t::line_info_t& line, const font_v_metrics_t& font_metrics, float line_spacing) {
@@ -226,8 +224,10 @@ void font_manager::append_layout_text(
if (next_line) {
cursor_y = total_height;
cursor_x = 0.0f;
const auto last_index = current_line.line_index;
current_line = text_layout_t::line_info_t{};
current_line.max_line_height = default_line_height;
current_line.line_index = last_index + 1; // 增加行索引
}
};

View File

@@ -135,15 +135,14 @@ struct text_layout_t {
float max_line_height = 0.0f;
float current_width = 0.0f;
bool has_content = false;
uint32_t prev_glyph_id = 0;
uint32_t prev_glyph_id = 0;
uint32_t line_index = 0; // 行索引
std::vector<pending_glyph_t> glyphs;
};
struct glyph_position_t {
bool is_emoji; // 是否为表情符号
uint32_t glyph_index; // 字符码点
Eigen::Vector2f position; // 屏幕位置
Eigen::Vector2f size; // 字形尺寸
atlas_region_t region; // 纹理图集区域
};

View File

@@ -31,6 +31,8 @@ void platform_window::handle_mouse_wheel(const Eigen::Vector2f& in_window_pos, w
on_mouse_wheel_delegate.broadcast(in_window_pos, delta);
}
void platform_window::handle_mouse_leave() {
on_mouse_leave_delegate.broadcast();
}
void platform_window::handle_mouse_leave() { on_mouse_leave_delegate.broadcast(); }
void platform_window::handle_key_down(key_code key, key_action action) { on_key_down_delegate.broadcast(key, action); }
void platform_window::handle_key_up(key_code key, key_action action) { on_key_up_delegate.broadcast(key, action); }

View File

@@ -201,6 +201,20 @@ public:
*/
void handle_mouse_leave();
/**
* @brief 处理键盘按下事件
* @param key 按下的键
* @param action 键盘动作
*/
void handle_key_down(key_code key, key_action action);
/**
* @brief 处理键盘释放事件
* @param key 释放的键
* @param action 键盘动作
*/
void handle_key_up(key_code key, key_action action);
/**
* @brief 轮询所有窗口的事件
* @return 如果有活动窗口则返回true
@@ -243,6 +257,9 @@ public:
multicast_delegate<const Eigen::Vector2f&, wheel_event> on_mouse_wheel_delegate;
multicast_delegate<> on_mouse_leave_delegate;
multicast_delegate<key_code, key_action> on_key_down_delegate;
multicast_delegate<key_code, key_action> on_key_up_delegate;
inline static std::vector<platform_window*> windows;
private:
/** 原生窗口句柄 */

View File

@@ -251,6 +251,32 @@ namespace mouse_events {
}
} // namespace mouse_events
namespace key_events {
LRESULT handle_window_key_down(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
if (const auto window = get_window_from_hwnd(hwnd)) {
// 将Windows消息转换为应用程序定义的键盘动作
const auto action = platform_event_to_key_action(msg, w_param);
const auto key = platform_key_to_key_code(static_cast<int32_t>(w_param));
// 分发按键按下事件
window->handle_key_down(key, action);
}
return 0;
}
LRESULT handle_window_key_up(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
if (const auto window = get_window_from_hwnd(hwnd)) {
// 将Windows消息转换为应用程序定义的键盘动作
const auto action = platform_event_to_key_action(msg, w_param);
const auto key = platform_key_to_key_code(static_cast<int32_t>(w_param));
// 分发按键释放事件
window->handle_key_up(key, action);
}
return 0;
}
} // namespace key_events
namespace ime_events {
bool ime_char_pred(UINT msg) {
return msg == WM_IME_CHAR || msg == WM_CHAR;
@@ -387,6 +413,12 @@ windows_window_event_handler::windows_window_event_handler() {
// 检测所有鼠标滚轮事件
register_predicate_handler(mouse_events::mouse_wheel_pred, mouse_events::handle_window_mouse_wheel);
// 注册键盘事件处理器
register_event_handler(WM_KEYDOWN, key_events::handle_window_key_down);
register_event_handler(WM_SYSKEYDOWN, key_events::handle_window_key_down);
register_event_handler(WM_KEYUP, key_events::handle_window_key_up);
register_event_handler(WM_SYSKEYUP, key_events::handle_window_key_up);
// 注册IME事件处理器
register_event_handler(WM_IME_COMPOSITION, ime_events::handle_window_ime_composition);
register_event_handler(WM_IME_ENDCOMPOSITION, ime_events::handle_window_ime_end_composition);

View File

@@ -56,7 +56,7 @@ void meditable_text_box::on_paint(mirage_paint_context& in_context) {
);
if (is_focus()) {
const float line_height = layout_.last_line.max_line_height;
const auto& cursor_pos = layout_.last_cursor + Eigen::Vector2f(round_, round_);
const auto& cursor_pos = layout_.last_cursor + Eigen::Vector2f(round_, round_);
// 绘制光标
in_context.drawer().make_rounded_rect(
cursor_pos,
@@ -82,9 +82,14 @@ void meditable_text_box::arrange_children(const geometry_t& in_allotted_geometry
}
hit_test_handle meditable_text_box::on_mouse_button_down(const Eigen::Vector2f& in_position, mouse_button in_button) {
set_focus(true);
set_focus();
return hit_test_handle::handled();
}
void meditable_text_box::on_key_down(key_code in_key, key_action in_action) {
mleaf_widget<editable_text_box_args>::on_key_down(in_key, in_action);
bool is_repeat = in_action == key_action::repeat;
in_key == key_code::left;
}
void meditable_text_box::process_ime_char(char32_t c) {
text_changed_ = true;

View File

@@ -22,6 +22,7 @@ public:
virtual void arrange_children(const geometry_t& in_allotted_geometry) override;
virtual hit_test_handle on_mouse_button_down(const Eigen::Vector2f& in_position, mouse_button in_button) override;
virtual void on_key_down(key_code in_key, key_action in_action) override;
const auto& get_text() const { return text_; }
@@ -38,10 +39,11 @@ public:
private:
bool warp_text_ = false;
bool text_changed_ = false;
float font_size_ = .0f;
float font_size_ = 0.f;
float line_spacing_ = 1.f;
float cursor_alpha_ = 0.f;
Eigen::Vector2f no_warp_size_{};
Eigen::Vector2i cursor_pos_{}; // 光标位置 值是字符索引
text_layout_t layout_{};
std::u32string text_; // 最终显示的文本
std::u32string temp_text_; // 当前输入的文本

View File

@@ -107,3 +107,17 @@ bool mwidget_interface::can_hit_test() const {
return true;
}
auto mwidget_interface::is_focus() const -> bool {
const auto window = get_window();
if (!window) {
return false;
}
return window->get_focused_widget() == shared_from_this();
}
void mwidget_interface::set_focus() {
const auto window = get_window();
if (!window)
return;
window->set_focused_widget(shared_from_this());
}

View File

@@ -1,8 +1,8 @@
#pragma once
#include "misc/invalidate_reason.h"
#include "widget_tree/hit_test_result.h"
#include "render/mirage_paint_context.h"
#include "misc/key_type/key_type.h"
#include "render/mirage_paint_context.h"
#include "widget_tree/hit_test_result.h"
class mwindow;
@@ -120,28 +120,30 @@ public:
// -------------- 键盘事件处理 --------------
/**
* @brief 处理键盘按下事件
* @param in_key 按下的键
* @param in_action 按键动作
*/
virtual void on_key_down(key_code in_key, key_action in_action) {}
/**
* @brief 处理键盘释放事件
* @param in_key 释放的键
* @param in_action 按键动作
*/
virtual void on_key_up(key_code in_key, key_action in_action) {}
// -------------- 焦点事件处理 --------------
auto is_focusable() const { return is_focusable_; }
void set_focusable(bool in_focusable) { is_focusable_ = in_focusable; }
auto is_focus() const { return is_focus_; }
void set_focus(bool in_focus) {
if (!is_focusable())
in_focus = false;
if (is_focus_ == in_focus)
return;
is_focus_ = in_focus;
if (is_focus_)
on_got_focus();
else
on_lost_focus();
}
auto is_focus() const -> bool;
void set_focus();
virtual void on_got_focus() {}
virtual void on_lost_focus() {}
protected:
bool enabled_ = true;
bool is_focusable_ = false;
bool is_focus_ = false;
invalidate_reason invalidate_{};
visibility_t visibility_ = visibility_t::self_hit_test_invisible;
std::optional<Eigen::Vector2f> desired_size_{};

View File

@@ -177,6 +177,49 @@ public:
*/
[[nodiscard]] auto get_platform_handle() const -> void*;
/**
* @brief 获取当前焦点控件
* @return 当前焦点控件的弱引用
*/
[[nodiscard]] auto get_focused_widget() const {
if (focused_widget_.expired())
return std::shared_ptr<mwidget_interface>{};
return focused_widget_.lock();
}
/**
* @brief 设置当前焦点控件
* @param widget 要设置为焦点的控件
*/
void set_focused_widget(const std::shared_ptr<mwidget_interface>& widget) {
const auto focused = focused_widget_.lock();
if (focused == widget) {
return; // 如果已经是同一个控件,则不需要处理
}
// 如果新的控件不存在,或者不可聚焦,则不处理
if (!widget || !widget->is_focusable()) {
return;
}
// 如果有焦点控件,先通知其失去焦点
if (focused) {
focused->on_lost_focus();
}
focused_widget_ = widget;
// 通知新的控件获得焦点
widget->on_got_focus();
}
/**
* @brief 清除当前焦点控件
* 如果当前焦点控件存在,则通知其失去焦点
*/
void clear_focused_widget() {
set_focused_widget(nullptr);
}
//-------------- 事件通知 --------------
/** 窗口关闭事件委托 */
multicast_delegate<mwindow*> on_close_delegate;
@@ -199,6 +242,8 @@ private:
class impl;
// 实现的实例
std::unique_ptr<impl> pimpl_;
// 当前焦点控件
std::weak_ptr<mwidget_interface> focused_widget_{};
// 静态窗口集合,使用弱引用管理
inline static std::vector<std::weak_ptr<mwindow>> windows_;

View File

@@ -53,11 +53,13 @@ public:
platform_window_->on_mouse_wheel_delegate.add_raw(this, &impl::process_mouse_wheel);
platform_window_->on_mouse_leave_delegate.add_raw(this, &impl::process_mouse_leave);
platform_window_->on_mouse_button_dbl_delegate.add_raw(this, &impl::process_mouse_button_dbl);
platform_window_->on_key_down_delegate.add_raw(this, &impl::process_key_down);
platform_window_->on_key_up_delegate.add_raw(this, &impl::process_key_up);
// 创建窗口渲染状态
const auto& window_frame_size = platform_window_->get_window_frame_size();
window_state_ = mirage_render_context::get()->create_window_state(window_frame_size,
platform_window_->get_window_handle());
const auto& window_frame_size = platform_window_->get_window_frame_size();
window_state_ = mirage_render_context::get()->create_window_state(window_frame_size,
platform_window_->get_window_handle());
// 初始化渲染上下文
paint_context_.init(window_frame_size);
@@ -150,32 +152,32 @@ public:
}
// 几何与变换
float get_dpi_scale() const {
[[nodiscard]] float get_dpi_scale() const {
return dpi_helper::global_scale() * platform_window_->get_window_dpi_scale();
}
transform2d get_local_to_screen_transform() const {
return transform2d(
[[nodiscard]] transform2d get_local_to_screen_transform() const {
return {
platform_window_->get_window_position().cast<float>(),
0,
{ get_dpi_scale(), get_dpi_scale() }
);
};
}
transform2d get_local_to_window_transform() const {
return transform2d(
[[nodiscard]] transform2d get_local_to_window_transform() const {
return {
{0, 0},
0,
{ get_dpi_scale(), get_dpi_scale() }
);
};
}
geometry_t get_window_geometry_in_screen() const {
[[nodiscard]] geometry_t get_window_geometry_in_screen() const {
const auto& local_to_screen = get_local_to_screen_transform();
return { platform_window_->get_window_frame_size().cast<float>(), local_to_screen, {} };
}
geometry_t get_window_geometry_in_window() const {
[[nodiscard]] geometry_t get_window_geometry_in_window() const {
const auto& local_to_window = get_local_to_window_transform();
return { platform_window_->get_window_frame_size().cast<float>(), local_to_window, local_to_window };
}
@@ -389,8 +391,7 @@ public:
}
void process_mouse_button_dbl(const Eigen::Vector2f& window_pos, mouse_button button) {
std::shared_ptr<mwidget_interface> hover_widget = mouse_.hover_widget.lock();
if (hover_widget) {
if (std::shared_ptr<mwidget_interface> hover_widget = mouse_.hover_widget.lock()) {
hover_widget->on_double_click(window_pos, button);
}
}
@@ -409,6 +410,16 @@ public:
mouse_.hover_widget.reset();
}
void process_key_down(key_code key, key_action action) {
if (auto focused = owner_->get_focused_widget())
focused->on_key_down(key, action);
}
void process_key_up(key_code key, key_action action) {
if (auto focused = owner_->get_focused_widget())
focused->on_key_up(key, action);
}
// 命中测试
hit_test_result perform_hit_test(
const Eigen::Vector2f& window_pos,