mirror of
https://github.com/0intro/wmii
synced 2024-11-22 13:52:17 +03:00
updated development notes, made some indent stuff cooler
This commit is contained in:
parent
49c95a808a
commit
1a966dc33e
@ -115,7 +115,6 @@ static void handle_configurerequest(XEvent * e)
|
|||||||
f = c->frame;
|
f = c->frame;
|
||||||
|
|
||||||
if (f) {
|
if (f) {
|
||||||
/*
|
|
||||||
Page *p = f->area->page;
|
Page *p = f->area->page;
|
||||||
if (cext_list_get_item_index(&p->areas, f->area)) {
|
if (cext_list_get_item_index(&p->areas, f->area)) {
|
||||||
Area *a = cext_list_get_item(&p->areas, 0);
|
Area *a = cext_list_get_item(&p->areas, 0);
|
||||||
@ -123,7 +122,6 @@ static void handle_configurerequest(XEvent * e)
|
|||||||
a->layout->attach(a, c);
|
a->layout->attach(a, c);
|
||||||
f = c->frame;
|
f = c->frame;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
bw = border_width(f);
|
bw = border_width(f);
|
||||||
tabh = tab_height(f);
|
tabh = tab_height(f);
|
||||||
}
|
}
|
||||||
|
@ -300,7 +300,7 @@ static void drop_moving(Frame *f, XRectangle *new, XPoint *pt)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Frame *other = cext_find_item(&tgt->frames, pt, comp_pointer_frame);
|
Frame *other = cext_find_item(&tgt->frames, pt, comp_pointer_frame);
|
||||||
if (other != f) {
|
if (other && other != f) {
|
||||||
cext_swap_items(&tgt->frames, f, other);
|
cext_swap_items(&tgt->frames, f, other);
|
||||||
iter_arrange_column(tgt, f->area);
|
iter_arrange_column(tgt, f->area);
|
||||||
select_col(f, True);
|
select_col(f, True);
|
||||||
|
233
doc/NOTES
233
doc/NOTES
@ -1,99 +1,42 @@
|
|||||||
Development notes of wmii
|
DEVELOPMENT NOTES
|
||||||
===============================================
|
|
||||||
Last change: 2005-06-29, garbeam
|
|
||||||
|
|
||||||
|
Architecture;
|
||||||
Audience
|
|
||||||
--------
|
|
||||||
This document is intended to describe the architectural decisions and
|
|
||||||
concepts of the wmii development. It is primary written for developers.
|
|
||||||
|
|
||||||
|
|
||||||
Motivation
|
|
||||||
----------
|
|
||||||
There're several reasons for rewriting wmi:
|
|
||||||
|
|
||||||
1. Monolithic object-oriented design
|
|
||||||
wmi consisted of a single binary which included all components we know,
|
|
||||||
the window manager itself, three different bars, a shortcut box and the
|
|
||||||
slot. Monolithic designs provide some advantages (no shared memory
|
|
||||||
needed between the different components, special optimizations possible),
|
|
||||||
but they lead to high coupling (code overhead) and reduce maintainability.
|
|
||||||
|
|
||||||
2. The XTextProperty based remote interface.
|
|
||||||
Originally the idea of wmiremote was derived from larswm and is based on
|
|
||||||
XTextProperties, which suffer from reliability and correct order under
|
|
||||||
high system load (maybe due to bugs in X itself). But for the context of
|
|
||||||
wmi they just work and do their job fine. However, a guy called Uriel
|
|
||||||
came up one day in #wmi IRC channel and asked to generalize the
|
|
||||||
interface and change its property-based character to a file input/output
|
|
||||||
interface similar to the 9p protocol of plan9.
|
|
||||||
In long discussions we agreed and tried a prototypical implementation in
|
|
||||||
wmi, which can be found between revisions 640-735 of the wmi Subversion
|
|
||||||
repository.
|
|
||||||
|
|
||||||
3. The wmi configuration interface lacked on-the-fly changes
|
|
||||||
If a user wanted to change a setting, he had to restart wmi. As
|
|
||||||
workaround, which produced much complexity, some convenience actions like
|
|
||||||
create-workspace or bind-shortcut have been implemented, that the user
|
|
||||||
was able to change a subset of often needed things on-the-fly. Anyway, this
|
|
||||||
sucked a lot and made wmi less attractive. Within the above revisions we
|
|
||||||
also implemented prototypical support for on-the-fly changes in wmi.
|
|
||||||
|
|
||||||
4. Software law
|
|
||||||
However the prototypical implementation was very time-consuming without
|
|
||||||
stable and usable results (in wmi Subversion repository they can be
|
|
||||||
found in trunk/current/wmi). Thus we realized, that wmi itself was
|
|
||||||
a prototype only around end of September 2004. Originally the
|
|
||||||
prototypical changes between revisions 640-735 were intended to be used
|
|
||||||
in wmi-10, but they changed things to deep. Thus wmii was born.
|
|
||||||
|
|
||||||
|
|
||||||
Architecture
|
|
||||||
------------
|
|
||||||
To solve the above issues found in wmi are the requirements for wmii:
|
|
||||||
|
|
||||||
1. Modularized design
|
1. Modularized design
|
||||||
wmii separates all different components into different binaries. We
|
|
||||||
evaluated the dlopen() mechanism to load modules dynamically (like ion
|
|
||||||
does), but skipped that for stability reasons (one single invalid memory
|
|
||||||
access would crash the whole application in dlopen() world).
|
|
||||||
To share code between components we separated also two libraries,
|
|
||||||
which are initially written for wmii, and most wmii components link
|
|
||||||
statically against them.
|
|
||||||
The components and libraries of wmii look as follows:
|
|
||||||
|
|
||||||
* libixp (remote interface library)
|
wmii separates all concerns into different binaries.
|
||||||
|
To share code between the binaries we also got a bunch of libraries,
|
||||||
|
which are initially written for wmii, and all wmii binaries are
|
||||||
|
statically linked with those libraries.
|
||||||
|
|
||||||
|
* libcext (collection of useful C-API extending functions)
|
||||||
|
* libixp (remote interface library, obsolete)
|
||||||
|
* libixp2 (remote interface library, 9P2000 compliant - the future)
|
||||||
* liblitz (non-wimp GUI-toolkit library)
|
* liblitz (non-wimp GUI-toolkit library)
|
||||||
* wmii (core WM)
|
* libwmii (convenience functions for wmii-tools)
|
||||||
* wmibar (a generic bar)
|
* cmd/wm/wmiiwm (core window manager)
|
||||||
* wmiinput (input bar)
|
* cmd/wmiibar (a generic bar)
|
||||||
* wmir (remote interface client)
|
* cmd/wmiimenu (a generic keyboard-driven one-line menu)
|
||||||
* wmikeys (shortcut handler)
|
* cmd/wmiikeys (shortcut handler)
|
||||||
|
* cmd/wmiifs (libixp fileserver multiplexer, obsolete)
|
||||||
|
* cmd/wmiir (remote interface client for obsolete libixp)
|
||||||
|
* cmd/wmiir2 (remote interface client for libixp2)
|
||||||
|
|
||||||
The modularization has been chosen by two different point of views:
|
liblitz contains all drawing code beside some geometru code, which is used by
|
||||||
a) The separation of independent tasks, which means that a pager or
|
all tools.
|
||||||
input bar should be independent from a window manager itself.
|
|
||||||
b) The separation of technically independent stuff, e.g. managing windows
|
|
||||||
is completely independent from shortcut handling - in X world at least.
|
|
||||||
|
|
||||||
The libixp is described below.
|
|
||||||
|
|
||||||
The liblitz contains primary all drawing code, which is used by
|
|
||||||
all separated components, and provides some util functions.
|
|
||||||
If you implement a function within a wmii component, first ask yourself,
|
|
||||||
if that function would make sense also in other components, if so,
|
|
||||||
export it to liblitz, the non-wimp GUI toolkit.
|
|
||||||
|
|
||||||
2. Remote interface
|
2. Remote interface
|
||||||
The remote interface is implemented with the new libixp library, which
|
|
||||||
|
The remote interface is implemented in the libixp library, which
|
||||||
is independent from all other parts of wmii and provides a client/server
|
is independent from all other parts of wmii and provides a client/server
|
||||||
API for a userland memory filesystem with a similar approach as 9p
|
API for a userland memory filesystem with a similar approach as 9p
|
||||||
server- and clients of the plan9 operating system.
|
server- and clients of the plan9 operating system. Note that the old libixp is
|
||||||
An IXP server provides and manages a memory file system which is accessed
|
obsolete and will be replaced by libixp2.
|
||||||
concurrently by several clients over a UNIX socket file. All above wmii
|
An IXP server provides and manages a memory file system (only the old libixp
|
||||||
components, except wmir, are IXP servers. Since the IXP server
|
does) which is accessed concurrently by several clients over a UNIX
|
||||||
dispatches its connections with a select() based loop, it also
|
socket file. wmiiwm, wmiibar, wmiimenu, wmiikeys and wmiifs are IXP servers,
|
||||||
|
wmiir is an IXP client.
|
||||||
|
An IXP server dispatches its connections with a select() based loop, it also
|
||||||
represents the X event loop for above components, because the
|
represents the X event loop for above components, because the
|
||||||
ConnectionNumber(X11) is the file descriptor of a connection to the X
|
ConnectionNumber(X11) is the file descriptor of a connection to the X
|
||||||
server. If requested, the IXP server also selects() for file descriptors
|
server. If requested, the IXP server also selects() for file descriptors
|
||||||
@ -112,82 +55,24 @@ content of files through following functions:
|
|||||||
* write (writes opened file)
|
* write (writes opened file)
|
||||||
* close (closes opened file)
|
* close (closes opened file)
|
||||||
|
|
||||||
Processes which implement such a file server can access the memory file
|
Note above functions are obsolete, in future libixp2 provides full 9P2000
|
||||||
system explicitly, which is done by all above components for
|
support due to following interface:
|
||||||
performance reasons. Because the server handles all accesses
|
|
||||||
sequentially there is no race condition.
|
|
||||||
|
|
||||||
An IXP client, like wmir, accesses an IXP server remotely to perform
|
int ixp_client_init(IXPClient * c, char *sockfile);
|
||||||
above functions. The wmir of wmii is not allowed to create or to remove
|
void ixp_client_deinit(IXPClient * c);
|
||||||
files/paths, because all components of wmii handle file creation and
|
int ixp_client_remove(IXPClient * c, u32 newfid, char *filepath);
|
||||||
destruction internally, because they are IXP servers and can do so.
|
int ixp_client_create(IXPClient * c, u32 dirfid, char *name, u32 perm, u8 mode);
|
||||||
But that is only a special case. In general each client is capable to
|
int ixp_client_walk(IXPClient * c, u32 newfid, char *filepath);
|
||||||
request the server to create or remove files.
|
int ixp_client_open(IXPClient * c, u32 newfid, char *filepath, u8 mode);
|
||||||
Not allowing all IXP functions to wmir is easy to understand, because
|
u32 ixp_client_read(IXPClient * c, u32 fid, u64 offset, void *result, u32 res_len);
|
||||||
the problematic of accidentally removals of important files,
|
u32 ixp_client_write(IXPClient * c, u32 fid, u64 offset, u32 count, u8 * data);
|
||||||
which guarantees the functionality of wmii components, is prevented.
|
int ixp_client_close(IXPClient * c, u32 fid);
|
||||||
If for example an IXP client would request to remove / in wmii, wmii
|
|
||||||
would crash immediately, because it won't be able to read its needed
|
|
||||||
files.
|
|
||||||
|
|
||||||
As you might notice, libixp provides accessing shared memory through a
|
|
||||||
decent file input/output based interface between an IXP server and IXP
|
|
||||||
clients, which is used for configuration and scripting. To get further
|
|
||||||
details about IXP, start with libixp/libixp.h.
|
|
||||||
|
|
||||||
3. Configuration
|
|
||||||
The above described remote interface is used for configuration. The idea
|
|
||||||
is very similar to the procfs of Linux and other Unices which is
|
|
||||||
accessed to configure the kernel. The above IXP servers provide following
|
|
||||||
special file systems which are used for configuration and can be
|
|
||||||
explored with:
|
|
||||||
|
|
||||||
wmir -s $HOME/.wmii/ixp/<socket file> read <path>
|
|
||||||
|
|
||||||
e.g.
|
|
||||||
|
|
||||||
wmir -s $HOME/.wmii/ixp/wmii-:0 read /
|
|
||||||
|
|
||||||
Reading a path which is no file, returns the contents of a directory. In
|
|
||||||
IXP there's no differentiation between files and directories. Whether a
|
|
||||||
file contains content (byte data) or it contains files (you can compare
|
|
||||||
the term 'file' in IXP to inodes in UNIX world).
|
|
||||||
|
|
||||||
Note: By default all wmi components use a socket file in
|
|
||||||
$HOME/.wmii/ixp/<component>-$DISPLAY. That arose some issues with the
|
|
||||||
$DISPLAY variable, because it is on X startup mostly set to ':0'
|
|
||||||
(':<display number>'), but if wmii runs and you invoke terms it is set
|
|
||||||
to the screen which is focused (important for multihead configurations),
|
|
||||||
that means that a ':0.<screen number>' is appended. Thus reading simply
|
|
||||||
using $HOME/.wmii/ixp/<component>-$DISPLAY might fail, because of the
|
|
||||||
appended '.<screen number>' - keep that in mind!
|
|
||||||
|
|
||||||
Each server developer decides by itself how its file system should look
|
|
||||||
like to configure it. A very basic configuration interface filesystem
|
|
||||||
can be found in wmipager, the most complex one can be found in wmii.
|
|
||||||
|
|
||||||
4. Software law
|
|
||||||
Yes, wmi was implemented with C++, but wmii is implemented with C. Most
|
|
||||||
people are surprised about that fact. But there're several reasons for
|
|
||||||
this. Most are rarely rational, but there're arguable ones:
|
|
||||||
|
|
||||||
* C code compiles faster
|
|
||||||
* all dependencies (Xlib, libc, ...) are implemented with C and
|
|
||||||
don't provide an object oriented API
|
|
||||||
* C code produces smaller binaries
|
|
||||||
|
|
||||||
One design goal of wmii is to win the challenge of simplicity, which
|
|
||||||
means that our upper boundary of code size is 10.000 SLOC (including
|
|
||||||
above components, libwmii and libixp).
|
|
||||||
|
|
||||||
|
|
||||||
Style guide
|
Technical Details;
|
||||||
-----------
|
|
||||||
We use the traditional Unix-style from Bell Labs in the source code.
|
1. Hint management
|
||||||
We only comment things which are hard to understand or not obvious.
|
|
||||||
|
|
||||||
Technical Details
|
|
||||||
-----------------
|
|
||||||
The window management of wmii conforms to the ICCCM specification,
|
The window management of wmii conforms to the ICCCM specification,
|
||||||
although client supplied icons and iconified window states are not
|
although client supplied icons and iconified window states are not
|
||||||
handled for simplicity reasons and because they don't fit well with the
|
handled for simplicity reasons and because they don't fit well with the
|
||||||
@ -196,3 +81,35 @@ Apart from this, wmii conforms partly to the EWMH specification to fit
|
|||||||
well with the requirements of more recent applications in the area of
|
well with the requirements of more recent applications in the area of
|
||||||
the KDE and Gnome desktop, although to fulfill these hints are no primary
|
the KDE and Gnome desktop, although to fulfill these hints are no primary
|
||||||
target of wmii's window management capabilities.
|
target of wmii's window management capabilities.
|
||||||
|
|
||||||
|
2. Layout interface
|
||||||
|
|
||||||
|
wmii provides an C-API interface to extend the core window manager with new layouts.
|
||||||
|
See wmii/cmd/wm/layout_*.c for samples how to implement a layout.
|
||||||
|
|
||||||
|
The interface looks like:
|
||||||
|
|
||||||
|
struct Layout {
|
||||||
|
char *name;
|
||||||
|
void (*init) (Area *); /* called when layout is initialized */
|
||||||
|
void (*deinit) (Area *); /* called when layout is uninitialized */
|
||||||
|
void (*arrange) (Area *); /* called when area is resized */
|
||||||
|
Bool (*attach) (Area *, Client *); /* called on attach */
|
||||||
|
void (*detach) (Area *, Client *, Bool unmap); /* called on detach */
|
||||||
|
void (*resize) (Frame *, XRectangle *, XPoint *); /* called after resize */
|
||||||
|
void (*select) (Frame *, Bool raise); /* selection */
|
||||||
|
Container *(*get_frames) (Area *); /* called for drawing */
|
||||||
|
Action *(*get_actions) (Area *); /* local action table */
|
||||||
|
};
|
||||||
|
|
||||||
|
See wmii/cmd/wm/wm.h for further details about the structs.
|
||||||
|
See wmii/libcext/cext.h for details about the Container data
|
||||||
|
structure which provides a single linked list and a stack in one
|
||||||
|
implementation (list for navigation, stack for focus history) -
|
||||||
|
which is useful for frames, clients, areas and even pages.
|
||||||
|
|
||||||
|
To store arbitrary stuff in an area, there is an Area->aux
|
||||||
|
pointer, same can be done with frames, which contain a Frame->aux pointer.
|
||||||
|
Note that each layout implementation needs to create and destroy
|
||||||
|
frames by itself (this is required because otherwise a wmi-10
|
||||||
|
alike layout which assumes tabbing, won't be possible).
|
||||||
|
@ -181,19 +181,13 @@ typedef struct {
|
|||||||
int ixp_client_init(IXPClient * c, char *sockfile);
|
int ixp_client_init(IXPClient * c, char *sockfile);
|
||||||
void ixp_client_deinit(IXPClient * c);
|
void ixp_client_deinit(IXPClient * c);
|
||||||
int ixp_client_remove(IXPClient * c, u32 newfid, char *filepath);
|
int ixp_client_remove(IXPClient * c, u32 newfid, char *filepath);
|
||||||
int
|
int ixp_client_create(IXPClient * c, u32 dirfid, char *name, u32 perm, u8 mode);
|
||||||
ixp_client_create(IXPClient * c, u32 dirfid, char *name, u32 perm,
|
|
||||||
u8 mode);
|
|
||||||
int ixp_client_walk(IXPClient * c, u32 newfid, char *filepath);
|
int ixp_client_walk(IXPClient * c, u32 newfid, char *filepath);
|
||||||
int ixp_client_open(IXPClient * c, u32 newfid, char *filepath, u8 mode);
|
int ixp_client_open(IXPClient * c, u32 newfid, char *filepath, u8 mode);
|
||||||
u32
|
u32 ixp_client_read(IXPClient * c, u32 fid, u64 offset, void *result, u32 res_len);
|
||||||
ixp_client_read(IXPClient * c, u32 fid, u64 offset, void *result,
|
u32 ixp_client_write(IXPClient * c, u32 fid, u64 offset, u32 count, u8 * data);
|
||||||
u32 res_len);
|
|
||||||
u32
|
|
||||||
ixp_client_write(IXPClient * c, u32 fid, u64 offset, u32 count, u8 * data);
|
|
||||||
int ixp_client_close(IXPClient * c, u32 fid);
|
int ixp_client_close(IXPClient * c, u32 fid);
|
||||||
|
|
||||||
|
|
||||||
/* convert.c */
|
/* convert.c */
|
||||||
void *ixp_enc_u8(u8 * msg, u8 val);
|
void *ixp_enc_u8(u8 * msg, u8 val);
|
||||||
void *ixp_dec_u8(u8 * msg, u8 * val);
|
void *ixp_dec_u8(u8 * msg, u8 * val);
|
||||||
@ -220,13 +214,11 @@ u32 ixp_fcall_to_msg(Fcall * fcall, void *msg, u32 msglen);
|
|||||||
u32 ixp_msg_to_fcall(void *msg, u32 msglen, Fcall * fcall);
|
u32 ixp_msg_to_fcall(void *msg, u32 msglen, Fcall * fcall);
|
||||||
|
|
||||||
/* server.c */
|
/* server.c */
|
||||||
IXPConn *ixp_server_add_conn(IXPServer * s, int fd, int dont_close,
|
IXPConn *ixp_server_add_conn(IXPServer * s, int fd, int dont_close, void (*read) (IXPServer *, IXPConn *));
|
||||||
void (*read) (IXPServer *, IXPConn *));
|
|
||||||
int ixp_server_tversion(IXPServer *, IXPConn * c);
|
int ixp_server_tversion(IXPServer *, IXPConn * c);
|
||||||
void ixp_server_rm_conn(IXPServer * s, IXPConn * c);
|
void ixp_server_rm_conn(IXPServer * s, IXPConn * c);
|
||||||
void ixp_server_loop(IXPServer * s);
|
void ixp_server_loop(IXPServer * s);
|
||||||
int ixp_server_init(IXPServer * s, char *sockfile, IXPTFunc * funcs,
|
int ixp_server_init(IXPServer * s, char *sockfile, IXPTFunc * funcs, void (*freeconn) (IXPServer *, IXPConn *));
|
||||||
void (*freeconn) (IXPServer *, IXPConn *));
|
|
||||||
void ixp_server_deinit(IXPServer * s);
|
void ixp_server_deinit(IXPServer * s);
|
||||||
|
|
||||||
/* socket.c */
|
/* socket.c */
|
||||||
|
Loading…
Reference in New Issue
Block a user