[Xquartz-dev] Apple-WM usage

xquartz-dev.5.mzs at spamgourmet.com xquartz-dev.5.mzs at spamgourmet.com
Tue Apr 8 14:00:26 PDT 2008


Hi,

I have been investigating using a window manager other than quartz-wm. 
There was a post to the Apple X11-users list about Apple-WM and it sparked 
my curiousity. You can run 'man AppleWM' to see what I am talking about.

My idea was to patch an open source window manager so that it would do the 
Apple-WM stuff optionally, so I started off by writing a little program to 
do some Apple-WM stuff. It appears that few of the routines I call have 
any effect sadly. I have attached the source file wm.c as an example. It 
takes one option, the window id in hex which you can learn from something 
like xwininfo or xlsclients:

I have an .xinitrc that ends like so:

quartz-wm --only-proxy &
exec blackbox

Then I run this:

grief:AppleWM mzs$ gcc aw.c -o aw -L/usr/X11/lib -lX11 -lAppleWM -DDEBUG
grief:AppleWM mzs$ xterm &
[1] 17560
grief:AppleWM mzs$ xlsclients -l
Window 0x20000d:
   Machine:  grief.fnal.gov
   Name:  xterm
   Icon Name:  xterm
   Command:  xterm
   Instance/Class:  xterm/XTerm
grief:AppleWM mzs$ ./aw 0x20000d
strtoul(0x20000d, NULL, 16): 0x20000d
XOpenDisplay(/tmp/launch-IbGgSt/:0): 0x800000
XAppleWMQueryExtension: 1
event base: 68, error base: 130
XAppleWMQueryVersion: 1
major: 1, minor 0, patch 0
True = 1, False = 0
XAppleWMSetCanQuit(dpy, False): 1
XAppleWMSetFrontProcess(dpy): 1
XAppleWMSetWindowLevel(dpy, window, 0): 1
XAppleWMSetFrontProcess(dpy): 1
XAppleWMSetWindowLevel(dpy, window, 0): 1

Even though all those are returning 'True' XAppleWMSetCanQuit, 
XAppleWMSetFrontProcess, and XAppleWMSetWindowLevel appear to nat have any 
effect.

An example of the rationale for doing this is so:

For example you would like X11.app to pop-up a dialog box asking you to 
verify that you indeed wish to quit. So when you start-up your X11 session 
would like to do the XAppleWMSetCanQuit function.

There are lots of other places the window manager would like to do other 
Apple-WM specific things.

I have also tried to compile aw.c with -framework AppKit with no 
difference in behavior. Is there something I am doing wrong? Does it have 
to be the actual window manager that calls these? What is the future of 
Apple-WM?

I wanted to see if Apple-WM was actually being used, so I created inter.c 
which I have attached also. There is a comment at the beginning of the 
source file that explains how I used it. I see in the log file that 
XAppleWMSetCanQuit is being used by quartz-wm:

-[x_screen update_geometry]
-[x_screen update_geometry]: head 0: 0,22 1680x1028
-[x_screen update_geometry]: head 1: 1680,0 1280x1024
-[x_screen update_geometry]: main head has index 0
-[x_screen init_with_screen_id:]: 0, 2960x1050x24, root:44, 2 heads
-[x_screen adopt_window:initializing:]: 20000d
-[x_window init_with_id:screen:initializing:]: 20000d
-[x_window reparent_in]: 20000d
-[x_window update_shape:]: 20000d
-[x_window update_inner_windows:outer:inner:]: 20000d
-[x_window send_configure]: 20000d
-[x_window focus:raise:force:]: 20000d
XAppleWMSetCanQuit = 0x0x032780
XAppleWMFrameDraw = 0x0x031790
XAppleWMSetCanQuit: 0x810c00, 0
...

There is a bunch of Notify stuff with window 44 though, I wonder if that 
has something to do with the use of AppleWM?

Oh I am currently running the more recent release candidate (rc2) and 
there is that bug in this one where the Windows do not come forward until 
the dock icon is clicked twice. Possibly quartx-wm is not doing the 
XAppleWMSetWindowLevel stuff correctly itself.

What I was planning on doing was patching blackbox so that it would work 
better in rootless mode on OS X. For example the aforementioned 
XAppleWMSetCanQuit. Also behavior such as this:

When I click on an X11 window in the background it gets focus and comes to 
the foreground.

When I hold down a modifier and drag an X11 window in the background it 
gets focus and moves around but does not come to the forground.

etc...

I was hoping to ge this to work with the aid of Apple-WM but am having 
trouble getting it to do anything at all at this point and would really 
appreciate any helpful ideas.

Thanks,
mzs
-------------- next part --------------
/* gcc aw.c -o aw -L/usr/X11/lib -lX11 -lAppleWM */

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/applewm.h>

