Compare commits
3 Commits
8f671bd755
...
079f41ce8a
| Author | SHA1 | Date | |
|---|---|---|---|
|
079f41ce8a
|
|||
|
e1113c0052
|
|||
|
bf3de7fb92
|
@@ -6,12 +6,6 @@ IndentWidth: 2
|
|||||||
ConstructorInitializerIndentWidth: 2
|
ConstructorInitializerIndentWidth: 2
|
||||||
ContinuationIndentWidth: 2
|
ContinuationIndentWidth: 2
|
||||||
|
|
||||||
AlignConsecutiveAssignments:
|
|
||||||
Enabled: true
|
|
||||||
AcrossEmptyLines: false
|
|
||||||
AcrossComments: false
|
|
||||||
AlignCompound: true
|
|
||||||
PadOperators: true
|
|
||||||
AlignConsecutiveBitFields:
|
AlignConsecutiveBitFields:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
|||||||
@@ -42,15 +42,18 @@ add_executable(${APP_NAME}
|
|||||||
${SOURCE_DIR}/base/log.c
|
${SOURCE_DIR}/base/log.c
|
||||||
${SOURCE_DIR}/base/process.c
|
${SOURCE_DIR}/base/process.c
|
||||||
${SOURCE_DIR}/base/time.c
|
${SOURCE_DIR}/base/time.c
|
||||||
${SOURCE_DIR}/base/window_list.c
|
|
||||||
|
|
||||||
${SOURCE_DIR}/config/defaults.c
|
${SOURCE_DIR}/config/defaults.c
|
||||||
${SOURCE_DIR}/config/loader.c
|
${SOURCE_DIR}/config/loader.c
|
||||||
${SOURCE_DIR}/config/runtime_config.c
|
${SOURCE_DIR}/config/runtime_config.c
|
||||||
|
|
||||||
|
${SOURCE_DIR}/common/event.c
|
||||||
|
${SOURCE_DIR}/common/listeners.c
|
||||||
|
${SOURCE_DIR}/common/window.c
|
||||||
|
${SOURCE_DIR}/common/workspace.c
|
||||||
|
|
||||||
${SOURCE_DIR}/core/binding.c
|
${SOURCE_DIR}/core/binding.c
|
||||||
${SOURCE_DIR}/core/command_buffer.c
|
${SOURCE_DIR}/core/command_buffer.c
|
||||||
${SOURCE_DIR}/core/event.c
|
|
||||||
${SOURCE_DIR}/core/layer.c
|
${SOURCE_DIR}/core/layer.c
|
||||||
${SOURCE_DIR}/core/layout.c
|
${SOURCE_DIR}/core/layout.c
|
||||||
${SOURCE_DIR}/core/listeners.c
|
${SOURCE_DIR}/core/listeners.c
|
||||||
|
|||||||
136
docs/module-layering.org
Normal file
136
docs/module-layering.org
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
#+title: ZDWM 模块分层与依赖方向
|
||||||
|
#+OPTIONS: toc:2
|
||||||
|
|
||||||
|
* 动机
|
||||||
|
|
||||||
|
随着模块增加,跨模块的"契约"和"共享数据结构"开始散落:有的进了 =core/=(和窗口管理逻辑混在一起),有的不得不靠依赖倒置塞进消费方目录(如 tray 契约放 =bar/= 导致 backend 反向依赖 bar)。结果是 core 职责不清、=bar ↔ backend= 出现交叉依赖、依赖方向不再单向。
|
||||||
|
|
||||||
|
本文档定义一套分层约定,把"跨模块共享的东西"从具体实现里抽出来,集中到两个目录,使依赖方向回到干净的单向。
|
||||||
|
|
||||||
|
* 核心标准:按"谁直接消费类型"归类
|
||||||
|
|
||||||
|
判断一个跨模块的东西进哪个目录,不看它"属于哪个模块",也不只看"是声明还是实现",而是看**它的类型被哪些层直接消费**:
|
||||||
|
|
||||||
|
- 类型被**两个或以上对等的实现层**直接消费 → 类型放 =interface/=(跨模块声明)
|
||||||
|
- 只有**操作函数**被多个实现层共用、且这些层不该互相依赖 → 操作放 =common/=
|
||||||
|
- 类型 + 操作都只被一个实现层(及其依赖者)用 → 整个 ADT 放 =common/=,或就近放该实现层
|
||||||
|
|
||||||
|
关键推论:**只需消费"类型"的层,不该被迫背上"操作函数"的依赖**。这是把类型和操作分到两个目录的根本理由。
|
||||||
|
|
||||||
|
* 目录的定位
|
||||||
|
|
||||||
|
先明确三层关系:=base/= 是**项目无关**的通用底层(任何 C 项目都能直接用),=interface/= 和 =common/= 是**项目业务相关**的通用内容。后两者依赖前者(业务依赖基础设施)。
|
||||||
|
|
||||||
|
** =src/base/= :项目无关的通用底层,零业务依赖
|
||||||
|
|
||||||
|
放任何 C 项目都能直接用的纯工具(=memory= / =array= / =macros= / =color= / =log= / =time= / =process=)。不依赖 interface/common/任何实现层——它根本不知道 ZDWM 的业务。=interface/= 和 =common/= 都可以依赖它。
|
||||||
|
|
||||||
|
** =src/interface/= :跨模块共享的【声明】,零 .c
|
||||||
|
|
||||||
|
只放类型定义、多态接口的函数声明。绝对不放假装、零实现代码。被所有实现层依赖,自身不依赖任何实现层(可依赖 =base/= 的纯类型)。
|
||||||
|
|
||||||
|
** =src/common/= :被多实现层共用的【操作函数】,.h + .c
|
||||||
|
|
||||||
|
放自包含的 ADT 操作(构造/清理/查询)。操作只依赖 =interface/= 里的类型(和 =base/= 工具),不依赖任何实现层的内部状态。被"需要这些操作的层"依赖。
|
||||||
|
|
||||||
|
注意:=common/= 不是"什么都往里塞的杂物间"。只有当操作被**多个不该互相依赖的实现层**共用时,才进 =common/=;只被单一实现层用的操作,就近放该层。
|
||||||
|
|
||||||
|
* 依赖方向
|
||||||
|
|
||||||
|
#+begin_example
|
||||||
|
base/ ← 项目无关的通用底层(任何 C 项目可用),零业务依赖
|
||||||
|
↑
|
||||||
|
interface/ ← 零业务依赖(纯类型声明,含 backend 抽象接口);可依赖 base
|
||||||
|
↑
|
||||||
|
common/ ← 项目业务通用的共享 ADT 操作;依赖 interface + base
|
||||||
|
↑
|
||||||
|
core/ runtime/ backend/ bar/ ← 实现层,都依赖 common + interface(+ base)
|
||||||
|
#+end_example
|
||||||
|
|
||||||
|
注意:没有实现层"只依赖 interface"——所有实现层都用 =common/= 的业务通用操作。interface 的纯净性约束的是 interface *内部*(含 backend 抽象接口不依赖 interface 之外的任何东西),不是约束某个实现层的依赖深度。
|
||||||
|
|
||||||
|
不变量:
|
||||||
|
- =base/= 不依赖任何业务层(interface/common/实现层),是项目无关的纯工具。
|
||||||
|
- =interface/=(含 backend 抽象接口)不依赖 =interface/= 之外的任何业务内容;可依赖 =base/= 的纯类型(业务层依赖基础设施,合理)。
|
||||||
|
- =common/= 只依赖 =interface/= 和 =base/=,不依赖任何实现层。
|
||||||
|
- 所有实现层(core/runtime/backend/bar)都依赖 =common/= + =interface/=(+ =base/=);它们之间不直接相互依赖跨模块契约,都经由 =interface/= 或 =common/=。
|
||||||
|
- 因此 =bar ↔ backend= 这类对等层之间不再有交叉依赖:都通过 =interface/tray.h= 通信。
|
||||||
|
|
||||||
|
* 判定示例:effect / plan / event / listeners
|
||||||
|
|
||||||
|
用上面的标准,逐个判定现有跨模块类型:
|
||||||
|
|
||||||
|
** =effect_t= → interface(类型),无 .c
|
||||||
|
|
||||||
|
消费方:core(policy/plan 产生 =effect_t=)+ backend(执行 =effect_t=)。两个对等层直接消费类型,所以类型进 =interface/effect.h=。=effect_t= 是纯数据,构造它的活(=plan_push_*=)属于 plan 的操作,所以 effect 在 interface 里只有类型、没有 .c。
|
||||||
|
|
||||||
|
#+begin_src c
|
||||||
|
/* backend 只消费展开后的 effect 数组,从不碰 plan_t */
|
||||||
|
bool backend_apply_effect(backend_t *backend, const effect_t *effects, size_t effect_count);
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** =plan_t= → 留 core(完整 ADT:类型 + 操作)
|
||||||
|
|
||||||
|
消费方:只 core(policy 产生、收集 effect)和 runtime(提交后 reset/cleanup)。两者之间是 *runtime→core 的天然单向依赖*(runtime 是桥接层,本就依赖 core 的 policy/state 等)。把 =plan_t= 放 =core/plan.h= + =core/plan.c=,runtime 正向 include 即可,不破坏任何方向——所以它*不必*进 common。
|
||||||
|
|
||||||
|
这把 common 的门槛精确化:common 是为"对等、无天然依赖"的消费者中立化(见下文 =listeners_t=);若消费者之间已有单向依赖(如 plan 的 core+runtime),共享操作放被依赖方(core)即可,不必上浮 common。
|
||||||
|
|
||||||
|
** =event_t= → interface(类型)+ common(操作)
|
||||||
|
|
||||||
|
=event_t= 类型进 =interface/event.h= 的关键理由:interface 内的 =backend.h= 契约直接 *#include 了 event.h*——=backend_poll_event= / =backend_next_event= 的参数是 =event_t *=,且契约注释讨论 event 的所有权与 =event_cleanup= 语义。一份完整的后端契约要让读者看到 event_t 全貌(字段、联合、生命周期责任),而非甩一个前向声明。所以 event_t 必须在 interface:若放 common,=backend.h= 要么退化为前向声明(契约不完整),要么 interface 反向依赖 common(破坏零依赖)。
|
||||||
|
|
||||||
|
=event_reset= / =event_cleanup= 这些操作被 backend 和 runtime 共用,两者对等、不该互相依赖 → 操作落 =common/event.h= + =common/event.c=。于是 event 是"类型在 interface、操作在 common"的典型。
|
||||||
|
|
||||||
|
** =listeners_t= → common(类型 + 维护)+ core(notify)
|
||||||
|
|
||||||
|
=listeners_t= 类型被 bar(订阅)、core(发布)、runtime(生命周期)消费,但 **backend 完全不碰它**。判定关键:它的消费者(bar/config/runtime)都*既用类型又用维护操作*(=add_*= / =cleanup=),没有哪个层"只需类型、不需操作"——按核心推论(只有"只需消费类型"的层才迫使类型单独上提 interface),类型不必进 interface。与 =event_t= 的对照就在这里:=event_t= 因被 interface 内的 =backend.h= 契约需要完整定义而必须留 interface;=listeners_t= 则*不被 interface 内任何契约依赖*(=backend.h= 完全不碰它),所以能整个进 common:
|
||||||
|
|
||||||
|
- 类型 =listeners_t= + 维护操作 =add_*= / =cleanup=:自包含容器操作,被 bar/config/runtime 多个对等层共用 → 整个 ADT 进 =common/listeners.{h,c}=。
|
||||||
|
- =notify_*=(触发):单消费者(只 core/runtime 发布侧调用),且依赖 core 内部(把 =state_t= 翻译成 =zdwm_window_t= 等 DTO)→ 声明 + 实现都留 =core/listeners=。
|
||||||
|
|
||||||
|
真正的跨层契约(回调签名 =zdwm_window_added= 等 + DTO)已在 =include/zdwm/listeners.h=(比 interface 更公开的那层),=listeners_t= 只是这些回调的容器,所以它整个待在 common 自洽,不必单独占一个 interface 头。
|
||||||
|
|
||||||
|
* 汇总表
|
||||||
|
|
||||||
|
| 东西 | 类型在哪 | 操作在哪 | 判定理由 |
|
||||||
|
|------------------------------+-----------------------+-------------------------------------------+--------------------------------------------------------------------------|
|
||||||
|
| =effect_t= | =interface/effect.h= | (无,构造归 plan 操作) | 类型跨模块(core 产 + backend 执行),纯数据 |
|
||||||
|
| =plan_t= | =core/plan.h= | =core/plan.c= | 消费者 runtime→core 单向,放 core 不破坏方向,不必 common |
|
||||||
|
| =event_t= | =interface/event.h= | =common/event.h= + =common/event.c= | 类型跨模块;操作对等共用 |
|
||||||
|
| 后端接口(=backend_t= 等) | =interface/backend.h= | =backend/x11/*.c= | 多态接口:声明在 interface,实现在具体后端 |
|
||||||
|
| tray 契约(=tray_t= 等) | =interface/tray.h= | =backend/x11/tray.c= | 多态接口:bar 用、backend 实现,声明在 interface 消除 =bar↔backend= 交叉 |
|
||||||
|
| 通知协议(listeners) | =common/listeners.h= | =common/listeners.c= + =core/listeners.c= | 消费者 bar↔core 对等,必须 common 中立化;notify 依赖 core 留 core |
|
||||||
|
| 基础类型(=window_id_t= 等) | =interface/types.h= | (按需) | 所有层共用 |
|
||||||
|
|
||||||
|
* 多态接口 vs 共享 ADT:.c 归属的不同
|
||||||
|
|
||||||
|
=interface/= 里有两类声明,它们的 .c 归属不同,务必区分:
|
||||||
|
|
||||||
|
- **多态接口**(=backend.h=、=tray.h=):声明一组"由谁来实现"的函数,实现依赖具体实现层(xcb / 未来 wayland)。这类 .c **必须在实现层**(=backend/x11/=、=core/=),不能在 interface——否则 interface 就"知道"了具体实现。
|
||||||
|
- **共享 ADT 的操作**(event 的操作):实现自包含、不依赖任何实现层。这类 .c 进 =common/=。
|
||||||
|
|
||||||
|
换句话说:=interface/= 永远零 .c。多态接口的 .c 在实现层,共享操作的 .c 在 =common/=。
|
||||||
|
|
||||||
|
* 和 include/zdwm/ 的区别
|
||||||
|
|
||||||
|
- =include/zdwm/= 是**对外公共 API**(给用户配置、插件使用)。
|
||||||
|
- =src/interface/= 是**内部跨模块契约**(给各子系统互相通信)。
|
||||||
|
|
||||||
|
两者职责不同,不合并。像 =backend.h=、=event.h=、=effect.h= 是内部的,不该进 =include/zdwm/= 暴露给外部。
|
||||||
|
|
||||||
|
* 迁移指引
|
||||||
|
|
||||||
|
把现有代码按本分层整理时,建议顺序:
|
||||||
|
|
||||||
|
1. 建 =src/interface/= 和 =src/common/= 目录,加入 CMakeLists。
|
||||||
|
2. 先迁移"纯类型、零依赖"的声明进 =interface/=:=types.h=、=effect.h=(从 =core/plan.h= 抽出 =effect_t=)、=event.h= 的类型部分。
|
||||||
|
3. 多态接口声明迁移:=backend.h= 进 =interface/=(=.c= 留原处)。=listeners= 走共享 ADT、不进 interface:=listeners_t= 类型 + =add_*= / =cleanup= 整体进 =common/listeners.{h,c}=,=notify_*= 留 =core/listeners=(详见上方判定示例)。
|
||||||
|
4. 共享 ADT 迁移:=event.h= 操作部分 + =event.c= 进 =common/=。(=plan= 留 core:消费者 runtime→core 单向,不必上浮。)
|
||||||
|
5. 更新全项目 include 路径(="core/types.h"= → ="interface/types.h"= 等)。
|
||||||
|
6. 每步后编译验证,确保依赖方向单向、无循环。
|
||||||
|
|
||||||
|
注意边界:遇到"看起来该进 interface、但其类型依赖还在 core"的情况(如某个 event 子结构引用了 =core/window.h= 的类型),要么把那个被引用的类型也提到 =interface/=,要么承认它暂不进 interface——**进 interface 的前提是它的所有依赖都在 interface**,不能硬塞。
|
||||||
|
|
||||||
|
* tray 的落点
|
||||||
|
|
||||||
|
tray 的契约(=tray_t= / =tray_api_t=)是 bar 与 backend 之间的多态接口,按本分层落 =interface/tray.h=(声明),实现在 =backend/x11/tray.c=。这样 bar 和 backend 都只依赖 =interface/tray.h=,彻底消除 =bar ↔ backend= 交叉依赖——这正是引入这套分层的最初动机之一。详见 [[file:tray-design.org][tray-design.org]]。
|
||||||
256
docs/tray-design.org
Normal file
256
docs/tray-design.org
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
#+title: ZDWM Tray 系统托盘设计
|
||||||
|
#+OPTIONS: toc:2
|
||||||
|
|
||||||
|
* 背景与动机
|
||||||
|
|
||||||
|
ZDWM 当前没有系统托盘(system tray / systray)功能。本文档描述如何在 bar 中实现 X11 系统托盘,让外部应用(输入法、音量、蓝牙、网络等)的托盘图标显示在状态栏右侧并正常交互,同时保持现有前后端分离架构,为未来 Wayland 后端预留扩展空间。
|
||||||
|
|
||||||
|
* 设计目标与约束
|
||||||
|
|
||||||
|
** 前后端分离
|
||||||
|
|
||||||
|
tray 协议(=_NET_SYSTEM_TRAY= + XEMBED)必须*闭环在后端内部*。core 的 =event_t= / =policy= / =plan= 完全不感知 tray——tray 不产生 =event_t=、不进 policy 路由、不进 plan/effect。
|
||||||
|
|
||||||
|
这与现有架构的三条解耦通道一致:
|
||||||
|
- =backend -> core=:后端把平台原始事件归一化为 =event_t=
|
||||||
|
- =core -> backend=:core 产出 =effect_t=,后端执行
|
||||||
|
- =runtime= 作为唯一桥接点:bar 模块本身拿不到 backend,所有平台访问经 runtime 中转
|
||||||
|
|
||||||
|
** Wayland 预留
|
||||||
|
|
||||||
|
bar 与 runtime 层必须后端无关、零 xcb。未来加 Wayland 后端时,只需新增一个后端实现——Wayland 用 StatusNotifierItem(SNI)over D-Bus,icon 是像素数据而非真实窗口,由前端 cairo 绘制。只要后端接口形状不变,上层(bar/runtime)零改动。
|
||||||
|
|
||||||
|
** tray 是 bar 的附属组件
|
||||||
|
|
||||||
|
没有 bar 就没有 tray。tray 的生命周期随 bar 窗口,*不*作为独立公共接口(不进 =include/zdwm/=)。tray 能力内嵌在 bar 窗口的创建/销毁里。
|
||||||
|
|
||||||
|
* 方案选型:嵌入式容器子窗口(A')
|
||||||
|
|
||||||
|
X11 系统托盘协议只要求:tray 创建一个 window 成为 =_NET_SYSTEM_TRAY_S<n>= 的 selection owner,客户端向 owner 发 =_NET_SYSTEM_TRAY_REQUEST_DOCK= 请求,tray 用 XEMBED reparent icon。协议本身*不*规定 icon reparent 到 bar 窗口还是独立窗口。
|
||||||
|
|
||||||
|
** 为何不用独立 top-level 窗口
|
||||||
|
|
||||||
|
完全独立的 top-level tray 窗口(如 stalonetray)是为*没有状态栏*的环境设计的。ZDWM 已有 bar,用独立窗口会引入"两个窗口的几何/对齐同步"问题(tray 窗口要贴 bar 右端、随 icon 数动态 resize、跟随 bar 移动),且无功能收益。
|
||||||
|
|
||||||
|
** 为何用专门的容器子窗口
|
||||||
|
|
||||||
|
虽然直接 reparent 到 bar 的 cairo 绘制窗口技术上可行(bar 已是 ARGB,子窗口叠加在 cairo 内容之上),但用一个*专门的 tray 容器子窗口*做 selection owner 更正统、更干净:
|
||||||
|
|
||||||
|
1. *职责分离*:bar 窗口专注 cairo 绘制,tray 容器专注 XEMBED / icon 管理。dock 请求和 =_XEMBED= 消息定向到容器,不进 bar 的 =handle_client_message=。
|
||||||
|
2. *事件隔离*:tray 协议事件在容器窗口闭环,bar 的窗口管理事件流零污染。
|
||||||
|
3. *视觉不变*:容器是 bar 窗口的子窗口,位于 tray region 内,icon 跟随 bar 移动/resize(X 子窗口语义),不占额外屏幕空间。
|
||||||
|
|
||||||
|
* 后端接口设计
|
||||||
|
|
||||||
|
tray 契约独立成头 =src/bar/tray.h= —— *不放 core*,因为 tray 与 core 无关(core 不感知 tray)。由 bar 定义、后端实现(消费方定义接口、提供方实现的依赖倒置;契约是纯抽象头)。它只依赖 =core/types.h=(=window_id_t=),不含 =backend_t=,所以 bar include 它而不碰 =core/backend.h=,保持"bar 不知道后端内部"。=core/backend.h= 反过来 include =bar/tray.h=,让 =backend_bar_window_t= 内嵌 =tray_t=。
|
||||||
|
|
||||||
|
#+begin_src c
|
||||||
|
typedef void (*tray_icons_change_cb_t)(void *user_data);
|
||||||
|
|
||||||
|
typedef struct tray_api_t {
|
||||||
|
/* 返回 tray 当前挂载的 bar window_id;invalid 表示无 tray 挂载 */
|
||||||
|
window_id_t (*host_window)(void *handle);
|
||||||
|
/* 当前 icon 数量 */
|
||||||
|
size_t (*icon_count)(void *handle);
|
||||||
|
/* icon 边长(= bar height),bar 据此算 cell 宽度 */
|
||||||
|
int32_t (*icon_size)(void *handle);
|
||||||
|
/* 把容器 + icon 摆到 region 起点 x */
|
||||||
|
void (*place)(void *handle, int32_t x);
|
||||||
|
/* 注册 icon 数量变化回调 */
|
||||||
|
void (*set_listener)(void *handle,
|
||||||
|
tray_icons_change_cb_t cb,
|
||||||
|
void *user_data);
|
||||||
|
} tray_api_t;
|
||||||
|
|
||||||
|
typedef struct tray_t {
|
||||||
|
tray_api_t api; /* 值类型,后端总填充,一直可用 */
|
||||||
|
void *handle; /* 指向 backend(bar 不知其类型) */
|
||||||
|
} tray_t;
|
||||||
|
|
||||||
|
typedef struct backend_bar_window_t {
|
||||||
|
window_id_t window_id;
|
||||||
|
cairo_t *cr;
|
||||||
|
tray_t tray;
|
||||||
|
} backend_bar_window_t;
|
||||||
|
|
||||||
|
/* 扩展:加 enable_tray;icon_size 直接用 geometry.height */
|
||||||
|
backend_bar_window_t backend_create_bar_window(
|
||||||
|
backend_t *backend, rect_t geometry, uint32_t bg_pixel, bool enable_tray);
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** 关键设计点
|
||||||
|
|
||||||
|
- *api 是值类型*:后端用一个全局 =static const= vtable 填充,保证一直可用,bar 不需判 NULL。这与项目现有 =zdwm_bar_item_type_t=(纯 vtable)+ =zdwm_bar_item_t=(实例持有 api + state)的模式一致。
|
||||||
|
- *handle 总有效*:实际指向 =backend_t*=(tray api 函数内用 =backend->conn=、=backend->tray= host),对 bar 透明(=void*=)。有无 tray 统一由 =host_window()= 返回值判断(invalid = 无),不靠 api 是否 NULL,避免"先判 api、再判 host_window"两个判断点。
|
||||||
|
- *icon_size 来自 handle*(单一数据源):后端 configure icon 用的尺寸 = bar 查布局用的尺寸,杜绝两边各算导致 icon 错位/溢出。这比在 =tray_t= 冗余存一份快照更纯粹。
|
||||||
|
- *生命周期随 bar/backend*:=backend_create_bar_window(enable_tray=true)= 时创建/迁移 host;=backend_destroy= 释放。无 =tray_host_create/destroy= 独立入口,体现"tray 是 bar 附属"。
|
||||||
|
|
||||||
|
** 挂载语义
|
||||||
|
|
||||||
|
X11 的 =_NET_SYSTEM_TRAY_S0= selection owner *整个 display 只能有一个*,但 =backend_create_bar_window= 是 per-output 调用的。处理方式:
|
||||||
|
|
||||||
|
- tray host 是后端单例(内联在 =backend_t=)。
|
||||||
|
- 每次传 =enable_tray=true= 的 =create_bar_window= 把容器 reparent 到本次 bar 窗口,最终挂在*最后一个* true 的 output 上。
|
||||||
|
- =host_window()= 返回当前挂载的 bar window_id,bar 据此决定哪个 output 渲染 tray。
|
||||||
|
|
||||||
|
** 为何 set_listener 不配 remove_listener
|
||||||
|
|
||||||
|
tray icon 变化的唯一消费者是 bar 的 tray item,且其生命周期 = host 生命周期(=backend_destroy= 时自然消失)。与 core 的 =listeners= 模块一致(listener 跟宿主容器走,靠容器销毁回收),不引入 =remove_listener=。
|
||||||
|
|
||||||
|
* bar item 框架扩展
|
||||||
|
|
||||||
|
tray 作为 right-side 的普通 item,复用 =zdwm_bar_item_type_t= 框架。为支持 tray 的两个本质差异(cell 无文本 + 需要在 layout 后把结果同步到后端真实窗口),对框架做最小*通用*扩展——不为 tray 特例化。
|
||||||
|
|
||||||
|
** cell_api 全包 cell 相关(不引入 item_api)
|
||||||
|
|
||||||
|
=set_cell_count= / =get_cell_count= 本质是 *cell 集合的管理*(类比 =std::vector= 的 =size()/resize()= 与 =operator[]= 同属 vector),留在 =zdwm_bar_cell_api_t=。
|
||||||
|
|
||||||
|
新增两个 cell 级接口:
|
||||||
|
|
||||||
|
#+begin_src c
|
||||||
|
/* 固定宽度:>0 = 固定宽度,0 = 走文本测量(零值默认),<0 = 隐藏 */
|
||||||
|
void cell_set_fixed_width(zdwm_bar_item_t *, size_t index, int32_t width);
|
||||||
|
/* 单个 cell 的 region(layout 后的坐标) */
|
||||||
|
bar_x_region_t cell_get_region(zdwm_bar_item_t *, size_t index);
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
=bar_cell_t= 加 =int32_t fixed_width=,默认 =0=(走文本测量)。把零值留给最常见的默认行为(测量),=p_clear= 清零后新 cell 天然正确,=set_cell_count= 无需补初始化;=-1= 当"隐藏"哨兵(负数宽度本就无意义),与 =0=(测量)明确区分,没有歧义。
|
||||||
|
|
||||||
|
=bar_output_layout= 改一处:
|
||||||
|
|
||||||
|
#+begin_src c
|
||||||
|
int32_t width;
|
||||||
|
if (cell->fixed_width > 0) width = cell->fixed_width; /* 固定 */
|
||||||
|
else if (cell->fixed_width == 0) width = 文本测量; /* 测量(默认)*/
|
||||||
|
else width = 0; /* 隐藏 */
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** after_layout / after_draw 钩子
|
||||||
|
|
||||||
|
普通 item 是 cairo 绘制;tray 是"layout 后把 region 应用到后端真实窗口"。给 =zdwm_bar_item_type_t= 加两个*可空*通用钩子,参数打包(仿现有 =zdwm_bar_click_params_t= 先例):
|
||||||
|
|
||||||
|
#+begin_src c
|
||||||
|
typedef struct zdwm_bar_item_layout_params_t {
|
||||||
|
zdwm_bar_item_t *item;
|
||||||
|
const zdwm_bar_cell_api_t *cell_api;
|
||||||
|
bar_x_region_t region;
|
||||||
|
void *state;
|
||||||
|
} zdwm_bar_item_layout_params_t;
|
||||||
|
|
||||||
|
void (*after_layout)(const zdwm_bar_item_layout_params_t *); /* 可空 */
|
||||||
|
void (*after_draw)(const zdwm_bar_item_layout_params_t *); /* 可空 */
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
设计要点:
|
||||||
|
- 钩子为 NULL 则跳过,普通 item 零影响。
|
||||||
|
- =after_layout= / =after_draw= 比 =update= 多一个 =region=(它们在 layout 之后调用),且通过 =cell_api= 可调 =cell_get_region= 取 per-cell 位置。
|
||||||
|
- =update= 不打包参数(3 个参数不多,保持现有 =workspaces= / =binding= / =windows= 三个 item 零改动)。
|
||||||
|
|
||||||
|
=bar_draw= 流程:
|
||||||
|
|
||||||
|
#+begin_src c
|
||||||
|
bar_output_layout(bo, ctx);
|
||||||
|
for each item: if (after_layout) after_layout(params); /* params 含 region */
|
||||||
|
bar_output_draw(bo, ctx, bg);
|
||||||
|
for each item: if (after_draw) after_draw(params);
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* bar tray item
|
||||||
|
|
||||||
|
新增 =src/bar/tray.c=,作为普通 right-side item(参考 [[file:../src/bar/workspaces.c][workspaces.c]] 的实现模式):
|
||||||
|
|
||||||
|
#+begin_src c
|
||||||
|
zdwm_bar_item_type_t bar_tray = {
|
||||||
|
.create_state = bar_tray_create_state,
|
||||||
|
.update = bar_tray_update,
|
||||||
|
.on_click = bar_tray_on_click, /* 返回 NONE:icon 真实子窗口自收点击 */
|
||||||
|
.after_layout = bar_tray_after_layout,
|
||||||
|
.destroy_state = bar_tray_destroy_state,
|
||||||
|
};
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
- =create_state=:拷贝 =tray_t=,调 =set_listener= 注册回调(回调置 =state->dirty = true=)。
|
||||||
|
- =update=:=dirty= 时 =set_cell_count(icon_count)= + 循环 =cell_set_fixed_width(i, icon_size)=。
|
||||||
|
- =after_layout=:=place(handle, params->region.start)=。
|
||||||
|
|
||||||
|
tray cell 不画 cairo 内容(text 为空,=bar_item_draw= 只画融入 bar 的背景色块,被真实 icon 窗口盖住)。
|
||||||
|
|
||||||
|
* runtime 桥接
|
||||||
|
|
||||||
|
=runtime_init_bar=(=src/runtime/runtime.c=)的 create 循环:
|
||||||
|
|
||||||
|
#+begin_src c
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
bool enable_tray = ((int32_t)i == runtime->bar.config.tray_output_index);
|
||||||
|
auto bar_window = backend_create_bar_window(backend, bar_rect, color, enable_tray);
|
||||||
|
...
|
||||||
|
runtime->bar.tray = bar_window.tray; /* 每个返回都一样,存一份 */
|
||||||
|
}
|
||||||
|
bar_init(&runtime->bar, &runtime->listeners);
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
=bar_init= 遍历 =bar_output=,对 =host_window()= 匹配自身 =window_id= 的那个 output 调 =bar_output_add_tray=(right side),其余不加。tray 生命周期随 =backend_destroy=,runtime 无特殊清理。
|
||||||
|
|
||||||
|
* 配置
|
||||||
|
|
||||||
|
=zdwm_bar_config_t=(=include/zdwm/config.h=)加:
|
||||||
|
|
||||||
|
#+begin_src c
|
||||||
|
int32_t tray_output_index; /* 默认 0 = 第一个 output */
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
配置 setup 中可通过 output 信息确定具体 index。
|
||||||
|
|
||||||
|
* 数据流(触发链)
|
||||||
|
|
||||||
|
#+begin_example
|
||||||
|
icon 增删
|
||||||
|
-> 后端 set_listener 回调 -> state->dirty = true
|
||||||
|
-> 下个 timerfd tick -> bar_update -> bar_tray_update
|
||||||
|
-> set_cell_count + cell_set_fixed_width -> item 标 dirty
|
||||||
|
-> bar_draw -> bar_output_layout 重算 region(cell 数变了)
|
||||||
|
-> tray 的 after_layout -> backend place(handle, region.start)
|
||||||
|
-> 后端 move 容器 + configure 每个 icon 到 (region.start + i*icon_size, 0)
|
||||||
|
#+end_example
|
||||||
|
|
||||||
|
bar 重绘是 timerfd(fps)驱动,非事件驱动。tray icon 是真实窗口,X server 自管绘制,不依赖 cairo 重绘。
|
||||||
|
|
||||||
|
* 实现范围(第一版)
|
||||||
|
|
||||||
|
第一版做*基础可用*:
|
||||||
|
|
||||||
|
- =_NET_SYSTEM_TRAY_S0= selection owner + MANAGER 广播
|
||||||
|
- 基础 XEMBED(reparent 容器、=_XEMBED_EMBEDDED_NOTIFY=)
|
||||||
|
- icon 显示与点击
|
||||||
|
- icon 尺寸 = bar 高度(统一,不缩放)
|
||||||
|
|
||||||
|
放后续迭代:
|
||||||
|
- 完整 XEMBED 焦点 / 激活转发
|
||||||
|
- icon 尺寸协商与缩放
|
||||||
|
- 客户端异常断开的清理
|
||||||
|
|
||||||
|
*透明背景*第一版基本白送——bar 窗口已是 ARGB visual(见 =backend_create_bar_window= 调用 =window_get_visual(backend, true)=),tray 容器作为子窗口继承。
|
||||||
|
|
||||||
|
* 关键文件清单
|
||||||
|
|
||||||
|
| 文件 | 改动 |
|
||||||
|
|------------------------------+----------------------------------------------------------------------------------------------------------|
|
||||||
|
| =src/bar/tray.h= | **新增** tray 契约:=tray_t= / =tray_api_t= / =tray_icons_change_cb_t=(bar 定义、后端实现;不进 core) |
|
||||||
|
| =src/core/backend.h= | include =bar/tray.h=;=backend_bar_window_t= 内嵌 =tray_t=;扩展 =backend_create_bar_window=(加 =enable_tray=) |
|
||||||
|
| =src/backend/x11/tray.c= | *新增*:selection / MANAGER / 基础 XEMBED / icon 管理 / =place= |
|
||||||
|
| =src/backend/x11/internal.h= | =ATOM_LIST= 追加 tray/XEMBED atoms;=backend_t= 加 =tray= 字段 |
|
||||||
|
| =src/backend/x11/event.c= | 消化 tray 相关 client message(不产 =event_t=) |
|
||||||
|
| =src/backend/x11/backend.c= | =backend_create_bar_window= 实现 enable_tray 分支;=backend_destroy= 释放 tray |
|
||||||
|
| =src/bar/types.h= | =bar_cell_t= 加 =fixed_width=;=bar_t= 加 =tray= |
|
||||||
|
| =src/bar/cell.h= / =cell.c= | =cell_api= 加 =cell_set_fixed_width= / =cell_get_region= |
|
||||||
|
| =src/bar/bar.c= | layout 支持 =fixed_width=;=bar_draw= 调 after 钩子;=bar_init= 加 tray item;新增 layout params 类型 |
|
||||||
|
| =src/bar/tray.c= | *新增*:tray item 实现 |
|
||||||
|
| =src/runtime/runtime.c= | =runtime_init_bar= 传 =enable_tray=、存 =bar->tray= |
|
||||||
|
| =include/zdwm/config.h= | =zdwm_bar_config_t= 加 =tray_output_index= |
|
||||||
|
|
||||||
|
* 复用现有
|
||||||
|
|
||||||
|
- =backend_create_bar_window=(=src/backend/x11/backend.c=):bar 窗口已是 ARGB,tray 容器继承透明。
|
||||||
|
- =zdwm_bar_item_type_t= vtable 框架 + [[file:../src/bar/workspaces.c][workspaces.c]]:tray item 同模式落地。
|
||||||
|
- =zdwm_bar_click_params_t=:=after_layout= / =after_draw= 的 params 打包仿此先例。
|
||||||
|
- =cell_api= 机制:tray =update= 通过它操作 cell(与 workspaces 一致)。
|
||||||
@@ -25,6 +25,7 @@ typedef enum zdwm_button_t {
|
|||||||
ZDWM_BUTTON_MIDDLE,
|
ZDWM_BUTTON_MIDDLE,
|
||||||
} zdwm_button_t;
|
} zdwm_button_t;
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
typedef enum zdwm_modifier_bit_t {
|
typedef enum zdwm_modifier_bit_t {
|
||||||
ZDWM_MOD_NONE = 0u,
|
ZDWM_MOD_NONE = 0u,
|
||||||
ZDWM_MOD_SHIFT = 1u << 0,
|
ZDWM_MOD_SHIFT = 1u << 0,
|
||||||
@@ -35,6 +36,8 @@ typedef enum zdwm_modifier_bit_t {
|
|||||||
ZDWM_MOD_4 = 1u << 5,
|
ZDWM_MOD_4 = 1u << 5,
|
||||||
ZDWM_MOD_5 = 1u << 6,
|
ZDWM_MOD_5 = 1u << 6,
|
||||||
} zdwm_modifier_bit_t;
|
} zdwm_modifier_bit_t;
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
typedef uint32_t zdwm_modifier_mask_t;
|
typedef uint32_t zdwm_modifier_mask_t;
|
||||||
|
|
||||||
typedef struct zdwm_rect_t {
|
typedef struct zdwm_rect_t {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/backend.h"
|
#include "interface/backend.h"
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
static inline int32_t right(rect_t a) { return a.x + a.width; }
|
static inline int32_t right(rect_t a) { return a.x + a.width; }
|
||||||
static inline int32_t bottom(rect_t a) { return a.y + a.height; }
|
static inline int32_t bottom(rect_t a) { return a.y + a.height; }
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "core/backend.h"
|
#include "interface/backend.h"
|
||||||
#include "core/types.h"
|
|
||||||
|
|
||||||
backend_detect_t *
|
backend_detect_t *
|
||||||
output_remove_duplication(const output_info_t *output, const size_t count);
|
output_remove_duplication(const output_info_t *output, const size_t count);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "core/backend.h"
|
#include "interface/backend.h"
|
||||||
|
|
||||||
#include <cairo-xcb.h>
|
#include <cairo-xcb.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
@@ -25,11 +25,7 @@
|
|||||||
#include "base/log.h"
|
#include "base/log.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "base/window_list.h"
|
#include "common/window.h"
|
||||||
#include "core/event.h"
|
|
||||||
#include "core/plan.h"
|
|
||||||
#include "core/types.h"
|
|
||||||
#include "core/window.h"
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
typedef struct atom_item_t {
|
typedef struct atom_item_t {
|
||||||
@@ -734,8 +730,9 @@ backend_scan_result_t *backend_scan_windows(backend_t *backend) {
|
|||||||
auto transient_for = window_get_transient_for(backend, window);
|
auto transient_for = window_get_transient_for(backend, window);
|
||||||
auto r = transient_for == XCB_WINDOW_NONE ? result : sub_result;
|
auto r = transient_for == XCB_WINDOW_NONE ? result : sub_result;
|
||||||
auto slot = array_push(r->windows, r->count, r->capacity);
|
auto slot = array_push(r->windows, r->count, r->capacity);
|
||||||
if (!populate_window_event(backend, list[i], slot) ||
|
if (
|
||||||
slot->override_redirect) {
|
!populate_window_event(backend, list[i], slot) || slot->override_redirect
|
||||||
|
) {
|
||||||
window_layer_props_cleanup(&slot->props);
|
window_layer_props_cleanup(&slot->props);
|
||||||
window_metadata_cleanup(&slot->metadata);
|
window_metadata_cleanup(&slot->metadata);
|
||||||
r->count--;
|
r->count--;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
typedef struct modifier_map_t {
|
typedef struct modifier_map_t {
|
||||||
modifier_bit_t modifier;
|
modifier_bit_t modifier;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
modifier_mask_t modifiers_xcb_to_zdwm(uint16_t mask);
|
modifier_mask_t modifiers_xcb_to_zdwm(uint16_t mask);
|
||||||
uint16_t modifiers_zdwm_to_xcb(modifier_mask_t mask);
|
uint16_t modifiers_zdwm_to_xcb(modifier_mask_t mask);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "core/event.h"
|
#include "common/event.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -12,9 +12,8 @@
|
|||||||
#include "backend/x11/common.h"
|
#include "backend/x11/common.h"
|
||||||
#include "backend/x11/window.h"
|
#include "backend/x11/window.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/backend.h"
|
#include "interface/backend.h"
|
||||||
#include "core/types.h"
|
#include "interface/event.h"
|
||||||
#include "core/window.h"
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
static window_state_t *derive_window_states(
|
static window_state_t *derive_window_states(
|
||||||
@@ -58,8 +57,10 @@ static bool maximized_from_states(
|
|||||||
uint32_t state_count
|
uint32_t state_count
|
||||||
) {
|
) {
|
||||||
for (uint32_t i = 0; i < state_count; i++) {
|
for (uint32_t i = 0; i < state_count; i++) {
|
||||||
if (state_atoms[i] == atoms->_NET_WM_STATE_MAXIMIZED_VERT ||
|
if (
|
||||||
state_atoms[i] == atoms->_NET_WM_STATE_MAXIMIZED_HORZ)
|
state_atoms[i] == atoms->_NET_WM_STATE_MAXIMIZED_VERT ||
|
||||||
|
state_atoms[i] == atoms->_NET_WM_STATE_MAXIMIZED_HORZ
|
||||||
|
)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -341,8 +342,10 @@ static bool handle_property_notify(
|
|||||||
const xcb_property_notify_event_t *xcb_event
|
const xcb_property_notify_event_t *xcb_event
|
||||||
) {
|
) {
|
||||||
auto window_id = xcb_event->window;
|
auto window_id = xcb_event->window;
|
||||||
if (xcb_event->atom == backend->atoms.WM_NAME ||
|
if (
|
||||||
xcb_event->atom == backend->atoms._NET_WM_NAME) {
|
xcb_event->atom == backend->atoms.WM_NAME ||
|
||||||
|
xcb_event->atom == backend->atoms._NET_WM_NAME
|
||||||
|
) {
|
||||||
event->type = ZDWM_EVENT_WINDOW_METADATA_CHANGED;
|
event->type = ZDWM_EVENT_WINDOW_METADATA_CHANGED;
|
||||||
|
|
||||||
auto data = &event->as.window_metadata_change;
|
auto data = &event->as.window_metadata_change;
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
#include <xcb/xcb_keysyms.h>
|
#include <xcb/xcb_keysyms.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include "base/window_list.h"
|
#include "common/window.h"
|
||||||
#include "core/event.h"
|
#include "interface/event.h"
|
||||||
|
|
||||||
#define EWMH_ATOMS(X) \
|
#define EWMH_ATOMS(X) \
|
||||||
X(_NET_WM_NAME) \
|
X(_NET_WM_NAME) \
|
||||||
|
|||||||
@@ -12,8 +12,6 @@
|
|||||||
#include "backend/x11/cursor.h"
|
#include "backend/x11/cursor.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/backend.h"
|
|
||||||
#include "core/types.h"
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
static char *window_get_text_property(
|
static char *window_get_text_property(
|
||||||
@@ -38,10 +36,12 @@ static char *window_get_text_property(
|
|||||||
char *value = (char *)xcb_get_property_value(reply);
|
char *value = (char *)xcb_get_property_value(reply);
|
||||||
|
|
||||||
char *text = nullptr;
|
char *text = nullptr;
|
||||||
if (length && reply->format == 8 &&
|
if (
|
||||||
|
length && reply->format == 8 &&
|
||||||
(reply->type == XCB_ATOM_STRING ||
|
(reply->type == XCB_ATOM_STRING ||
|
||||||
reply->type == backend->atoms.UTF8_STRING ||
|
reply->type == backend->atoms.UTF8_STRING ||
|
||||||
reply->type == backend->atoms.COMPOUND_TEXT)) {
|
reply->type == backend->atoms.COMPOUND_TEXT)
|
||||||
|
) {
|
||||||
text = p_strndup(value, (size_t)length);
|
text = p_strndup(value, (size_t)length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include "base/app.h"
|
#include "base/app.h"
|
||||||
#include "core/backend.h"
|
#include "interface/backend.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
typedef struct atoms_t atoms_t;
|
typedef struct atoms_t atoms_t;
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "base/time.h"
|
#include "base/time.h"
|
||||||
#include "core/listeners.h"
|
|
||||||
|
|
||||||
static zdwm_bar_item_t *bar_add_item(
|
static zdwm_bar_item_t *bar_add_item(
|
||||||
zdwm_output_id_t output_id,
|
zdwm_output_id_t output_id,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#include "bar/text.h"
|
#include "bar/text.h"
|
||||||
#include "bar/types.h"
|
#include "bar/types.h"
|
||||||
#include "base/color.h"
|
#include "base/color.h"
|
||||||
#include "core/listeners.h"
|
#include "common/listeners.h"
|
||||||
|
|
||||||
typedef struct bar_output_t {
|
typedef struct bar_output_t {
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <zdwm/types.h>
|
#include <zdwm/types.h>
|
||||||
|
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/listeners.h"
|
#include "common/listeners.h"
|
||||||
|
|
||||||
typedef struct bar_binding_state_t {
|
typedef struct bar_binding_state_t {
|
||||||
zdwm_binding_mode_notify_t mode;
|
zdwm_binding_mode_notify_t mode;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <zdwm/bar.h>
|
#include <zdwm/bar.h>
|
||||||
|
|
||||||
#include "core/listeners.h"
|
#include "common/listeners.h"
|
||||||
|
|
||||||
typedef struct bar_binding_config_t {
|
typedef struct bar_binding_config_t {
|
||||||
bool show_default;
|
bool show_default;
|
||||||
|
|||||||
@@ -84,13 +84,17 @@ bar_cell_set_icon(zdwm_bar_item_t *item, size_t index, zdwm_icon_t icon) {
|
|||||||
if (icon_ptr->type == icon.type) {
|
if (icon_ptr->type == icon.type) {
|
||||||
switch (icon.type) {
|
switch (icon.type) {
|
||||||
case ZDWM_ICON_TEXT:
|
case ZDWM_ICON_TEXT:
|
||||||
if (icon_ptr->as.text == icon.as.text ||
|
if (
|
||||||
strcmp(icon_ptr->as.text, icon.as.text) == 0) {
|
icon_ptr->as.text == icon.as.text ||
|
||||||
|
strcmp(icon_ptr->as.text, icon.as.text) == 0
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case ZDWM_ICON_IMAGE:
|
case ZDWM_ICON_IMAGE:
|
||||||
if (icon_ptr->as.image_path == icon.as.image_path ||
|
if (
|
||||||
strcmp(icon_ptr->as.image_path, icon.as.image_path) == 0) {
|
icon_ptr->as.image_path == icon.as.image_path ||
|
||||||
|
strcmp(icon_ptr->as.image_path, icon.as.image_path) == 0
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,6 +119,7 @@ bar_cell_set_indicator(zdwm_bar_item_t *item, size_t index, bool show) {
|
|||||||
item->dirty = true;
|
item->dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
zdwm_bar_cell_api_t bar_cell_api = {
|
zdwm_bar_cell_api_t bar_cell_api = {
|
||||||
.get_cell_count = bar_cell_get_count,
|
.get_cell_count = bar_cell_get_count,
|
||||||
.set_cell_count = bar_cell_set_count,
|
.set_cell_count = bar_cell_set_count,
|
||||||
@@ -124,6 +129,7 @@ zdwm_bar_cell_api_t bar_cell_api = {
|
|||||||
.cell_set_icon = bar_cell_set_icon,
|
.cell_set_icon = bar_cell_set_icon,
|
||||||
.cell_set_indicator = bar_cell_set_indicator,
|
.cell_set_indicator = bar_cell_set_indicator,
|
||||||
};
|
};
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
void bar_cell_set_region(
|
void bar_cell_set_region(
|
||||||
zdwm_bar_item_t *item,
|
zdwm_bar_item_t *item,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/listeners.h"
|
#include "common/listeners.h"
|
||||||
|
|
||||||
typedef struct bar_windows_state_t {
|
typedef struct bar_windows_state_t {
|
||||||
zdwm_output_id_t output_id;
|
zdwm_output_id_t output_id;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <zdwm/bar.h>
|
#include <zdwm/bar.h>
|
||||||
|
|
||||||
#include "core/listeners.h"
|
#include "common/listeners.h"
|
||||||
|
|
||||||
typedef struct bar_windows_config_t {
|
typedef struct bar_windows_config_t {
|
||||||
uint32_t cell_padding;
|
uint32_t cell_padding;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/listeners.h"
|
#include "common/listeners.h"
|
||||||
|
|
||||||
typedef struct bar_workspace_t {
|
typedef struct bar_workspace_t {
|
||||||
zdwm_workspace_t info;
|
zdwm_workspace_t info;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <zdwm/bar.h>
|
#include <zdwm/bar.h>
|
||||||
|
|
||||||
#include "core/listeners.h"
|
#include "common/listeners.h"
|
||||||
|
|
||||||
typedef struct bar_workspace_config_t {
|
typedef struct bar_workspace_config_t {
|
||||||
uint32_t cell_padding;
|
uint32_t cell_padding;
|
||||||
|
|||||||
@@ -98,11 +98,11 @@ array_erase_impl(void *items, size_t item_size, size_t *count, size_t index) {
|
|||||||
#define array_reserve(items, capacity, need) \
|
#define array_reserve(items, capacity, need) \
|
||||||
array_reserve_impl((void **)&(items), sizeof(*(items)), &(capacity), (need))
|
array_reserve_impl((void **)&(items), sizeof(*(items)), &(capacity), (need))
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
/** @brief 为具体类型数组追加一个槽位。 */
|
/** @brief 为具体类型数组追加一个槽位。 */
|
||||||
#define array_push(items, count, capacity)\
|
#define array_push(items, count, capacity)\
|
||||||
( \
|
(typeof(items))array_push_impl((void **)&(items), sizeof(*(items)), &(count), &(capacity))
|
||||||
typeof(items) \
|
/* clang-format on */
|
||||||
)array_push_impl((void **)&(items), sizeof(*(items)), &(count), &(capacity))
|
|
||||||
|
|
||||||
/** @brief 删除具体类型数组中指定下标的元素。 */
|
/** @brief 删除具体类型数组中指定下标的元素。 */
|
||||||
#define array_erase(items, count, index) \
|
#define array_erase(items, count, index) \
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ bool hex_color_to_rgba(const char *hex, uint32_t *rgba) {
|
|||||||
|
|
||||||
size_t len = strlen(hex);
|
size_t len = strlen(hex);
|
||||||
char extended[9] = {0};
|
char extended[9] = {0};
|
||||||
uint32_t color = 0x00000000;
|
uint32_t color = 0x00'00'00'00;
|
||||||
|
|
||||||
if (len == 3 || len == 4) {
|
if (len == 3 || len == 4) {
|
||||||
extended[0] = extended[1] = hex[0];
|
extended[0] = extended[1] = hex[0];
|
||||||
@@ -76,7 +76,7 @@ bool hex_color_to_rgba(const char *hex, uint32_t *rgba) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
color = strtoul(extended, nullptr, 16) & 0xffffffff;
|
color = strtoul(extended, nullptr, 16) & 0xff'ff'ff'ff;
|
||||||
*rgba = color;
|
*rgba = color;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
#include "base/window_list.h"
|
|
||||||
|
|
||||||
#include <zdwm/types.h>
|
|
||||||
|
|
||||||
#include "base/array.h"
|
|
||||||
#include "base/memory.h"
|
|
||||||
|
|
||||||
void window_list_push(
|
|
||||||
window_list_t *window_list,
|
|
||||||
zdwm_window_id_t window_id
|
|
||||||
) {
|
|
||||||
zdwm_window_id_t *window =
|
|
||||||
array_push(window_list->windows, window_list->count, window_list->capacity);
|
|
||||||
*window = window_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void window_list_reset(window_list_t *window_list) {
|
|
||||||
p_clear(window_list->windows, window_list->capacity);
|
|
||||||
window_list->count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void window_list_cleanup(window_list_t *window_list) {
|
|
||||||
p_delete(&window_list->windows);
|
|
||||||
window_list->count = 0;
|
|
||||||
window_list->capacity = 0;
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "core/event.h"
|
#include "interface/event.h"
|
||||||
|
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/window.h"
|
#include "common/window.h"
|
||||||
|
|
||||||
void event_cleanup(event_t *event) {
|
void event_cleanup(event_t *event) {
|
||||||
if (!event || event->type == ZDWM_EVENT_NONE) return;
|
if (!event || event->type == ZDWM_EVENT_NONE) return;
|
||||||
6
src/common/event.h
Normal file
6
src/common/event.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "interface/event.h"
|
||||||
|
|
||||||
|
void event_cleanup(event_t *event);
|
||||||
|
void event_reset(event_t *event);
|
||||||
107
src/common/listeners.c
Normal file
107
src/common/listeners.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#include "common/listeners.h"
|
||||||
|
|
||||||
|
#include <zdwm/listeners.h>
|
||||||
|
|
||||||
|
#include "base/array.h"
|
||||||
|
#include "base/memory.h"
|
||||||
|
|
||||||
|
#define ADD_LISTENER(FIELD) \
|
||||||
|
auto list = &listeners->FIELD; \
|
||||||
|
auto item = array_push(list->items, list->count, list->capacity); \
|
||||||
|
item->fn = fn; \
|
||||||
|
item->user_data = user_data
|
||||||
|
|
||||||
|
void listeners_add_output_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_current_output_id_listener fn,
|
||||||
|
void *user_data
|
||||||
|
) {
|
||||||
|
ADD_LISTENER(output_listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
void listeners_add_initial_workspace_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_initial_workspace_list fn,
|
||||||
|
void *user_data
|
||||||
|
) {
|
||||||
|
ADD_LISTENER(initial_workspace_listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
void listeners_add_active_workspace_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_workspace_active_updated fn,
|
||||||
|
void *user_data
|
||||||
|
) {
|
||||||
|
ADD_LISTENER(active_workspace_listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
void listeners_add_layout_notify(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_layout_notify fn,
|
||||||
|
void *user_data
|
||||||
|
) {
|
||||||
|
ADD_LISTENER(layout_listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
void listeners_add_binding_mode_notify(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_binding_mode_notify fn,
|
||||||
|
void *user_data
|
||||||
|
) {
|
||||||
|
ADD_LISTENER(binding_mode_listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
void listeners_add_initial_window_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_initial_window_list fn,
|
||||||
|
void *user_data
|
||||||
|
) {
|
||||||
|
ADD_LISTENER(initial_window_listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
void listeners_add_window_added_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_window_added fn,
|
||||||
|
void *user_data
|
||||||
|
) {
|
||||||
|
ADD_LISTENER(window_added_listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
void listeners_add_window_updated_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_window_updated fn,
|
||||||
|
void *user_data
|
||||||
|
) {
|
||||||
|
ADD_LISTENER(window_updated_listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
void listeners_add_window_removed_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_window_removed fn,
|
||||||
|
void *user_data
|
||||||
|
) {
|
||||||
|
ADD_LISTENER(window_removed_listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef ADD_LISTENER
|
||||||
|
|
||||||
|
#define CLEANUP_LIST(FIELD) \
|
||||||
|
p_delete(&listeners->FIELD.items); \
|
||||||
|
listeners->FIELD.count = 0; \
|
||||||
|
listeners->FIELD.capacity = 0
|
||||||
|
|
||||||
|
void listeners_cleanup(listeners_t *listeners) {
|
||||||
|
if (!listeners) return;
|
||||||
|
|
||||||
|
CLEANUP_LIST(output_listeners);
|
||||||
|
CLEANUP_LIST(initial_workspace_listeners);
|
||||||
|
CLEANUP_LIST(active_workspace_listeners);
|
||||||
|
CLEANUP_LIST(layout_listeners);
|
||||||
|
CLEANUP_LIST(binding_mode_listeners);
|
||||||
|
CLEANUP_LIST(initial_window_listeners);
|
||||||
|
CLEANUP_LIST(window_added_listeners);
|
||||||
|
CLEANUP_LIST(window_updated_listeners);
|
||||||
|
CLEANUP_LIST(window_removed_listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CLEANUP_LIST
|
||||||
94
src/common/listeners.h
Normal file
94
src/common/listeners.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <zdwm/listeners.h>
|
||||||
|
|
||||||
|
typedef struct binding_table_t binding_table_t;
|
||||||
|
typedef struct layout_registry_t layout_registry_t;
|
||||||
|
typedef struct state_t state_t;
|
||||||
|
|
||||||
|
#define ITEM(NAME, FN_TYPE) \
|
||||||
|
typedef struct NAME##_listener_item_t { \
|
||||||
|
FN_TYPE *fn; \
|
||||||
|
void *user_data; \
|
||||||
|
} NAME##_listener_item_t
|
||||||
|
|
||||||
|
#define LISTENERS(NAME, FN_TYPE) \
|
||||||
|
ITEM(NAME, FN_TYPE); \
|
||||||
|
typedef struct NAME##_listeners_t { \
|
||||||
|
NAME##_listener_item_t *items; \
|
||||||
|
size_t count; \
|
||||||
|
size_t capacity; \
|
||||||
|
} NAME##_listeners_t
|
||||||
|
|
||||||
|
LISTENERS(output, zdwm_current_output_id_listener);
|
||||||
|
LISTENERS(initial_workspace_list, zdwm_initial_workspace_list);
|
||||||
|
LISTENERS(workspace_active, zdwm_workspace_active_updated);
|
||||||
|
LISTENERS(layout, zdwm_layout_notify);
|
||||||
|
LISTENERS(binding_mode, zdwm_binding_mode_notify);
|
||||||
|
LISTENERS(initial_window_list, zdwm_initial_window_list);
|
||||||
|
LISTENERS(window_added, zdwm_window_added);
|
||||||
|
LISTENERS(window_updated, zdwm_window_updated);
|
||||||
|
LISTENERS(window_removed, zdwm_window_removed);
|
||||||
|
|
||||||
|
#undef ITEM
|
||||||
|
#undef LISTENERS
|
||||||
|
|
||||||
|
typedef struct listeners_t {
|
||||||
|
output_listeners_t output_listeners;
|
||||||
|
initial_workspace_list_listeners_t initial_workspace_listeners;
|
||||||
|
workspace_active_listeners_t active_workspace_listeners;
|
||||||
|
layout_listeners_t layout_listeners;
|
||||||
|
binding_mode_listeners_t binding_mode_listeners;
|
||||||
|
initial_window_list_listeners_t initial_window_listeners;
|
||||||
|
window_added_listeners_t window_added_listeners;
|
||||||
|
window_updated_listeners_t window_updated_listeners;
|
||||||
|
window_removed_listeners_t window_removed_listeners;
|
||||||
|
} listeners_t;
|
||||||
|
|
||||||
|
void listeners_add_output_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_current_output_id_listener fn,
|
||||||
|
void *user_data
|
||||||
|
);
|
||||||
|
void listeners_add_initial_workspace_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_initial_workspace_list fn,
|
||||||
|
void *user_data
|
||||||
|
);
|
||||||
|
void listeners_add_active_workspace_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_workspace_active_updated fn,
|
||||||
|
void *user_data
|
||||||
|
);
|
||||||
|
void listeners_add_layout_notify(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_layout_notify fn,
|
||||||
|
void *user_data
|
||||||
|
);
|
||||||
|
void listeners_add_binding_mode_notify(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_binding_mode_notify fn,
|
||||||
|
void *user_data
|
||||||
|
);
|
||||||
|
void listeners_add_initial_window_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_initial_window_list fn,
|
||||||
|
void *user_data
|
||||||
|
);
|
||||||
|
void listeners_add_window_added_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_window_added fn,
|
||||||
|
void *user_data
|
||||||
|
);
|
||||||
|
void listeners_add_window_updated_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_window_updated fn,
|
||||||
|
void *user_data
|
||||||
|
);
|
||||||
|
void listeners_add_window_removed_listener(
|
||||||
|
listeners_t *listeners,
|
||||||
|
zdwm_window_removed fn,
|
||||||
|
void *user_data
|
||||||
|
);
|
||||||
|
|
||||||
|
void listeners_cleanup(listeners_t *listeners);
|
||||||
55
src/common/window.c
Normal file
55
src/common/window.c
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#include "common/window.h"
|
||||||
|
|
||||||
|
#include "base/array.h"
|
||||||
|
#include "base/memory.h"
|
||||||
|
#include "interface/types.h"
|
||||||
|
|
||||||
|
window_layer_type_t window_classify_layer(const window_layer_props_t *props) {
|
||||||
|
for (size_t i = 0; i < props->type_count; ++i) {
|
||||||
|
window_type_t type = props->types[i];
|
||||||
|
if (type == ZDWM_WINDOW_TYPE_NOTIFICATION) return ZDWM_WINDOW_LAYER_OVERLAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < props->state_count; ++i) {
|
||||||
|
window_state_t state = props->states[i];
|
||||||
|
if (state == ZDWM_WINDOW_STATE_ABOVE) return ZDWM_WINDOW_LAYER_TOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ZDWM_WINDOW_LAYER_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_layer_props_cleanup(window_layer_props_t *props) {
|
||||||
|
if (!props) return;
|
||||||
|
|
||||||
|
p_delete(&props->types);
|
||||||
|
props->type_count = 0;
|
||||||
|
p_delete(&props->states);
|
||||||
|
props->state_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_metadata_cleanup(window_metadata_t *metadata) {
|
||||||
|
if (!metadata) return;
|
||||||
|
|
||||||
|
p_delete(&metadata->title);
|
||||||
|
p_delete(&metadata->app_id);
|
||||||
|
p_delete(&metadata->role);
|
||||||
|
p_delete(&metadata->class_name);
|
||||||
|
p_delete(&metadata->instance_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_list_push(window_list_t *window_list, zdwm_window_id_t window_id) {
|
||||||
|
zdwm_window_id_t *window =
|
||||||
|
array_push(window_list->windows, window_list->count, window_list->capacity);
|
||||||
|
*window = window_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_list_reset(window_list_t *window_list) {
|
||||||
|
p_clear(window_list->windows, window_list->capacity);
|
||||||
|
window_list->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_list_cleanup(window_list_t *window_list) {
|
||||||
|
p_delete(&window_list->windows);
|
||||||
|
window_list->count = 0;
|
||||||
|
window_list->capacity = 0;
|
||||||
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stddef.h>
|
#include "interface/types.h"
|
||||||
#include <zdwm/types.h>
|
|
||||||
|
window_layer_type_t window_classify_layer(const window_layer_props_t *props);
|
||||||
|
void window_layer_props_cleanup(window_layer_props_t *props);
|
||||||
|
void window_metadata_cleanup(window_metadata_t *metadata);
|
||||||
|
|
||||||
typedef struct window_list_t {
|
typedef struct window_list_t {
|
||||||
zdwm_window_id_t *windows;
|
zdwm_window_id_t *windows;
|
||||||
46
src/common/workspace.c
Normal file
46
src/common/workspace.c
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include "common/workspace.h"
|
||||||
|
|
||||||
|
#include "base/memory.h"
|
||||||
|
|
||||||
|
void workspace_desc_cleanup(workspace_desc_t *workspace) {
|
||||||
|
if (!workspace) return;
|
||||||
|
|
||||||
|
p_delete(&workspace->name);
|
||||||
|
p_delete(&workspace->layout_ids);
|
||||||
|
workspace->output_index = 0;
|
||||||
|
workspace->layout_count = 0;
|
||||||
|
workspace->initial_layout_id = ZDWM_LAYOUT_ID_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void workspace_desc_list_cleanup(workspace_desc_t **list, size_t *count) {
|
||||||
|
if (!list || !count) return;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < *count; i++) {
|
||||||
|
workspace_desc_cleanup(&(*list)[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
p_delete(list);
|
||||||
|
*count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool workspace_desc_layouts_valid(const workspace_desc_t *workspace) {
|
||||||
|
if (!workspace || !workspace->layout_count || !workspace->layout_ids) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < workspace->layout_count; i++) {
|
||||||
|
if (workspace->layout_ids[i] == workspace->initial_layout_id) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool workspace_desc_valid(
|
||||||
|
const workspace_desc_t *workspace,
|
||||||
|
size_t output_count
|
||||||
|
) {
|
||||||
|
if (!workspace || !workspace->name) return false;
|
||||||
|
if (workspace->output_index >= output_count) return false;
|
||||||
|
|
||||||
|
return workspace_desc_layouts_valid(workspace);
|
||||||
|
}
|
||||||
21
src/common/workspace.h
Normal file
21
src/common/workspace.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "interface/types.h"
|
||||||
|
|
||||||
|
typedef struct workspace_desc_t {
|
||||||
|
size_t output_index; /* 对应 state_init() 中 outputs[] 的索引 */
|
||||||
|
const char *name;
|
||||||
|
const layout_id_t *layout_ids;
|
||||||
|
size_t layout_count;
|
||||||
|
layout_id_t initial_layout_id;
|
||||||
|
} workspace_desc_t;
|
||||||
|
|
||||||
|
void workspace_desc_cleanup(workspace_desc_t *workspace);
|
||||||
|
void workspace_desc_list_cleanup(workspace_desc_t **list, size_t *count);
|
||||||
|
bool workspace_desc_layouts_valid(const workspace_desc_t *workspace);
|
||||||
|
bool workspace_desc_valid(
|
||||||
|
const workspace_desc_t *workspace,
|
||||||
|
size_t output_count
|
||||||
|
);
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "base/log.h"
|
#include "base/log.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
static constexpr char launcher[] =
|
static constexpr char launcher[] =
|
||||||
"rofi -show combi -modes combi -combi-modes window,drun,run,ssh,windowcd";
|
"rofi -show combi -modes combi -combi-modes window,drun,run,ssh,windowcd";
|
||||||
@@ -52,10 +52,12 @@ bool config_defaults_build(
|
|||||||
);
|
);
|
||||||
zdwm_layout_id_t floating_id =
|
zdwm_layout_id_t floating_id =
|
||||||
api->register_layout(builder, "floating", "><>", "floating", nullptr);
|
api->register_layout(builder, "floating", "><>", "floating", nullptr);
|
||||||
if (fair_id == ZDWM_LAYOUT_ID_INVALID ||
|
if (
|
||||||
|
fair_id == ZDWM_LAYOUT_ID_INVALID ||
|
||||||
maximize_id == ZDWM_LAYOUT_ID_INVALID ||
|
maximize_id == ZDWM_LAYOUT_ID_INVALID ||
|
||||||
fullscreen_id == ZDWM_LAYOUT_ID_INVALID ||
|
fullscreen_id == ZDWM_LAYOUT_ID_INVALID ||
|
||||||
floating_id == ZDWM_LAYOUT_ID_INVALID) {
|
floating_id == ZDWM_LAYOUT_ID_INVALID
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,18 +5,19 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <zdwm/bar.h>
|
#include <zdwm/bar.h>
|
||||||
#include <zdwm/config.h>
|
#include <zdwm/config.h>
|
||||||
|
#include <zdwm/listeners.h>
|
||||||
|
|
||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
#include "base/color.h"
|
#include "base/color.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
|
#include "common/listeners.h"
|
||||||
|
#include "common/workspace.h"
|
||||||
#include "config/defaults.h"
|
#include "config/defaults.h"
|
||||||
#include "config/loader.h"
|
#include "config/loader.h"
|
||||||
#include "core/binding.h"
|
#include "core/binding.h"
|
||||||
#include "core/layout.h"
|
#include "core/layout.h"
|
||||||
#include "core/listeners.h"
|
|
||||||
#include "core/rules.h"
|
#include "core/rules.h"
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
#include "core/wm_desc.h"
|
|
||||||
#include "layouts/fair.h"
|
#include "layouts/fair.h"
|
||||||
#include "layouts/fullscreen.h"
|
#include "layouts/fullscreen.h"
|
||||||
#include "layouts/maximize.h"
|
#include "layouts/maximize.h"
|
||||||
@@ -38,8 +39,10 @@ struct zdwm_config_builder_t {
|
|||||||
void runtime_config_cleanup(runtime_init_desc_t *desc) {
|
void runtime_config_cleanup(runtime_init_desc_t *desc) {
|
||||||
if (!desc) return;
|
if (!desc) return;
|
||||||
|
|
||||||
if (desc->layouts.slots || desc->layouts.slot_count ||
|
if (
|
||||||
desc->layouts.slot_capacity) {
|
desc->layouts.slots || desc->layouts.slot_count ||
|
||||||
|
desc->layouts.slot_capacity
|
||||||
|
) {
|
||||||
layout_registry_cleanup(&desc->layouts);
|
layout_registry_cleanup(&desc->layouts);
|
||||||
}
|
}
|
||||||
binding_table_destroy(desc->binding_table);
|
binding_table_destroy(desc->binding_table);
|
||||||
@@ -53,8 +56,10 @@ void runtime_config_cleanup(runtime_init_desc_t *desc) {
|
|||||||
static void config_builder_cleanup(zdwm_config_builder_t *builder) {
|
static void config_builder_cleanup(zdwm_config_builder_t *builder) {
|
||||||
if (!builder) return;
|
if (!builder) return;
|
||||||
|
|
||||||
if (builder->layouts.slots || builder->layouts.slot_count ||
|
if (
|
||||||
builder->layouts.slot_capacity) {
|
builder->layouts.slots || builder->layouts.slot_count ||
|
||||||
|
builder->layouts.slot_capacity
|
||||||
|
) {
|
||||||
layout_registry_cleanup(&builder->layouts);
|
layout_registry_cleanup(&builder->layouts);
|
||||||
}
|
}
|
||||||
workspace_desc_list_cleanup(&builder->workspaces, &builder->workspace_count);
|
workspace_desc_list_cleanup(&builder->workspaces, &builder->workspace_count);
|
||||||
@@ -336,10 +341,10 @@ static bool runtime_config_build(
|
|||||||
builder.output_count = output_count;
|
builder.output_count = output_count;
|
||||||
builder.binding_table = binding_table_create();
|
builder.binding_table = binding_table_create();
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
zdwm_api_t api = {
|
zdwm_api_t api = {
|
||||||
.abi_version = ZDWM_CONFIG_ABI_VERSION,
|
.abi_version = ZDWM_CONFIG_ABI_VERSION,
|
||||||
.builtin_layouts =
|
.builtin_layouts = {
|
||||||
{
|
|
||||||
.fair = fair,
|
.fair = fair,
|
||||||
.fullscreen = fullscreen,
|
.fullscreen = fullscreen,
|
||||||
.maximize = maximize,
|
.maximize = maximize,
|
||||||
@@ -356,19 +361,18 @@ static bool runtime_config_build(
|
|||||||
.set_interaction_fps = runtime_config_set_interaction_fps,
|
.set_interaction_fps = runtime_config_set_interaction_fps,
|
||||||
|
|
||||||
.subscribe_current_output = runtime_config_subscribe_current_output,
|
.subscribe_current_output = runtime_config_subscribe_current_output,
|
||||||
.subscribe_initial_workspace_list =
|
.subscribe_initial_workspace_list = runtime_config_subscribe_initial_workspace_list,
|
||||||
runtime_config_subscribe_initial_workspace_list,
|
|
||||||
.subscribe_workspace_active = runtime_config_subscribe_workspace_active,
|
.subscribe_workspace_active = runtime_config_subscribe_workspace_active,
|
||||||
.subscribe_layout = runtime_config_subscribe_layout,
|
.subscribe_layout = runtime_config_subscribe_layout,
|
||||||
.subscribe_binding_mode = runtime_config_subscribe_binding_mode,
|
.subscribe_binding_mode = runtime_config_subscribe_binding_mode,
|
||||||
.subscribe_initial_window_list =
|
.subscribe_initial_window_list = runtime_config_subscribe_initial_window_list,
|
||||||
runtime_config_subscribe_initial_window_list,
|
|
||||||
.subscribe_window_added = runtime_config_subscribe_window_added,
|
.subscribe_window_added = runtime_config_subscribe_window_added,
|
||||||
.subscribe_window_updated = runtime_config_subscribe_window_updated,
|
.subscribe_window_updated = runtime_config_subscribe_window_updated,
|
||||||
.subscribe_window_removed = runtime_config_subscribe_window_removed,
|
.subscribe_window_removed = runtime_config_subscribe_window_removed,
|
||||||
|
|
||||||
.set_bar_config = runtime_config_set_bar_config,
|
.set_bar_config = runtime_config_set_bar_config,
|
||||||
};
|
};
|
||||||
|
/* clang-format on */
|
||||||
bool ok = setup(&api, &builder, outputs, output_count) &&
|
bool ok = setup(&api, &builder, outputs, output_count) &&
|
||||||
config_builder_finish(&builder, out);
|
config_builder_finish(&builder, out);
|
||||||
config_builder_cleanup(&builder);
|
config_builder_cleanup(&builder);
|
||||||
|
|||||||
@@ -5,13 +5,12 @@
|
|||||||
#include <zdwm/bar.h>
|
#include <zdwm/bar.h>
|
||||||
#include <zdwm/types.h>
|
#include <zdwm/types.h>
|
||||||
|
|
||||||
#include "core/backend.h"
|
#include "common/listeners.h"
|
||||||
|
#include "common/workspace.h"
|
||||||
#include "core/binding.h"
|
#include "core/binding.h"
|
||||||
#include "core/layout.h"
|
#include "core/layout.h"
|
||||||
#include "core/listeners.h"
|
|
||||||
#include "core/rules.h"
|
#include "core/rules.h"
|
||||||
#include "core/types.h"
|
#include "interface/backend.h"
|
||||||
#include "core/wm_desc.h"
|
|
||||||
|
|
||||||
typedef struct runtime_init_desc_t {
|
typedef struct runtime_init_desc_t {
|
||||||
backend_t *backend;
|
backend_t *backend;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
typedef struct binding_mode_t {
|
typedef struct binding_mode_t {
|
||||||
zdwm_binding_mode_id_t id;
|
zdwm_binding_mode_id_t id;
|
||||||
@@ -82,8 +82,10 @@ static const mod_entry_t mod_table[] = {
|
|||||||
|
|
||||||
static modifier_mask_t lookup_modifier(const char *name, size_t len) {
|
static modifier_mask_t lookup_modifier(const char *name, size_t len) {
|
||||||
for (size_t i = 0; i < countof(mod_table); ++i) {
|
for (size_t i = 0; i < countof(mod_table); ++i) {
|
||||||
if (strlen(mod_table[i].name) == len &&
|
if (
|
||||||
strncmp(name, mod_table[i].name, len) == 0) {
|
strlen(mod_table[i].name) == len &&
|
||||||
|
strncmp(name, mod_table[i].name, len) == 0
|
||||||
|
) {
|
||||||
return mod_table[i].mask;
|
return mod_table[i].mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <zdwm/action.h>
|
#include <zdwm/action.h>
|
||||||
#include <zdwm/types.h>
|
#include <zdwm/types.h>
|
||||||
|
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
typedef struct binding_table_t binding_table_t;
|
typedef struct binding_table_t binding_table_t;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/types.h"
|
#include "core/window_info.h"
|
||||||
#include "core/wm_desc.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
typedef enum command_type_t {
|
typedef enum command_type_t {
|
||||||
ZDWM_COMMAND_MANAGE_WINDOW,
|
ZDWM_COMMAND_MANAGE_WINDOW,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
void layer_stack_cleanup(layer_stack_t *layer) {
|
void layer_stack_cleanup(layer_stack_t *layer) {
|
||||||
p_delete(&layer->order);
|
p_delete(&layer->order);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
typedef struct layer_stack_t {
|
typedef struct layer_stack_t {
|
||||||
window_id_t *order;
|
window_id_t *order;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
void layout_result_cleanup(layout_result_t *result) {
|
void layout_result_cleanup(layout_result_t *result) {
|
||||||
p_delete(&result->items);
|
p_delete(&result->items);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <zdwm/layout.h>
|
#include <zdwm/layout.h>
|
||||||
|
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
typedef zdwm_layout_ctx_t layout_ctx_t;
|
typedef zdwm_layout_ctx_t layout_ctx_t;
|
||||||
typedef zdwm_layout_item_t layout_item_t;
|
typedef zdwm_layout_item_t layout_item_t;
|
||||||
|
|||||||
@@ -1,112 +1,11 @@
|
|||||||
#include "core/listeners.h"
|
#include "core/listeners.h"
|
||||||
|
|
||||||
#include "base/array.h"
|
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
|
#include "common/listeners.h"
|
||||||
#include "core/binding.h"
|
#include "core/binding.h"
|
||||||
#include "core/layout.h"
|
#include "core/layout.h"
|
||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
|
|
||||||
#define ADD_LISTENER(FIELD) \
|
|
||||||
auto list = &listeners->FIELD; \
|
|
||||||
auto item = array_push(list->items, list->count, list->capacity); \
|
|
||||||
item->fn = fn; \
|
|
||||||
item->user_data = user_data
|
|
||||||
|
|
||||||
void listeners_add_output_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_current_output_id_listener fn,
|
|
||||||
void *user_data
|
|
||||||
) {
|
|
||||||
ADD_LISTENER(output_listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
void listeners_add_initial_workspace_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_initial_workspace_list fn,
|
|
||||||
void *user_data
|
|
||||||
) {
|
|
||||||
ADD_LISTENER(initial_workspace_listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
void listeners_add_active_workspace_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_workspace_active_updated fn,
|
|
||||||
void *user_data
|
|
||||||
) {
|
|
||||||
ADD_LISTENER(active_workspace_listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
void listeners_add_layout_notify(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_layout_notify fn,
|
|
||||||
void *user_data
|
|
||||||
) {
|
|
||||||
ADD_LISTENER(layout_listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
void listeners_add_binding_mode_notify(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_binding_mode_notify fn,
|
|
||||||
void *user_data
|
|
||||||
) {
|
|
||||||
ADD_LISTENER(binding_mode_listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
void listeners_add_initial_window_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_initial_window_list fn,
|
|
||||||
void *user_data
|
|
||||||
) {
|
|
||||||
ADD_LISTENER(initial_window_listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
void listeners_add_window_added_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_window_added fn,
|
|
||||||
void *user_data
|
|
||||||
) {
|
|
||||||
ADD_LISTENER(window_added_listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
void listeners_add_window_updated_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_window_updated fn,
|
|
||||||
void *user_data
|
|
||||||
) {
|
|
||||||
ADD_LISTENER(window_updated_listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
void listeners_add_window_removed_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_window_removed fn,
|
|
||||||
void *user_data
|
|
||||||
) {
|
|
||||||
ADD_LISTENER(window_removed_listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef ADD_LISTENER
|
|
||||||
|
|
||||||
#define CLEANUP_LIST(FIELD) \
|
|
||||||
p_delete(&listeners->FIELD.items); \
|
|
||||||
listeners->FIELD.count = 0; \
|
|
||||||
listeners->FIELD.capacity = 0
|
|
||||||
|
|
||||||
void listeners_cleanup(listeners_t *listeners) {
|
|
||||||
if (!listeners) return;
|
|
||||||
|
|
||||||
CLEANUP_LIST(output_listeners);
|
|
||||||
CLEANUP_LIST(initial_workspace_listeners);
|
|
||||||
CLEANUP_LIST(active_workspace_listeners);
|
|
||||||
CLEANUP_LIST(layout_listeners);
|
|
||||||
CLEANUP_LIST(binding_mode_listeners);
|
|
||||||
CLEANUP_LIST(initial_window_listeners);
|
|
||||||
CLEANUP_LIST(window_added_listeners);
|
|
||||||
CLEANUP_LIST(window_updated_listeners);
|
|
||||||
CLEANUP_LIST(window_removed_listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef CLEANUP_LIST
|
|
||||||
|
|
||||||
#define FOR_EACH_LISTENER(FIELD, BODY) \
|
#define FOR_EACH_LISTENER(FIELD, BODY) \
|
||||||
do { \
|
do { \
|
||||||
if (!(listeners)) return; \
|
if (!(listeners)) return; \
|
||||||
|
|||||||
@@ -3,98 +3,8 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <zdwm/listeners.h>
|
#include <zdwm/listeners.h>
|
||||||
|
|
||||||
#include "core/types.h"
|
#include "common/listeners.h"
|
||||||
|
#include "interface/types.h"
|
||||||
typedef struct binding_table_t binding_table_t;
|
|
||||||
typedef struct layout_registry_t layout_registry_t;
|
|
||||||
typedef struct state_t state_t;
|
|
||||||
|
|
||||||
#define ITEM(NAME, FN_TYPE) \
|
|
||||||
typedef struct NAME##_listener_item_t { \
|
|
||||||
FN_TYPE *fn; \
|
|
||||||
void *user_data; \
|
|
||||||
} NAME##_listener_item_t
|
|
||||||
|
|
||||||
#define LISTENERS(NAME, FN_TYPE) \
|
|
||||||
ITEM(NAME, FN_TYPE); \
|
|
||||||
typedef struct NAME##_listeners_t { \
|
|
||||||
NAME##_listener_item_t *items; \
|
|
||||||
size_t count; \
|
|
||||||
size_t capacity; \
|
|
||||||
} NAME##_listeners_t
|
|
||||||
|
|
||||||
LISTENERS(output, zdwm_current_output_id_listener);
|
|
||||||
LISTENERS(initial_workspace_list, zdwm_initial_workspace_list);
|
|
||||||
LISTENERS(workspace_active, zdwm_workspace_active_updated);
|
|
||||||
LISTENERS(layout, zdwm_layout_notify);
|
|
||||||
LISTENERS(binding_mode, zdwm_binding_mode_notify);
|
|
||||||
LISTENERS(initial_window_list, zdwm_initial_window_list);
|
|
||||||
LISTENERS(window_added, zdwm_window_added);
|
|
||||||
LISTENERS(window_updated, zdwm_window_updated);
|
|
||||||
LISTENERS(window_removed, zdwm_window_removed);
|
|
||||||
|
|
||||||
#undef ITEM
|
|
||||||
#undef LISTENERS
|
|
||||||
|
|
||||||
typedef struct listeners_t {
|
|
||||||
output_listeners_t output_listeners;
|
|
||||||
initial_workspace_list_listeners_t initial_workspace_listeners;
|
|
||||||
workspace_active_listeners_t active_workspace_listeners;
|
|
||||||
layout_listeners_t layout_listeners;
|
|
||||||
binding_mode_listeners_t binding_mode_listeners;
|
|
||||||
initial_window_list_listeners_t initial_window_listeners;
|
|
||||||
window_added_listeners_t window_added_listeners;
|
|
||||||
window_updated_listeners_t window_updated_listeners;
|
|
||||||
window_removed_listeners_t window_removed_listeners;
|
|
||||||
} listeners_t;
|
|
||||||
|
|
||||||
void listeners_add_output_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_current_output_id_listener fn,
|
|
||||||
void *user_data
|
|
||||||
);
|
|
||||||
void listeners_add_initial_workspace_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_initial_workspace_list fn,
|
|
||||||
void *user_data
|
|
||||||
);
|
|
||||||
void listeners_add_active_workspace_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_workspace_active_updated fn,
|
|
||||||
void *user_data
|
|
||||||
);
|
|
||||||
void listeners_add_layout_notify(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_layout_notify fn,
|
|
||||||
void *user_data
|
|
||||||
);
|
|
||||||
void listeners_add_binding_mode_notify(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_binding_mode_notify fn,
|
|
||||||
void *user_data
|
|
||||||
);
|
|
||||||
void listeners_add_initial_window_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_initial_window_list fn,
|
|
||||||
void *user_data
|
|
||||||
);
|
|
||||||
void listeners_add_window_added_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_window_added fn,
|
|
||||||
void *user_data
|
|
||||||
);
|
|
||||||
void listeners_add_window_updated_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_window_updated fn,
|
|
||||||
void *user_data
|
|
||||||
);
|
|
||||||
void listeners_add_window_removed_listener(
|
|
||||||
listeners_t *listeners,
|
|
||||||
zdwm_window_removed fn,
|
|
||||||
void *user_data
|
|
||||||
);
|
|
||||||
|
|
||||||
void listeners_cleanup(listeners_t *listeners);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 通知当前 output 信息
|
* @brief 通知当前 output 信息
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
|
|
||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/types.h"
|
#include "interface/effect.h"
|
||||||
|
#include "interface/types.h"
|
||||||
|
|
||||||
static void free_memory_hold_by_effects(effect_t *effects, size_t count) {
|
static void free_memory_hold_by_effects(effect_t *effects, size_t count) {
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
|||||||
@@ -1,89 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "base/color.h"
|
#include "base/color.h"
|
||||||
#include "core/types.h"
|
#include "interface/effect.h"
|
||||||
|
#include "interface/types.h"
|
||||||
typedef enum effect_type_t {
|
|
||||||
ZDWM_EFFECT_MAP_WINDOW = 1,
|
|
||||||
ZDWM_EFFECT_UNMAP_WINDOW,
|
|
||||||
ZDWM_EFFECT_FOCUS_WINDOW,
|
|
||||||
ZDWM_EFFECT_KILL_WINDOW,
|
|
||||||
ZDWM_EFFECT_WITHDRAW_WINDOW,
|
|
||||||
ZDWM_EFFECT_START_MOVE_WINDOW,
|
|
||||||
ZDWM_EFFECT_START_RESIZE_WINDOW,
|
|
||||||
ZDWM_EFFECT_MINIMIZE_WINDOW,
|
|
||||||
ZDWM_EFFECT_MAXIMIZE_WINDOW,
|
|
||||||
ZDWM_EFFECT_FULLSCREEN_WINDOW,
|
|
||||||
ZDWM_EFFECT_CONFIGURE_WINDOW,
|
|
||||||
ZDWM_EFFECT_CHANGE_BORDER_COLOR,
|
|
||||||
ZDWM_EFFECT_CHANGE_WINDOW_LIST,
|
|
||||||
ZDWM_EFFECT_RESTACK_WINDOWS,
|
|
||||||
ZDWM_EFFECT_BIND_KEY,
|
|
||||||
ZDWM_EFFECT_GRAB_BUTTON,
|
|
||||||
ZDWM_EFFECT_UNGRAB_POINTER,
|
|
||||||
} effect_type_t;
|
|
||||||
|
|
||||||
typedef struct effect_move_window_t {
|
|
||||||
window_id_t window;
|
|
||||||
point_t left_top_point;
|
|
||||||
} effect_move_window_t;
|
|
||||||
|
|
||||||
typedef struct effect_resize_window_t {
|
|
||||||
window_id_t window;
|
|
||||||
int32_t width;
|
|
||||||
int32_t height;
|
|
||||||
} effect_resize_window_t;
|
|
||||||
|
|
||||||
typedef struct effect_change_border_color_t {
|
|
||||||
window_id_t window;
|
|
||||||
const color_t *color;
|
|
||||||
} effect_change_border_color_t;
|
|
||||||
|
|
||||||
typedef struct effect_window_list_t {
|
|
||||||
const window_id_t *windows;
|
|
||||||
size_t count;
|
|
||||||
} effect_window_list_t;
|
|
||||||
|
|
||||||
typedef struct effect_bind_key_t {
|
|
||||||
const key_bind_t *keys;
|
|
||||||
size_t count;
|
|
||||||
} effect_bind_key_t;
|
|
||||||
|
|
||||||
typedef struct effect_grab_button_t {
|
|
||||||
window_id_t window;
|
|
||||||
const grab_button_t *buttons;
|
|
||||||
size_t count;
|
|
||||||
} effect_grab_button_t;
|
|
||||||
|
|
||||||
typedef struct effect_bool_window_t {
|
|
||||||
window_id_t window;
|
|
||||||
bool value;
|
|
||||||
} effect_bool_window_t;
|
|
||||||
|
|
||||||
typedef struct effect_t {
|
|
||||||
effect_type_t type;
|
|
||||||
union {
|
|
||||||
only_window_data_t map;
|
|
||||||
only_window_data_t unmap;
|
|
||||||
only_window_data_t focus;
|
|
||||||
only_window_data_t kill;
|
|
||||||
only_window_data_t withdraw;
|
|
||||||
only_window_data_t move;
|
|
||||||
only_window_data_t resize;
|
|
||||||
effect_bool_window_t minimize;
|
|
||||||
effect_bool_window_t maximize;
|
|
||||||
effect_bool_window_t fullscreen;
|
|
||||||
configure_data_t configure;
|
|
||||||
effect_change_border_color_t change_border_color;
|
|
||||||
effect_window_list_t change_window_list;
|
|
||||||
effect_window_list_t restack_windows;
|
|
||||||
effect_bind_key_t bind_key;
|
|
||||||
effect_grab_button_t grab_button;
|
|
||||||
} as;
|
|
||||||
} effect_t;
|
|
||||||
|
|
||||||
typedef struct plan_t {
|
typedef struct plan_t {
|
||||||
effect_t *effects;
|
effect_t *effects;
|
||||||
|
|||||||
@@ -10,19 +10,19 @@
|
|||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "base/process.h"
|
#include "base/process.h"
|
||||||
#include "base/time.h"
|
#include "base/time.h"
|
||||||
#include "base/window_list.h"
|
#include "common/listeners.h"
|
||||||
|
#include "common/window.h"
|
||||||
#include "core/binding.h"
|
#include "core/binding.h"
|
||||||
#include "core/command.h"
|
#include "core/command.h"
|
||||||
#include "core/command_buffer.h"
|
#include "core/command_buffer.h"
|
||||||
#include "core/event.h"
|
|
||||||
#include "core/layout.h"
|
#include "core/layout.h"
|
||||||
#include "core/listeners.h"
|
#include "core/listeners.h"
|
||||||
#include "core/plan.h"
|
#include "core/plan.h"
|
||||||
#include "core/rules.h"
|
#include "core/rules.h"
|
||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
#include "core/types.h"
|
|
||||||
#include "core/window.h"
|
#include "core/window.h"
|
||||||
#include "core/wm_desc.h"
|
#include "interface/event.h"
|
||||||
|
#include "interface/types.h"
|
||||||
|
|
||||||
static void quit(bool restart, command_buffer_t *command_buffer) {
|
static void quit(bool restart, command_buffer_t *command_buffer) {
|
||||||
command_t quit_command = {
|
command_t quit_command = {
|
||||||
@@ -609,6 +609,7 @@ static void route_map_request(
|
|||||||
if (window) layer_type = MAX(window->layer, layer_type);
|
if (window) layer_type = MAX(window->layer, layer_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
command_t manage_window_cmd = {
|
command_t manage_window_cmd = {
|
||||||
.type = ZDWM_COMMAND_MANAGE_WINDOW,
|
.type = ZDWM_COMMAND_MANAGE_WINDOW,
|
||||||
.as.manage_window = {
|
.as.manage_window = {
|
||||||
@@ -635,6 +636,7 @@ static void route_map_request(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
rule_action_t action = {.workspace = ZDWM_WORKSPACE_ID_INVALID};
|
rule_action_t action = {.workspace = ZDWM_WORKSPACE_ID_INVALID};
|
||||||
bool have_rule_match = rules_resolve(rules, &e->metadata, &action);
|
bool have_rule_match = rules_resolve(rules, &e->metadata, &action);
|
||||||
@@ -1431,16 +1433,20 @@ static void send_window_to_workspace(
|
|||||||
|
|
||||||
if (src_visible) {
|
if (src_visible) {
|
||||||
if (src_ws && src_ws->focused_window_id != src_old_focused) {
|
if (src_ws && src_ws->focused_window_id != src_old_focused) {
|
||||||
if (!window_id_invalid(src_old_focused) &&
|
if (
|
||||||
state_window_get(state, src_old_focused)) {
|
!window_id_invalid(src_old_focused) &&
|
||||||
|
state_window_get(state, src_old_focused)
|
||||||
|
) {
|
||||||
plan_push_change_border_color_effect(
|
plan_push_change_border_color_effect(
|
||||||
plan,
|
plan,
|
||||||
src_old_focused,
|
src_old_focused,
|
||||||
&ctx->border->normal_color
|
&ctx->border->normal_color
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!window_id_invalid(src_ws->focused_window_id) &&
|
if (
|
||||||
state_window_get(state, src_ws->focused_window_id)) {
|
!window_id_invalid(src_ws->focused_window_id) &&
|
||||||
|
state_window_get(state, src_ws->focused_window_id)
|
||||||
|
) {
|
||||||
plan_push_focus_effect(plan, src_ws->focused_window_id);
|
plan_push_focus_effect(plan, src_ws->focused_window_id);
|
||||||
plan_push_change_border_color_effect(
|
plan_push_change_border_color_effect(
|
||||||
plan,
|
plan,
|
||||||
@@ -1469,8 +1475,10 @@ static void send_window_to_workspace(
|
|||||||
|
|
||||||
auto listeners = ctx->listeners;
|
auto listeners = ctx->listeners;
|
||||||
listeners_notify_window_updated(listeners, state, command->window);
|
listeners_notify_window_updated(listeners, state, command->window);
|
||||||
if (src_ws && src_ws->focused_window_id != src_old_focused &&
|
if (
|
||||||
!window_id_invalid(src_ws->focused_window_id)) {
|
src_ws && src_ws->focused_window_id != src_old_focused &&
|
||||||
|
!window_id_invalid(src_ws->focused_window_id)
|
||||||
|
) {
|
||||||
listeners_notify_window_updated(
|
listeners_notify_window_updated(
|
||||||
listeners,
|
listeners,
|
||||||
state,
|
state,
|
||||||
@@ -1555,12 +1563,14 @@ static void switch_workspace(
|
|||||||
auto output_id = workspace->output_id;
|
auto output_id = workspace->output_id;
|
||||||
workspace_id_t old_workspace = ZDWM_WORKSPACE_ID_INVALID;
|
workspace_id_t old_workspace = ZDWM_WORKSPACE_ID_INVALID;
|
||||||
|
|
||||||
if (state_output_set_current_workspace(
|
if (
|
||||||
|
state_output_set_current_workspace(
|
||||||
state,
|
state,
|
||||||
output_id,
|
output_id,
|
||||||
workspace_id,
|
workspace_id,
|
||||||
&old_workspace
|
&old_workspace
|
||||||
)) {
|
)
|
||||||
|
) {
|
||||||
plan->need_relayout = true;
|
plan->need_relayout = true;
|
||||||
add_switch_workspace_effects(state, old_workspace, workspace_id, plan);
|
add_switch_workspace_effects(state, old_workspace, workspace_id, plan);
|
||||||
listeners_notify_workspace_active(listeners, output_id, workspace_id);
|
listeners_notify_workspace_active(listeners, output_id, workspace_id);
|
||||||
|
|||||||
@@ -3,16 +3,29 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <zdwm/action.h>
|
#include <zdwm/action.h>
|
||||||
|
|
||||||
#include "base/window_list.h"
|
#include "common/listeners.h"
|
||||||
|
#include "common/window.h"
|
||||||
#include "core/binding.h"
|
#include "core/binding.h"
|
||||||
#include "core/command_buffer.h"
|
#include "core/command_buffer.h"
|
||||||
#include "core/event.h"
|
|
||||||
#include "core/layout.h"
|
#include "core/layout.h"
|
||||||
#include "core/listeners.h"
|
|
||||||
#include "core/plan.h"
|
#include "core/plan.h"
|
||||||
#include "core/rules.h"
|
#include "core/rules.h"
|
||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
#include "core/types.h"
|
#include "interface/event.h"
|
||||||
|
|
||||||
|
typedef enum window_interaction_mode_t {
|
||||||
|
ZDWM_WINDOW_INTERACTION_NONE,
|
||||||
|
ZDWM_WINDOW_INTERACTION_MOVE,
|
||||||
|
ZDWM_WINDOW_INTERACTION_RESIZE,
|
||||||
|
} window_interaction_mode_t;
|
||||||
|
|
||||||
|
typedef struct window_interaction_state_t {
|
||||||
|
window_interaction_mode_t mode;
|
||||||
|
window_id_t window;
|
||||||
|
point_t start_coordinate;
|
||||||
|
rect_t origin_rect;
|
||||||
|
uint64_t last_change_time;
|
||||||
|
} window_interaction_state_t;
|
||||||
|
|
||||||
typedef struct policy_bar_t {
|
typedef struct policy_bar_t {
|
||||||
bool *visible;
|
bool *visible;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <zdwm/types.h>
|
#include <zdwm/types.h>
|
||||||
|
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
bool rules_move(rules_t *src, rules_t *dest) {
|
bool rules_move(rules_t *src, rules_t *dest) {
|
||||||
if (!dest || !src) return false;
|
if (!dest || !src) return false;
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
#include "core/window.h"
|
|
||||||
|
|
||||||
typedef struct rule_item_t {
|
typedef struct rule_item_t {
|
||||||
rule_match_t match;
|
rule_match_t match;
|
||||||
|
|||||||
@@ -8,11 +8,12 @@
|
|||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
#include "base/log.h"
|
#include "base/log.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "base/window_list.h"
|
#include "common/window.h"
|
||||||
|
#include "common/workspace.h"
|
||||||
#include "core/layer.h"
|
#include "core/layer.h"
|
||||||
#include "core/types.h"
|
|
||||||
#include "core/window.h"
|
#include "core/window.h"
|
||||||
#include "core/wm_desc.h"
|
#include "core/window_info.h"
|
||||||
|
#include "interface/types.h"
|
||||||
|
|
||||||
void state_init(
|
void state_init(
|
||||||
state_t *state,
|
state_t *state,
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "base/window_list.h"
|
#include "common/window.h"
|
||||||
|
#include "common/workspace.h"
|
||||||
#include "core/layer.h"
|
#include "core/layer.h"
|
||||||
#include "core/types.h"
|
|
||||||
#include "core/window.h"
|
#include "core/window.h"
|
||||||
#include "core/wm_desc.h"
|
#include "core/window_info.h"
|
||||||
|
#include "interface/types.h"
|
||||||
|
|
||||||
typedef struct workspace_t {
|
typedef struct workspace_t {
|
||||||
workspace_id_t id;
|
workspace_id_t id;
|
||||||
|
|||||||
@@ -1,40 +1,7 @@
|
|||||||
#include "core/window.h"
|
#include "core/window.h"
|
||||||
|
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
window_layer_type_t window_classify_layer(const window_layer_props_t *props) {
|
|
||||||
for (size_t i = 0; i < props->type_count; ++i) {
|
|
||||||
window_type_t type = props->types[i];
|
|
||||||
if (type == ZDWM_WINDOW_TYPE_NOTIFICATION) return ZDWM_WINDOW_LAYER_OVERLAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < props->state_count; ++i) {
|
|
||||||
window_state_t state = props->states[i];
|
|
||||||
if (state == ZDWM_WINDOW_STATE_ABOVE) return ZDWM_WINDOW_LAYER_TOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ZDWM_WINDOW_LAYER_NORMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void window_layer_props_cleanup(window_layer_props_t *props) {
|
|
||||||
if (!props) return;
|
|
||||||
|
|
||||||
p_delete(&props->types);
|
|
||||||
props->type_count = 0;
|
|
||||||
p_delete(&props->states);
|
|
||||||
props->state_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void window_metadata_cleanup(window_metadata_t *metadata) {
|
|
||||||
if (!metadata) return;
|
|
||||||
|
|
||||||
p_delete(&metadata->title);
|
|
||||||
p_delete(&metadata->app_id);
|
|
||||||
p_delete(&metadata->role);
|
|
||||||
p_delete(&metadata->class_name);
|
|
||||||
p_delete(&metadata->instance_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void window_set_fullscreen(window_t *window, bool fullscreen) {
|
void window_set_fullscreen(window_t *window, bool fullscreen) {
|
||||||
window->fullscreen = fullscreen;
|
window->fullscreen = fullscreen;
|
||||||
|
|||||||
@@ -3,66 +3,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
/* Internal semantic window types mapped from backend-specific protocols. */
|
|
||||||
typedef enum window_type_t {
|
|
||||||
ZDWM_WINDOW_TYPE_NORMAL = 0,
|
|
||||||
ZDWM_WINDOW_TYPE_DESKTOP,
|
|
||||||
ZDWM_WINDOW_TYPE_DOCK,
|
|
||||||
ZDWM_WINDOW_TYPE_TOOLBAR,
|
|
||||||
ZDWM_WINDOW_TYPE_DIALOG,
|
|
||||||
ZDWM_WINDOW_TYPE_UTILITY,
|
|
||||||
ZDWM_WINDOW_TYPE_SPLASH,
|
|
||||||
ZDWM_WINDOW_TYPE_MENU,
|
|
||||||
ZDWM_WINDOW_TYPE_DROPDOWN_MENU,
|
|
||||||
ZDWM_WINDOW_TYPE_POPUP_MENU,
|
|
||||||
ZDWM_WINDOW_TYPE_TOOLTIP,
|
|
||||||
ZDWM_WINDOW_TYPE_COMBO,
|
|
||||||
ZDWM_WINDOW_TYPE_DND,
|
|
||||||
ZDWM_WINDOW_TYPE_NOTIFICATION,
|
|
||||||
} window_type_t;
|
|
||||||
|
|
||||||
/* Internal semantic window states mapped from backend-specific protocols. */
|
|
||||||
typedef enum window_state_t {
|
|
||||||
ZDWM_WINDOW_STATE_ABOVE = 0,
|
|
||||||
ZDWM_WINDOW_STATE_FULLSCREEN,
|
|
||||||
ZDWM_WINDOW_STATE_MODAL,
|
|
||||||
ZDWM_WINDOW_STATE_STICKY,
|
|
||||||
} window_state_t;
|
|
||||||
|
|
||||||
/* 层级从低到高 */
|
|
||||||
typedef enum window_layer_type_t {
|
|
||||||
ZDWM_WINDOW_LAYER_DESKTOP = 0,
|
|
||||||
ZDWM_WINDOW_LAYER_NORMAL,
|
|
||||||
ZDWM_WINDOW_LAYER_TOP,
|
|
||||||
ZDWM_WINDOW_LAYER_OVERLAY,
|
|
||||||
ZDWM_WINDOW_LAYER_COUNT,
|
|
||||||
} window_layer_type_t;
|
|
||||||
|
|
||||||
typedef enum window_metadata_change_flags_t {
|
|
||||||
ZDWM_WINDOW_METADATA_CHANGE_TITLE = 1u << 0,
|
|
||||||
ZDWM_WINDOW_METADATA_CHANGE_APP_ID = 1u << 1,
|
|
||||||
ZDWM_WINDOW_METADATA_CHANGE_ROLE = 1u << 2,
|
|
||||||
ZDWM_WINDOW_METADATA_CHANGE_CLASS = 1u << 3,
|
|
||||||
ZDWM_WINDOW_METADATA_CHANGE_INSTANCE = 1u << 4,
|
|
||||||
} window_metadata_change_flags_t;
|
|
||||||
|
|
||||||
typedef struct window_layer_props_t {
|
|
||||||
window_type_t *types;
|
|
||||||
size_t type_count;
|
|
||||||
|
|
||||||
window_state_t *states;
|
|
||||||
size_t state_count;
|
|
||||||
} window_layer_props_t;
|
|
||||||
|
|
||||||
typedef struct window_metadata_t {
|
|
||||||
char *title;
|
|
||||||
char *app_id;
|
|
||||||
char *role;
|
|
||||||
char *class_name;
|
|
||||||
char *instance_name;
|
|
||||||
} window_metadata_t;
|
|
||||||
|
|
||||||
typedef struct window_t {
|
typedef struct window_t {
|
||||||
window_id_t id;
|
window_id_t id;
|
||||||
@@ -95,11 +36,6 @@ typedef struct window_t {
|
|||||||
uint32_t border_width;
|
uint32_t border_width;
|
||||||
} window_t;
|
} window_t;
|
||||||
|
|
||||||
window_layer_type_t window_classify_layer(const window_layer_props_t *props);
|
|
||||||
|
|
||||||
void window_layer_props_cleanup(window_layer_props_t *props);
|
|
||||||
void window_metadata_cleanup(window_metadata_t *metadata);
|
|
||||||
|
|
||||||
void window_set_fullscreen(window_t *window, bool fullscreen);
|
void window_set_fullscreen(window_t *window, bool fullscreen);
|
||||||
void window_set_maximized(window_t *window, bool maximized);
|
void window_set_maximized(window_t *window, bool maximized);
|
||||||
void window_set_minimized(window_t *window, bool minimized);
|
void window_set_minimized(window_t *window, bool minimized);
|
||||||
|
|||||||
30
src/core/window_info.h
Normal file
30
src/core/window_info.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "interface/types.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 由 backend 提供的窗口基础信息。
|
||||||
|
*
|
||||||
|
* 这些字符串由调用方提供;state 如需长期持有,应自行复制。
|
||||||
|
*/
|
||||||
|
typedef struct window_info_t {
|
||||||
|
window_id_t id;
|
||||||
|
window_id_t transient_for;
|
||||||
|
rect_t frame_rect;
|
||||||
|
|
||||||
|
const char *title;
|
||||||
|
const char *app_id;
|
||||||
|
const char *role;
|
||||||
|
const char *class_name;
|
||||||
|
const char *instance_name;
|
||||||
|
|
||||||
|
window_layer_type_t layer_type;
|
||||||
|
bool fullscreen;
|
||||||
|
bool maximized;
|
||||||
|
bool minimized;
|
||||||
|
bool urgent;
|
||||||
|
bool skip_taskbar;
|
||||||
|
|
||||||
|
zdwm_size_t min_size;
|
||||||
|
zdwm_size_t max_size;
|
||||||
|
} window_info_t;
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "base/memory.h"
|
|
||||||
#include "core/types.h"
|
|
||||||
#include "core/window.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 由 backend 提供的窗口基础信息。
|
|
||||||
*
|
|
||||||
* 这些字符串由调用方提供;state 如需长期持有,应自行复制。
|
|
||||||
*/
|
|
||||||
typedef struct window_info_t {
|
|
||||||
window_id_t id;
|
|
||||||
window_id_t transient_for;
|
|
||||||
rect_t frame_rect;
|
|
||||||
|
|
||||||
const char *title;
|
|
||||||
const char *app_id;
|
|
||||||
const char *role;
|
|
||||||
const char *class_name;
|
|
||||||
const char *instance_name;
|
|
||||||
|
|
||||||
window_layer_type_t layer_type;
|
|
||||||
bool fullscreen;
|
|
||||||
bool maximized;
|
|
||||||
bool minimized;
|
|
||||||
bool urgent;
|
|
||||||
bool skip_taskbar;
|
|
||||||
|
|
||||||
zdwm_size_t min_size;
|
|
||||||
zdwm_size_t max_size;
|
|
||||||
} window_info_t;
|
|
||||||
|
|
||||||
typedef struct workspace_desc_t {
|
|
||||||
size_t output_index; /* 对应 state_init() 中 outputs[] 的索引 */
|
|
||||||
const char *name;
|
|
||||||
const layout_id_t *layout_ids;
|
|
||||||
size_t layout_count;
|
|
||||||
layout_id_t initial_layout_id;
|
|
||||||
} workspace_desc_t;
|
|
||||||
|
|
||||||
static inline void workspace_desc_cleanup(workspace_desc_t *workspace) {
|
|
||||||
if (!workspace) return;
|
|
||||||
|
|
||||||
p_delete(&workspace->name);
|
|
||||||
p_delete(&workspace->layout_ids);
|
|
||||||
workspace->output_index = 0;
|
|
||||||
workspace->layout_count = 0;
|
|
||||||
workspace->initial_layout_id = ZDWM_LAYOUT_ID_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
workspace_desc_list_cleanup(workspace_desc_t **list, size_t *count) {
|
|
||||||
if (!list || !count) return;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < *count; i++) {
|
|
||||||
workspace_desc_cleanup(&(*list)[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
p_delete(list);
|
|
||||||
*count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* workspace 描述校验接口。
|
|
||||||
*
|
|
||||||
* 这组接口只校验描述表自身的一致性,不访问 state。
|
|
||||||
*/
|
|
||||||
static inline bool workspace_desc_layouts_valid(
|
|
||||||
const workspace_desc_t *workspace
|
|
||||||
) {
|
|
||||||
if (!workspace || !workspace->layout_count || !workspace->layout_ids) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < workspace->layout_count; i++) {
|
|
||||||
if (workspace->layout_ids[i] == workspace->initial_layout_id) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
workspace_desc_valid(const workspace_desc_t *workspace, size_t output_count) {
|
|
||||||
if (!workspace || !workspace->name) return false;
|
|
||||||
if (workspace->output_index >= output_count) return false;
|
|
||||||
|
|
||||||
return workspace_desc_layouts_valid(workspace);
|
|
||||||
}
|
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "core/event.h"
|
#include "interface/effect.h"
|
||||||
#include "core/plan.h"
|
#include "interface/event.h"
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
|
|
||||||
typedef struct backend_t backend_t;
|
typedef struct backend_t backend_t;
|
||||||
|
|
||||||
95
src/interface/effect.h
Normal file
95
src/interface/effect.h
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "base/color.h"
|
||||||
|
#include "interface/types.h"
|
||||||
|
|
||||||
|
typedef enum effect_type_t {
|
||||||
|
ZDWM_EFFECT_MAP_WINDOW = 1,
|
||||||
|
ZDWM_EFFECT_UNMAP_WINDOW,
|
||||||
|
ZDWM_EFFECT_FOCUS_WINDOW,
|
||||||
|
ZDWM_EFFECT_KILL_WINDOW,
|
||||||
|
ZDWM_EFFECT_WITHDRAW_WINDOW,
|
||||||
|
ZDWM_EFFECT_START_MOVE_WINDOW,
|
||||||
|
ZDWM_EFFECT_START_RESIZE_WINDOW,
|
||||||
|
ZDWM_EFFECT_MINIMIZE_WINDOW,
|
||||||
|
ZDWM_EFFECT_MAXIMIZE_WINDOW,
|
||||||
|
ZDWM_EFFECT_FULLSCREEN_WINDOW,
|
||||||
|
ZDWM_EFFECT_CONFIGURE_WINDOW,
|
||||||
|
ZDWM_EFFECT_CHANGE_BORDER_COLOR,
|
||||||
|
ZDWM_EFFECT_CHANGE_WINDOW_LIST,
|
||||||
|
ZDWM_EFFECT_RESTACK_WINDOWS,
|
||||||
|
ZDWM_EFFECT_BIND_KEY,
|
||||||
|
ZDWM_EFFECT_GRAB_BUTTON,
|
||||||
|
ZDWM_EFFECT_UNGRAB_POINTER,
|
||||||
|
} effect_type_t;
|
||||||
|
|
||||||
|
typedef struct effect_move_window_t {
|
||||||
|
window_id_t window;
|
||||||
|
point_t left_top_point;
|
||||||
|
} effect_move_window_t;
|
||||||
|
|
||||||
|
typedef struct effect_resize_window_t {
|
||||||
|
window_id_t window;
|
||||||
|
int32_t width;
|
||||||
|
int32_t height;
|
||||||
|
} effect_resize_window_t;
|
||||||
|
|
||||||
|
typedef struct effect_change_border_color_t {
|
||||||
|
window_id_t window;
|
||||||
|
const color_t *color;
|
||||||
|
} effect_change_border_color_t;
|
||||||
|
|
||||||
|
typedef struct effect_window_list_t {
|
||||||
|
const window_id_t *windows;
|
||||||
|
size_t count;
|
||||||
|
} effect_window_list_t;
|
||||||
|
|
||||||
|
typedef struct key_bind_t {
|
||||||
|
modifier_mask_t modifiers;
|
||||||
|
keysym_t keysym;
|
||||||
|
} key_bind_t;
|
||||||
|
|
||||||
|
typedef struct effect_bind_key_t {
|
||||||
|
const key_bind_t *keys;
|
||||||
|
size_t count;
|
||||||
|
} effect_bind_key_t;
|
||||||
|
|
||||||
|
typedef struct grab_button_t {
|
||||||
|
modifier_mask_t modifiers;
|
||||||
|
button_t button;
|
||||||
|
} grab_button_t;
|
||||||
|
|
||||||
|
typedef struct effect_grab_button_t {
|
||||||
|
window_id_t window;
|
||||||
|
const grab_button_t *buttons;
|
||||||
|
size_t count;
|
||||||
|
} effect_grab_button_t;
|
||||||
|
|
||||||
|
typedef struct effect_bool_window_t {
|
||||||
|
window_id_t window;
|
||||||
|
bool value;
|
||||||
|
} effect_bool_window_t;
|
||||||
|
|
||||||
|
typedef struct effect_t {
|
||||||
|
effect_type_t type;
|
||||||
|
union {
|
||||||
|
only_window_data_t map;
|
||||||
|
only_window_data_t unmap;
|
||||||
|
only_window_data_t focus;
|
||||||
|
only_window_data_t kill;
|
||||||
|
only_window_data_t withdraw;
|
||||||
|
only_window_data_t move;
|
||||||
|
only_window_data_t resize;
|
||||||
|
effect_bool_window_t minimize;
|
||||||
|
effect_bool_window_t maximize;
|
||||||
|
effect_bool_window_t fullscreen;
|
||||||
|
configure_data_t configure;
|
||||||
|
effect_change_border_color_t change_border_color;
|
||||||
|
effect_window_list_t change_window_list;
|
||||||
|
effect_window_list_t restack_windows;
|
||||||
|
effect_bind_key_t bind_key;
|
||||||
|
effect_grab_button_t grab_button;
|
||||||
|
} as;
|
||||||
|
} effect_t;
|
||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "core/types.h"
|
#include "interface/types.h"
|
||||||
#include "core/window.h"
|
|
||||||
|
|
||||||
typedef enum event_type_t {
|
typedef enum event_type_t {
|
||||||
ZDWM_EVENT_NONE,
|
ZDWM_EVENT_NONE,
|
||||||
@@ -75,11 +74,13 @@ typedef struct window_metadata_change_event_t {
|
|||||||
window_metadata_t metadata;
|
window_metadata_t metadata;
|
||||||
} window_metadata_change_event_t;
|
} window_metadata_change_event_t;
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
typedef enum window_activation_source_t {
|
typedef enum window_activation_source_t {
|
||||||
ZDWM_WINDOW_ACTIVATION_SOURCE_LEGACY = 0,
|
ZDWM_WINDOW_ACTIVATION_SOURCE_LEGACY = 0,
|
||||||
ZDWM_WINDOW_ACTIVATION_SOURCE_APPLICATION = 1,
|
ZDWM_WINDOW_ACTIVATION_SOURCE_APPLICATION = 1,
|
||||||
ZDWM_WINDOW_ACTIVATION_SOURCE_PAGER = 2,
|
ZDWM_WINDOW_ACTIVATION_SOURCE_PAGER = 2,
|
||||||
} window_activation_source_t;
|
} window_activation_source_t;
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
typedef struct window_activate_request_event_t {
|
typedef struct window_activate_request_event_t {
|
||||||
window_id_t window;
|
window_id_t window;
|
||||||
@@ -109,6 +110,3 @@ typedef struct event_t {
|
|||||||
configure_data_t configure_request;
|
configure_data_t configure_request;
|
||||||
} as;
|
} as;
|
||||||
} event_t;
|
} event_t;
|
||||||
|
|
||||||
void event_cleanup(event_t *event);
|
|
||||||
void event_reset(event_t *event);
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <zdwm/rules.h>
|
#include <zdwm/rules.h>
|
||||||
#include <zdwm/types.h>
|
#include <zdwm/types.h>
|
||||||
@@ -32,25 +33,64 @@ typedef struct point_t {
|
|||||||
int32_t y;
|
int32_t y;
|
||||||
} point_t;
|
} point_t;
|
||||||
|
|
||||||
typedef enum focus_direction_t {
|
typedef struct zdwm_size_t {
|
||||||
ZDWM_FOCUS_PREV,
|
int32_t width;
|
||||||
ZDWM_FOCUS_NEXT,
|
int32_t height;
|
||||||
} focus_direction_t;
|
} zdwm_size_t;
|
||||||
|
|
||||||
typedef enum cross_output_policy_t {
|
typedef struct only_window_data_t {
|
||||||
ZDWM_CROSS_OUTPUT_KEEP_WORKSPACE,
|
window_id_t window;
|
||||||
ZDWM_CROSS_OUTPUT_MOVE_TO_TARGET_WORKSPACE,
|
} only_window_data_t;
|
||||||
} cross_output_policy_t;
|
|
||||||
|
|
||||||
typedef struct key_bind_t {
|
/* clang-format off */
|
||||||
modifier_mask_t modifiers;
|
typedef enum configure_field_t {
|
||||||
keysym_t keysym;
|
ZDWM_CONFIGURE_FIELD_X = 1u << 0,
|
||||||
} key_bind_t;
|
ZDWM_CONFIGURE_FIELD_Y = 1u << 1,
|
||||||
|
ZDWM_CONFIGURE_FIELD_WIDTH = 1u << 2,
|
||||||
|
ZDWM_CONFIGURE_FIELD_HEIGHT = 1u << 3,
|
||||||
|
ZDWM_CONFIGURE_FIELD_BORDER_WIDTH = 1u << 4,
|
||||||
|
ZDWM_CONFIGURE_FIELD_SIBLING = 1u << 5,
|
||||||
|
ZDWM_CONFIGURE_FIELD_STACK_MODE = 1u << 6,
|
||||||
|
} configure_field_t;
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
typedef struct grab_button_t {
|
typedef struct configure_data_t {
|
||||||
modifier_mask_t modifiers;
|
window_id_t window;
|
||||||
button_t button;
|
uint32_t changed_fields;
|
||||||
} grab_button_t;
|
int32_t x;
|
||||||
|
int32_t y;
|
||||||
|
int32_t width;
|
||||||
|
int32_t height;
|
||||||
|
uint32_t border_width;
|
||||||
|
window_id_t sibling;
|
||||||
|
uint32_t stack_mode;
|
||||||
|
} configure_data_t;
|
||||||
|
|
||||||
|
/* Internal semantic window types mapped from backend-specific protocols. */
|
||||||
|
typedef enum window_type_t {
|
||||||
|
ZDWM_WINDOW_TYPE_NORMAL = 0,
|
||||||
|
ZDWM_WINDOW_TYPE_DESKTOP,
|
||||||
|
ZDWM_WINDOW_TYPE_DOCK,
|
||||||
|
ZDWM_WINDOW_TYPE_TOOLBAR,
|
||||||
|
ZDWM_WINDOW_TYPE_DIALOG,
|
||||||
|
ZDWM_WINDOW_TYPE_UTILITY,
|
||||||
|
ZDWM_WINDOW_TYPE_SPLASH,
|
||||||
|
ZDWM_WINDOW_TYPE_MENU,
|
||||||
|
ZDWM_WINDOW_TYPE_DROPDOWN_MENU,
|
||||||
|
ZDWM_WINDOW_TYPE_POPUP_MENU,
|
||||||
|
ZDWM_WINDOW_TYPE_TOOLTIP,
|
||||||
|
ZDWM_WINDOW_TYPE_COMBO,
|
||||||
|
ZDWM_WINDOW_TYPE_DND,
|
||||||
|
ZDWM_WINDOW_TYPE_NOTIFICATION,
|
||||||
|
} window_type_t;
|
||||||
|
|
||||||
|
/* Internal semantic window states mapped from backend-specific protocols. */
|
||||||
|
typedef enum window_state_t {
|
||||||
|
ZDWM_WINDOW_STATE_ABOVE = 0,
|
||||||
|
ZDWM_WINDOW_STATE_FULLSCREEN,
|
||||||
|
ZDWM_WINDOW_STATE_MODAL,
|
||||||
|
ZDWM_WINDOW_STATE_STICKY,
|
||||||
|
} window_state_t;
|
||||||
|
|
||||||
typedef enum window_state_request_type_t {
|
typedef enum window_state_request_type_t {
|
||||||
ZDWM_WINDOW_STATE_REQUEST_FULLSCREEN,
|
ZDWM_WINDOW_STATE_REQUEST_FULLSCREEN,
|
||||||
@@ -65,48 +105,46 @@ typedef enum window_state_request_action_t {
|
|||||||
ZDWM_WINDOW_STATE_ACTION_TOGGLE,
|
ZDWM_WINDOW_STATE_ACTION_TOGGLE,
|
||||||
} window_state_request_action_t;
|
} window_state_request_action_t;
|
||||||
|
|
||||||
typedef enum configure_field_t {
|
/* 层级从低到高 */
|
||||||
ZDWM_CONFIGURE_FIELD_X = 1u << 0,
|
typedef enum window_layer_type_t {
|
||||||
ZDWM_CONFIGURE_FIELD_Y = 1u << 1,
|
ZDWM_WINDOW_LAYER_DESKTOP = 0,
|
||||||
ZDWM_CONFIGURE_FIELD_WIDTH = 1u << 2,
|
ZDWM_WINDOW_LAYER_NORMAL,
|
||||||
ZDWM_CONFIGURE_FIELD_HEIGHT = 1u << 3,
|
ZDWM_WINDOW_LAYER_TOP,
|
||||||
ZDWM_CONFIGURE_FIELD_BORDER_WIDTH = 1u << 4,
|
ZDWM_WINDOW_LAYER_OVERLAY,
|
||||||
ZDWM_CONFIGURE_FIELD_SIBLING = 1u << 5,
|
ZDWM_WINDOW_LAYER_COUNT,
|
||||||
ZDWM_CONFIGURE_FIELD_STACK_MODE = 1u << 6,
|
} window_layer_type_t;
|
||||||
} configure_field_t;
|
|
||||||
|
|
||||||
typedef struct configure_data_t {
|
typedef struct window_layer_props_t {
|
||||||
window_id_t window;
|
window_type_t *types;
|
||||||
uint32_t changed_fields;
|
size_t type_count;
|
||||||
int32_t x;
|
|
||||||
int32_t y;
|
|
||||||
int32_t width;
|
|
||||||
int32_t height;
|
|
||||||
uint32_t border_width;
|
|
||||||
window_id_t sibling;
|
|
||||||
uint32_t stack_mode;
|
|
||||||
} configure_data_t;
|
|
||||||
|
|
||||||
typedef struct border_config_t {
|
window_state_t *states;
|
||||||
uint32_t width;
|
size_t state_count;
|
||||||
color_t normal_color;
|
} window_layer_props_t;
|
||||||
color_t focused_color;
|
|
||||||
} border_config_t;
|
|
||||||
|
|
||||||
typedef struct only_window_data_t {
|
/* clang-format off */
|
||||||
window_id_t window;
|
typedef enum window_metadata_change_flags_t {
|
||||||
} only_window_data_t;
|
ZDWM_WINDOW_METADATA_CHANGE_TITLE = 1u << 0,
|
||||||
|
ZDWM_WINDOW_METADATA_CHANGE_APP_ID = 1u << 1,
|
||||||
|
ZDWM_WINDOW_METADATA_CHANGE_ROLE = 1u << 2,
|
||||||
|
ZDWM_WINDOW_METADATA_CHANGE_CLASS = 1u << 3,
|
||||||
|
ZDWM_WINDOW_METADATA_CHANGE_INSTANCE = 1u << 4,
|
||||||
|
} window_metadata_change_flags_t;
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
typedef struct window_metadata_t {
|
||||||
|
char *title;
|
||||||
|
char *app_id;
|
||||||
|
char *role;
|
||||||
|
char *class_name;
|
||||||
|
char *instance_name;
|
||||||
|
} window_metadata_t;
|
||||||
|
|
||||||
typedef enum hint_field_t {
|
typedef enum hint_field_t {
|
||||||
ZDWM_HINT_FIELD_URGENT,
|
ZDWM_HINT_FIELD_URGENT,
|
||||||
ZDWM_HINT_FIELD_SIZE,
|
ZDWM_HINT_FIELD_SIZE,
|
||||||
} hint_field_t;
|
} hint_field_t;
|
||||||
|
|
||||||
typedef struct zdwm_size_t {
|
|
||||||
int32_t width;
|
|
||||||
int32_t height;
|
|
||||||
} zdwm_size_t;
|
|
||||||
|
|
||||||
typedef struct hints_data_t {
|
typedef struct hints_data_t {
|
||||||
window_id_t window;
|
window_id_t window;
|
||||||
uint32_t changed_fields;
|
uint32_t changed_fields;
|
||||||
@@ -115,19 +153,11 @@ typedef struct hints_data_t {
|
|||||||
zdwm_size_t max_size;
|
zdwm_size_t max_size;
|
||||||
} hints_data_t;
|
} hints_data_t;
|
||||||
|
|
||||||
typedef enum window_interaction_mode_t {
|
typedef struct border_config_t {
|
||||||
ZDWM_WINDOW_INTERACTION_NONE,
|
uint32_t width;
|
||||||
ZDWM_WINDOW_INTERACTION_MOVE,
|
color_t normal_color;
|
||||||
ZDWM_WINDOW_INTERACTION_RESIZE,
|
color_t focused_color;
|
||||||
} window_interaction_mode_t;
|
} border_config_t;
|
||||||
|
|
||||||
typedef struct window_interaction_state_t {
|
|
||||||
window_interaction_mode_t mode;
|
|
||||||
window_id_t window;
|
|
||||||
point_t start_coordinate;
|
|
||||||
rect_t origin_rect;
|
|
||||||
uint64_t last_change_time;
|
|
||||||
} window_interaction_state_t;
|
|
||||||
|
|
||||||
static inline bool window_id_invalid(window_id_t window_id) {
|
static inline bool window_id_invalid(window_id_t window_id) {
|
||||||
return window_id == ZDWM_WINDOW_ID_INVALID;
|
return window_id == ZDWM_WINDOW_ID_INVALID;
|
||||||
@@ -17,21 +17,23 @@
|
|||||||
#include "base/log.h"
|
#include "base/log.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "base/window_list.h"
|
#include "common/event.h"
|
||||||
|
#include "common/listeners.h"
|
||||||
|
#include "common/window.h"
|
||||||
|
#include "common/workspace.h"
|
||||||
#include "config/runtime_config.h"
|
#include "config/runtime_config.h"
|
||||||
#include "core/backend.h"
|
|
||||||
#include "core/binding.h"
|
#include "core/binding.h"
|
||||||
#include "core/command_buffer.h"
|
#include "core/command_buffer.h"
|
||||||
#include "core/event.h"
|
|
||||||
#include "core/layout.h"
|
#include "core/layout.h"
|
||||||
#include "core/listeners.h"
|
#include "core/listeners.h"
|
||||||
#include "core/plan.h"
|
#include "core/plan.h"
|
||||||
#include "core/policy.h"
|
#include "core/policy.h"
|
||||||
#include "core/rules.h"
|
#include "core/rules.h"
|
||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
#include "core/types.h"
|
|
||||||
#include "core/window.h"
|
#include "core/window.h"
|
||||||
#include "core/wm_desc.h"
|
#include "interface/backend.h"
|
||||||
|
#include "interface/event.h"
|
||||||
|
#include "interface/types.h"
|
||||||
|
|
||||||
typedef struct runtime_t {
|
typedef struct runtime_t {
|
||||||
bool running;
|
bool running;
|
||||||
@@ -178,8 +180,10 @@ static void runtime_init_desc_cleanup(runtime_init_desc_t *desc) {
|
|||||||
desc->backend = nullptr;
|
desc->backend = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc->layouts.slots || desc->layouts.slot_count ||
|
if (
|
||||||
desc->layouts.slot_capacity) {
|
desc->layouts.slots || desc->layouts.slot_count ||
|
||||||
|
desc->layouts.slot_capacity
|
||||||
|
) {
|
||||||
layout_registry_cleanup(&desc->layouts);
|
layout_registry_cleanup(&desc->layouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user