source: doc/owl-window.txt @ 4eee948

Last change on this file since 4eee948 was 4eee948, checked in by David Benjamin <>, 11 years ago
Eugh. Create the sepwin before the recwin The sepwin depends on a value computed by the recwin's draw handler. This is kinda nasty...
  • Property mode set to 100644
File size: 7.9 KB
1                                ==========
2                                owl_window
3                                ==========
5owl_window is intended to be a wrapper over ncurses WINDOW and PANEL
6objects to abstract away much of the nastiness that is ncurses. It
7provides redraw scheduling, and sane window moving and resizing.
10Hierarchy and types
13owl_window creates a hierarchy of window objects. The hierarchy
14currently uses ncurses' built-in window hierarchy system with
15subwins. This was easier to implement but has some caveats, detailed
18At the top level, we have the screen window which represents the
19actual screen. The screen window is not usually interacted with
20directly, but rather it is a handle to interface with the terminal as
21if it were a normal window.
23Underneath the screen, we have top-level windows, or panels. Panels
24are normal WINDOWs (newwin) connected to a PANEL (from
25libpanel). Panels may overlap freely and maintain a stacking
26order. (For now, this stacking order is not exposed except for a
27mechanism to move a panel to the top. This is not difficult to
28otherwise correct otherwise.)
30Under each panel is a tree of subwins. These are backed by ncurses
31subwins. Because ncurses subwins simply share their parent windows'
32buffer, we cannot provide as many nice guarantees about
33ordering. Sibling subwins may not overlap, and parents must
34(sometimes) take children position into account. More on this
35later. This model is sufficient for BarnOwl's current purposes. Should
36we need to, this may later be reworked. (Specifically, we'd want to
37back everything by pads and build a compositing window manager.)
39Each of these three types is temporarily stuffed into one type. We can
40later do subtyping of sorts, but that will require more heavy use of
43As an example, here is the graph used by BarnOwl's current interface:
45                        +==========+
46                        || screen ||
47                        +==========+
48                          /      \
49                +-----------+   +--------+
50                | mainpanel |   | popwin |
51                +-----------+   +--------+
52               /   /    |    \          \
53         recwin sepwin msgwin typwin   viewwin
56A window may be unlinked from its parent with a call to
57owl_window_unlink. From then on, the object is still accessible, but
58it will not do anything. If desired, we may add the ability to relink
59a window in future. This behavior allows us to safely hold references
60to windows, even after they have been "destroyed".
66Each window maintains state for whether or not the user has requested
67it be visible. A user calls owl_window_show to flip the 'shown' bit on
68a window and owl_window_show_all to do so recursively. Likewise,
69owl_window_hide disables this bit. If a window and all its parents are
70shown, then the user has requested this window be visible.
72We say a window is realized if it has a corresponding on-screen
73window. A window will only be realized if it is requested to be
74shown. Furthermore, the window's parent must also be realized (unless
75it is the screen). If a window is failed to be created for any reason
76(most notably if its dimensions are zero), owl_window will cope and
77consider it unrealized.
79This realized/unrealized state fixes two nuisances with the old code:
81     First, owl_window can safely manage all NULL windows. Interacting
82     code needn't check to avoid segfaults; the owl_window is never
83     NULL, and code requesting the WINDOW will never be called when
84     NULL.
86     Second, we have a consistent handle to a logical window, despite
87     changes in the physical window. This is important for resizing
88     windows. It is difficult to safely resize windows in ncurses. It
89     is usually far easier to destroy everything and recreate it.
91Note that this means owl_window will intentionally never expose the
92underlying WINDOW except during appropriate events.
98Windows may be moved and resized with owl_window_move,
99owl_window_resize, and owl_window_set_position. Internally, resizing
100is very simple. We unrealize the window, set new position, and then
101realize it at the new location. When a window changes size, it emits a
102"resized" signal which windows may react to. It may actually possible
103to optimize moves, but this has a slight nuisance with incorrect
104begy/begx values which cursors currently rely on.
106It is intended that top-level windows connect to this signal to change
107themselves, while windows containing subwins connect to their own
108signals to relayout their subwins. This is because top-level windows
109may be sized independently, while sibling subwins should not
110overlap. The signals are implemented currently with GObject signals.
116Currently, users of widgets in BarnOwl must remember to call
117owl_foo_redisplay when a widget needs to be redrawn. This is quite
118annoying and an implementation detail that functions like
119owl_editwin_insert_string should take care of. To allow widget
120implementations to redraw themselves without calling an expensive
121redisplay many times, owl_window_dirty flags a window as "dirty". The
122framework will promise to redraw that window before the next doupdate,
123while repeated owl_window_dirty calls remain cheap.
125Windows currently redraw with a "redraw" GObject signal. This and the
126resize signal, is somewhat awkward for the editwin which attaches to
127and releases windows, as we must remember signal ids. However, if we
128make widget objects (owl_editwin, owl_mainwin, etc.) also GObjects,
129these signals will automatically detach. We may also consider a
130different mechanism than continuously attaching/detaching
131things. That's kinda weird anyway.
133(We may want to replace it with a normal callback at some
134point. Mostly using the GObject signals to play with them, and because
135we'd likely get some form of automatic binding generation.)
138Known issues and notes
141- owl_window does not export the underlying WINDOW*. This is
142  intentional. To safely resize windows, owl_window reserves the right
143  to destroy/recreate the window whenever it feels like. We can add
144  "window-realized"/"window-unrealized" signals if people really want
145  though.
147- This is currently using GObject. This buys us a lot of niceness, but
148  it is adding a new library with full-blown (and somewhat
149  overengineered) object system. It's very useful for prototyping, but
150  if people want, it can be replaced. I think it's actually
151  worthwhile, as most of the overengineering is explicitly designed
152  for language bindings, something we could be better at.
154- There is this really sketchy "three types in one" thing going on
155  with the screen, panels, and subwins. I'd like to refactor that into
156  some sort of subtyping, but that would ideally involve even more use
157  of GObject.
159- owl_mainwin is not very well ported and the windows do not have a
160  very consistent implementation. This is a known problem that will be
161  addressed in the next iteration. The current ports were done partly
162  as experiments for conventions and mostly to get something working
163  as soon as possible. Among things that should change is for the
164  widgets to all use new/delete/pointers instead of
165  init/cleanup/embed-in-struct.
167- There is a generated GObject that emits signals for all variables
168  and random other properties. It's currently not used much. It may be
169  useful later, or not. I think there is some value in having change
170  notifications for all our variables, although the initial port of
171  the mainwin and sepbar turned out not to use it.
173- The editwin and a few others are strange and keep track of signal
174  ids. This is somewhat a side effect of us not using GObject
175  everywhere; the signals can automatically disconnect in the right
176  contexts if we do.
178- The sepbar depends on a value computed while the mainwin is drawn,
179  so we currently ensure the windows are created in the right order
180  for the repaints to occur correctly. This is rather poor and should
181  be refactored later.
Note: See TracBrowser for help on using the repository browser.