Weston 窗口管理(2)

article/2025/10/11 1:48:50

窗口管理(2)

本文基于 weston 分支 10.0.2 进行描述.

五、概述

本文为窗口管理(1)的续章,更多站在开发者角度,以 weston 的代码实现讲解窗口管理(1)中所实现的部分业务场景.

六、数据结构

窗口管理(1)中曾经描述过 weston 具体的分层逻辑,如下:

请添加图片描述

再进一步可以把 WESTON_LAYER_POSITION_NORMAL 展开为 workspace,那么就可以用下图来进行描述:

请添加图片描述

weston 有关于窗口管理部分的逻辑代码实现大多数位于 desktop-shell 文件夹下,有关于此的数据描述为:

// file : desktop-shell/shell.h
struct desktop_shell {// ...struct weston_layer fullscreen_layer;    /* 全屏层     (WESTON_LAYER_POSITION_FULLSCREEN) */struct weston_layer panel_layer;         /* 系统桌面层  (WESTON_LAYER_POSITION_UI) 对于 weston 参考 panel-position (weston.ini) */struct weston_layer background_layer;    /* 背景层     (WESTON_LAYER_POSITION_BACKGROUND) */struct weston_layer lock_layer;          /* 锁屏层     (WESTON_LAYER_POSITION_LOCK) */struct weston_layer input_panel_layer;   /* 输入层     (WESTON_LAYER_POSITION_TOP_UI) 一般输入法位于此层 */struct weston_layer minimized_layer;     /* 最小化层   (逻辑层) */// ...struct {struct wl_array array;unsigned int current;                   /* 索引(array),指向当前工作空间 */unsigned int num;                       /* 工作空间的最大数量 */// ...} workspaces;
};

其中单个 worksapce 的数据结构为:

struct workspace {struct weston_layer layer;                      /* 普通应用层 (WESTON_LAYER_POSITION_NORMAL) */// ...
};

以上删除了部分与此无关的代码,从整理逻辑上来看 weston 的分层设计确实就是一个简单的二维链表(layer 中包含多个 view), 其中 normal layer 的实现比较特殊,可以看做是三维链表;除此之外并没有太多需要说明的地方.

除了上述的数据结构之外,窗口管理(1) 中还曾经说到过最终这些都会转化为一个一维只包含有 views 的链表:

请添加图片描述

支撑起右侧的数据结构为:

// file : libweston/compositor.c
struct weston_compositor {// ...struct wl_list layer_list;  /* struct weston_layer::link */struct wl_list view_list;   /* struct weston_view::link */// ...
};

从这里也可以看出来其实 weston 其实也是"业务"代码,各种上下文状态变量疯狂变更转移,实际上都是在内存里操作数据,真正干事的还是得靠系统接口;只是比较接近于系统级(虽然它也算是系统级程序,但本质来说也是一个应用层程序).

七、业务行为

(1) desktop_shellweston_compositor 数据绑定

要想实现将 layer 的二维数据结构转化为一维数据结构,而二维数据结构存放在 desktop_shell::*_layer 中,一维数据结构则是存放在 weston_compositor::view_list 中;所以需要将 desktop_shellweston_compositor 部分数据结构进行绑定.

首先是先需要提供 desktop_shell 中的 layer 注册至 weston_compositor, 这主要是以下两个接口实现的:

void weston_layer_set_position(struct weston_layer *layer, enum weston_layer_position position)
{struct weston_layer *below;wl_list_remove(&layer->link);/* 根据 position 将其按序添加入 compositor */layer->position = position;wl_list_for_each_reverse(below, &layer->compositor->layer_list, link) {if (below->position >= layer->position) {wl_list_insert(&below->link, &layer->link);return;}}wl_list_insert(&layer->compositor->layer_list, &layer->link);
}void weston_layer_unset_position(struct weston_layer *layer)
{// Hint : layer->link 实际指向到了 weston_compositor::layer_list, 注意 weston_compositor 中的注释// See also : 有兴趣也可以了解一下Linux内核实现 `container_of` (百度),然后在看看 wayland CBB 的具体实现wl_list_remove(&layer->link);wl_list_init(&layer->link);
}

以上代码实际上非常简单,但是 weston 是基于 wayland 开发了,使用了 wayland 提供的 CBB 基础组件库,所以需要理解这个库的成本,在这里展开.

weston_layer_set_position 中出现了描述 layer 优先级的枚举 weston_layer_position, 其定义如下:

