XWorkstation.st
changeset 150 5d0b9d669832
parent 146 8fdc30b8e8b1
child 152 17cc0709e898
--- a/XWorkstation.st	Fri May 19 15:41:39 1995 +0200
+++ b/XWorkstation.st	Sun Jun 04 18:38:31 1995 +0200
@@ -13,7 +13,8 @@
 DeviceWorkstation subclass:#XWorkstation
        instanceVariableNames:'screen
 			      hasShapeExtension hasFaxExtension hasShmExtension
-			      hasDPSExtension hasSaveUnder ignoreBackingStore
+			      hasDPSExtension hasMbufExtension hasXVideoExtension
+			      hasSaveUnder ignoreBackingStore
 			      blackpixel whitepixel redMask greenMask blueMask
 			      protocolsAtom deleteWindowAtom saveYourselfAtom
 			      quitAppAtom
@@ -23,7 +24,7 @@
 			      eventRootX eventRootY
 			      displayName eventTrace
 			      dispatchingExpose
-			      rgbVisual virtualRootId
+			      rgbVisual virtualRootId rootId
 			      eventBuffer'
        classVariableNames:   ''
        poolDictionaries:''
@@ -34,7 +35,7 @@
 COPYRIGHT (c) 1989 by Claus Gittinger
 	      All Rights Reserved
 
-$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.45 1995-05-18 15:40:16 claus Exp $
+$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.46 1995-06-04 16:38:31 claus Exp $
 '!
 
 !XWorkstation class methodsFor:'documentation'!
@@ -55,7 +56,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.45 1995-05-18 15:40:16 claus Exp $
+$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.46 1995-06-04 16:38:31 claus Exp $
 "
 !
 
@@ -69,6 +70,8 @@
     process for the other display(s) and create the other views with a slightly
     different protocol. However, 'normal' applications do not have to care for
     all of this ...
+
+    See more documentation in my superclass, DeviceWorkstation.
 "
 ! !
 
@@ -89,6 +92,9 @@
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
 
+#define XK_MISCELLANY
+#include <X11/keysymdef.h>
+
 /*
  * this define adds support for two-byte-strings.
  * leaving it undefined does not really save you much
@@ -105,7 +111,7 @@
 #endif
 
 /*
- * shared memory extension currently not supported
+ * shared memory extension access is currently not supported
  * (only query is implemented)
  */
 #ifdef SHM
@@ -113,6 +119,22 @@
 #endif
 
 /*
+ * multiBuffer extension access is currently not supported
+ * (only query is implemented)
+ */
+#ifdef MBUF
+# include <X11/extensions/multibuf.h>
+#endif
+
+/*
+ * XVideo extension access is currently not supported
+ * (only query is implemented)
+ */
+#ifdef XVIDEO
+# include <X11/extensions/Xv.h>
+#endif
+
+/*
  * this is a non-standard fax-image decompression extension
  * (only found in megascan servers ported by myself)
  */
@@ -165,6 +187,7 @@
 #define _DPSContextVal(o)    (DPSContext)(MKCP(o))
 
 #define myDpy _DisplayVal(_INST(displayId))
+#define ISCONNECTED (_INST(displayId) != nil)
 
 #ifndef THISCONTEXT_IN_REGISTER
 # define BLOCKINTERRUPTS()      /* */
@@ -180,13 +203,13 @@
 					\
 	__thisContext__ = __thisContext;\
 	if (!__interruptsBlocked) {     \
-	    BLOCKINTERRUPTS();          \
+	    __BLOCKINTERRUPTS();        \
 	    needUnblock = 1;            \
 	}
 
 # define END_INTERRUPTSBLOCKED          \
 	if (needUnblock) {              \
-	    UNBLOCKINTERRUPTS();        \
+	    __UNBLOCKINTERRUPTS();      \
 	}                               \
 	__thisContext__ = 0;            \
     }
@@ -422,28 +445,42 @@
 	    _INST(hasShapeExtension) = true;
 	else
 #endif
-	_INST(hasShapeExtension) = false;
+	  _INST(hasShapeExtension) = false;
 
 #ifdef SHM
 	if (XShmQueryExtension(dpy, &shmEventBase, &shmErrorBase))
 	    _INST(hasShmExtension) = true;
 	else
 #endif
-	_INST(hasShmExtension) = false;
+	  _INST(hasShmExtension) = false;
 
 #ifdef FAX
 	if (XFAXImageQueryExtension(dpy, &faxEventBase, &faxErrorBase))
 	    _INST(hasFaxExtension) = true;
 	else
 #endif
-	_INST(hasFaxExtension) = false;
+	  _INST(hasFaxExtension) = false;
 
 #ifdef DPS
 	if (XQueryExtension(dpy, "DPSExtension", &dummy, &dummy, &dummy))
 	    _INST(hasDPSExtension) = true;
 	else
 #endif
