core: 添加 pointer enter 事件
This commit is contained in:
@@ -31,7 +31,8 @@ request event,而不是直接改 core 状态。
|
||||
4. =policy=
|
||||
负责把事件路由为命令,并把命令应用到状态。
|
||||
=WM_EVENT_KEY_PRESS= / =WM_EVENT_POINTER_BUTTON_PRESS= 的路由都使用 bootstrap
|
||||
固定下来的输入绑定表。
|
||||
固定下来的输入绑定表;像 =WM_EVENT_POINTER_ENTER= 这种不经绑定的输入事实,
|
||||
则由 policy 配置决定是否转换为 =FOCUS_WINDOW=。
|
||||
|
||||
5. =layout=
|
||||
负责为某个输出上当前显示的工作区中的平铺窗口计算外框几何。
|
||||
@@ -224,16 +225,19 @@ end
|
||||
1. =focus_raises=
|
||||
焦点切换时是否隐式执行 raise。
|
||||
|
||||
2. =sticky_windows_participate_in_direction_focus=
|
||||
2. =pointer_enter_focuses_window=
|
||||
收到 =WM_EVENT_POINTER_ENTER= 时是否切换焦点(focus-follows-mouse)。
|
||||
|
||||
3. =sticky_windows_participate_in_direction_focus=
|
||||
sticky 窗口是否参与方向焦点搜索。
|
||||
|
||||
3. =manage_sets_focus=
|
||||
4. =manage_sets_focus=
|
||||
新受管窗口是否默认夺取所属 workspace 的焦点。
|
||||
|
||||
4. =switch_workspace_restores_last_focus=
|
||||
5. =switch_workspace_restores_last_focus=
|
||||
切换工作区时是否恢复该 workspace 的最近焦点。
|
||||
|
||||
5. =minimize_clears_focus=
|
||||
6. =minimize_clears_focus=
|
||||
最小化当前焦点窗口时是否清空或重选该 workspace 焦点。
|
||||
|
||||
* 边框约定
|
||||
|
||||
@@ -26,6 +26,7 @@ void wm_runtime_process_event(wm_runtime_t *runtime, const wm_event_t *event) {
|
||||
if (!consumed) {
|
||||
wm_policy_route_event(
|
||||
&runtime->state,
|
||||
&runtime->policy,
|
||||
&runtime->keybindings,
|
||||
&runtime->pointer_bindings,
|
||||
event,
|
||||
@@ -320,6 +321,7 @@ typedef struct wm_runtime_bootstrap_t {
|
||||
|
||||
#+BEGIN_SRC c
|
||||
bool wm_policy_route_event(const wm_state_t *state,
|
||||
const wm_policy_config_t *policy,
|
||||
const wm_key_binding_table_t *keybindings,
|
||||
const wm_pointer_binding_table_t *pointer_bindings,
|
||||
const wm_event_t *event,
|
||||
@@ -333,6 +335,10 @@ bool wm_policy_route_event(const wm_state_t *state,
|
||||
return route_pointer_press(state, pointer_bindings,
|
||||
&event->data.pointer_button_press, out);
|
||||
|
||||
case WM_EVENT_POINTER_ENTER:
|
||||
return route_pointer_enter(state, policy,
|
||||
&event->data.pointer_enter, out);
|
||||
|
||||
case WM_EVENT_WINDOW_MAP_REQUEST:
|
||||
return route_map_request(state, &event->data.window_map_request, out);
|
||||
|
||||
@@ -514,6 +520,43 @@ static bool route_pointer_press(const wm_state_t *state,
|
||||
return wm_command_buffer_push(out, cmd);
|
||||
}
|
||||
|
||||
static bool route_pointer_enter(const wm_state_t *state,
|
||||
const wm_policy_config_t *policy,
|
||||
const wm_pointer_enter_event_t *e,
|
||||
wm_command_buffer_t *out) {
|
||||
const wm_window_t *win;
|
||||
const wm_workspace_t *ws;
|
||||
|
||||
if (!policy->pointer_enter_focuses_window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e->window == WM_WINDOW_ID_INVALID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
win = wm_state_window_get(state, e->window);
|
||||
if (!win) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (win->workspace_id >= state->workspace_count) {
|
||||
return false;
|
||||
}
|
||||
ws = &state->workspaces[win->workspace_id];
|
||||
|
||||
if (ws->focused_window_id == win->id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return wm_command_buffer_push(out, (wm_command_t){
|
||||
.type = WM_COMMAND_FOCUS_WINDOW,
|
||||
.as.focus_window = {
|
||||
.window_id = win->id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 窗口映射请求路由
|
||||
static bool route_map_request(const wm_state_t *state,
|
||||
const wm_window_map_request_event_t *e,
|
||||
@@ -757,6 +800,7 @@ static bool route_move_floating_event(wm_runtime_t *runtime,
|
||||
|---------|---------------|------|
|
||||
| KEY_PRESS | 任意命令(通过键盘绑定) | 绑定存在 |
|
||||
| POINTER_BUTTON_PRESS | 任意窗口命令 / BEGIN_*_INTERACTION(通过鼠标绑定) | 绑定存在 |
|
||||
| POINTER_ENTER | FOCUS_WINDOW | policy.pointer_enter_focuses_window == true 且窗口已管理 |
|
||||
| WINDOW_MAP_REQUEST | MANAGE_WINDOW | 窗口未管理 |
|
||||
| WINDOW_REMOVE | UNMANAGE_WINDOW | 窗口已管理 |
|
||||
| WINDOW_ACTIVATE_REQUEST | SWITCH_WORKSPACE + FOCUS_WINDOW / SET_WINDOW_URGENT | source == pager / source != pager |
|
||||
@@ -768,9 +812,11 @@ static bool route_move_floating_event(wm_runtime_t *runtime,
|
||||
|
||||
1. `WM_EVENT_CONFIGURE_REQUEST` 只携带稀疏几何字段,不直接镜像 X11 全量协议载荷。
|
||||
2. 最小核心当前只会把这些几何请求映射到 floating 窗口的 move/resize 语义。
|
||||
3. `border_width` / `sibling` / `stack_mode` 这类协议细节留在 backend / adapter 层。
|
||||
4. fullscreen / maximize / minimize 这类窗口模式切换不属于 configure request。
|
||||
5. `WM_EVENT_WINDOW_STATE_REQUEST` 表达后端看到的原始 add/remove/toggle 请求;
|
||||
3. `WM_EVENT_POINTER_ENTER` 是“pointer focus 进入窗口”的输入事实,不经过 pointer binding 表。
|
||||
4. 类似 `raise_or_run` 这类程序化恢复鼠标位置导致的单次 crossing 抑制,应由 runtime 维护瞬时状态后在路由前过滤,而不是下沉到 backend 业务逻辑。
|
||||
5. `border_width` / `sibling` / `stack_mode` 这类协议细节留在 backend / adapter 层。
|
||||
6. fullscreen / maximize / minimize 这类窗口模式切换不属于 configure request。
|
||||
7. `WM_EVENT_WINDOW_STATE_REQUEST` 表达后端看到的原始 add/remove/toggle 请求;
|
||||
core command 仍保持 =SET_*= 这种最终状态语义。
|
||||
|
||||
* 事件处理的边界条件
|
||||
|
||||
@@ -16,6 +16,8 @@ typedef enum wm_event_type_t {
|
||||
WM_EVENT_POINTER_BUTTON_PRESS,
|
||||
WM_EVENT_POINTER_BUTTON_RELEASE,
|
||||
WM_EVENT_POINTER_MOTION,
|
||||
// 指针焦点进入某个窗口;对应 X11 EnterNotify / Wayland wl_pointer.enter
|
||||
WM_EVENT_POINTER_ENTER,
|
||||
WM_EVENT_WINDOW_MAP_REQUEST,
|
||||
WM_EVENT_WINDOW_REMOVE,
|
||||
WM_EVENT_WINDOW_METADATA_CHANGED,
|
||||
@@ -64,6 +66,15 @@ typedef struct wm_pointer_motion_event_t {
|
||||
wm_window_id_t window;
|
||||
} wm_pointer_motion_event_t;
|
||||
|
||||
typedef struct wm_pointer_enter_event_t {
|
||||
// 全局桌面坐标
|
||||
wm_point_t root;
|
||||
// 相对 window 的坐标;若 window == WM_WINDOW_ID_INVALID,则该值未定义
|
||||
wm_point_t local;
|
||||
// 当前进入并获得 pointer focus 的窗口;若未命中窗口,则为 WM_WINDOW_ID_INVALID
|
||||
wm_window_id_t window;
|
||||
} wm_pointer_enter_event_t;
|
||||
|
||||
typedef struct wm_window_map_request_event_t {
|
||||
wm_window_info_t info;
|
||||
// 仅用于 manage 路由判断,不进入持久 state
|
||||
@@ -204,6 +215,7 @@ typedef struct wm_event_t {
|
||||
wm_pointer_button_event_t pointer_button_press;
|
||||
wm_pointer_button_event_t pointer_button_release;
|
||||
wm_pointer_motion_event_t pointer_motion;
|
||||
wm_pointer_enter_event_t pointer_enter;
|
||||
wm_window_map_request_event_t window_map_request;
|
||||
wm_window_remove_event_t window_remove;
|
||||
wm_window_metadata_changed_event_t window_metadata_changed;
|
||||
|
||||
@@ -21,6 +21,7 @@ void wm_command_buffer_shutdown(wm_command_buffer_t *buffer);
|
||||
bool wm_command_buffer_push(wm_command_buffer_t *buffer, wm_command_t command);
|
||||
|
||||
bool wm_policy_route_event(const wm_state_t *state,
|
||||
const wm_policy_config_t *policy,
|
||||
const wm_key_binding_table_t *keybindings,
|
||||
const wm_pointer_binding_table_t *pointer_bindings,
|
||||
const wm_event_t *event,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
typedef struct wm_policy_config_t {
|
||||
bool focus_raises;
|
||||
bool pointer_enter_focuses_window;
|
||||
bool sticky_windows_participate_in_direction_focus;
|
||||
bool manage_sets_focus;
|
||||
bool switch_workspace_restores_last_focus;
|
||||
|
||||
Reference in New Issue
Block a user