// file : include/libweston/libweston.h
/*** Higher value means higher in the stack.** These values are based on well-known concepts in a classic desktop* environment. Third-party modules based on libweston are encouraged to use* them to integrate better with other projects.** A fully integrated environment can use any value, based on these or not,* at their discretion.*/
enum weston_layer_position {/** Special value to make the layer invisible and still rendered.* This is used by compositors wanting e.g. minimized surfaces to still* receive frame callbacks.*/WESTON_LAYER_POSITION_HIDDEN     = 0x00000000,/** There should always be a background layer with a surface covering* the visible area.** If the compositor handles the background itself, it should use* BACKGROUND.** If the compositor supports runtime-loadable modules to set the* background, it should put a solid color surface at (BACKGROUND - 1)* and modules must use BACKGROUND.*/WESTON_LAYER_POSITION_BACKGROUND = 0x00000002,/* For "desktop widgets" and applications like conky. */WESTON_LAYER_POSITION_BOTTOM_UI  = 0x30000000,/* For regular applications, only one layer should have this value* to ensure proper stacking control. */WESTON_LAYER_POSITION_NORMAL     = 0x50000000,/* For desktop UI, like panels. */WESTON_LAYER_POSITION_UI         = 0x80000000,/* For fullscreen applications that should cover UI. */WESTON_LAYER_POSITION_FULLSCREEN = 0xb0000000,/* For special UI like on-screen keyboard that fullscreen applications* will need. */WESTON_LAYER_POSITION_TOP_UI     = 0xe0000000,/* For the lock surface. */WESTON_LAYER_POSITION_LOCK       = 0xffff0000,/* Values reserved for libweston internal usage */WESTON_LAYER_POSITION_CURSOR     = 0xfffffffe,WESTON_LAYER_POSITION_FADE       = 0xffffffff,
};

基于以上的代码片段可知, weston_compositor::layer_listlayer 的排序是有顺序的,并且按照 weston_layer_position 的规则;其次 weston_compositor::layer_list 中的数据只是引用,其实都是来自于 desktop_shell.

然后 desktop_shell 会将 layer 插入 weston_compositor 中去,大致分为初始化以及运行时,截取部分初始化代码如下:

