
Post in continuation of
this topic . Just over a month ago, I showed Systemicus OS and its slow similarity to the graphical interface. All this time (when it was at my disposal) I worked on improvements and now present the results to the public. Perhaps this article will help someone in developing their GUI, because I have not found good material on some aspects of this topic.
Grand total
As promised in the
previous topic, I found a subtle place (more precisely, places) in performance - they were the scheduler (cyclical) and the error of double redrawing of all windows.
Anti-result was the problem of the size of the executable shell file (explorer.exe). I was hoping to fit the entire shell code into one PE section (4096 bytes), but so far this has not happened. The code section at the moment is 4800 bytes (the file itself weighs almost 10 KB :-(). Perhaps in the future it will be possible to reduce the size a little, but since there is a lot more to be added in the shell, then the size of explorer.exe can even reach 16 kilobytes.
')
Principle of operation
Immediately, I note that the miser pays twice. Because of my desire to save extra kilobytes of RAM, I initially rejected the way to create a byte screen mask (where each pixel corresponds to a byte with the window number [up to 256 windows]). And the problem is not only in saving memory, but also in saving CPU resources, because in the absence of this technology there is no need to check its belonging to a certain window before outputting each pixel of the screen. But ... when it came to clipping (i.e., drawing only part of the window that lies under another window), I realized how deeply wrong I was. It would be good if the window being drawn lies only under one window - there the clipping can be calculated - just a rectangular area. And what to do if the window being drawn overlaps in a most indefensible manner at once several other windows and the area being drawn turns out to be of a very bizarre form?
In general, went back and entered the screen mask byte. Memory consumption has increased, but the amount of code has decreased (it has become easier to calculate, although this does not mean that the speed has increased).
So, everything is simple to disgrace. There is a byte screen mask, where each pixel is assigned a zero value or otherwise, if the point belongs to the window. There is a window structure, I have this type:
WNDLIST_ITEM: .handle dd 0 ; +00 .x dd 0 ; +04 .y dd 0 ; +08 .width dd 0 ; +12 .height dd 0 ; +16 .flags dd 0 ; +20 .rsrc dd 0 ; +24 .parent dd 0 ; +28 .wbmp dd 0 ; +32 .caption dd 0 ; +36 ; if DESKTOP: db Leftbuttonstate ; +36 ; db RightButtonState ; +37 ; dw reserved ; +38 .clickx dw 0 ; +40 .clicky dw 0 ; +42 .winstyle dd 0 db 16 dup 0
The parent and winstyle values ​​were unused and therefore reserved (like 16 bytes after). With this data, we can build a window in a hidden wbmp buffer (double buffering technology). In order to save memory in the buffer, everything is drawn in 8-bit color (so far only 16 are used), i.e. 1 byte per point, and when displayed on the screen, this color is converted to 24/32 bit using the color value matching table.
All drawing operations when different window events occur take place in the buffer, and the buffer is displayed on the screen in whole (or partially), i.e. nothing is drawn directly into the screen (text, buttons, etc.).
Now about the elements of the window. For all elements of all windows, there is only one common global table of elements, each element of which contains a link to the window (1 byte, because there are only 256 maximum windows), position relative to the window and element sizes (2 bytes each), status byte and 2 double words - link (to text, for example, for buttons or other info for other elements) and extras (icon for the button or other data depending on the type of element). Status byte: the lower 4 bits indicate the type of element (button, checkbox, text field, etc.), the older ones indicate its state (active, hover).
The main explorer process receives an event from the mouse driver. What happens: the window is searched by pointer coordinates. The window is passed the parameters of the pointer, namely whether the key is pressed, if pressed, this is pressing or releasing the key. When you click first, we activate the window, i.e. make it active and redraw in the foreground. Further, using the global table of elements, we search for all elements belonging to the window, and among them - those falling under the coordinates of the mouse. If found, then in accordance with the parameters of the mouse pointer, we process (draw, redraw, etc.).
If the pointer is outside of windows, then this event is also processed. In this case, if a key is pressed on the desktop, and the Start menu is open, then you need to close it. In the future, these events will be needed to create shortcuts and other desktop functions.
Having this functionality, it is not difficult to implement simple shell functions - event handling, dragging windows, clipping window overlays between each other.
Plan for the near future
In the current implementation, many problems remain, in particular, sometimes there are errors when drawing the mouse cursor after clicking on the desktop - a copy of the cursor remains on the table)) There are some other problems, however small.
From the important thing - a full-fledged textarea element with scrolling text, the interrelation of radio buttons of one name (i.e. the inclusion of only one button at a time for the group radiobuttons). This is out of complexity. An interesting but not very difficult task is to bind applications to their windows, since now these are all test windows displayed by the shell itself.
There is an idea of ​​implementing a terminal by creating a window and copying content from address 0xB8000 into it (naturally, turning each character into an area of ​​8 * 16 pixels).
And then - porting a couple of applications, first of all fasmw, some small toy and, probably, a calculator. Then I will unsubscribe to the respected habrasoobschestvu.
And finally, a small video. No, I will not post the video, because CamStudio slows down Qemu. I post the image to run Qemu. Choose Partition 2, any mode, but a 640 * 480 there is a small problem with the background) And do not scold, this is ALPHA ... a lot of bugs. You will scold for the beta version :-) Also, I apologize for the style and errors (if any), it is already deep night ...
Link to file:
http://nebka.ru/files/647-0.02_qemu.7z