--- a/XWorkstation.st Thu Aug 28 17:14:38 2014 +0200
+++ b/XWorkstation.st Sat Sep 20 15:30:53 2014 +0200
@@ -27,7 +27,7 @@
selectionFetchers selectionHandlers preWaitAction xlibTimeout
xlibTimeoutForWindowCreation hasConnectionBroken uniqueDeviceID
stxDeviceAtom uuidAtom primaryBuffer windowGroupWindow
- maxOperationsUntilFlush operationsUntilFlush'
+ maxOperationsUntilFlush operationsUntilFlush lastError'
classVariableNames:'RawKeySymTranslation ConservativeSync MaxStringLength
DefaultXLibTimeout DefaultXLibTimeoutForWindowCreation
ErrorDBCache'
@@ -564,6 +564,9 @@
!XWorkstation class methodsFor:'initialization'!
initialize
+ "/ ConservativeSync is required for some Xlib implementation,
+ "/ where eventPending returns wrong if we do not flush the buffer.
+ "/ (especially Win32 & Xlib)
ConservativeSync := OperatingSystem isMSWINDOWSlike.
"/ some XServers crash, when given too long strings in XDrawString/XDrawInageString.
@@ -4998,10 +5001,6 @@
"forward an expose event for some view"
self exposeX:x y:y width:w height:h view:view.
-
-
-
-
!
focusIn:view mode:mode detail:detail
@@ -5026,10 +5025,6 @@
"forward a graphics-expose event for some view"
self graphicsExposeX:x y:y width:w height:h final:(count==0) view:view
-
-
-
-
!
keyPress:view key:key code:keyCode state:state x:x y:y rootX:rX rootY:rY time:time
@@ -5053,6 +5048,7 @@
"very low-level mapping of X11 event symbols to common ST/X event symbols"
commonKey := rawKeySymTranslation at:key ifAbsent:key.
+view errorPrint. ' key:' errorPrint. commonKey errorPrintCR.
self keyPress:commonKey x:x y:y view:view.
!
@@ -5352,6 +5348,10 @@
!
dispatchEvent:evArray
+ "a raw event array as coming from the low level C code is converted
+ to a message send here.
+ Also, the windowID from the event array is mapped to a view object."
+
|viewId view evType arguments|
viewId := evArray at:1.
@@ -5372,9 +5372,10 @@
self perform:evType withArguments:arguments.
^ true.
].
-'********** unhandled event:' errorPrintCR.
-evType errorPrintCR. (evArray at:2) errorPrintCR.
-'********** see dispatchEvent' errorPrintCR.
+
+ '********** unhandled event:' errorPrintCR.
+ evType errorPrintCR. (evArray at:2) errorPrintCR.
+ '********** see dispatchEvent' errorPrintCR.
^ false
!
@@ -5681,14 +5682,14 @@
!
getEventFor:aViewIdOrNil withMask:eventMask into:anEventArray
- "read next event if there is one and put events data into anEventArray.
+ "read next event if there is one and put event's data into anEventArray.
If aViewIdOrNil is nil, events for any view are fetched;
otherwise only events for that specific view will be fetched.
Returns true, if there was an event, false otherwise.
This method may block - so you better check for pending events
before calling for it.
- The event fields are placed them into anEventArray (must be at least size 13):
+ The event fields are placed into anEventArray (must be at least size 13):
the fields are:
1: windowID
2: eventType-ID
@@ -6421,107 +6422,112 @@
int state;
if (__isSmallInteger(stateMask)) {
- state = __intVal(stateMask);
+ state = __intVal(stateMask);
} else {
- state = 0;
+ state = 0;
}
if (ISCONNECTED
&& __isSmallInteger(xPos) && __isSmallInteger(yPos)
&& (__isSmallInteger(keySymCodeOrButtonNr) || __isStringLike(keySymCodeOrButtonNr))
&& (__isExternalAddress(targetId) || __isInteger(targetId))) {
- Display *dpy = myDpy;
-
- XEvent ev;
- Window target;
- Status result;
- KeySym keySym, *syms;
- int screen = __intVal(__INST(screen));
- char s[2];
- int nSyms;
-
- if ((typeSymbol == @symbol(keyPress))
- || (typeSymbol == @symbol(keyRelease))) {
- if (__isStringLike(keySymCodeOrButtonNr)) {
- keySym = XStringToKeysym(__stringVal(keySymCodeOrButtonNr));
- } else {
- if (__isCharacter(keySymCodeOrButtonNr)) {
- s[0] = __intVal(__characterVal(keySymCodeOrButtonNr));
- s[1] = '\0';
- keySym = XStringToKeysym(s);
- } else {
- keySym = (KeySym) __intVal(keySymCodeOrButtonNr);
- }
- }
- ev.xkey.keycode = XKeysymToKeycode(dpy, keySym);
-
- if (stateMask == nil) {
- /*
- * get the modifier from the keySym
- */
- nSyms = 0;
- syms = XGetKeyboardMapping(dpy, ev.xkey.keycode, 1, &nSyms);
- if (syms) {
- int i;
-
- for (i=0; i<nSyms; i++) {
- if (syms[i] == keySym) {
+ Display *dpy = myDpy;
+
+ XEvent ev;
+ Window target;
+ Status result;
+ KeySym keySym, *syms;
+ int screen = __intVal(__INST(screen));
+ int nSyms;
+
+ if ((typeSymbol == @symbol(keyPress))
+ || (typeSymbol == @symbol(keyRelease))) {
+ if (__isStringLike(keySymCodeOrButtonNr)) {
+ keySym = XStringToKeysym(__stringVal(keySymCodeOrButtonNr));
+ } else {
+ if (__isCharacter(keySymCodeOrButtonNr)) {
+ char s[2];
+ s[0] = __intVal(__characterVal(keySymCodeOrButtonNr));
+ s[1] = '\0';
+ keySym = XStringToKeysym(s);
+ } else {
+ if (__isSmallInteger(keySymCodeOrButtonNr)) {
+ keySym = (KeySym) __intVal(keySymCodeOrButtonNr);
+ } else {
+ goto notOk;
+ }
+ }
+ }
+ ev.xkey.keycode = XKeysymToKeycode(dpy, keySym);
+
+ if (stateMask == nil) {
+ /*
+ * get the modifier from the keySym
+ */
+ nSyms = 0;
+ syms = XGetKeyboardMapping(dpy, ev.xkey.keycode, 1, &nSyms);
+ if (syms) {
+ int i;
+
+ for (i=0; i<nSyms; i++) {
+ if (syms[i] == keySym) {
#ifdef MODIFIERDEBUG
- console_printf("modifier-index is %d\n", i);
-#endif
- if (i) state = (1 << (i-1));
- break;
- }
- }
- XFree(syms);
- }
- }
- } else {
- if ((typeSymbol == @symbol(buttonPress))
- || (typeSymbol == @symbol(buttonRelease))) {
- if (__isSmallInteger(keySymCodeOrButtonNr)) {
- ev.xbutton.button = __intVal(keySymCodeOrButtonNr);
- } else {
- ev.xbutton.button = 1;
- }
- } else {
- DPRINTF(("invalid sendEvent typeSymbol\n"));
- RETURN (false);
- }
- }
-
- if (typeSymbol == @symbol(keyPress))
- ev.xany.type = KeyPress;
- else if (typeSymbol == @symbol(keyRelease))
- ev.xany.type = KeyRelease;
- else if (typeSymbol == @symbol(buttonPress))
- ev.xany.type = ButtonPress;
- else if (typeSymbol == @symbol(buttonRelease))
- ev.xany.type = ButtonRelease;
-
- if (__isExternalAddress(targetId)) {
- target = __WindowVal(targetId);
- } else {
- target = (Window) __longIntVal(targetId);
- }
- ev.xkey.window = target;
- ev.xkey.same_screen = 1;
- ev.xkey.subwindow = 0;
- ev.xkey.root = RootWindow(dpy, screen);
- ev.xkey.x = __intVal(xPos);
- ev.xkey.y = __intVal(yPos);
- ev.xkey.state = state;
- ev.xkey.time = CurrentTime;
-
- ENTER_XLIB();
- result = XSendEvent(dpy, target, False, 0 , &ev);
- LEAVE_XLIB();
- if ((result == BadValue) || (result == BadWindow)) {
- DPRINTF(("bad status\n"));
- RETURN ( false )
- }
- RETURN (true)
- }
+ console_printf("modifier-index is %d\n", i);
+#endif
+ if (i) state = (1 << (i-1));
+ break;
+ }
+ }
+ XFree(syms);
+ }
+ }
+ } else {
+ if ((typeSymbol == @symbol(buttonPress))
+ || (typeSymbol == @symbol(buttonRelease))) {
+ if (__isSmallInteger(keySymCodeOrButtonNr)) {
+ ev.xbutton.button = __intVal(keySymCodeOrButtonNr);
+ } else {
+ ev.xbutton.button = 1;
+ }
+ } else {
+ DPRINTF(("invalid sendEvent typeSymbol\n"));
+ RETURN (false);
+ }
+ }
+
+ if (typeSymbol == @symbol(keyPress))
+ ev.xany.type = KeyPress;
+ else if (typeSymbol == @symbol(keyRelease))
+ ev.xany.type = KeyRelease;
+ else if (typeSymbol == @symbol(buttonPress))
+ ev.xany.type = ButtonPress;
+ else if (typeSymbol == @symbol(buttonRelease))
+ ev.xany.type = ButtonRelease;
+
+ if (__isExternalAddress(targetId)) {
+ target = __WindowVal(targetId);
+ } else {
+ target = (Window) __longIntVal(targetId);
+ }
+ ev.xkey.window = target;
+ ev.xkey.same_screen = 1;
+ ev.xkey.subwindow = 0;
+ ev.xkey.root = RootWindow(dpy, screen);
+ ev.xkey.x = __intVal(xPos);
+ ev.xkey.y = __intVal(yPos);
+ ev.xkey.state = state;
+ ev.xkey.time = CurrentTime;
+
+ ENTER_XLIB();
+ result = XSendEvent(dpy, target, False, 0 , &ev);
+ LEAVE_XLIB();
+ if ((result == BadValue) || (result == BadWindow)) {
+ DPRINTF(("bad status\n"));
+ RETURN ( false )
+ }
+ RETURN (true)
+ }
+ notOk: ;
%}.
self primitiveFailedOrClosedConnection.
^ false
@@ -6535,63 +6541,63 @@
v selectFromCharacterPosition:1 to:5.
"/ CTRL-c
- v device
- sendKeyOrButtonEvent:#keyPress
- x:10 y:10
- keyOrButton:#'Control'
- state:(v device ctrlModifierMask)
- toViewId: v id.
-
- v device
- sendKeyOrButtonEvent:#keyPress
- x:10 y:10
- keyOrButton:'c'
- state:(v device ctrlModifierMask)
- toViewId: v id.
-
- v device
- sendKeyOrButtonEvent:#keyRelease
- x:10 y:10
- keyOrButton:'c'
- state:(v device ctrlModifierMask)
- toViewId: v id.
-
- v device
- sendKeyOrButtonEvent:#keyRelease
- x:10 y:10
- keyOrButton:#'Control'
- state:0
- toViewId: v id.
+ v device
+ sendKeyOrButtonEvent:#keyPress
+ x:10 y:10
+ keyOrButton:#'Control'
+ state:(v device ctrlModifierMask)
+ toViewId: v id.
+
+ v device
+ sendKeyOrButtonEvent:#keyPress
+ x:10 y:10
+ keyOrButton:'c'
+ state:(v device ctrlModifierMask)
+ toViewId: v id.
+
+ v device
+ sendKeyOrButtonEvent:#keyRelease
+ x:10 y:10
+ keyOrButton:'c'
+ state:(v device ctrlModifierMask)
+ toViewId: v id.
+
+ v device
+ sendKeyOrButtonEvent:#keyRelease
+ x:10 y:10
+ keyOrButton:#'Control'
+ state:0
+ toViewId: v id.
"/ CTRL-v
- v device
- sendKeyOrButtonEvent:#keyPress
- x:10 y:10
- keyOrButton:#'Control'
- state:(v device ctrlModifierMask)
- toViewId: v id.
-
- v device
- sendKeyOrButtonEvent:#keyPress
- x:10 y:10
- keyOrButton:'v'
- state:(v device ctrlModifierMask)
- toViewId: v id.
-
- v device
- sendKeyOrButtonEvent:#keyRelease
- x:10 y:10
- keyOrButton:'v'
- state:(v device ctrlModifierMask)
- toViewId: v id.
-
- v device
- sendKeyOrButtonEvent:#keyRelease
- x:10 y:10
- keyOrButton:#'Control'
- state:0
- toViewId: v id.
+ v device
+ sendKeyOrButtonEvent:#keyPress
+ x:10 y:10
+ keyOrButton:#'Control'
+ state:(v device ctrlModifierMask)
+ toViewId: v id.
+
+ v device
+ sendKeyOrButtonEvent:#keyPress
+ x:10 y:10
+ keyOrButton:'v'
+ state:(v device ctrlModifierMask)
+ toViewId: v id.
+
+ v device
+ sendKeyOrButtonEvent:#keyRelease
+ x:10 y:10
+ keyOrButton:'v'
+ state:(v device ctrlModifierMask)
+ toViewId: v id.
+
+ v device
+ sendKeyOrButtonEvent:#keyRelease
+ x:10 y:10
+ keyOrButton:#'Control'
+ state:0
+ toViewId: v id.
END"
! !
@@ -7548,23 +7554,23 @@
|names|
listOfXFonts isNil ifTrue:[
- names := self getAvailableFontsMatching:'*'.
- names isNil ifTrue:[
- "no names returned ..."
- ^ nil
- ].
- listOfXFonts := names collect:[:aName | self fontDescriptionFromXFontName:aName].
- listOfXFonts := FontDescription genericFonts, listOfXFonts.
+ names := self getAvailableFontsMatching:'*'.
+ names isNil ifTrue:[
+ "no names returned ..."
+ ^ nil
+ ].
+ listOfXFonts := names collect:[:aName | self fontDescriptionFromXFontName:aName].
+ listOfXFonts := FontDescription genericFonts, listOfXFonts.
].
(XftFontDescription notNil
- and:[ XftFontDescription isLoaded
- and:[ self supportsXFTFonts ]]
+ and:[ XftFontDescription isLoaded
+ and:[ self supportsXFTFonts ]]
) ifTrue:[
- UserPreferences current useXftFontsOnly ifTrue:[
- ^ (XftFontDescription listOfAvailableFonts)
- ].
- ^ listOfXFonts , (XftFontDescription listOfAvailableFonts).
+ UserPreferences current useXftFontsOnly ifTrue:[
+ ^ (XftFontDescription listOfAvailableFonts)
+ ].
+ ^ listOfXFonts , (XftFontDescription listOfAvailableFonts).
].
^ listOfXFonts
@@ -7860,6 +7866,196 @@
^ 0
! !
+!XWorkstation methodsFor:'grabbing-keys'!
+
+grabKey:keySymCodeOrChar modifier:modifierMaskOrNil window:aWindowIdOrNil
+ "grab a single key either for an individual window
+ or the whole screen (if aWindowIdOrNil is nil).
+ The keySymCodeOrChar argument may be a keySym (name of a key) or an integer (the keySymCode)
+ or a character.
+ The modifierMaskOrNil is as mask as returned by altModifierMask, ctrlModifierMask, etc.
+ if nil, the key is grabbed with AnyModifier.
+ Only the key is passed to myself - no permanent grab is installed.
+ (GrabModeAsync)"
+
+ ^ sekf
+ grabKey:keySymCodeOrChar
+ modifier:modifierMaskOrNil
+ grabModeKeyboard:#GrabModeAsync
+ grabModePointer:#GrabModeAsync
+ window:aWindowIdOrNil
+!
+
+grabKey:keySymCodeOrChar modifier:modifierMaskOrNil grabModeKeyboard:modeKbd grabModePointer:modePtr window:aWindowIdOrNil
+ "internal basic entry to grab a single key either for an individual window
+ or the whole screen (if aWindowIdOrNil is nil).
+ The keySymCodeOrChar argument may be a keySym (name of a key) or an integer (the keySymCode)
+ or a character.
+ The modifierMaskOrNil is as mask as returned by altModifierMask, ctrlModifierMask, etc.
+ if nil, the key is grabbed with AnyModifier.
+ ModeKbd and modePtr are symbols GrabModeAsync or GrabModeSync.
+
+ After that, this key-event will no longer be sent to the window/screen.
+
+ Use with care: the only useful application is to define a special hotKey
+ to start/stop event recorders without a need for a click or focus change.
+ Once grabbed, those key events will be exclusively reported to me.
+
+ Use GrabModeSync with big care - you can easily lock up your Xserver,
+ and have to kill ST/X or force an ungrab from a remote login if you have.
+ "
+
+%{
+ int modifierMask = AnyModifier;
+ KeySym keySym, *syms;
+
+ if (__isStringLike(keySymCodeOrChar)) {
+ keySym = XStringToKeysym(__stringVal(keySymCodeOrChar));
+ } else {
+ if (__isCharacter(keySymCodeOrChar)) {
+ char s[2];
+
+ s[0] = __intVal(__characterVal(keySymCodeOrChar));
+ s[1] = '\0';
+ keySym = XStringToKeysym(s);
+ } else {
+ if (__isSmallInteger(keySymCodeOrChar)) {
+ keySym = (KeySym) __intVal(keySymCodeOrChar);
+ } else {
+ goto notOK;
+ }
+ }
+ }
+
+ if (modifierMaskOrNil != nil) {
+ if (__isSmallInteger(modifierMaskOrNil)) {
+ modifierMask = __intVal(modifierMaskOrNil);
+ } else {
+ goto notOK;
+ }
+ }
+
+ if (ISCONNECTED) {
+ Display *dpy;
+ Window window;
+ int keyCode;
+ int result;
+ int mKbd, mPtr;
+
+ mKbd = modeKbd == @symbol(GrabModeAsync) ? GrabModeAsync :GrabModeSync;
+ mPtr = modePtr == @symbol(GrabModeAsync) ? GrabModeAsync :GrabModeSync;
+
+ dpy = myDpy;
+ keyCode = XKeysymToKeycode(dpy, keySym);
+ if (__isExternalAddress(aWindowIdOrNil)) {
+ window = __WindowVal(aWindowIdOrNil);
+ } else {
+ int screen;
+
+ screen = DefaultScreen(dpy);
+ window = RootWindow(dpy, screen);
+ }
+ ENTER_XLIB();
+
+ result = XGrabKey (dpy,
+ keyCode, modifierMask, window,
+ False, mKbd, mPtr );
+
+ XSync(dpy, True);
+ XFlush(dpy);
+
+ LEAVE_XLIB();
+
+ if (result != Success) {
+ if (result == BadAccess) {
+ __INST(lastError) = @symbol(badAccess);
+ } else {
+ __INST(lastError) = @symbol(other);
+ }
+ RETURN (false);
+ }
+ RETURN (true);
+ }
+ notOK: ;
+%}.
+ self primitiveFailedOrClosedConnection
+!
+
+ungrabKey:keySymCodeOrChar modifier:modifierMaskOrNil window:aWindowIdOrNil
+ "ungrab a single key as previously grabbed via grabKey:
+ Read the comment there."
+
+%{
+ int modifierMask = AnyModifier;
+ KeySym keySym, *syms;
+
+ if (__isStringLike(keySymCodeOrChar)) {
+ keySym = XStringToKeysym(__stringVal(keySymCodeOrChar));
+ } else {
+ if (__isCharacter(keySymCodeOrChar)) {
+ char s[2];
+
+ s[0] = __intVal(__characterVal(keySymCodeOrChar));
+ s[1] = '\0';
+ keySym = XStringToKeysym(s);
+ } else {
+ if (__isSmallInteger(keySymCodeOrChar)) {
+ keySym = (KeySym) __intVal(keySymCodeOrChar);
+ } else {
+ goto notOK;
+ }
+ }
+ }
+
+ if (modifierMaskOrNil != nil) {
+ if (__isSmallInteger(modifierMaskOrNil)) {
+ modifierMask = __intVal(modifierMaskOrNil);
+ } else {
+ goto notOK;
+ }
+ }
+
+ if (ISCONNECTED) {
+ Display *dpy;
+ Window window;
+ int keyCode;
+ int result;
+
+ dpy = myDpy;
+ if (__isExternalAddress(aWindowIdOrNil)) {
+ window = __WindowVal(aWindowIdOrNil);
+ } else {
+ int screen;
+
+ screen = DefaultScreen(dpy);
+ window = RootWindow(dpy, screen);
+ }
+ keyCode = XKeysymToKeycode(dpy, keySym);
+
+ ENTER_XLIB();
+
+ result = XUngrabKey (dpy, keyCode, modifierMask, window);
+
+ XSync(dpy, True);
+ XFlush(dpy);
+
+ LEAVE_XLIB();
+
+ if (result != Success) {
+ if (result == BadAccess) {
+ __INST(lastError) = @symbol(badAccess);
+ } else {
+ __INST(lastError) = @symbol(other);
+ }
+ RETURN (false);
+ }
+ RETURN (true);
+ }
+ notOK: ;
+%}.
+ self primitiveFailedOrClosedConnection
+! !
+
!XWorkstation methodsFor:'grabbing'!
allowEvents:mode
@@ -13362,11 +13558,11 @@
!XWorkstation class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.596 2014-07-22 10:49:13 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.597 2014-09-20 13:30:53 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.596 2014-07-22 10:49:13 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.597 2014-09-20 13:30:53 cg Exp $'
!
version_SVN