XWorkstation.st
changeset 5033 27bc058343f0
parent 4928 4e457b74f5d2
child 5034 c2e7d8a07da8
--- a/XWorkstation.st	Wed Sep 03 10:39:40 2008 +0200
+++ b/XWorkstation.st	Fri Sep 12 20:42:11 2008 +0200
@@ -2808,125 +2808,128 @@
 
     (msgType := self atomIDOf:#DndProtocol) notNil ifTrue:[
 
-	"/ DND can drop files, file, dir, links, dirLink and text
-	"/ check for this.
-
-	dropObjects isCollection ifFalse:[
-	    dropColl := Array with:dropObjects
-	] ifTrue:[
-	    dropColl := dropObjects
-	].
-	anyFile := anyDir := anyText := anyOther := false.
-	dropColl do:[:aDropObject |
-	    aDropObject isFileObject ifTrue:[
-		aDropObject theObject isDirectory ifTrue:[
-		    anyDir := true
-		] ifFalse:[
-		    anyFile := true
-		]
-	    ] ifFalse:[
-		aDropObject isTextObject ifTrue:[
-		    anyText := true
-		] ifFalse:[
-		    anyOther := true
-		]
-	    ]
-	].
-
-	anyOther ifTrue:[
-	    "/ DND does not support this ...
-	    'XWorkstation [info]: DND can only drop files or text' infoPrintCR.
-	    ^ false
-	].
-	anyText ifTrue:[
-	    (anyFile or:[anyDir]) ifTrue:[
-		"/ DND does not support mixed types
-		'XWorkstation [info]: DND cannot drop both files and text' infoPrintCR.
-		^ false
-	    ]
-	].
-
-	dropCollSize := dropColl size.
-	anyFile ifTrue:[
-	    dropType := #DndFiles.
-	    dropCollSize == 1 ifTrue:[
-		dropType := #DndFile
-	    ]
-	] ifFalse:[
-	    anyDir ifTrue:[
-		dropType := #DndFiles.
-		dropCollSize == 1 ifTrue:[
-		    dropType := #DndDir
-		]
-	    ] ifFalse:[
-		anyText ifTrue:[
-		    dropCollSize == 1 ifTrue:[
-			dropType := #DndText
-		    ] ifFalse:[
-			"/ can only drop a single text object
-			'XWorkstation [info]: DND can only drop a single text' infoPrintCR.
-			^ false
-		    ]
-		] ifFalse:[
-		    "/ mhmh ...
-		    'XWorkstation [info]: DND cannot drop this' infoPrintCR.
-		    ^ false
-		]
-	    ]
-	].
-
-	dropTypeCode := self dndDropTypes indexOf:dropType.
-	dropTypeCode == 0 ifTrue:[
-	    'XWorkstation [info]: DND cannot drop this' infoPrintCR.
-	    ^ false
-	].
-	dropTypeCode := dropTypeCode - 1.
-
-
-	"/ place the selection inTo the DndSelection property
-	"/ of the rootView ...
-	"/ ... need a single string, with 0-terminated parts.
-
-	strings := OrderedCollection new.
-	sz := 0.
-	dropColl do:[:anObject |
-	    |s o|
-
-	    o := anObject theObject.
-	    anObject isFileObject ifTrue:[
-		o := o pathName
-	    ].
-	    s := o asString.
-	    strings add:s.
-	    sz := sz + (s size) + 1.
-	].
-	val := String new:sz.
-	idx := 1.
-	strings do:[:aString |
-	    |sz|
-
-	    sz := aString size.
-	    val replaceFrom:idx to:(idx + sz - 1) with:aString startingAt:1.
-	    idx := idx + sz.
-	    val at:idx put:(Character value:0).
-	    idx := idx + 1
-	].
-
-	self
-	    setProperty:(self atomIDOf:#DndSelection)
-	    type:(self atomIDOf:#STRING)
-	    value:val
-	    for:rootId.
-
-	^ self
-	    sendClientEvent:msgType
-	    format:32
-	    to:destinationId
-	    data1:dropTypeCode
-	    data2:0
-	    data3:destinationId
-	    data4:nil
-	    data5:nil.
+        "/ DND can drop files, file, dir, links, dirLink and text
+        "/ check for this.
+
+        dropObjects isCollection ifFalse:[
+            dropColl := Array with:dropObjects
+        ] ifTrue:[
+            dropColl := dropObjects
+        ].
+        anyFile := anyDir := anyText := anyOther := false.
+        dropColl do:[:aDropObject |
+            aDropObject isFileObject ifTrue:[
+                aDropObject theObject isDirectory ifTrue:[
+                    anyDir := true
+                ] ifFalse:[
+                    anyFile := true
+                ]
+            ] ifFalse:[
+                aDropObject isTextObject ifTrue:[
+                    anyText := true
+                ] ifFalse:[
+                    anyOther := true
+                ]
+            ]
+        ].
+
+        anyOther ifTrue:[
+            "/ DND does not support this ...
+            'XWorkstation [info]: DND can only drop files or text' infoPrintCR.
+            ^ false
+        ].
+        anyText ifTrue:[
+            (anyFile or:[anyDir]) ifTrue:[
+                "/ DND does not support mixed types
+                'XWorkstation [info]: DND cannot drop both files and text' infoPrintCR.
+                ^ false
+            ]
+        ].
+
+        dropCollSize := dropColl size.
+        anyFile ifTrue:[
+            dropType := #DndFiles.
+            dropCollSize == 1 ifTrue:[
+                dropType := #DndFile
+            ]
+        ] ifFalse:[
+            anyDir ifTrue:[
+                dropType := #DndFiles.
+                dropCollSize == 1 ifTrue:[
+                    dropType := #DndDir
+                ]
+            ] ifFalse:[
+                anyText ifTrue:[
+                    dropCollSize == 1 ifTrue:[
+                        dropType := #DndText
+                    ] ifFalse:[
+                        "/ can only drop a single text object
+                        'XWorkstation [info]: DND can only drop a single text' infoPrintCR.
+                        ^ false
+                    ]
+                ] ifFalse:[
+                    "/ mhmh ...
+                    'XWorkstation [info]: DND cannot drop this' infoPrintCR.
+                    ^ false
+                ]
+            ]
+        ].
+
+        dropTypeCode := self dndDropTypes indexOf:dropType.
+        dropTypeCode == 0 ifTrue:[
+            'XWorkstation [info]: DND cannot drop this' infoPrintCR.
+            ^ false
+        ].
+        dropTypeCode := dropTypeCode - 1.
+
+
+        "/ place the selection inTo the DndSelection property
+        "/ of the rootView ...
+        "/ ... need a single string, with 0-terminated parts.
+
+        strings := OrderedCollection new.
+        sz := 0.
+        dropColl do:[:anObject |
+            |s o|
+
+            o := anObject theObject.
+            anObject isFileObject ifTrue:[
+                o := o pathName
+            ].
+            s := o asString.
+            strings add:s.
+            sz := sz + (s size) + 1.
+        ].
+        val := String new:sz.
+        idx := 1.
+        strings do:[:aString |
+            |sz|
+
+            sz := aString size.
+            val replaceFrom:idx to:(idx + sz - 1) with:aString startingAt:1.
+            idx := idx + sz.
+            val at:idx put:(Character value:0).
+            idx := idx + 1
+        ].
+
+        self
+            setProperty:(self atomIDOf:#DndSelection)
+            type:(self atomIDOf:#STRING)
+            value:val
+            for:rootId.
+
+        ^ self
+            sendClientEvent:msgType
+            format:32
+            to:destinationId
+            propagate:true
+            eventMask:nil
+            window:destinationId
+            data1:dropTypeCode
+            data2:0
+            data3:destinationId
+            data4:nil
+            data5:nil.
     ].
 
     ^ false
@@ -5021,6 +5024,8 @@
     else if (anEventSymbol == @symbol(resizeRedirect)) m = ResizeRedirectMask;
     else if (anEventSymbol == @symbol(propertyChange)) m = PropertyChangeMask;
     else if (anEventSymbol == @symbol(colormapChange)) m = ColormapChangeMask;
+    else if (anEventSymbol == @symbol(substructureNotify)) m = SubstructureNotifyMask;
+    else if (anEventSymbol == @symbol(substructureRedirect)) m = SubstructureRedirectMask;
     RETURN (__MKSMALLINT(m));
 %}
 !
@@ -5752,7 +5757,7 @@
 
 !XWorkstation methodsFor:'event sending'!
 
-sendClientEvent:msgType format:msgFormat to:targetWindowID data1:d1 data2:d2 data3:d3 data4:d4 data5:d5
+sendClientEvent:msgType format:msgFormat to:targetWindowID propagate:propagate eventMask:eventMask window:windowID data1:d1 data2:d2 data3:d3 data4:d4 data5:d5
     "send a ClientMessage to some other (possibly: non-ST/X) view.
      The client message gets message_type and msgFormat as specified by
      the arguments. The additional data arguments specify up to
@@ -5764,94 +5769,110 @@
     "/ Event.xclient.display           = dpy;
     "/ Event.xclient.message_type      = msgType;
     "/ Event.xclient.format            = msgFormat;
-    "/ Event.xclient.window            = targetWindowID;
+    "/ Event.xclient.window            = windowID;
     "/ Event.xclient.data.l[0]         = d1
     "/ Event.xclient.data.l[1]         = d2
     "/ Event.xclient.data.l[2]         = d3
     "/ Event.xclient.data.l[3]         = d4
     "/ Event.xclient.data.l[4]         = d5
     "/
-    "/ XSendEvent(dpy,DispatchWindow,True,NoEventMask,&Event);
+    "/ XSendEvent(dpy, targetWindowID, propagate, eventMask, &Event);
 
     <context: #return>
 %{
     int type;
     int state;
+    int __eventMask;
 
     if (ISCONNECTED
      && __isInteger(msgType)
      && __isInteger(msgFormat)
+     && (eventMask == nil || __isInteger(eventMask))
+     && (__isExternalAddress(windowID) || __isInteger(windowID))
      && (__isExternalAddress(targetWindowID) || __isInteger(targetWindowID))) {
-	Display *dpy = myDpy;
-	XEvent ev;
-	Status result;
-
-	if (__isInteger(d1)) {
-	    ev.xclient.data.l[0] = __longIntVal(d1);
-	} else {
-	    if (__isExternalAddress(d1)) {
-		ev.xclient.data.l[0] = (INT)__externalAddressVal(d1);
-	    } else {
-		ev.xclient.data.l[0] = 0;
-	    }
-	}
-	if (__isInteger(d2)) {
-	    ev.xclient.data.l[1] = __longIntVal(d2);
-	} else {
-	    if (__isExternalAddress(d2)) {
-		ev.xclient.data.l[1] = (INT)__externalAddressVal(d2);
-	    } else {
-		ev.xclient.data.l[1] = 0;
-	    }
-	}
-	if (__isInteger(d3)) {
-	    ev.xclient.data.l[2] = __longIntVal(d3);
-	} else {
-	    if (__isExternalAddress(d3)) {
-		ev.xclient.data.l[2] = (INT)__externalAddressVal(d3);
-	    } else {
-		ev.xclient.data.l[2] = 0;
-	    }
-	}
-	if (__isInteger(d4)) {
-	    ev.xclient.data.l[3] = __longIntVal(d4);
-	} else {
-	    if (__isExternalAddress(d4)) {
-		ev.xclient.data.l[3] = (INT)__externalAddressVal(d4);
-	    } else {
-		ev.xclient.data.l[3] = 0;
-	    }
-	}
-	if (__isInteger(d5)) {
-	    ev.xclient.data.l[4] = __longIntVal(d5);
-	} else {
-	    if (__isExternalAddress(d5)) {
-		ev.xclient.data.l[4] = (INT)__externalAddressVal(d5);
-	    } else {
-		ev.xclient.data.l[4] = 0;
-	    }
-	}
-
-	if (__isExternalAddress(targetWindowID)) {
-	    ev.xclient.window = __WindowVal(targetWindowID);
-	} else {
-	    ev.xclient.window = (Window)__longIntVal(targetWindowID);
-	}
-
-	ev.xclient.type              = ClientMessage;
-	ev.xclient.display           = dpy;
-	ev.xclient.message_type      = __longIntVal(msgType);
-	ev.xclient.format            = __longIntVal(msgFormat);
-
-	ENTER_XLIB();
-	result = XSendEvent(dpy, ev.xclient.window, True, NoEventMask , &ev);
-	LEAVE_XLIB();
-
-	if ((result == BadValue) || (result == BadWindow)) {
-	    DPRINTF(("bad status in sendClientEvent\n"));
-	    RETURN ( false )
-	}
-	RETURN (true)
+        Display *dpy = myDpy;
+        XEvent ev;
+        Status result;
+        Window targetWindow;
+
+        if (__isInteger(d1)) {
+            ev.xclient.data.l[0] = __longIntVal(d1);
+        } else {
+            if (__isExternalAddress(d1)) {
+                ev.xclient.data.l[0] = (INT)__externalAddressVal(d1);
+            } else {
+                ev.xclient.data.l[0] = 0;
+            }
+        }
+        if (__isInteger(d2)) {
+            ev.xclient.data.l[1] = __longIntVal(d2);
+        } else {
+            if (__isExternalAddress(d2)) {
+                ev.xclient.data.l[1] = (INT)__externalAddressVal(d2);
+            } else {
+                ev.xclient.data.l[1] = 0;
+            }
+        }
+        if (__isInteger(d3)) {
+            ev.xclient.data.l[2] = __longIntVal(d3);
+        } else {
+            if (__isExternalAddress(d3)) {
+                ev.xclient.data.l[2] = (INT)__externalAddressVal(d3);
+            } else {
+                ev.xclient.data.l[2] = 0;
+            }
+        }
+        if (__isInteger(d4)) {
+            ev.xclient.data.l[3] = __longIntVal(d4);
+        } else {
+            if (__isExternalAddress(d4)) {
+                ev.xclient.data.l[3] = (INT)__externalAddressVal(d4);
+            } else {
+                ev.xclient.data.l[3] = 0;
+            }
+        }
+        if (__isInteger(d5)) {
+            ev.xclient.data.l[4] = __longIntVal(d5);
+        } else {
+            if (__isExternalAddress(d5)) {
+                ev.xclient.data.l[4] = (INT)__externalAddressVal(d5);
+            } else {
+                ev.xclient.data.l[4] = 0;
+            }
+        }
+
+        if (__isExternalAddress(windowID)) {
+            ev.xclient.window = __WindowVal(windowID);
+        } else {
+            ev.xclient.window = (Window)__longIntVal(windowID);
+        }
+
+        if (__isExternalAddress(targetWindowID)) {
+            targetWindow = __WindowVal(targetWindowID);
+        } else {
+            targetWindow = (Window)__longIntVal(targetWindowID);
+        }
+
+        ev.xclient.type              = ClientMessage;
+        ev.xclient.display           = dpy;
+        ev.xclient.message_type      = __longIntVal(msgType);
+        ev.xclient.format            = __longIntVal(msgFormat);
+
+        if (eventMask == nil) {
+            __eventMask = NoEventMask;
+        } else {
+            __eventMask = __longIntVal(eventMask);
+        }
+
+        ENTER_XLIB();
+        result = XSendEvent(dpy, targetWindow, (propagate == true ? True : False), __eventMask , &ev);
+        LEAVE_XLIB();
+
+        if ((result == BadValue) || (result == BadWindow)) {
+            DPRINTF(("bad status in sendClientEvent\n"));
+            RETURN ( false )
+        }
+        RETURN (true)
     }
 %}.
     self primitiveFailedOrClosedConnection.
@@ -9534,7 +9555,7 @@
 !XWorkstation methodsFor:'resources'!
 
 atomIDOf:aStringOrSymbol
-    "return an X11 atoms ID; dont create if not already present.
+    "return an X11 atoms ID.
      This is highly X specific and only for local use (with selections).
      The default is to create the atom, if it does not exist, in order to
      speed up future lookups"
@@ -11196,6 +11217,31 @@
     self primitiveFailedOrClosedConnection
 !
 
+setForegroundWindow:aWindowId
+    "bring a window to front.
+     Send a specific message to the WindowManager"
+
+    |activeWindowAtom|
+
+    self raiseWindow:aWindowId.
+
+    activeWindowAtom := self atomIDOf:#'_NET_ACTIVE_WINDOW'.
+    activeWindowAtom notNil ifTrue:[
+        self
+            sendClientEvent:activeWindowAtom
+            format:32
+            to:(self rootWindowId)
+            propagate:false
+            eventMask:((self eventMaskFor:#substructureNotify) bitOr:(self eventMaskFor:#substructureRedirect))
+            window:aWindowId
+            data1:2                 "activate request from pager. This is a trick: kwm ignores requests from applications (1)"
+            data2:nil
+            data3:nil
+            data4:nil
+            data5:nil.
+    ].
+!
+
 setIconName:aString in:aWindowId
     "define a windows iconname"
 
@@ -11927,7 +11973,7 @@
 !XWorkstation class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.496 2008-03-15 17:17:21 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.497 2008-09-12 18:42:11 stefan Exp $'
 ! !
 
 XWorkstation initialize!