Phantom OS:窗口子系统-做控件

今天,我们将讨论图形Phantom UI的布置方式。

(您可以通过阅读这些文章来了解什么是Phantom OS。)

更准确地说-此图形用户界面是如何诞生的。 长期以来,幻影只有一个图形上的结论-用鼠标将任何东西传达给系统几乎是不可能的。

现在至少应该使事情变得简单了-但是对于应用程序来说,这意味着-您需要UI。 无论如何-我们会说实话,这个系统看起来很可怕。 这现在还不流行。

UI项目开始时有哪些可用? 原则上-很多。

实际上,有图形-视频驱动程序,处于仅显示模式的窗口子系统,位图字体,窗口事件子系统(事件),窗口焦点控制和相关的原语。

现在的步骤和更多。

视频驱动程序子系统可以依次运行多个驱动程序的probe()函数,从它们那里接收最大分辨率和色彩位的请求,以及在2D加速器模式下工作的能力。 系统要求至少24位颜色。 在此级别上,我们有一个帧缓冲区(内存中的屏幕),鼠标和几种类型的bitblt基元。

Bitblt基元-实现了三种基本类型-图形的完整复制(切出矩形),复制时考虑到二进制透明性(像素完全透明或完全不透明)和z缓冲区。 也就是说,仅在屏幕上复制z坐标大于现有像素的z坐标的那些像素的能力-计算出窗口的部分重叠。

功能的下一层是窗口子系统。 这里有一个窗口的概念,窗口装饰(框架,带有按钮的标题窗口),窗口的x / y / z坐标以及一组负责在屏幕上绘制窗口并控制其沿所有轴移动的功能。

该文件

接下来的事件是-微任务队列,由低级驱动程序处理,以呈现和管理窗口的状态。

应当指出,人类的最聪明的想法是,在没有多线程事件的情况下,无法编写在多线程环境中稳定运行且没有问题的窗口图形系统。 迄今为止,我无视此声明的尝试仅证实了这一点。 放弃消息队列并使所有线程请求该程序的窗口事件非常困难,有时会在屏幕上引发战争。

因此,与大于窗口内图像的任何事物有关的窗口系统的大多数原语都是通过消息队列实现的。 该请求将消息“在屏幕上绘制此区域”或“将窗口重新布置在其他区域上”发送到队列,并且下面的一个单独线程以有序和周到的方式执行它们。

它仅从鼠标(按下,拖动),键盘(按下,释放)和窗口系统本身(次要事件-向上移动窗口后,重新绘制屏幕区域)获取事件流。

在事件流层面上的一个单独任务是所谓的焦点。 聚焦的窗口从键盘接收事件流,实际上,它是在屏幕上清楚地突出显示以解决用户活动的点。 除了选择指导事件的窗口这一显而易见的任务外,该系统还向窗口通知焦点丢失,这有时很重要。

该文件

下一级别是用于在窗口上绘制的图形基元。

有两个主要的实现选项。 旧的,经济的-当窗口不存储所绘制内容的副本时。 如果擦除了这样的窗口,并且您需要再次绘制擦除的窗口(例如,该窗口从边缘返回到屏幕),则该窗口将从其程序中调用该函数,并且该函数应绘制所需的所有内容。 这是典型的模型,由于种种原因,非常不便。 在Phantom中选择了第二个-每个窗口都有一个位图,当前在其中绘制窗口的内容。 图形系统始终可以引用此副本并在屏幕上对其进行更新,而无需拉出用户程序。

请注意,Phantom中属于用户程序(而不是内核)的窗口是永久性的,存储在永久性内存中,并且在重新启动操作系统后,会将绘制的所有内容保存在其中。 顺便说一句,这令人惊讶地有用,并且在某些地方简化了应用程序代码,使其显得不雅。

一组绘图基元允许应用程序代码像往常一样在位图字体中绘制点,线,位图,文本行以及窗口中的其他一些小东西。

在图形子系统的丰富性上,项目“ New Phantom UI”的开始并结束了。 原则上,这个绅士工具包足以应付很多事情,但只针对用户。 无输入。

更准确地说,对“按钮”的概念有基本的支持,但只能使用鼠标,只能在工具栏中,并且只能关闭窗口。 :)

开发任务如下:

  • TrueType 没有这个,这是一个耻辱。
  • 键盘事件和键盘控件。 至少基本。
  • 考虑布局的本地化-至少是西里尔字母,但为更改布局奠定了基础。
  • 控件-按钮,单选按钮,文本字段,标签,菜单等。
  • 控制的重点是在窗口内部选择控制点。
  • 用于管理屏幕上的窗口的某种屏幕组件。 任务栏?
  • 实际上,控件的图像以及总体上某种形式的UI设计-不应像过去那样具有集体农场。

就像这样:

图片

在途中,事实证明还需要alpha混合,即叠加图片时像素的部分透明度。 好吧,很明显,现在是时候触摸Unicode了。

权衡的方法分为三大部分:设计,特朗普,其余。

简而言之,关于设计:Internet上有免费的UI设计,没有邪恶的使用要求。 三天的搜索和选择时间,无休止的时间用于图形元素的艺术切割。

特朗普型


我对此感到害怕,但事实证明,这是徒劳的。 有libfreetype,有应用程序示例,两天后,矢量字体的渲染在测试模式下运行良好。

但是,有一些微妙之处,并且还没有涵盖所有方面。 即。 使用内核中的字体-is。 然后,字体由硬编码驱动到内核二进制文件中。 对于系统字体而言,这是不可避免的,但是用户代码必须具有自己的加载机制。 而且,尽管《幻影》中的某些FS当然是,将来也会,但对于他来说,这种模式并不自然。 您需要能够将字体存储在持久对象中,并通过网络获取它们。

