From joubert at joubster.com Sun Aug 12 14:22:38 2007 From: joubert at joubster.com (Joubert Nel) Date: Sun, 12 Aug 2007 10:22:38 -0400 Subject: [cl-cairo2-devel] XLib-context and UIs Message-ID: <1186928558.5711.4.camel@joubert-desktop> Hello, I'm keen on using CL-Cairo2 as a means to draw GUIs. I've done some initial exploration of the library and am wondering: 1) There's an xlib-context example, but the windows are fixed-size. Is it possible to make resizable windows? 2) Is it possible to receive mouse and keyboard events int the xlib-context? Thanks Joubert From tpapp at Princeton.EDU Sun Aug 12 20:16:17 2007 From: tpapp at Princeton.EDU (Tamas K Papp) Date: Sun, 12 Aug 2007 22:16:17 +0200 Subject: [cl-cairo2-devel] XLib-context and UIs In-Reply-To: <1186928558.5711.4.camel@joubert-desktop> References: <1186928558.5711.4.camel@joubert-desktop> Message-ID: <20070812201617.GA29384@pu100877.student.princeton.edu> On Sun, Aug 12, 2007 at 10:22:38AM -0400, Joubert Nel wrote: Hi Joubert, > I'm keen on using CL-Cairo2 as a means to draw GUIs. I've done some > initial exploration of the library and am wondering: > > 1) There's an xlib-context example, but the windows are fixed-size. Is > it possible to make resizable windows? The main problem with X is refreshing the window when X asks for it (ie the window receives an Expose event). In order to do it correctly, you either have to keep track of all operations or double-buffer. cl-cairo2 does the latter, as it is easier to implement, but this does not allow resizing. Peter Hildebrandt experimented with the former approach: http://groups.google.com/group/comp.lang.lisp/msg/9258d245145323b3 you might want to ask him about the current status. This approach would allow resizing, but is more complicated. If you know what subset of cl-cairo2 you will be using, perhaps you can get away implementing recording operations for that subset. > 2) Is it possible to receive mouse and keyboard events int the > xlib-context? The framework is there, you just have to write and event handler. A new version of cl-cairo2 will be released tomorrow, which contains a rewritten x11 surface, implemented entirely in Lisp using CFFI (no extra C glue). If you want to refine the event handler, I suggest you wait for that and your job will be much easier. Best, Tamas From joubert at joubster.com Tue Aug 14 00:54:57 2007 From: joubert at joubster.com (Joubert Nel) Date: Mon, 13 Aug 2007 20:54:57 -0400 Subject: [cl-cairo2-devel] XLib-context and UIs In-Reply-To: <20070812201617.GA29384@pu100877.student.princeton.edu> References: <1186928558.5711.4.camel@joubert-desktop> <20070812201617.GA29384@pu100877.student.princeton.edu> Message-ID: <1187052897.5675.5.camel@joubert-desktop> Hello Tamas, On Sun, 2007-08-12 at 22:16 +0200, Tamas K Papp wrote: > > 1) There's an xlib-context example, but the windows are fixed-size. Is > > it possible to make resizable windows? > > The main problem with X is refreshing the window when X asks for it > (ie the window receives an Expose event). In order to do it > correctly, you either have to keep track of all operations or > double-buffer. cl-cairo2 does the latter, as it is easier to > implement, but this does not allow resizing. > > Peter Hildebrandt experimented with the former approach: > > http://groups.google.com/group/comp.lang.lisp/msg/9258d245145323b3 > > you might want to ask him about the current status. This approach > would allow resizing, but is more complicated. If you know what > subset of cl-cairo2 you will be using, perhaps you can get away > implementing recording operations for that subset. I was thinking the same approach, since redrawing might include re-spacing/changing layout of items, and not merely "drawing them again". Previously, I used CL-Cairo and created the Cairo context within a GDK window. This gave me sizing as well as mouse events etc. > > > 2) Is it possible to receive mouse and keyboard events int the > > xlib-context? > > The framework is there, you just have to write and event handler. > > A new version of cl-cairo2 will be released tomorrow, which contains a > rewritten x11 surface, implemented entirely in Lisp using CFFI (no > extra C glue). If you want to refine the event handler, I suggest you > wait for that and your job will be much easier. I see it is up on common-lisp.net. I should give it a try - will let you know what I find. Joubert PS: have you looked at the Lispbuilder project? What are your thoughts on it? From joubert at joubster.com Sat Aug 25 02:44:40 2007 From: joubert at joubster.com (Joubert Nel) Date: Fri, 24 Aug 2007 22:44:40 -0400 Subject: [cl-cairo2-devel] X11 sample in Aug 22 version Message-ID: <1188009880.14233.17.camel@joubert-desktop> Hi, When I try to run the X11 example in the Aug 22 version, the following happens: -------------------------------------------------------------- CL-USER> (load "/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp") ; in: LAMBDA NIL ; CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY ; ; caught STYLE-WARNING: ; undefined function: OPEN-X11-DISPLAY ; ; caught STYLE-WARNING: ; This function is undefined: ; OPEN-X11-DISPLAY ; ; compilation unit finished ; caught 2 STYLE-WARNING conditions ; Evaluation aborted. CL-USER> -------------------------------------------------------------- Does it work for anybody else? Joubert PS: here is a full stack trace: function CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY is undefined. [Condition of type UNDEFINED-FUNCTION] Restarts: 0: [ABORT] Return to SLIME's top level. 1: [TERMINATE-THREAD] Terminate this thread (#) Backtrace: 0: ("bogus stack frame") 1: (SB-INT:SIMPLE-EVAL-IN-LEXENV (CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY ":0") #) 2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SB-IMPL::%DEFPARAMETER 'CAIRO-XLIB-EXAMPLE::*DISPLAY* (CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY ":0") NIL 'NIL (SB-C:SOURCE-LOCATION)) #) 3: (SB-INT:SIMPLE-EVAL-IN-LEXENV (EVAL-WHEN (:LOAD-TOPLEVEL :EXECUTE) (SB-IMPL::%DEFPARAMETER 'CAIRO-XLIB-EXAMPLE::*DISPLAY* (CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY ":0") NIL 'NIL (SB-C:SOURCE-LOCATION))) #) 4: (SB-INT:SIMPLE-EVAL-IN-LEXENV (DEFPARAMETER CAIRO-XLIB-EXAMPLE::*DISPLAY* (CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY ":0")) #) 5: (SB-FASL::LOAD-AS-SOURCE # NIL NIL) 6: (SB-FASL::INTERNAL-LOAD #P"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp" #P"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp" :ERROR NIL NIL :SOURCE :DEFAULT) 7: (SB-FASL::INTERNAL-LOAD #P"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp" #P"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp" :ERROR NIL NIL NIL :DEFAULT) 8: (LOAD "/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp") 9: (SB-INT:SIMPLE-EVAL-IN-LEXENV (LOAD "/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp") #) 10: (SWANK::EVAL-REGION "(load \"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp\") " T) 11: ((LAMBDA ())) 12: ((LAMBDA (SWANK-BACKEND::FN)) #) 13: (SWANK::CALL-WITH-BUFFER-SYNTAX #) 14: (SWANK:LISTENER-EVAL "(load \"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp\") ") 15: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK:LISTENER-EVAL "(load \"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp\") ") #) 16: ((LAMBDA ())) 17: ((LAMBDA (SWANK-BACKEND::HOOK SWANK-BACKEND::FUN)) # #) 18: ((LAMBDA ())) 19: ((LAMBDA (SWANK-BACKEND::HOOK SWANK-BACKEND::FUN)) # #) 20: (SWANK::CALL-WITH-REDIRECTED-IO # #) 21: (SWANK::CALL-WITH-CONNECTION # #) 22: (SWANK::HANDLE-REQUEST #) 23: (SWANK::REPL-LOOP #) 24: (SWANK::REPL-LOOP #) 25: (SWANK::CALL-WITH-BINDINGS NIL #) 26: ((FLET SB-THREAD::WITH-MUTEX-THUNK)) 27: (SB-UNIX::CALL-WITH-LOCAL-INTERRUPTS # T) 28: ((FLET SB-UNIX::WITHOUT-INTERRUPTS-THUNK) T) 29: ((FLET SB-UNIX::RUN-WITHOUT-INTERRUPTS)) 30: (SB-UNIX::CALL-WITHOUT-INTERRUPTS #) 31: (SB-THREAD::CALL-WITH-MUTEX # #S(SB-THREAD:MUTEX :NAME "thread result lock" :VALUE #) # T) 32: ((LAMBDA ())) 33: ("foreign function: call_into_lisp") 34: ("foreign function: funcall0") 35: ("foreign function: new_thread_trampoline") 36: ("foreign function: #xB7FBE31B") function CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY is undefined. [Condition of type UNDEFINED-FUNCTION] Restarts: 0: [ABORT] Return to SLIME's top level. 1: [TERMINATE-THREAD] Terminate this thread (#) Backtrace: 0: ("bogus stack frame") 1: (SB-INT:SIMPLE-EVAL-IN-LEXENV (CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY ":0") #) 2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SB-IMPL::%DEFPARAMETER 'CAIRO-XLIB-EXAMPLE::*DISPLAY* (CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY ":0") NIL 'NIL (SB-C:SOURCE-LOCATION)) #) 3: (SB-INT:SIMPLE-EVAL-IN-LEXENV (EVAL-WHEN (:LOAD-TOPLEVEL :EXECUTE) (SB-IMPL::%DEFPARAMETER 'CAIRO-XLIB-EXAMPLE::*DISPLAY* (CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY ":0") NIL 'NIL (SB-C:SOURCE-LOCATION))) #) 4: (SB-INT:SIMPLE-EVAL-IN-LEXENV (DEFPARAMETER CAIRO-XLIB-EXAMPLE::*DISPLAY* (CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY ":0")) #) 5: (SB-FASL::LOAD-AS-SOURCE # NIL NIL) 6: (SB-FASL::INTERNAL-LOAD #P"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp" #P"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp" :ERROR NIL NIL :SOURCE :DEFAULT) 7: (SB-FASL::INTERNAL-LOAD #P"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp" #P"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp" :ERROR NIL NIL NIL :DEFAULT) 8: (LOAD "/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp") 9: (SB-INT:SIMPLE-EVAL-IN-LEXENV (LOAD "/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp") #) 10: (SWANK::EVAL-REGION "(load \"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp\") " T) 11: ((LAMBDA ())) 12: ((LAMBDA (SWANK-BACKEND::FN)) #) 13: (SWANK::CALL-WITH-BUFFER-SYNTAX #) 14: (SWANK:LISTENER-EVAL "(load \"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp\") ") 15: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK:LISTENER-EVAL "(load \"/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp\") ") #) 16: ((LAMBDA ())) 17: ((LAMBDA (SWANK-BACKEND::HOOK SWANK-BACKEND::FUN)) # #) 18: ((LAMBDA ())) 19: ((LAMBDA (SWANK-BACKEND::HOOK SWANK-BACKEND::FUN)) # #) 20: (SWANK::CALL-WITH-REDIRECTED-IO # #) 21: (SWANK::CALL-WITH-CONNECTION # #) 22: (SWANK::HANDLE-REQUEST #) 23: (SWANK::REPL-LOOP #) 24: (SWANK::REPL-LOOP #) 25: (SWANK::CALL-WITH-BINDINGS NIL #) 26: ((FLET SB-THREAD::WITH-MUTEX-THUNK)) 27: (SB-UNIX::CALL-WITH-LOCAL-INTERRUPTS # T) 28: ((FLET SB-UNIX::WITHOUT-INTERRUPTS-THUNK) T) 29: ((FLET SB-UNIX::RUN-WITHOUT-INTERRUPTS)) 30: (SB-UNIX::CALL-WITHOUT-INTERRUPTS #) 31: (SB-THREAD::CALL-WITH-MUTEX # #S(SB-THREAD:MUTEX :NAME "thread result lock" :VALUE #) # T) 32: ((LAMBDA ())) 33: ("foreign function: call_into_lisp") 34: ("foreign function: funcall0") 35: ("foreign function: new_thread_trampoline") 36: ("foreign function: #xB7FBE31B") From tpapp at Princeton.EDU Sat Aug 25 12:42:11 2007 From: tpapp at Princeton.EDU (Tamas K Papp) Date: Sat, 25 Aug 2007 14:42:11 +0200 Subject: [cl-cairo2-devel] X11 sample in Aug 22 version In-Reply-To: <1188009880.14233.17.camel@joubert-desktop> References: <1188009880.14233.17.camel@joubert-desktop> Message-ID: <20070825124211.GA32204@pu100877.student.princeton.edu> On Fri, Aug 24, 2007 at 10:44:40PM -0400, Joubert Nel wrote: > Hi, > > When I try to run the X11 example in the Aug 22 version, the following > happens: > > -------------------------------------------------------------- > > CL-USER> (load > "/tank/lisp/sbcl/lib/sbcl/site/cl-cairo2-latest/tutorial/x11-example.lisp") > ; in: LAMBDA NIL > ; CAIRO-XLIB-EXAMPLE::OPEN-X11-DISPLAY > ; > ; caught STYLE-WARNING: > ; undefined function: OPEN-X11-DISPLAY > > ; > ; caught STYLE-WARNING: > ; This function is undefined: > ; OPEN-X11-DISPLAY > ; > ; compilation unit finished > ; caught 2 STYLE-WARNING conditions > ; Evaluation aborted. > CL-USER> > > -------------------------------------------------------------- > > Does it work for anybody else? Hi Joubert, My mistake, the X11 code has been rewritten again. Sorry for the frequent changes, the only justification is that I hope it is getting better and cleaner each time. You will find the corrected version of x11-example.lisp on the site now. In the current version, each window has its own event loop and thread (in the previous code, it used to be one loop/thread per display). I find this approach eliminates some rare but nasty redrawing bugs. Currently, you can create xlib contexts with (create-xlib-context width height) and you can supply optional arguments display-name (if nil as by default, Xlib will use your $DISPLAY settings) and window-name (the title of the window). Also, in the current version you will find sync-lock, sync-unlock and the macro (with-sync-lock (context) ...) which suspends redrawing the window for operations in its body. Use it for drawings with lots of elements, they will appear on the screen at the same time, and drawing will be much faster. I hope that there will be no more major reorganizations in the X11 code, at least the API. HTH, Tamas From joubert at joubster.com Sat Aug 25 13:46:50 2007 From: joubert at joubster.com (Joubert Nel) Date: Sat, 25 Aug 2007 09:46:50 -0400 Subject: [cl-cairo2-devel] X11 sample in Aug 22 version In-Reply-To: <20070825124211.GA32204@pu100877.student.princeton.edu> References: <1188009880.14233.17.camel@joubert-desktop> <20070825124211.GA32204@pu100877.student.princeton.edu> Message-ID: <1188049610.14233.24.camel@joubert-desktop> On Sat, 2007-08-25 at 14:42 +0200, Tamas K Papp wrote: > > > > Does it work for anybody else? > > Hi Joubert, > > My mistake, the X11 code has been rewritten again. Sorry for the > frequent changes, the only justification is that I hope it is getting > better and cleaner each time. No problem; I'm still in the early growing pains of my GUI framework (busy switching from cl-cairo) so this comes with the territory. > > You will find the corrected version of x11-example.lisp on the site > now. In the current version, each window has its own event loop and Got it from svn - works fine. > thread (in the previous code, it used to be one loop/thread per > display). I find this approach eliminates some rare but nasty > redrawing bugs. > Currently, you can create xlib contexts with > > (create-xlib-context width height) > > and you can supply optional arguments display-name (if nil as by > default, Xlib will use your $DISPLAY settings) and window-name > (the title of the window). That's good, I know previously you had to call it with ":0". > > Also, in the current version you will find sync-lock, sync-unlock and > the macro > > (with-sync-lock (context) > ...) > > which suspends redrawing the window for operations in its body. Use > it for drawings with lots of elements, they will appear on the screen > at the same time, and drawing will be much faster. I did notice the speed increase in the X11 sample. Joubert From joubert at joubster.com Mon Aug 27 03:20:11 2007 From: joubert at joubster.com (Joubert Nel) Date: Sun, 26 Aug 2007 23:20:11 -0400 Subject: [cl-cairo2-devel] Garbage on display: "create-xlib-context" Message-ID: <1188184811.31172.5.camel@joubert-desktop> Hello, I see some interesting behavior. When I do: (cl-cairo2:create-xlib-context 600 400 :window-name "gomer") I get a window alright, but the content is a scrambled image (even though I didn't start any painting). Sometimes, I don't get a scrambled image, but rather an image that was "recently" displayed on my computer (e.g. from web browser, or from the splash screen of an application). Is this expected? Joubert From joubert at joubster.com Fri Aug 31 02:58:40 2007 From: joubert at joubster.com (Joubert Nel) Date: Thu, 30 Aug 2007 22:58:40 -0400 Subject: [cl-cairo2-devel] xlib-context / window functionality Message-ID: <1188529120.31172.17.camel@joubert-desktop> Hello Tamas, I'm experimenting with the xlib-context and have modified lines 170 and 172 to set maxheight and maxwidth to a large number. This allows the resulting Xlib window to be resizable. Before I continue down this path, I'd like to know whether you are open to the idea of expanding xlib-context so that it can play host to an interactive UI, instead of only *presenting* graphics. I'm thinking about creating a mechanism for passing along Xlib events etc. to a code that consumes cl-cairo2. Joubert From tpapp at Princeton.EDU Fri Aug 31 15:40:31 2007 From: tpapp at Princeton.EDU (Tamas K Papp) Date: Fri, 31 Aug 2007 17:40:31 +0200 Subject: [cl-cairo2-devel] xlib-context / window functionality In-Reply-To: <1188529120.31172.17.camel@joubert-desktop> References: <1188529120.31172.17.camel@joubert-desktop> Message-ID: <20070831154031.GA32446@pu100877.student.princeton.edu> On Thu, Aug 30, 2007 at 10:58:40PM -0400, Joubert Nel wrote: > Hello Tamas, > > I'm experimenting with the xlib-context and have modified lines 170 and > 172 to set maxheight and maxwidth to a large number. > > This allows the resulting Xlib window to be resizable. > > Before I continue down this path, I'd like to know whether you are open > to the idea of expanding xlib-context so that it can play host to an > interactive UI, instead of only *presenting* graphics. > I'm thinking about creating a mechanism for passing along Xlib events > etc. to a code that consumes cl-cairo2. Hi Joubert, Generally, I am happy to accept contributions. However, I don't really understand what you are doing. Presenting graphics is very simple and can be done with little user interaction, since the flow of data is one way (Lisp application -> pixmap buffer -> X11 display). This allows a particularly simple event model, where I can start the event loops as threads and the "main" application doesn't need to care about them any longer. This suits me fine, the purpose of this context was that I could debug my cairo code while watching stuff happen on screen. In an application where the GUI is not a sideshow but the main feature, you would have a single event loop that orchestrates everything, including GUI management and whatever background processes you need. Plain vanilla Xlib is not really suitable for that, as it is a pain in the ass to program. That's why people came up with toolkits like Gtk or Qt. I would suggest that you familiarize yourself with the framework of your choice, and then ask on the appropriate mailing list (cairo list is a good place to start). The only thing to keep in mind is that cl-cairo2 will need an Xlib display, a visual and a drawable to create a surface. Once you have that, you can use all the drawing efunctions and take care of syncing in the event loop. If I recall correctly, I have seen some gtk & cl library which would be suitable, but I can't recall which. Maybe I can help more if you tell us what it is you are trying to achieve (what kind of application etc). Do you have any prior experience with using any of the X toolkits? HTH, Tamas From joubert at joubster.com Fri Aug 31 16:27:44 2007 From: joubert at joubster.com (Joubert Nel) Date: Fri, 31 Aug 2007 12:27:44 -0400 Subject: [cl-cairo2-devel] xlib-context / window functionality In-Reply-To: <20070831154031.GA32446@pu100877.student.princeton.edu> References: <1188529120.31172.17.camel@joubert-desktop> <20070831154031.GA32446@pu100877.student.princeton.edu> Message-ID: <1188577664.18685.10.camel@joubert-desktop> On Fri, 2007-08-31 at 17:40 +0200, Tamas K Papp wrote: > On Thu, Aug 30, 2007 at 10:58:40PM -0400, Joubert Nel wrote: > > Hello Tamas, > > > > I'm experimenting with the xlib-context and have modified lines 170 and > > 172 to set maxheight and maxwidth to a large number. > > > > This allows the resulting Xlib window to be resizable. > > > > Before I continue down this path, I'd like to know whether you are open > > to the idea of expanding xlib-context so that it can play host to an > > interactive UI, instead of only *presenting* graphics. > > I'm thinking about creating a mechanism for passing along Xlib events > > etc. to a code that consumes cl-cairo2. > In an application where the GUI is not a sideshow but the main > feature, you would have a single event loop that orchestrates > everything, including GUI management and whatever background processes > you need. Plain vanilla Xlib is not really suitable for that, as it > is a pain in the ass to program. That's why people came up with > toolkits like Gtk or Qt. I would suggest that you familiarize > yourself with the framework of your choice, and then ask on the > appropriate mailing list (cairo list is a good place to start). Yes, perhaps I wasn't explicit enough. I am building a widget toolkit that aims to be smaller in scope yet fundamentally more flexible than either Gtk or Qt. The ideas are taken from the WPF in the .NET Framework 3.0, which I know very well. In other words, I would need to extend the xlib bits in cl-cairo2 so that my widget toolkit can consume lower-level events that Xlib would pass, e.g. mousedown, resize window, key down, etc. > > Maybe I can help more if you tell us what it is you are trying to > achieve (what kind of application etc). Do you have any prior > experience with using any of the X toolkits? So, I'm building a widget toolkit that aims to provide the bits I want from the WPF model, because its content model makes it easy for users to build new powerful controls that are composed of other controls and also do data and visual templating. I have; however, I haven't found anything that has something like the powerful content model that WPF (on Windows - .NET Framework 3.0) does. None of these toolkits' project pages seem to indicate that they're going to move in this direction either. I guess I'm trying to figure out which lower-level library I want to use for the drawing + low level events in X. Joubert