Simulate keydown event - smalltalk

How can I simulate a key (ctrl) being hold down while some other code is executed? What would be the implementation of the following method?
self ctrlDownWhile: [self doSomething]

You could try to "trick" the input state, by changing its "ctrlDown" state.
The bad news is that it does not have a setter-method to access it (maybe only in my version), so you may have to get there with a trick:
ctrlDownWhile:aBlock
"aBlock will see ctrlDown as true"
|indexOfCtrlState|
indexOfCtrlState := InputState allInstVarNames indexOf:'ctrlState'.
InputState default instVarAt:indexOfCtrlState put:1.
aBlock
ensure: [
InputState default instVarAt:indexOfCtrlState put:0.
].
an alternative is to create keyPress & keyRelease-events for the CTRL-key, and enqueue them into the WindowSensor, before and after the block's evaluation.

Related

Enforcing and contract methods in Squeak

So I created a class that enforces every method (message) that is sent to it's class instance.
i.e that code:
|a|
a := Animal new.
a makeSound: 'bark'
should lead to a call to "doesNotUnderstand" (even though it exists in the class) and it should check wehther the post and pre conditions are there, i'll explain:
If a method looks like this:
makeSound: aNoise
"%self assert: [canMakeNoise = true]%"
"#self assert: [numOfLegs >= 0]#"
numOfLegs := -1
it means that asside from that main method, there is also a method called: PREmakeSound which is implementation is:
self assert: [canMakeNoise = true]
and onther method called POSTmakeSiund which is implemented as follows:
self assert: [numOfLegs >= 0]
---My question is - because of the fact that every method call is calling doesNotUnderstand, whenever I want to actually activate the method (after I cheked whatever i needed) how can I activate it as is?
hope my problem is clear...
Maybe using method wrappers would work better than using #doesNotUnderstand:?
Create a class PrePostMethod with a compiledMethod instance variable. You can then install instances of PrePostMethod in the method dictionary of a class instead of instances of CompiledMethod.
When the VM looks-up a message and gets this PrePostMethod instance instead of a CompiledMethod, it doesn't know what to do with it. Consequently, it will send "run: aSelector with: arguments in: receiver" to that PrePostMethod object. This is where you can perform custom action like checking pre-post condition.
For example:
PrePostMethod>>run: aSelector with: arguments in: receiver
| result |
self checkPrecondition: receiver
result := compiledMethod run: aSelector with: arguments in: receiver
self checkPostCondition: receiver.
^ result
As Sean suggests, an alternative solution is to change the way these methods are compiled.
You could transform the AST of the method before compilation, or change the compilation process itself. For example, with the AST transformation approach you can transform:
makeSound: aNoise
"%self assert: [ self canMakeNoise]%"
"#self assert: [ self numOfLegs >= 0]#"
numOfLegs := -1
into:
makeSound: aNoise
self assert: [
"The preconditions goes here"
self canMakeNoise ]
^ [ "Original method body + self at the end if there is no return"
numOfLegs := -1.
self ] ensure: [
"The postcondition goes here"
self assert: [ self numOfLegs >= 0 ] ]
One the one hand, these solutions would be more tedious to implement but one the other hand, they are more performant.
HTH
Could you explain more about why you're using doesNotUnderstand? My first thought would be injecting extra byte codes during compilation...
Although, the way to send a message from doesNotUnderstand would be something like:
self perform: newSelector withArguments: aMessage arguments.
The problem is that if this message is that it's easy to get into an infinite loop this way.

Initial position of a SystemWindow (Cuis Smalltalk)