第二个更简单-大量免费字体,它们的组织时间不会很长。

但是第一个...

您可能不知道,但是对于不习惯持久化的程序员,Phantom中的字符串变量具有意外的属性。 他们可以替换文件。 字节流是字节流。 不仅如此,根据定义,它也是内存映射的-它是一个变量。 也就是说,原则上,我们在常规操作系统中存储在文件中的文件,在Phantom中,您可以简单地将其放在字符串变量中。 我经常这样做-Phantom编译器甚至有一个设计-都将文件吸入字符串常量。 因此,在用户区中,“幻影”会穿透位图。 但这也是一种可耻的方法,因为在运行时需要对该变量进行解析以获得对象的可操作表示形式。 但是,关于位图,为了尊重Phantom概念,在这里一切都很好。 我们在编译时将图形文件编译为字符串,当首次启动Phantom时,它将转换为bitmep类型的持久二进制对象,并且在任意数量的OS重新启动之后它已在以后使用,不需要原始源。 它也应该用字体来完成,但这并不常见。 在工作时,矢量字体会渲染到栅格中,因此有必要仅存储这样的渲染栅格。 这不是技巧,也不是问题-它们可以再次折叠到Phantom对象中,例如位图,但是已经需要某种基础结构-字体绘制样式,样式,样式,大小字形(UTF代码)字形位图。

这并不困难,但是显然是下一阶段的任务。 字体在上诉时被光栅化。

该文件

统一码


根据定义渲染字体涉及使用Unicode。 当然,这很好,因为必须在某个时间开始。 实际上,为渲染器配备从UTF-8到UTF-32的转换器就足够了(这是字体中的字形数字),下载带有西里尔字母的字体,这部分本地化工作了。 而且,如果我们要使用其他语言,那么替换字体是必要且充分的。 但是,所选的基本字体包含很多内容-对于欧洲来说,绝对足够。 是的,中国将需要替换字体。

使用键盘


根本没有采取军事行动的迹象,但是我比战斗更抱有希望。 原来,旧的键盘驱动程序仍在...希望从IBM PC XT看硬件。 是的,上个世纪。 事实是,键盘控制器能够(能够!)将现代键盘的扫描代码(所谓的第二组代码)转换成那个古老的代码。

事实证明,由于QEMU的后期,这种转换显然最终被排除了。 还是不小心摔坏了。 但事实是,驾驶员拒绝工作。 在一个母亲的痛苦下,一个小时,我将它从友好的uOS移植到了Phantom中。 只是发现他有同样的问题。 第一套。 我不得不重写扫描代码表和解析器。 我没有回到那位老司机,这就是为什么。 事实证明,来自uOS的驱动程序对系统具有更优雅的界面。 也就是说,他没有像通常那样返回一对(字符代码,按钮扫描代码),而是返回一个32位UTF-32字符。 事实证明,在UTF中,为本地使用分配了特殊的代码范围,对于所有可能的功能键而言,它们已绰绰有余。 在UI代码中使用此类事件流要简单得多。

而且,本地化完全落在这种模型上。 为所需的语言(字符集)覆盖ASCII-> UTF32表就足够了,并且加油-我们有西里尔字母。 好-差不多了。 现在,有必要将其转码为UTF-8,或将用户界面的某些部分的内脏重新制成UTF-32。 我也把这一刻作为低优先级。

控制项



按钮,单选,复选框和其他特定的UI元素。

常见的基础设施包括:

  • 用于存储与窗口有关的控件的机制
  • 典型的控件可视化元素-框架,背景,文本,图标等。
  • 传输到事件控制和典型的响应模式(按/切换)
  • 跟踪鼠标事件和悬停状态
  • 回调和辅助事件的生成以通知状态变化

焦点控制


为了不使用鼠标就可以使用控件(例如按钮),需要做一些事情。

  • 从键盘选择它的能力
  • 显示此选择
  • 键盘回应
  • 焦点丢失检测。

后者是最困难的。

实际上,该控件同时使用键盘和鼠标进行聚焦,并且这是一个相同的实体-如果我们使用鼠标选择文本字段,它也会响应按键。 如果之后按TAB键,则使用键盘的权利将转到另一个键盘。

一项单独的任务是可以对某些控件进行分组,并且需要以相关方式更新其状态。 按下无线电蝙蝠号可以“挤压”它的邻居。

再一次回到我们正在编写一个持久性OS的事实。 这意味着潜在的控制权可以存储在持久性RAM中,并且在系统内核重新启动后仍然存在。

即,其与核的连接将有利于最小化。 重新引导后,指向非永久性内存(实际上是指向内核)的每个指针都是无效的,必须将其还原。 这意味着此类指针无权存储有关控件状态的信息。 光标位置为整数-是。 指向内核中缓冲区(其位置由光标位置确定)的指针不是。 好吧,是的,仍然只有一个整数,它更重要。 实际上这不是很麻烦,但我们必须记住。

最后,任务栏。 这是在屏幕底部(侧面,顶部)的东西,如果用户丢失了窗口,则在其中戳戳。

原则上,这应该已经是用户领域的一部分,但是...内核已经在积极使用GUI,因此现在这部分也位于底部。 我暂时希望。

合计


图片

我认为,朝着这个方向确定的任务已基本解决。 当然,完美无止境,但在我看来,该界面已从黑客迈向了通用,迈出了切实的一步。

Source: https://habr.com/ru/post/zh-CN472160/


All Articles