/* trick to verbosely do an expression */
#ifdef	DEBUG
#define	debug(expr, fmt, args...)	\
	((void)fprintf(stderr, fmt "\n", ## args, expr))
#else
#define	debug(expr, fmt, args...)	(void)(expr)
#endif

int
main(int argc, const char *argv[])
{
	Display* dpy;
	char *display;
	Window window;
	int event, error;
	int major, minor, patch;
	int level;

	if (argc != 2) {
		(void)fprintf(stderr, "Usage %s window\n", argv[0]);
		return (2);
	}

	errno = 0;
	debug(window = strtoul(argv[1], NULL, 16),
	      "strtoul(%s, NULL, 16): 0x%x", argv[1]);
	if (errno != 0) {
		perror(argv[0]);
		return (1);
	}

	display = getenv("DISPLAY");
	if (display == NULL)
		display = ":0";

	debug(dpy = XOpenDisplay(display),
	      "XOpenDisplay(%s): 0x%x", display);
	if (dpy == NULL) {
		(void)fprintf(stderr, "Cannot connect to X server %s\n",
		              display);
		return (1);
	}

	debug(XAppleWMQueryExtension(dpy, &event, &error),
	      "XAppleWMQueryExtension: %d");

	(void)printf("event base: %d, error base: %d\n", event, error);

	debug(XAppleWMQueryVersion(dpy, &major, &minor, &patch),
	      "XAppleWMQueryVersion: %d");

	(void)printf("major: %d, minor %d, patch %d\n", major, minor, patch);

	debug(False, "True = %d, False = %d", True);

	debug(XAppleWMSetCanQuit(dpy, False),
	      "XAppleWMSetCanQuit(dpy, False): %d");

	level = AppleWMWindowLevelNormal;

	debug(XAppleWMSetFrontProcess(dpy),
	      "XAppleWMSetFrontProcess(dpy): %d");

	debug(XAppleWMSetWindowLevel(dpy, window, level),
	      "XAppleWMSetWindowLevel(dpy, window, %d): %d", level);

	debug(XAppleWMSetFrontProcess(dpy),
	      "XAppleWMSetFrontProcess(dpy): %d");

	debug(XAppleWMSetWindowLevel(dpy, window, level),
	      "XAppleWMSetWindowLevel(dpy, window, %d): %d", level);

	return (0);
}
-------------- next part --------------
/*
 * This is a library that interposes on Apple-WM for debugging of why AppleWM
 * does not seem to work for me. Here is how you use it:
 *
 * Verify that you do not have libinter.dylib or quartz-wm.txt in your home dir
 * as something you would not like to lose then:
 *
 * gcc -dynamiclib -o libinter.dylib inter.c
 * cp libinter.dylib "$HOME"
 *
 * Open another terminal window and do this to see the log file:
 *
 * touch "$HOME"/quartz-wm.txt
 * tail -f "$HOME"/quartz-wm.txt
 *
 * If you do not have an .xinitrc file, copy the system one to your home dir and
 * modify it so that it runs this:
 *
 * DEBUG=1023; export DEBUG
 * DYLD_FORCE_FLAT_NAMESPACE=1; export DYLD_FORCE_FLAT_NAMESPACE
 * DYLD_INSERT_LIBRARIES="$HOME"/libinter.dylib; export DYLD_INSERT_LIBRARIES
 * exec quartz-wm 2>"$HOME"/quartz-wm.txt
 *
 * Now fire-up X11 with something like xlsclients and experiment.
 */

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <X11/Xlib.h>
#include <X11/extensions/applewm.h>

/* RTLD_NEXT does not seem to work, so I'll just dlopen it myself */
static const char dylib[] = "/usr/X11/lib/libAppleWM.dylib";

static Bool (*setcanquit)(Display *, Bool) = NULL;
static Bool (*framedraw)(
  Display *, int, Window, unsigned int, unsigned int,
  short, short, short, short, short, short, short, short,
  unsigned int, const unsigned char*
) = NULL;

/* return address with symbol name n from handle h */
static void *
addr(void *h, const char *n)
{
	void *a;

	a = dlsym(h, n);
	if (a == NULL) {
		(void)fprintf(stderr, "%s: %s\n", n, dlerror());
		exit(2);
	}

	(void)fprintf(stderr, "%s = 0x%08p\n", n, a);

	return (a);
}

static void
init(void)
{
	void *lh;

	lh = dlopen(dylib, RTLD_GLOBAL);
	if (lh == NULL) {
		(void)fprintf(stderr, "%: %s\n", dylib, dlerror());
		exit(2);
	}

       	setcanquit = addr(lh, "XAppleWMSetCanQuit");
       	framedraw = addr(lh, "XAppleWMFrameDraw");
}

Bool
XAppleWMSetCanQuit(Display *dpy, Bool state)
{
	if (setcanquit == NULL)
		init();

	(void)fprintf(stderr, "XAppleWMSetCanQuit: %p, %d\n", dpy, state);

	return (setcanquit(dpy, state));
}

int
XAppleWMFrameDraw(
    Display *dpy, int screen,
    Window window,
    unsigned int frame_class,
    unsigned int frame_attr,
    short inner_x, short inner_y,
    short inner_w, short inner_h,
    short outer_x, short outer_y,
    short outer_w, short outer_h,
    unsigned int title_length,
    const unsigned char *title_bytes)
{
	if (framedraw == NULL)
		init();

	(void)fprintf(stderr, "XAppleWMFrameDraw: "
	    "%p, %d, 0x%x, 0x%x, 0x%x, "
	    "%hd, %hd, %hd, %hd, %hd, %hd, %hd, %hd, "
	    "%d, %.*s\n",
	    dpy, screen, window, frame_class, frame_attr,
	    inner_x, inner_y, inner_w, inner_h,
	    outer_x, outer_y, outer_w, outer_h,
	    title_length, title_length, title_bytes);

	return (framedraw(dpy, screen, window, frame_class,
		    frame_attr, inner_x, inner_y, inner_w, inner_h,
		    outer_x, outer_y, outer_w, outer_h,
		    title_length, title_bytes));
}


More information about the Xquartz-dev mailing list