I have made a subclass #Mosaic1 of #SystemWindow and I would like to control the initial position of the window. How do I do that? Class #RealEstateAgent is involved but how? The class comment says
Responsible for real-estate management on the screen,
which is to say, controlling where new windows appear,
with what sizes, etc. 5/20/96 sw
So I am asking for an explanation how to configure and use the class #RealEstateAgent.
Notes:
#RealEstateAgent is a singleton. It only has class side methods
It is only referenced by #SystemWindow
A new SystemWindow gets its initial extent from RealEstateAgent class>> standardWindowExtent
One solution is to bypass the class #RealEstateAgent and write your own code to handle the initial size and position of a new instance of SystemWindow.
This may be done by overriding SystemWindow>>openInWorld:extent:
openInWorld: aWorld extent: extent
"This msg and its callees result in the window being activeOnlyOnTop"
aWorld addMorph: self.
self morphPosition:
(RealEstateAgent initialFrameFor: self world: aWorld) topLeft;
morphExtent: extent.
aWorld startSteppingSubmorphsOf: self.
"Do it deferred. Was needed for text cursor to start blinking
if (Preferences disable: #focusFollowsMouse) "
WorldState addDeferredUIMessage: [ self activate ]
Replace
self morphPosition:
(RealEstateAgent initialFrameFor: self world: aWorld) topLeft;
morphExtent: extent.
Calculate
thePositionOfTheWindow
theExtentOfTheWindow
Then do
self morphPosition: thePositionOfTheWindow morphExtent: theExtentOfTheWindow.

Resignalling exceptions unless they are of a certain type

I want to make sure that evaluating aBlock only raises errors of type SomeCustomError. Is there a better way than using isKindOf: ?
aBlock
on: Core.Error
do: [:ex |
(ex isKindOf: SomeCustomError)
ifTrue: [ex pass]
ifFalse: [(SomeCustomError identification: #generalError messageText: ex messageText) raise]]
Another approach - define method isMyTerribleException at class Exception and it should return false. At your CustomException class define redefine method with returning true
aBlock
on: Core.Error
do: [:ex |
(ex isMyTerribleException)
ifTrue: [ex pass]
ifFalse: [(SomeCustomError identification: #generalError messageText: ex messageText) raise]]
It would be better, because you can are introducing new Exception classes, which must be catched
This sounds strange to me. Two things
1) HOW:
You are resignalling from the handler context.
Is it really what you want?
Or do you want to resignal from original context where first error was raised?
In the latter case you should use something like:
ex resignalAs: (SomeCustomError identification: #generalError messageText: ex messageText)
2) WHAT:
It's not isKindOf: which bothers me, but the whole idea...
Catch all kind of Error and replace by specific one?
What is the use case?
Who will catch the specific one?
Or does the specific one has a different default action?

is there way to check if performSelector:withObject:afterDelay: has been registered?

I whould like to know if there is a way to determine if performSelector:withObject:afterDelay: for the given object has been called (registered to be called). (I could use cancelPreviousPerformRequestsWithTarget:selector:object: and re-call performSelector:withObject:afterDelay:, ok but I'm interested to know if there is the alternative).
Thanks
The best thing to do would be to make sure that the selector being called can be called multiple times safely.
For example, use a flag in the target object to track if the method has already been invoked e.g.
-targetSelector: (id) param
{
if (!hasBeenRun) // hasBeenRun is a boolean intance variable
{
hasBeenRun = true;
// other stuff
}
}

How can my app detect a change to another app's window?

In Cocoa on the Mac, I'd like to detect when a window belonging to another app is moved, resized, or repainted. How can I do this?
You would need to use the Accessibility APIs, which are plain-C, located inside the ApplicationServices framework. For instance:
First you create an application object:
AXUIElementRef app = AXUIElementCreateApplication( targetApplicationProcessID );
Then you get the window from this. You can request the window list and enumerate, or you can get the frontmost window (look in AXAttributeConstants.h for all the attribute names you'd use).
AXUIElementRef frontWindow = NULL;
AXError err = AXUIElementCopyAttributeValue( app, kAXMainWindowAttribute, &frontWindow );
if ( err != kAXErrorSuccess )
// it failed -- maybe no main window (yet)
Now you can request notification via a C callback function when a property of this window changes. This is a four-step process:
First you need a callback function to receive the notifications:
void MyAXObserverCallback( AXObserverRef observer, AXUIElementRef element,
CFStringRef notificationName, void * contextData )
{
// handle the notification appropriately
// when using ObjC, your contextData might be an object, therefore you can do:
SomeObject * obj = (SomeObject *) contextData;
// now do something with obj
}
Next you need an AXObserverRef, which manages the callback routine. This requires the same process ID you used to create the 'app' element above:
AXObserverRef observer = NULL;
AXError err = AXObserverCreate( applicationProcessID, MyObserverCallback, &observer );
if ( err != kAXErrorSuccess )
// handle the error
Having got your observer, the next step is to request notification of certain things. See AXNotificationConstants.h for the full list, but for window changes you'll probably only need these two:
AXObserverAddNotification( observer, frontWindow, kAXMovedNotification, self );
AXObserverAddNotification( observer, frontWindow, kAXResizedNotification, self );
Note that the last parameter there is passing an assumed 'self' object as the contextData. This is not retained, so it's important to call AXObserverRemoveNotification when this object goes away.
Having got your observer and added notification requests, you now want to attach the observer to your runloop so you can be sent these notifications in an asynchronous manner (or indeed at all):
CFRunLoopAddSource( [[NSRunLoop currentRunLoop] getCFRunLoop],
AXObserverGetRunLoopSource(observer),
kCFRunLoopDefaultMode );
AXUIElementRefs are CoreFoundation-style objects, so you need to use CFRelease() to dispose of them cleanly. For cleanliness here, for example, you would use CFRelease(app) once you've obtained the frontWindow element, since you'll no longer need the app.
A note about Garbage-Collection: To keep an AXUIElementRef as a member variable, declare it like so:
__strong AXUIElementRef frontWindow;
This instructs the garbage collector to keep track of this reference to it. When assigning it, for compatibility with GC and non-GC, use this:
frontWindow = (AXUIElementRef) CFMakeCollectable( CFRetain(theElement) );
Further research turned up "Quartz Display Services"
The interesting function for my needs is CGRegisterScreenRefreshCallback.