System 6 (Systemicus) GUI, some aspects

image

Work continues on OS System 6 (formerly Systemicus). I figured it out a bit with the GUI - in addition to some shortcomings, it is already close to the working version. What is this short article about.

Looking ahead, I post ( github.com/omegicus/System6 ) the image of the HDD for testing on QEMU (it is too early to experiment with the minimum memory value - specify from 64 MB, although it should work at lower values). If anyone wants to open an image - here is a link to GitHub with a brief description of the file system and the Windows-tool for mounting it. github.com/omegicus/OMFS3

So, I’ll just share my experience (far from final) of creating a GUI for the operating environment. In essence, two files are responsible for everything - explorer.exe (9 kilobytes) and user32.dll (31 Kb).

Actually, we should already be able to display graphic primitives and I will not describe this topic, in my opinion it is the “ins and outs” that are more interesting.

The main structure of the window manager is the window structure. Each record is represented by the following structure (in my implementation): Of interest is a .rsrc containing a .gui section of a PE executable file (some analogy of a rsrc Windows PE file). When PE is loaded into the memory under the .gui section, a standard 64Kb memory block is allocated and the indicated section is copied there. .parent points to the parent window (usually = 0, i.e. parent is the desktop)

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
;
.clickx dw 0 ; +40
.clicky dw 0 ; +42
.winstyle dd 0 ; +44
.icon dd 0 ; +48
;
.message dd 0 ; +52
.processid dd 0 ; +56
.res dd 0 ; +60
WNDLIST_ITEM_SZ = 64





.wbmp points to memory containing an 8-bit window image. 256 colors may seem small, but for my implementation this is enough. Those. a window is drawn in this buffer and only then displayed on the screen. Those. this is a shadow buffer.

.clickx, .clicky - contain the coordinates of the window where the cursor is now (even if the key is not pressed).
To track events (including pressing a keyboard or mouse) there is a .message field - this is where the pointer to the record in the message structure is placed. The very structure of messages and their implementation may be different for everyone, so I am not writing about it here.

An example of sending a message to an active application:
invoke SendMessage, [activeHndlr], WM_LBUTTONDOWN, param1, param2


A separate story with a kind of Ddraw. I did not limit myself to the usual display of the picture. The program should initiate the creation of a DDraw area and write there directly. While this is implemented through an intermediate buffer, but the tru-approach is, of course, in remapping virtual memory so that the buffer points directly to video memory. This is ahead. In the meantime, the structure of the Ddraw windows is used, in which the coordinates and sizes of the output window are recorded, the address of the video memory (more precisely, the offset in it from which the output starts) and the address of the buffer where the applications write. The address of the video memory offset is an optional thing, i.e. it can be calculated by the system, but this is done to speed up, so that at each output of the frame on the screen does not calculate this offset.

image

Now about the composition. In principle, the biggest problem that I encountered when creating a graphical environment is clipping pixels when the windows overlap with each other. There is only one window in this demo, but a working implementation can be seen in one of my previous posts. Otherwise, the principle of operation is as follows:

1) rendering of the background
2) rendering of windows in shadow buffers (including window elements)
3) displaying these buffers on the screen.

Next, we monitor the changes, namely the keyboard and mouse clicks, transfer these messages to the appropriate windows. There are some changes in the shadow buffers (either the application itself drew something, or we changed the state of the buttons (this is what the system does)) and after that the desktop is updated, i.e. there is a redrawing of everything. This happens quickly enough because hidden buffers are simply copied to the screen.

Everything is quite simple and obvious, but this is at first glance. There is very little documentation sanctioned on this topic and for those who write something from scratch (like me), many things are opened by trial and error.


Also popular now: