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;
|
||||
|
||||
if (f) {
|
||||
/*
|
||||
Page *p = f->area->page;
|
||||
if (cext_list_get_item_index(&p->areas, f->area)) {
|
||||
Area *a = cext_list_get_item(&p->areas, 0);
|
||||
@ -123,7 +122,6 @@ static void handle_configurerequest(XEvent * e)
|
||||
a->layout->attach(a, c);
|
||||
f = c->frame;
|
||||
}
|
||||
*/
|
||||
bw = border_width(f);
|
||||
tabh = tab_height(f);
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ static void drop_moving(Frame *f, XRectangle *new, XPoint *pt)
|
||||
}
|
||||
else {
|
||||
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);
|
||||
iter_arrange_column(tgt, f->area);
|
||||
select_col(f, True);
|
||||
|
233
doc/NOTES
233
doc/NOTES
@ -1,99 +1,42 @@
|
||||
Development notes of wmii
|
||||
===============================================
|
||||
Last change: 2005-06-29, garbeam
|
||||
DEVELOPMENT NOTES
|
||||
|
||||
|
||||
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:
|
||||
Architecture;
|
||||
|
||||
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)
|
||||
* wmii (core WM)
|
||||
* wmibar (a generic bar)
|
||||
* wmiinput (input bar)
|
||||
* wmir (remote interface client)
|
||||
* wmikeys (shortcut handler)
|
||||
* libwmii (convenience functions for wmii-tools)
|
||||
* cmd/wm/wmiiwm (core window manager)
|
||||
* cmd/wmiibar (a generic bar)
|
||||
* cmd/wmiimenu (a generic keyboard-driven one-line menu)
|
||||
* 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:
|
||||
a) The separation of independent tasks, which means that a pager or
|
||||
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.
|
||||
liblitz contains all drawing code beside some geometru code, which is used by
|
||||
all tools.
|
||||
|
||||
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
|
||||
API for a userland memory filesystem with a similar approach as 9p
|
||||
server- and clients of the plan9 operating system.
|
||||
An IXP server provides and manages a memory file system which is accessed
|
||||
concurrently by several clients over a UNIX socket file. All above wmii
|
||||
components, except wmir, are IXP servers. Since the IXP server
|
||||
dispatches its connections with a select() based loop, it also
|
||||
server- and clients of the plan9 operating system. Note that the old libixp is
|
||||
obsolete and will be replaced by libixp2.
|
||||
An IXP server provides and manages a memory file system (only the old libixp
|
||||
does) which is accessed concurrently by several clients over a UNIX
|
||||
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
|
||||
ConnectionNumber(X11) is the file descriptor of a connection to the X
|
||||
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)
|
||||
* close (closes opened file)
|
||||
|
||||
Processes which implement such a file server can access the memory file
|
||||
system explicitly, which is done by all above components for
|
||||
performance reasons. Because the server handles all accesses
|
||||
sequentially there is no race condition.
|
||||
Note above functions are obsolete, in future libixp2 provides full 9P2000
|
||||
support due to following interface:
|
||||
|
||||
An IXP client, like wmir, accesses an IXP server remotely to perform
|
||||
above functions. The wmir of wmii is not allowed to create or to remove
|
||||
files/paths, because all components of wmii handle file creation and
|
||||
destruction internally, because they are IXP servers and can do so.
|
||||
But that is only a special case. In general each client is capable to
|
||||
request the server to create or remove files.
|
||||
Not allowing all IXP functions to wmir is easy to understand, because
|
||||
the problematic of accidentally removals of important files,
|
||||
which guarantees the functionality of wmii components, is prevented.
|
||||
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).
|
||||
int ixp_client_init(IXPClient * c, char *sockfile);
|
||||
void ixp_client_deinit(IXPClient * c);
|
||||
int ixp_client_remove(IXPClient * c, u32 newfid, char *filepath);
|
||||
int 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_open(IXPClient * c, u32 newfid, char *filepath, u8 mode);
|
||||
u32 ixp_client_read(IXPClient * c, u32 fid, u64 offset, void *result, 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);
|
||||
|
||||
|
||||
Style guide
|
||||
-----------
|
||||
We use the traditional Unix-style from Bell Labs in the source code.
|
||||
We only comment things which are hard to understand or not obvious.
|
||||
Technical Details;
|
||||
|
||||
1. Hint management
|
||||
|
||||
Technical Details
|
||||
-----------------
|
||||
The window management of wmii conforms to the ICCCM specification,
|
||||
although client supplied icons and iconified window states are not
|
||||
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
|
||||
the KDE and Gnome desktop, although to fulfill these hints are no primary
|
||||
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);
|
||||
void ixp_client_deinit(IXPClient * c);
|
||||
int ixp_client_remove(IXPClient * c, u32 newfid, char *filepath);
|
||||
int
|
||||
ixp_client_create(IXPClient * c, u32 dirfid, char *name, u32 perm,
|
||||
u8 mode);
|
||||
int 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_open(IXPClient * c, u32 newfid, char *filepath, u8 mode);
|
||||
u32
|
||||
ixp_client_read(IXPClient * c, u32 fid, u64 offset, void *result,
|
||||
u32 res_len);
|
||||
u32
|
||||
ixp_client_write(IXPClient * c, u32 fid, u64 offset, u32 count, u8 * data);
|
||||
u32 ixp_client_read(IXPClient * c, u32 fid, u64 offset, void *result, 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);
|
||||
|
||||
|
||||
/* convert.c */
|
||||
void *ixp_enc_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);
|
||||
|
||||
/* server.c */
|
||||
IXPConn *ixp_server_add_conn(IXPServer * s, int fd, int dont_close,
|
||||
void (*read) (IXPServer *, IXPConn *));
|
||||
IXPConn *ixp_server_add_conn(IXPServer * s, int fd, int dont_close, void (*read) (IXPServer *, IXPConn *));
|
||||
int ixp_server_tversion(IXPServer *, IXPConn * c);
|
||||
void ixp_server_rm_conn(IXPServer * s, IXPConn * c);
|
||||
void ixp_server_loop(IXPServer * s);
|
||||
int ixp_server_init(IXPServer * s, char *sockfile, IXPTFunc * funcs,
|
||||
void (*freeconn) (IXPServer *, IXPConn *));
|
||||
int ixp_server_init(IXPServer * s, char *sockfile, IXPTFunc * funcs, void (*freeconn) (IXPServer *, IXPConn *));
|
||||
void ixp_server_deinit(IXPServer * s);
|
||||
|
||||
/* socket.c */
|
||||
|
Loading…
Reference in New Issue
Block a user