-	_INST(hasDPSExtension) = false;
+	  _INST(hasDPSExtension) = false;
+
+#ifdef XVIDEO
+	if (XQueryExtension(dpy, "XVideo", &dummy, &dummy, &dummy))
+	    _INST(hasXVideoExtension) = true;
+	else
+#endif
+	  _INST(hasXVideoExtension) = false;
+
+#ifdef MBUF
+	if (XQueryExtension(dpy, "Multi-Buffering", &dummy, &dummy, &dummy))
+	    _INST(hasMbufExtension) = true;
+	else
+#endif
+	  _INST(hasMbufExtension) = false;
 
 	/*
 	 * look for RGB visual
@@ -560,7 +597,7 @@
     dispatchingExpose := false.
     isSlow := false.
     shiftDown := false.
-    controlDown := false.
+    ctrlDown := false.
     metaDown := false.
     altDown := false.
     motionEventCompression := true.
@@ -587,7 +624,9 @@
 %{
     sz = _MKSMALLINT(sizeof(XEvent) + 100);
 %}.
-    eventBuffer := ByteArray new:sz.
+    eventBuffer isNil ifTrue:[
+	eventBuffer := ByteArray new:sz.
+    ].
 !
 
 initializeSpecialFlags
@@ -613,7 +652,7 @@
 
 %{  /* NOCONTEXT */
 
