实现键盘事件
This commit is contained in:
@@ -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 平台原生事件类型
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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; // 增加行索引
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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; // 纹理图集区域
|
||||
};
|
||||
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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:
|
||||
/** 原生窗口句柄 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_; // 当前输入的文本
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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_{};
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user