composite manager thoughts

Jaymz Julian jaymz@artificial-stupidity.net
Fri, 26 Dec 2003 02:57:52 +1100


--vmttodhTwj0NAgWp
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

[touchy hacker disclaimer] No-one should interrpet any of the below as a "you
should go and code this!!!" demand - it's just a bunch of thoughts that i'd be
quite happy to implent myself if people want them.  As always, I'm not
attached to any of this, so feel free to tell me to go to hell. [/touchy
hacker disclaimer]

Two things that I would like to see happen/have an interest in making happen,
which I will say first, and then attempt to justify.

 * I would like to see the composite manager split up into a libcompmgr, and a
 * main refrence application.

 * I would like to see users of libcompmgr be able to redirect functions on
 * both a global and a per-window basis.

Some justification of this:

 * Window managers will probably want to do compositing themselves in some
   cases, for example, in order to implented the macosx style "genie" minimise
   effect correctly.  Having 20 different composite manager implentations is a
   bad thing, in my view, as they will all have 20 different sets of bugs.  In
   the world I propose above, the window manager would be able to say to
   libcompmgr "Window x is being handled by minimiseGenie() now.  Please just
   pass it to me".

 * This makes it easier for writers of alternate composite manager backend
   implentations, for example, rendering to GL, or to windows GDI windows, to
   implent without having to re-implent, badly, the same infrastructure (the
   design I have sketched out in my head that I really should write down would
   allow both this and the above, by exposing functions to make "composite
   manager level" windows, like happens for the shadows now, and allowing them
   to be redirected.  So, minimiseGenie() calls makeCompmgrWindow() or
   whatever it's called, and fills it with the genie'd window data).

 * I dislike the current shadows astetically, but since the *code* is fine,
   changing them is obviously a bad thing :).  This would allow this to be
   pluggable, and hence easily changed without me pissing people off (more)
   :).

(side note: i added a '-noshadows' flag to my local tree, which i have no
short terms plans to commit, since it falls under the definition of
"nontrivial functionality change" rather than optimization ;), which makes
things a *lot* faster under the current code base - as in, 3x faster, because
compositing with a mask is hideously slow right now.  The above would be a
much better way to handle both of my shadow issues.  I attached the patch in
case anyone is interested to use it, tho, anyhow, but it's for curiosity at
best).

I don't have a written down API spec or anything like that yet, obvisouly,
because I wanted to test the waters before I put in much work in this
direction.  So, I guess this is a "tell me what you think" thing more than a
"here is something concrete that i am going to implent" thing.  Flame on!

        -- jaymz

p.s. merry christmas :).


--vmttodhTwj0NAgWp
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="xcompmgr-commandline.patch"

Index: xcompmgr.c
===================================================================
RCS file: /cvs/xapps/xcompmgr/xcompmgr.c,v
retrieving revision 1.19
diff -u -3 -p -r1.19 xcompmgr.c
--- xcompmgr.c	2 Dec 2003 09:51:12 -0000	1.19
+++ xcompmgr.c	20 Dec 2003 09:55:12 -0000
@@ -92,6 +92,12 @@ Atom            intAtom;
 
 conv            *gaussianMap;
 
+/* How large should the background tile be? */
+int tileSize;
+
+/* should we apply shadows to windows? */
+Bool useShadows;
+
 #define WINDOW_SOLID	0
 #define WINDOW_TRANS	1
 #define WINDOW_ARGB	2
@@ -384,7 +390,7 @@ root_tile (Display *dpy)
     }
     if (!pixmap)
     {
-	pixmap = XCreatePixmap (dpy, root, 1, 1, DefaultDepth (dpy, scr));
+	pixmap = XCreatePixmap (dpy, root, tileSize, tileSize, DefaultDepth (dpy, scr));
 	fill = True;
     }
     pa.repeat = True;
@@ -399,7 +405,7 @@ root_tile (Display *dpy)
 	c.red = c.green = c.blue = 0x8080;
 	c.alpha = 0xffff;
 	XRenderFillRectangle (dpy, PictOpSrc, picture, &c, 
-			      0, 0, 1, 1);
+			      0, 0, tileSize, tileSize);
     }
     return picture;
 }
@@ -428,7 +434,7 @@ win_extents (Display *dpy, win *w)
     {
 	XRectangle  sr;
 	
-	if (!w->shadow)
+	if (!w->shadow && useShadows)
 	{
 	    double	opacity = SHADOW_OPACITY;
 	    if (w->mode == WINDOW_TRANS)
@@ -1042,6 +1048,52 @@ ev_window (XEvent *ev)
     }
 }
 
+void showUsage()
+{
+    printf("X Composite Manager usage: \n");
+    printf("\t-help: Uhn, this text, most likely...\n");
+    printf("\t-tilesize n: tile the background in n x n tiles (default: 1)\n");
+    printf("\t-noshadows: Don't apply a shadow to windows\n");
+}
+
+int handleArgs(int argc, char **argv)
+{
+    int j;
+    for(j=1;j<argc;j++)
+    {
+	if(strcasecmp(argv[j], "-help")==0)
+	{
+	    showUsage();
+	    return 0;
+	}
+	else if(strcasecmp(argv[j], "-tilesize")==0)
+	{
+	    j++;
+	    if(j>=argc)
+	    {
+		printf("-tilesize requires an argument.\n");
+		return 0;
+	    }
+	    tileSize=atoi(argv[j]);
+	    if(tileSize<1)
+	    {
+		printf("Invalid tile size: %s\n", argv[j]);
+		return 0;
+	    }
+	}
+	else if(strcasecmp(argv[j], "-noshadows")==0)
+	{
+		useShadows=False;
+	}
+	else
+	{
+		printf("Unknown parameter: %s\n", argv[j]);
+		return 1;
+	}
+    }
+    return 1;
+}
+
 int
 main (int argc, char **argv)
 {
@@ -1078,6 +1130,13 @@ main (int argc, char **argv)
     scr = DefaultScreen (dpy);
     root = RootWindow (dpy, scr);
 
+    // set defaults, and then handle arguments
+    tileSize=1;
+    useShadows=True;
+    if(argc>0)
+	if(!handleArgs(argc, argv))
+	    return 1;
+
     /* get atoms */
     transPropAtom = XInternAtom(dpy, TRANS_PROP, False);
     intAtom = XInternAtom(dpy, "INTEGER", True);

--vmttodhTwj0NAgWp--