-    if (_INST(displayId) != nil) {
+    if (ISCONNECTED) {
 	BEGIN_INTERRUPTSBLOCKED
 	XCloseDisplay(myDpy);
 	_INST(displayId) = nil;
@@ -623,7 +662,7 @@
 !
 
 reinitialize
-    virtualRootId := nil.
+    virtualRootId := rootId := nil.
     super reinitialize.
     dispatchingExpose := nil
 ! !
@@ -640,7 +679,7 @@
 %{  /* NOCONTEXT */
     int arg;
 
-    if (__isSmallInteger(aWindowId)) {
+    if (__isSmallInteger(aWindowId) && ISCONNECTED) {
 	if (revertSymbol == @symbol(parent))
 	    arg = RevertToParent;
 	else if (revertSymbol == @symbol(root))
@@ -662,9 +701,11 @@
 
 %{  /* NOCONTEXT */
 
-    BEGIN_INTERRUPTSBLOCKED
-    XSynchronize(myDpy, 1);
-    END_INTERRUPTSBLOCKED
+    if (ISCONNECTED) {
+	BEGIN_INTERRUPTSBLOCKED
+	XSynchronize(myDpy, 1);
+	END_INTERRUPTSBLOCKED
+    }
 %}
     "Display unbuffered"
 !
@@ -674,9 +715,11 @@
 
 %{  /* NOCONTEXT */
 
-    BEGIN_INTERRUPTSBLOCKED
-    XSynchronize(myDpy, 0);
-    END_INTERRUPTSBLOCKED
+    if (ISCONNECTED) {
+	BEGIN_INTERRUPTSBLOCKED
+	XSynchronize(myDpy, 0);
+	END_INTERRUPTSBLOCKED
+    }
 %}
     "Display buffered"
 !
@@ -686,9 +729,11 @@
 
 %{  /* NOCONTEXT */
 
-    BEGIN_INTERRUPTSBLOCKED
-    XSync(myDpy, 0);
-    END_INTERRUPTSBLOCKED
+    if (ISCONNECTED) {
+	BEGIN_INTERRUPTSBLOCKED
+	XSync(myDpy, 0);
+	END_INTERRUPTSBLOCKED
+    }
 %}
 !
 
@@ -713,7 +758,7 @@
 %{
     int volume;
 
-    if (__isSmallInteger(volumeInPercent)) {
+    if (__isSmallInteger(volumeInPercent) && ISCONNECTED) {
 	/* stupid: X wants -100 .. 100 and calls this percent */
 	volume = _intVal(volumeInPercent) * 2 - 100;
 	if (volume < -100) volume = -100;
@@ -755,7 +800,10 @@
 
 %{  /* NOCONTEXT */
 
-    RETURN ( MKOBJ(ConnectionNumber(myDpy)) );
+    if (ISCONNECTED) {
+	RETURN ( MKOBJ(ConnectionNumber(myDpy)) );
+    }
+    RETURN (nil);
 %}
 !
 
@@ -773,7 +821,10 @@
      any interrest, but can be for special cases
      (to avoid bugs in certain implementations)"
 %{
-    RETURN ( _MKSTRING(XServerVendor(myDpy), __context) );
+    if (ISCONNECTED) {
+	RETURN ( _MKSTRING(XServerVendor(myDpy), __context) );
+    }
+    RETURN (nil);
 %}
 
     "
@@ -787,7 +838,10 @@
      (to avoid bugs in certain implementations)"
 
 %{  /* NOCONTEXT */
-    RETURN ( _MKSMALLINT(XVendorRelease(myDpy)) );
+    if (ISCONNECTED) {
+	RETURN ( _MKSMALLINT(XVendorRelease(myDpy)) );
+    }
+    RETURN (nil);
 %}
 
     "
@@ -800,7 +854,10 @@
      any interrest"
 
 %{  /* NOCONTEXT */
-    RETURN ( _MKSMALLINT(XProtocolVersion(myDpy)) );
+    if (ISCONNECTED) {
+	RETURN ( _MKSMALLINT(XProtocolVersion(myDpy)) );
+    }
+    RETURN (nil);
 %}
 
     "
@@ -819,7 +876,7 @@
 !
 
 hasShm
-    "return true, if this workstation supports shared pixmaps"
+    "return true, if this workstation supports the shared pixmap extension"
 
     ^ hasShmExtension
 !
@@ -836,18 +893,54 @@
     ^ hasDPSExtension
 !
 
+hasMultibuffer
+    "return true, if this workstation supports the multibuffer extension"
+
+    ^ hasMbufExtension
+!
+
+hasXVideo
+    "return true, if this workstation supports the XVideo extension"
+
+    ^ hasXVideoExtension
+!
+
+hasExtension:extensionString
+    "query for an X extension. The argument, extensionString
+     should be the name of the extension (i.e. 'SHAPE', 'XInputExtension' etc).
+     Return true, if that extension is available."
+
+%{
+    int dummy;
+
+    if (__isString(extensionString) && ISCONNECTED) {
+	if (XQueryExtension(myDpy, __stringVal(extensionString), &dummy, &dummy, &dummy)) {
+	    RETURN ( true );
+	}
+    }
+%}.
+    ^ false
+!
+
 supportedImageFormats
     "return an array with supported image formats; each array entry
      is another array, consisting of depth and bitsPerPixel values."
 
-    |nFormats formatArray|
+    |nFormats "{ Class: SmallInteger }"
+     formatArray|
 %{
     Display *dpy = myDpy;
+
+    if (! ISCONNECTED) {
+	RETURN (nil);
+    }
     nFormats = _MKSMALLINT(DISPLAYACCESS(dpy)->nformats);
 %}.
     formatArray := Array new:nFormats.
-    1 to:nFormats do:[:i |
-	|bitsPerPixelInfo depthInfo|
+    1 to:nFormats do:[:index |
+	|bitsPerPixelInfo depthInfo i|
+
+	i := index.
 %{
 	ScreenFormat *format;
 	Display *dpy = myDpy;
@@ -857,7 +950,7 @@
 	bitsPerPixelInfo = _MKSMALLINT(format->bits_per_pixel);
 	depthInfo = _MKSMALLINT(format->depth);
 %}.
-	formatArray at:i put:(Array with:depthInfo with:bitsPerPixelInfo).
+	formatArray at:index put:(Array with:depthInfo with:bitsPerPixelInfo).
     ].
     ^ formatArray
 
@@ -945,6 +1038,7 @@
 %{  /* NOCONTEXT */
     RETURN (_MKSMALLINT( ExposureMask | StructureNotifyMask |
 			 KeyPressMask | KeyReleaseMask |
+			 EnterWindowMask | LeaveWindowMask |
 			 ButtonPressMask | ButtonMotionMask | ButtonReleaseMask ));
 %}
 !
@@ -1115,7 +1209,7 @@
     int screen = _intVal(_INST(screen));
     Pixmap newBitmap;
 
-    if (__bothSmallInteger(w, h)) {
+    if (__bothSmallInteger(w, h) && ISCONNECTED) {
 	BEGIN_INTERRUPTSBLOCKED
 	newBitmap = XCreatePixmap(dpy, RootWindow(dpy, screen),
 				       _intVal(w), _intVal(h), 1);
@@ -1138,7 +1232,7 @@
     int screen = _intVal(_INST(screen));
     Pixmap newBitmap;
 
-    if (__bothSmallInteger(w, h)) {
+    if (__bothSmallInteger(w, h) && ISCONNECTED) {
 	BEGIN_INTERRUPTSBLOCKED
 	newBitmap = XCreatePixmap(dpy, RootWindow(dpy, screen),
 				       _intVal(w), _intVal(h), _intVal(d));
@@ -1163,19 +1257,21 @@
     int b_x_hot, b_y_hot;
     int status;
 
-    if (__isString(aString) || __isSymbol(aString)) {
-	filename = (char *)_stringVal(aString);
-
-	BEGIN_INTERRUPTSBLOCKED
-	status = XReadBitmapFile(dpy, RootWindow(dpy, screen),
-				 filename, &b_width, &b_height, &newBitmap,
-				 &b_x_hot, &b_y_hot);
-	END_INTERRUPTSBLOCKED
-
-	if (status == BitmapSuccess) {
-	    w = _MKSMALLINT(b_width);
-	    h = _MKSMALLINT(b_height);
-	    id = MKOBJ(newBitmap);
+    if (ISCONNECTED) {
+	if (__isString(aString) || __isSymbol(aString)) {
+	    filename = (char *)_stringVal(aString);
+
+	    BEGIN_INTERRUPTSBLOCKED
+	    status = XReadBitmapFile(dpy, RootWindow(dpy, screen),
+				     filename, &b_width, &b_height, &newBitmap,
+				     &b_x_hot, &b_y_hot);
+	    END_INTERRUPTSBLOCKED
+
+	    if (status == BitmapSuccess) {
+		w = _MKSMALLINT(b_width);
+		h = _MKSMALLINT(b_height);
+		id = MKOBJ(newBitmap);
+	    }
 	}
     }
 %}
@@ -1285,14 +1381,13 @@
 
 %{  /* NOCONTEXT */
 
-    if (__isSmallInteger(aDrawableId)) {
+    if (__isSmallInteger(aDrawableId) && ISCONNECTED) {
 	BEGIN_INTERRUPTSBLOCKED
 	XFreePixmap(myDpy, _PixmapVal(aDrawableId));
 	END_INTERRUPTSBLOCKED
 	RETURN ( self );
     }
-%}
-.
+%}.
     self primitiveFailed
 !
 
@@ -1308,38 +1403,57 @@
 	RETURN ( self );
     }
 #endif
-%}
-.
+%}.
     self primitiveFailed
 !
 
-realRootWindowFor:aView
+realRootWindowId
+    "return the id of the real root window.
+     This may not be the window you see as background,
+     since some window managers install a virtual root window on top
+     of it. Except for very special cases, use #rootWindowId, which takes
+     care of any virtual root."
+
 %{  /* NOCONTEXT */
+
     int screen = _intVal(_INST(screen));
     Window root;
 
-    root = RootWindow(myDpy, screen);
-    if (! root) {
-	RETURN ( nil );
-    }
-    RETURN( MKOBJ(root) );
-%}
-!
-
-rootWindowFor:aView
-    |id|
-%{
+    if (_INST(rootId) != nil) {
+	RETURN (_INST(rootId));
+    }
+
+    if (ISCONNECTED) {
+	root = RootWindow(myDpy, screen);
+	if (! root) {
+	    RETURN ( nil );
+	}
+	_INST(rootId) = MKOBJ(root);
+	RETURN (_INST(rootId));
+    }
+%}.
+    self primitiveFailed
+!
+
+rootWindowId
+    "return the id of the root window.
+     This is the window you see as background, 
+     however, it may or may not be the real physical root window,
+     since some window managers install a virtual root window on top
+     of the real one. If this is the case, that views id is returned here."
+
+%{  /* NOCONTEXT */
     int screen = _intVal(_INST(screen));
-    Window root;
-    OBJ vRoot;
-
-    vRoot = _INST(virtualRootId);
-    if (__isSmallInteger(vRoot)) {
-	root = _WindowVal(vRoot);
-    } else {
+    Window rootWin, vRootWin;
+
+    if (_INST(virtualRootId) != nil) {
+	RETURN (_INST(virtualRootId));
+    }
+
+    if (ISCONNECTED) {
+	vRootWin = rootWin = RootWindow(myDpy, screen);
+#ifndef IRIS
 	BEGIN_INTERRUPTSBLOCKED
-	root = RootWindow(myDpy, screen);
-#ifndef IRIS
 	/*
 	 * on IRIS, this creates a badwindow error - why ?
 	 * children contains a funny window (000034)
@@ -1355,7 +1469,7 @@
 	    Window* children;
 	    unsigned int numChildren;
 
-	    if (XQueryTree(myDpy, root, 
+	    if (XQueryTree(myDpy, rootWin, 
 			   &rootReturn, &parentReturn, 
 			   &children, &numChildren)) {
 		vRootAtom = XInternAtom(myDpy, "__SWM_VROOT", True );
@@ -1373,7 +1487,7 @@
 						     &nitems, &bytesafter,
 						     (unsigned char**) &newRoot
 						   ) == Success && newRoot) {
-				root = *newRoot;
+				vRootWin = *newRoot;
 				break;
 			    }
 			}
@@ -1382,15 +1496,38 @@
 		}
 	    }
 	}
+	END_INTERRUPTSBLOCKED
 #endif
-	END_INTERRUPTSBLOCKED
-    }
-    if (! root) {
-	RETURN ( nil );
-    }
-    id = _INST(virtualRootId) = MKOBJ(root);
+    }
+
+    /* cannot happen */
+    if (! vRootWin) {
+	vRootWin = rootWin;
+	if (! rootWin) {
+	    RETURN ( nil );
+	}
+    }
+    _INST(rootId) = MKOBJ(rootWin);
+    _INST(virtualRootId) = MKOBJ(vRootWin);
+    RETURN ( _INST(virtualRootId) );
 %}
-.
+!
+
+realRootWindowFor:aView
+    "the name of this method is historic;
+     - it will vanish"
+
+    |id|
+
+    id := self realRootWindowId.
+    self addKnownView:aView withId:id.
+    ^ id
+!
+
+rootWindowFor:aView
+    |id|
+
+    id := self rootWindowId.
     self addKnownView:aView withId:id.
     ^ id
 !
@@ -1433,7 +1570,12 @@
     |xpos ypos wwidth wheight minWidth minHeight maxWidth maxHeight 
      bColorId wsuperViewId wcursorId wiconId windowId
      weventMask wiconViewId bitGravity viewGravity vBgColor
-     vBgForm deepForm preferedVisual preferedDepth|
+     vBgForm deepForm preferredVisual preferredDepth|
+
+    displayId isNil ifTrue:[
+	self primitiveFailed.
+	^ nil
+    ].
 
     origin notNil ifTrue:[
 	xpos := origin x.
@@ -1492,8 +1634,8 @@
 
 "/    bitGravity := aView bitGravity.
 "/    viewGravity := aView viewGravity.
-    preferedVisual := aView preferedVisual.
-    preferedDepth := aView preferedDepth.
+    preferredVisual := aView preferredVisual.
+    preferredDepth := aView preferredDepth.
 
 %{  /* STACK:16000 */
     Display *dpy = myDpy;
@@ -1641,6 +1783,7 @@
     /* these may not be disabled */
     xswa.event_mask |= ExposureMask | StructureNotifyMask |
 		       KeyPressMask | KeyReleaseMask |
+		       EnterWindowMask | LeaveWindowMask |
 		       ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
 #endif
 
@@ -1663,26 +1806,26 @@
     }
 
     visual.visualid = CopyFromParent;
-    if (__isSmallInteger(preferedDepth)) {
-	depth = _intVal(preferedDepth);
+    if (__isSmallInteger(preferredDepth)) {
+	depth = _intVal(preferredDepth);
     }
 
     BEGIN_INTERRUPTSBLOCKED
-    if (preferedVisual != nil) {
+    if (preferredVisual != nil) {
 	XVisualInfo vi;
 	int cls;
 
-	if (preferedVisual == @symbol(StaticGray))
+	if (preferredVisual == @symbol(StaticGray))
 	    cls = StaticGray;
-	else if (preferedVisual == @symbol(GrayScale)) 
+	else if (preferredVisual == @symbol(GrayScale)) 
 	    cls = StaticGray;
-	else if (preferedVisual == @symbol(StaticColor)) 
+	else if (preferredVisual == @symbol(StaticColor)) 
 	    cls = StaticColor;
-	else if (preferedVisual == @symbol(PseudoColor)) 
+	else if (preferredVisual == @symbol(PseudoColor)) 
 	    cls = PseudoColor;
-	else if (preferedVisual == @symbol(TrueColor)) 
+	else if (preferredVisual == @symbol(TrueColor)) 
 	    cls = TrueColor;
-	else if (preferedVisual == @symbol(DirectColor)) 
+	else if (preferredVisual == @symbol(DirectColor)) 
 	    cls = DirectColor;
 	else
 	    cls = PseudoColor;
@@ -1811,7 +1954,7 @@
 
 destroyView:aView withId:aWindowId
 %{
-    if (__isSmallInteger(aWindowId)) {
+    if (__isSmallInteger(aWindowId) && ISCONNECTED) {
 	BEGIN_INTERRUPTSBLOCKED
 	XDestroyWindow(myDpy, _WindowVal(aWindowId));
 	END_INTERRUPTSBLOCKED
@@ -1824,7 +1967,7 @@
 destroyGC:aGCId
 
 %{  /* NOCONTEXT */
-    if (__isSmallInteger(aGCId)) {
+    if (__isSmallInteger(aGCId) && ISCONNECTED) {
 	BEGIN_INTERRUPTSBLOCKED
 	XFreeGC(myDpy, _GCVal(aGCId));
 	END_INTERRUPTSBLOCKED
@@ -1840,7 +1983,7 @@
     int screen = _intVal(_INST(screen));
     GC gc;
 
-    if (__isSmallInteger(aDrawableId)) {
+    if (__isSmallInteger(aDrawableId) && ISCONNECTED) {
 	BEGIN_INTERRUPTSBLOCKED
 	gc = XCreateGC(myDpy, (Drawable)_WindowVal(aDrawableId),
 			      0L, (XGCValues *)0);
@@ -1860,7 +2003,7 @@
     DPSContext dps;
     int height;
 
-    if (__bothSmallInteger(aDrawableId, aGCId)) {
+    if (__bothSmallInteger(aDrawableId, aGCId) && ISCONNECTED) {
 	BEGIN_INTERRUPTSBLOCKED
 	dps = XDPSCreateContext(myDpy, (Drawable)_WindowVal(aDrawableId),
 				       _GCVal(aGCId),
@@ -1885,7 +2028,8 @@
     char *rslt;
 
     if ((__isString(name) || __isSymbol(name))
-     && (__isString(cls) || __isSymbol(cls))) {
+     && (__isString(cls) || __isSymbol(cls))
+     && ISCONNECTED) {
 	BEGIN_INTERRUPTSBLOCKED
 	rslt = XGetDefault(myDpy, (char *)_stringVal(cls),
 				  (char *)_stringVal(name));
@@ -1932,6 +2076,7 @@
     unsigned int value;
 
     if (__bothSmallInteger(propertyID, typeID) 
+     && ISCONNECTED
      && (__isString(anObject) 
 	 || __isSmallInteger(anObject) 
 	 || __isSymbol(anObject) 
@@ -2084,7 +2229,7 @@
     Atom selection;
     Window window;
 
-    if (__isSmallInteger(selectionID)) {
+    if (__isSmallInteger(selectionID) && ISCONNECTED) {
 	window = XGetSelectionOwner(dpy, _AtomVal(selectionID));
 	if (window == None) {
 	    RETURN (nil);
@@ -2102,7 +2247,7 @@
 %{  /* NOCONTEXT */
     Display *dpy = myDpy;
 
-    if (__bothSmallInteger(aWindowId, selectionID)) {
+    if (__bothSmallInteger(aWindowId, selectionID) && ISCONNECTED) {
 	XSetSelectionOwner(dpy, _AtomVal(selectionID), _WindowVal(aWindowId), CurrentTime);
 	if (XGetSelectionOwner(dpy, _AtomVal(selectionID)) != _WindowVal(aWindowId)) {
 	    RETURN (false);
@@ -2145,6 +2290,7 @@
     char *cp;
 
     if (_isSmallInteger(aWindowId)
+     && ISCONNECTED
      && __bothSmallInteger(typeID, selectionID)) {
 	if (XGetSelectionOwner(dpy, _AtomVal(selectionID)) == None) {
 	    /*
@@ -2202,14 +2348,16 @@
 %{  /* NOCONTEXT */
     Atom prop;
 
-    if (__isString(aStringOrSymbol)
-     || __isSymbol(aStringOrSymbol)) {
-	prop = XInternAtom(myDpy, _stringVal(aStringOrSymbol), 
-				  (create == true) ? False : True);
-	if (prop == None) {
-	    RETURN (nil);
+    if (ISCONNECTED) {
+	if (__isString(aStringOrSymbol)
+	 || __isSymbol(aStringOrSymbol)) {
+	    prop = XInternAtom(myDpy, _stringVal(aStringOrSymbol), 
+				      (create == true) ? False : True);
+	    if (prop == None) {
+		RETURN (nil);
+	    }
+	    RETURN ( MKOBJ(prop) );
 	}
-	RETURN ( MKOBJ(prop) );
     }
 %}.
     self primitiveFailed.
@@ -2259,6 +2407,7 @@
     Display *dpy = myDpy;
 
     if (__bothSmallInteger(propertyID, requestorID)
+     && ISCONNECTED
      && __bothSmallInteger(targetID, selectionID)) {
 	XEvent ev;
 	int requestor = (int)(_AtomVal(requestorID));
@@ -2681,11 +2830,13 @@
 
     XFontStruct *newFont;
 
-    if (__isString(aFontName) || __isSymbol(aFontName)) {
-	BEGIN_INTERRUPTSBLOCKED
-	newFont = XLoadQueryFont(myDpy, (char *)_stringVal(aFontName));
-	END_INTERRUPTSBLOCKED
-	RETURN ( newFont ? MKOBJ(newFont) : nil );
+    if (ISCONNECTED) {
+	if (__isString(aFontName) || __isSymbol(aFontName)) {
+	    BEGIN_INTERRUPTSBLOCKED
+	    newFont = XLoadQueryFont(myDpy, (char *)_stringVal(aFontName));
+	    END_INTERRUPTSBLOCKED
+	    RETURN ( newFont ? MKOBJ(newFont) : nil );
+	}
     }
 %}
 .
@@ -2706,12 +2857,14 @@
 
     XFontStruct *f;
 
-    if (__isSmallInteger(aFontId)) {
-	f = _FontVal(aFontId);
-	BEGIN_INTERRUPTSBLOCKED
-	XFreeFont(myDpy, f);
-	END_INTERRUPTSBLOCKED
-	RETURN ( self );
+    if (ISCONNECTED) {
+	if (__isSmallInteger(aFontId)) {
+	    f = _FontVal(aFontId);
+	    BEGIN_INTERRUPTSBLOCKED
+	    XFreeFont(myDpy, f);
+	    END_INTERRUPTSBLOCKED
+	    RETURN ( self );
+	}
     }
 %}
 .
@@ -2789,9 +2942,6 @@
     XFontStruct *f;
     char *cp;
     int len, n;
-#ifdef TWOBYTESTRINGS
-    extern OBJ TwoByteString;
-#endif
 
     if (__isSmallInteger(aFontId)) {
 	f = _FontVal(aFontId);
@@ -2804,7 +2954,7 @@
 	    RETURN ( _MKSMALLINT(len) );
 	}
 #ifdef TWOBYTESTRINGS
-	if (__Class(aString) == TwoByteString) {
+	if (__Class(aString) == @global(TwoByteString)) {
 	    n = _byteArraySize(aString) / 2;
 	    cp = (char *) _stringVal(aString);
 	    BEGIN_INTERRUPTSBLOCKED
@@ -2827,9 +2977,6 @@
     XFontStruct *f;
     char *cp;
     int len, n, i1, i2;
-#ifdef TWOBYTESTRINGS
-    extern OBJ TwoByteString;
-#endif
 
     if (__bothSmallInteger(index1, index2)
      && __isSmallInteger(aFontId)) {
@@ -2848,7 +2995,7 @@
 	    }
 	}
 #ifdef TWOBYTESTRINGS
-	if (__Class(aString) == TwoByteString) {
+	if (__Class(aString) == @global(TwoByteString)) {
 	    cp = (char *) _stringVal(aString);
 	    n = _byteArraySize(aString) / 2;
 	    if ((i1 >= 0) && (i2 >= i1) && (i2 < n)) {
@@ -2894,11 +3041,13 @@
 
 %{  /* NOCONTEXT */
 
-    if (__isSmallInteger(aCursorId)) {
-	BEGIN_INTERRUPTSBLOCKED
-	XFreeCursor(myDpy, _CursorVal(aCursorId));
-	END_INTERRUPTSBLOCKED
-	RETURN ( self );
+    if (ISCONNECTED) {
+	if (__isSmallInteger(aCursorId)) {
+	    BEGIN_INTERRUPTSBLOCKED
+	    XFreeCursor(myDpy, _CursorVal(aCursorId));
+	    END_INTERRUPTSBLOCKED
+	    RETURN ( self );
+	}
     }
 %}
 .
@@ -2910,6 +3059,10 @@
 
     |id sourceId maskId|
 
+    displayId isNil ifTrue:[
+	self primitiveFailed.
+	^ nil
+    ].
     sourceId := sourceForm id.
     maskId := maskForm id.
 %{
@@ -2977,6 +3130,10 @@
 
     |number id|
 
+    displayId isNil ifTrue:[
+	self primitiveFailed.
+	^ nil
+    ].
     number := self shapeNumberFromSymbol:aShape.
 %{
     Cursor newCursor;
@@ -3229,6 +3386,7 @@
     "return the current pointer position in root-window coordinates"
 
     |xpos ypos|
+
 %{
     Display *dpy = myDpy;
     Window w;
@@ -3345,7 +3503,7 @@
     unsigned long color;
     int screen = _intVal(_INST(screen));
 
-    if (__isSmallInteger(colorIndex)) {
+    if (__isSmallInteger(colorIndex) && ISCONNECTED) {
 	color = (long) _intVal(colorIndex);
 	BEGIN_INTERRUPTSBLOCKED
 	XFreeColors(dpy, DefaultColormap(dpy, screen), &color, 1, 0L);
@@ -3388,7 +3546,9 @@
     int screen = _intVal(_INST(screen));
     Status ok;
 
-    if (__bothSmallInteger(r, g) && __isSmallInteger(b)) {
+    if (__bothSmallInteger(r, g) 
+     && __isSmallInteger(b)
+     && ISCONNECTED) {
 	ecolor.red = _intVal(r);
 	ecolor.green= _intVal(g);
 	ecolor.blue = _intVal(b);
@@ -3418,19 +3578,21 @@
     int screen =_intVal(_INST(screen));
     Status ok;
 
-    if (__isString(aString) || __isSymbol(aString)) {
-	colorname = (char *)_stringVal(aString);
-
-	BEGIN_INTERRUPTSBLOCKED
-	ok = XParseColor(dpy, DefaultColormap(dpy, screen), colorname, &ecolor);
-	if (ok) {
-	    ok = XAllocColor(dpy, DefaultColormap(dpy, screen), &ecolor);
+    if (ISCONNECTED) {
+	if (__isString(aString) || __isSymbol(aString)) {
+	    colorname = (char *)_stringVal(aString);
+
+	    BEGIN_INTERRUPTSBLOCKED
+	    ok = XParseColor(dpy, DefaultColormap(dpy, screen), colorname, &ecolor);
+	    if (ok) {
+		ok = XAllocColor(dpy, DefaultColormap(dpy, screen), &ecolor);
+	    }
+	    END_INTERRUPTSBLOCKED
+	    if (! ok) {
+		RETURN ( nil );
+	    }
+	    RETURN ( _MKSMALLINT(ecolor.pixel) );
 	}
-	END_INTERRUPTSBLOCKED
-	if (! ok) {
-	    RETURN ( nil );
-	}
-	RETURN ( _MKSMALLINT(ecolor.pixel) );
     }
 %}
 .
@@ -3515,6 +3677,11 @@
      and evaluate the 3-arg block, aBlock with them"
 
     |r g b|
+
+    displayId isNil ifTrue:[
+	self pimitiveFailed.
+	^ nil
+    ].
 %{
     Display *dpy = myDpy;
     int screen = _intVal(_INST(screen));
@@ -4698,9 +4865,6 @@
     unsigned char *cp;
     int n;
     OBJ cls;
-#ifdef TWOBYTESTRINGS
-    extern OBJ TwoByteString;
-#endif
 
     if (__bothSmallInteger(aGCId, aDrawableId)
      && __isNonNilObject(aString)
@@ -4717,7 +4881,7 @@
 	    RETURN ( self );
 	}
 #ifdef TWOBYTESTRINGS
-	if (cls == TwoByteString) {
+	if (cls == @global(TwoByteString)) {
 	    cp = _stringVal(aString);
 	    n = _byteArraySize(aString) / 2;
 	    if (n > 1000) n = 1000;
@@ -4746,9 +4910,6 @@
     unsigned char *cp;
     OBJ cls;
     int  i1, i2, l, n;
-#ifdef TWOBYTESTRINGS
-    extern OBJ TwoByteString;
-#endif
 
     if (__bothSmallInteger(aGCId, aDrawableId)
      && __isNonNilObject(aString)
@@ -4774,7 +4935,7 @@
 	    }
 	}
 #ifdef TWOBYTESTRINGS
-	if (cls == TwoByteString) {
+	if (cls == @global(TwoByteString)) {
 	    i1 = _intVal(index1) - 1;
 	    i2 = _intVal(index2) - 1;
 	    n = _byteArraySize(aString) / 2;
@@ -5380,6 +5541,7 @@
 	/* these may not be disabled */
 	mask |= ExposureMask | StructureNotifyMask |
 		KeyPressMask | KeyReleaseMask |
+		EnterWindowMask | LeaveWindowMask |
 		ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
 #endif
 
@@ -5500,6 +5662,10 @@
     OBJ eB;
     XEvent *ev;
 
+    if (! ISCONNECTED) {
+	RETURN (false);
+    }
+
     eB = _INST(eventBuffer);
     if (__isByteArray(eB)) {
 	ev = (XEvent *)(_ByteArrayInstPtr(eB)->ba_element);
@@ -5561,6 +5727,7 @@
     char keySymStringBuffer[32];
     static unsigned multiClickTime = 0;
     unsigned nextMultiClickTime;
+    OBJ upDown;
 
     struct inlineCache *ipS;
     static struct inlineCache vid = _ILC1;
@@ -5633,12 +5800,14 @@
 	case KeyRelease:
 	    symS = @symbol(keyRelease:x:y:view:);
 	    ipS = &skrS;
+	    upDown = false;
 	    goto keyPressAndRelease;
-	    break;
 
 	case KeyPress:
 	    symS = @symbol(keyPress:x:y:view:);
 	    ipS = &skpS;
+	    upDown = true;
+	    /* FALL INTO */
 
 	keyPressAndRelease:
 	    _INST(eventRootX) = _MKSMALLINT(ke->x_root);
@@ -5646,7 +5815,7 @@
 	    _INST(altDown) = (ke->state & Mod2Mask) ? true : false;
 	    _INST(metaDown) = (ke->state & Mod1Mask) ? true : false;
 	    _INST(shiftDown) = (ke->state & ShiftMask) ? true : false;
-	    _INST(controlDown) = (ke->state & ControlMask) ? true : false;
+	    _INST(ctrlDown) = (ke->state & ControlMask) ? true : false;
 
 	    arg = nil;
 	    nchars = XLookupString(ke, (char *)buffer, sizeof(buffer), &keySym, NULL);
@@ -5656,6 +5825,25 @@
 		arg = _MKCHARACTER(buffer[0])/* *_CharacterTable[buffer[0]] */;
 		keySymString = NULL;
 	    } else {
+		switch (keySym) {
+		    case XK_Control_L:
+		    case XK_Control_R:
+			_INST(ctrlDown) = upDown;
+			break;
+		    case XK_Shift_L:
+		    case XK_Shift_R:
+			_INST(shiftDown) = upDown;
+			break;
+		    case XK_Meta_L:
+		    case XK_Meta_R:
+			_INST(metaDown) = upDown;
+			break;
+		    case XK_Alt_L:
+		    case XK_Alt_R:
+			_INST(altDown) = upDown;
+			break;
+		}
+
 		keySymString = XKeysymToString(keySym);
 		if (keySymString) {
 		    if (keySymString[0] == 'D') {
@@ -5765,6 +5953,11 @@
 	    _INST(eventRootX) = _MKSMALLINT(me->x_root);
 	    _INST(eventRootY) = _MKSMALLINT(me->y_root);
 
+	    _INST(altDown) = (me->state & Mod2Mask) ? true : false;
+	    _INST(metaDown) = (me->state & Mod1Mask) ? true : false;
+	    _INST(shiftDown) = (me->state & ShiftMask) ? true : false;
+	    _INST(ctrlDown) = (me->state & ControlMask) ? true : false;
+
 	    (*motS.ilc_func)(self, 
 			     @symbol(buttonMotion:x:y:view:)
 			     COMMA_CON, nil, &motS,
@@ -5789,6 +5982,11 @@
 	    break;
 
 	case EnterNotify:
+	    _INST(altDown) = (ewe->state & Mod2Mask) ? true : false;
+	    _INST(metaDown) = (ewe->state & Mod1Mask) ? true : false;
+	    _INST(shiftDown) = (ewe->state & ShiftMask) ? true : false;
+	    _INST(ctrlDown) = (ewe->state & ControlMask) ? true : false;
+
 	    (*peS.ilc_func)(self, 
 			    @symbol(pointerEnter:x:y:view:)
 			    COMMA_CON, nil, &peS,
@@ -6067,8 +6265,13 @@
 
     Display *dpy = myDpy;
 
-    XSync(dpy, 0);      /* make certain everything is flushed */
-    RETURN ( (XPending(dpy)) ? true : false );
+    if (ISCONNECTED) {
+	XSync(dpy, 0);      /* make certain everything is flushed */
+	if (XPending(dpy)) {
+	    RETURN (true);
+	}
+    }
+    RETURN ( false );
 %}
 !
 
@@ -6077,7 +6280,12 @@
 
 %{  /* UNLIMITEDSTACK */
 
-    RETURN ( (XPending(myDpy)) ? true : false );
+    if (ISCONNECTED) {
+	if (XPending(myDpy)) {
+	    RETURN (true);
+	}
+    }
+    RETURN ( false );
 %}
 !
 
@@ -6091,16 +6299,18 @@
     Window win;
     int thereIsOne;
 
-    XSync(dpy, 0);      /* make certain everything is flushed */
-    if (__isSmallInteger(aWindowIdOrNil)) {
-	win = _WindowVal(aWindowIdOrNil);
-	thereIsOne = XCheckWindowEvent(dpy, win, ExposureMask, &ev);
-    } else {
-	thereIsOne = XCheckMaskEvent(dpy, ExposureMask, &ev);
-    }
-    if (thereIsOne) {
-	XPutBackEvent(dpy, &ev);
-	RETURN ( true );
+    if (ISCONNECTED) {
+	XSync(dpy, 0);      /* make certain everything is flushed */
+	if (__isSmallInteger(aWindowIdOrNil)) {
+	    win = _WindowVal(aWindowIdOrNil);
+	    thereIsOne = XCheckWindowEvent(dpy, win, ExposureMask, &ev);
+	} else {
+	    thereIsOne = XCheckMaskEvent(dpy, ExposureMask, &ev);
+	}
+	if (thereIsOne) {
+	    XPutBackEvent(dpy, &ev);
+	    RETURN ( true );
+	}
     }
     RETURN ( false );
 %}
@@ -6116,7 +6326,7 @@
     Window win;
     int thereIsOne;
 
-    if (__isSmallInteger(anEventMask)) {
+    if (ISCONNECTED && __isSmallInteger(anEventMask)) {
 	XSync(dpy, 0);      /* make certain everything is flushed */
 	if (__isSmallInteger(aWindowIdOrNil)) {
 	    win = _WindowVal(aWindowIdOrNil);