diff --git a/cmd/wm/event.c b/cmd/wm/event.c index 0a163030..4f4b9d82 100644 --- a/cmd/wm/event.c +++ b/cmd/wm/event.c @@ -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); } diff --git a/cmd/wm/layout_column.c b/cmd/wm/layout_column.c index 0626d37e..cbae4dcd 100644 --- a/cmd/wm/layout_column.c +++ b/cmd/wm/layout_column.c @@ -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); diff --git a/doc/NOTES b/doc/NOTES index 661ea615..53e37961 100644 --- a/doc/NOTES +++ b/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/ read - -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/-$DISPLAY. That arose some issues with the -$DISPLAY variable, because it is on X startup mostly set to ':0' -(':'), 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.' is appended. Thus reading simply -using $HOME/.wmii/ixp/-$DISPLAY might fail, because of the -appended '.' - 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). diff --git a/libixp2/ixp.h b/libixp2/ixp.h index 7c5eecad..2b62af1e 100644 --- a/libixp2/ixp.h +++ b/libixp2/ixp.h @@ -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 */