// file : desktop-shell/shell.c
int wet_shell_init(struct weston_compositor *ec, int *argc, char *argv[])
{// ...weston_layer_init(&shell->fullscreen_layer, ec);weston_layer_init(&shell->panel_layer, ec);weston_layer_init(&shell->background_layer, ec);weston_layer_init(&shell->lock_layer, ec);weston_layer_init(&shell->input_panel_layer, ec);weston_layer_set_position(&shell->fullscreen_layer,WESTON_LAYER_POSITION_FULLSCREEN);weston_layer_set_position(&shell->panel_layer,WESTON_LAYER_POSITION_UI);weston_layer_set_position(&shell->background_layer,WESTON_LAYER_POSITION_BACKGROUND);// ...// 工作空间初始化 (normal layer)for (i = 0; i < shell->workspaces.num; i++) {pws = wl_array_add(&shell->workspaces.array, sizeof *pws);if (pws == NULL)return -1;*pws = workspace_create(shell);if (*pws == NULL)return -1;}activate_workspace(shell, 0);// ...

(2) layer 平面化

有了第一点 desktop_shellweston_compositor 数据绑定 的描述,这一步就非常简单了,就操作一下链表就完事了:

void weston_compositor_build_view_list(struct weston_compositor *compositor, struct weston_output *output)
{struct weston_view *view, *tmp;struct weston_layer *layer;// ...// (1) 清空 compositor::view_listwl_list_for_each_safe(view, tmp, &compositor->view_list, link)wl_list_init(&view->link);wl_list_init(&compositor->view_list);// (2) 遍历 compositor::layer_list, 并将其中的 view 插入到 compositor::view_listwl_list_for_each(layer, &compositor->layer_list, link) {wl_list_for_each(view, &layer->view_list.link, layer_link.link) {view_list_add(compositor, view, output);}}// ...
}

经过了 weston_compositor_build_view_list 就实现了 layer 的平面化 (逻辑意义上的).

请添加图片描述

Tips : weston_compositor_build_view_list 何时调用? 每次 UI 刷新都调用,不使用缓存,从而确保图层关系正确刷新.

(3) 切换工作空间

快捷键 WIN + Fx

// file : desktop-shell/shell.c
void update_workspace(struct desktop_shell *shell, unsigned int index, struct workspace *from /* 原来的工作空间 */, struct workspace *to /* 现在的工作空间 */)
{shell->workspaces.current = index;weston_layer_set_position(&to->layer, WESTON_LAYER_POSITION_NORMAL);  // 添加至 weston_compositor::layer_listweston_layer_unset_position(&from->layer);                            // 从 weston_compositor::layer_list 中移除
}

(4) NORMAL layer 工作区域计算

// file :esktop-shell/shell.c
void
get_output_work_area(struct desktop_shell *shell,struct weston_output *output, /* 存储屏幕宽高 */pixman_rectangle32_t *area)
{int32_t panel_width = 0, panel_height = 0;if (!output) {area->x = 0;area->y = 0;area->width = 0;area->height = 0;return;}area->x = output->x;area->y = output->y;// 获取任务栏宽高get_output_panel_size(shell, output, &panel_width, &panel_height);switch (shell->panel_position) /* 任务栏其实有上下左右四个位置,默认为上 */ {case WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP:default:area->y += panel_height;/* fallthrough */case WESTON_DESKTOP_SHELL_PANEL_POSITION_BOTTOM:area->width = output->width;area->height = output->height - panel_height;break;case WESTON_DESKTOP_SHELL_PANEL_POSITION_LEFT:area->x += panel_width;/* fallthrough */case WESTON_DESKTOP_SHELL_PANEL_POSITION_RIGHT:area->width = output->width - panel_width;area->height = output->height;break;}
}

(5) 最大化实现

void
shell_configure_fullscreen(struct shell_surface *shsurf)
{// ...// 将 weston view 从之前绑定的 layer 删除(如果存在的话),一般来说应该是处于某个 workspace 中的 normal layerweston_layer_entry_remove(&shsurf->view->layer_link);// 并将其转移到 fullscreen layerweston_layer_entry_insert(&shsurf->shell->fullscreen_layer.view_list,&shsurf->view->layer_link);// ...
}

(6) 最小化实现

void set_minimized(struct weston_desktop_surface *desktop_surface, struct weston_surface *surface)
{// ...// 从 workspace layer 中移除weston_layer_entry_remove(&view->layer_link);// 将其缓存至 desktop_shell 中的 minimized_layerweston_layer_entry_insert(&shsurf->shell->minimized_layer.view_list, &view->layer_link);// 并将输入设备的焦点从其移除 (不在本章讨论范围之内)drop_focus_state(shsurf->shell, current_ws, view->surface);surface_keyboard_focus_lost(surface);// ...
}

八、结语

实际上本章只是初步讲解了一下有关于窗口管理相关的一些数据结构,并利用这些数据结构描述了一些具体场景;实际上的业务场景还将更加复杂,例如在本章最后一个最小化实现的例子中出现了焦点的概念,以及view还是套娃的结构,具有 sub view,同时 view 还要跟 surface 扯上关系,各种各样的;如果全部描述清楚工作量是相当大的,并且没有什么太大的价值;本文的职责实际就是一个引子而已,减低入门门槛罢了.


http://chatgpt.dhexx.cn/article/NxGVKPTJ.shtml

相关文章

01-weston 简介

参考​​​​​​weston wiki Weston - Gentoo Wiki weston (1): Linux man pages – code.tools Weston-1.12.0 非常详尽&#xff0c;多图慎入&#xff1a;Wayland与Weston简介 - 云社区 - 腾讯云 什么是weston&#xff1f; Wayland是一套display server(Wayland compos…

disunity的使用

1. 下载并安装好jdk: 下载地址&#xff1a;http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 安装教程&#xff1a;http://jingyan.baidu.com/article/6dad5075d1dc40a123e36ea3.html 2.下载disunity: https://…

T-digest

目录 算法算法原理空间消耗及错误界限 示例T-digest的建立T-digest的查询 相关链接 上一篇博客中讲述了使用 R a n d o m Random Random算法进行 q u a n t i l e quantile quantile估算&#xff0c;详情可见Random&#xff0c;本博客将讲诉另外一个 q u a n t i l e quantile …

[反编译U3D]Decompile Unity Resources 修正

反编译unity project的资源文件&#xff0c;包括ios&#xff0c;android&#xff0c;pc等&#xff0c;仅供学习使用&#xff01; 1.disunity Examples 1.1disunityGUI 1.1.2DiunityGUI 使用方法 2.unity3d decompiler 3.UnityAssetsExplorer 反编译unity project的资源文件&…

edit distance 理解

一直没有理解到inert i delete j 的意思。看看图就可以明白了。 对于那道面试题&#xff1a;http://www.careercup.com/question?id6287528252407808 k-palindrome. 最精妙的地方在于只考虑 k 长度以内的改变&#xff0c;这样就可以判断出来了。速度是O(k*n) 1. Definition o…

Tiny-DSOD: Lightweight Object Detection for Resource-Restricted Usages

Y uxi Li1 lyxok1sjtu.edu.cn Jiuwei Li2 jiuwei.liintel.com Weiyao Lin1 wylinsjtu.edu.cn Jianguo Li2 jianguo.liintel.com 1Shanghai Jiao Tong University , China 2Intel Lab China Abstract 近年来&#xff0c;随着深度学习的发展&#xff0c;目标检测技术取得了长足…

android density

为什么要引入dip —The reason for dip to exist is simple enough. Take for instance the T-Mobile G1. It has a pixel resolution of 320x480 pixels. Now image another device, with the same physical screen size, but more pixels, for instance 640x480. This devic…

手游游戏资源提取 (破解、AssetStudio、VGMToolbox、disunity、Il2CppDumper、 .NET Reflector)...

参考&#xff1a; 公主连结 游戏资源提取(解包)简明教程 Unity3D研究院之mac上从.ipa中提取unity3D游戏资源 吾爱破解&#xff1a;记一次unity3d data修改 GitHub&#xff1a;Il2CppDumper 想拿点知名IP的手游素材做点demo&#xff0c;然后搜了下如何能拿到app的素材资源 一 下…

DISN:Deep Implicit Surface Network for High-quality Single-view 3D Reconstruction

时间&#xff1a;2019年 作者&#xff1a;Weiyue Wang ,University of Southern California etc. Abstract&#xff1a; 1.DISN 通过预测基本符号距离场来从二维图像中生成高质量的细节丰富的三维网格&#xff1b; 2.DISN 在二维图像上预测每一个三维点的投影位置&#xff…

Dist

这道题只要找到我们距离的规律就行了&#xff0c;我们可以发现&#xff0c;当行数小于列数时,列数(列数-1)/k,否则&#xff0c;行数(行数-1)/k&#xff0c;没记算一次我们的距离就会增加1&#xff0c;应为行数一减你就往下了一个&#xff0c;所以这个要加1. #include<bits/…

unity3D 如何提取游戏资源 (反编译)+代码反编译【P.M.出品】

转自&#xff1a;https://blog.csdn.net/LANGZI7758521/article/details/52291564 首先感谢 雨松MOMO 的一篇帖子 教我们怎么提取 .ipa 中的游戏资源。教我们初步的破解unity3d资源的基本方法 附上原帖的链接&#xff1a;http://www.xuanyusong.com/archives/2584 下面我会从头…

Unity游戏资源逆向工具

Unity游戏资源逆向工具 https://www.cnblogs.com/kekec/p/12175547.html disunity是一款Java编写&#xff08;需安装jdk1.8&#xff0c;即Java8&#xff09;的解析Unity asset和asset bundle文件&#xff08;流式加载&#xff0c;支持热更新&#xff09;的命令行工具&#xf…

Distillation

蒸馏&#xff0c;把有杂质的东西变成纯度高的 知识从教师网络集成到学生网络&#xff0c;这个过程叫迁移&#xff0c;这么做的原因是终端的算力有限&#xff0c;需要高效率 有关嵌入式开发也有教程&#xff01;&#xff01; 问题的引入&#xff1a;标签有问题&#xff0c;马更…

Unity 提取资源 Disunity、Unity Studio

提取Unity3d资源&#xff0c;用过2个工具 Disunity https://github.com/ata4/disunityUnity Studio https://github.com/RaduMC/UnityStudio 解压XXX.apk.&#xff0c;如果能在XXXX\assets\bin\Data\Managed路径下找到UnityEngine.dll&#xff0c;则表明该游戏由Unity3d打包。…

【逆向工程】 disunity的使用

1. 下载并安装好jdk: 下载地址&#xff1a;http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 安装教程&#xff1a;http://jingyan.baidu.com/article/6dad5075d1dc40a123e36ea3.html 2.下载disunity: https:/…

oracle怎么ping监听,请教TNSPING无监听的问题

请教各位高人&#xff0c;我在自己的虚拟机上装的是solaris10&#xff0c;数据库是oracle10.1.0.3.0&#xff0c;主机名如下&#xff1a; $ hostname fanww $ 在TELNET到虚拟机上之后可以正常启动监听&#xff0c;数据库也能启动&#xff0c;如下&#xff1a; $ lsnrctl start …

oracle数据库怎么ping,Oracle中tnsping命令解析

Oracle Net 工具(命令)tnsping&#xff0c;是一个OSI会话层的工具&#xff0c;它用来&#xff1a; 1)验证名字解析(name resolution&#xff0c;是oracle自己的网络服务名) 2)远程的listener是否启动 1.远程tnsping 2.关闭监听 3.启动监听&#xff0c;重新验证 总结&#xff1a…

Linux下Oracle的tnsping不显示sqlnet.ora文件路径

Tnsping在Linux与Windows下显示不一样 我的环境是&#xff1a;Centos7.6Oracle11.2.0.4 区别是&#xff1a;Linux下没有显示sqlnet.ora的路径名。 Linux下&#xff1a;Used parameter files:是空的 Windows下&#xff1a;Used parameter files显示路径名。 误导 因为我经常…

Oracle中tnsping无响应

1、tnsping 127.0.0.1&#xff08;数据库服务器地址&#xff09;无返回结果&#xff1b; 2、重启数据库服务或者重启数据库服务器问题依然不能解决&#xff1b; 3、最后发现&#xff0c;是 listener.log文件到4G了&#xff0c;删了这个文件 就正常了&#xff1b; 文件路径&…