Cocoa check if a keyboard shortcut is in use - cocoa

I have a user specified global hotkey and want to check and make sure it's not going to collide with other applications. Is there any API that can ask other applications for their shortcuts or am I stuck manually checking if the selected shortcut is a common one (Cmd+v, Cmd+C etc.)?
Thanks

You have to ask the responder chain, in particular [NSResponder tryToPerform:with:] method will return if anything handles your action. Don't worry about what other apps are doing, just check if the user's shortcut is already in use.
tryToPerform:with:
Attempts to perform the action indicated method with a specified argument.
(BOOL)tryToPerform:(SEL)anAction with:(id)anObject
Parameters
anAction
The selector identifying the action method.
anObject
The object to use as the sole argument of the action method.
Return Value
Returns NO if no responder is found that responds to anAction, YES otherwise.
Discussion
If the receiver responds to anAction, it invokes the method with anObject as the argument and returns YES. If the receiver doesn’t respond, it sends this message to its next responder with the same selector and object.
Availability
Available in OS X v10.0 and later.
See Also
– doCommandBySelector:
sendAction:to:from: (NSApplication)
Declared In
NSResponder.h
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/nsresponder_Class/Reference/Reference.html#//apple_ref/occ/instm/NSResponder/tryToPerform:with:

Related

Darwin - Use a kernel extension as an UserClient for another kernel extension

I have been wondering if a kernel extension can be written to act as an UserClient for another Kernel extension. Typically, we use IOConnect on the user's side to access IOUserClient methods on a kernel extension. But no such method is available in the Kernel.framework (I absolutely understand the fact that it is intended to be used this way). But I'm just wondering if the above is possible.
First off, when you call IOServiceOpen() in user space, this calls IOService::newUserClient() on the service whose handle you passed in. An object of which class is created as a result depends on whether and how the service overrides that method.
There are a 2 main possibilities, which in turn determine how you might be able to override the default behaviour.
If the service does not override newUserClient, or if it calls down to the IOService::newUserClient() default implementation in some cases (e.g. if it doesn't know the type that was passed in), the user client class is determined by the IOUserClient property on the service.
If the service does override newUserClient(), the class of user client(s) is typically hard-coded, otherwise some kext-specific logic will be followed.
To override the user client class when using the IOUserClient property (1):
Create a kext containing your user client class implementation, and make sure this is loadable, etc.
In the Info.plist, create a copy of the original kext's IOKitPersonality.
Increase the IOProbeScore (or add a nonzero IOProbeScore if none was present) in your version of it, so your personality takes precedence over the original kext's.
Set the IOUserClient property to the user client class you want to use.
I'm not 100% sure on this, but I think you need to change the CFBundleIdentifier of the personality to your kext's, and list the other kext under OSBundleLibraries. If that doesn't work, try with the original bundle identifier.
If the original kext's Info.plist has a value for the OSBundleReqired key, make sure you copy that to yours too, with the same value.
This can still fail to work if the service specifically contains code to prevent user clients that it doesn't know about.
Note: including the original kext in OSBundleLibraries will only work if the original kext's Info.plist contains a OSBundleCompatibleVersion value. If it doesn't, you can't add it to your OSBundleLibraries, but you may still be able to make it work - if you're only calling virtual member functions on the old kext, for example.
Note 2: This will entirely override the old user client class of course. Any process creating a user client connection will get your client, not the original one. This may interfere with sandboxed apps.
Note 3: You may need to add a dummy IOResources-bound service to keep your kext loaded while there are no user clients, as normally kexts are unloaded if there are no instances of any of their classes active.
To override the user client class by overriding the newUserClient() function (2):
This works similarly to above, but you actually subclass the original service class and directly override newUserClient. This allows you to add user clients (e.g. for a different type value) rather than replace the only existing one. You'll again need to replace the original's IOKitPersonality with a higher-scoring implementation, but this time you're also changing the IOClass to your class.
Some further restrictions in this one:
You'll need (stable) headers for the class you're overriding. If there's no ABI guarantee that the class won't change size in future, you need to tread very, very carefully.
The original kext must have OSBundleCompatibleVersion set, or you won't be able to link against it - this is needed for upcalling to its constructor, filling out the vtable of your subclass, etc.
I probably don't need to point this out but: generally be extra careful when doing this, especially when overriding system kexts, you may cause the OS to malfunction if you get it wrong. I'd only do something like this as a last resort, if whatever I'm ultimately trying to do isn't possible any other way.

Delegation in Pharo Smalltalk

What is the best way of doing delegation in Smalltalk, more specifically in Pharo? I know of the doesNotUnderstand strategy, but it does not delegates subclassResponsability messages.
I was thinking on something that delegates every message send not explicitly implemented on the class to some specified object, like I can do, for example, with #Delegate in Groovy. Is there some already known way of doing this?
doesNotUndersand: will only work on methods that the object does not understand (thus the name), so if you already have implemented a method it will not be used (as is the case with subclassResponsibility.
If you use Pharo 5 (which should be released this week (May 2016)), you could use MetaLinks. It's a bit of an overkill, however what you are doing doesn't seem right to begin with (why would you want to delegate subclassResponsibility)?
In either case, MetaLinks allow to attach runtime behavior to your methods, for example:
You have some method that you want to delegate
MyObject>>someMethod
^ self subclassResponsiblity
And an object to which you wish to delegate to…
MyObject>>delegate
^ delegate
So you create a MetaLink
link := MetaLink new
metaObject: [ :object :selector :arguments |
object delegate perform: selector withArguments: argument ];
selector: #perform:withArguments:;
arguments: #(object selector arguments);
control: #instead.
Which you can install to any method AST you want.
(MyObject>>someMethod ast) link: link.
Now every time the method will be called, instead (that's what the control: does) of executing the method, the arguments of the message (if any) will be given to the block in metaObject:.
Although this should work and is extremely powerful mechanism, right now there are serious disadvantages that currently being addressed:
no documentation
little tooling support (it's pretty hard to debug)
a lot of work (we are working on a framework that would ease this as you would want to easily install them and uninstall them everywhere you need, but it's not ready yet, so it has to be done by hand)
recompilation removes the link (see point above)
Summary
To summarize, this is possible to do with MetaLinks as I've shown, however at the moment it's quite a lot of work, but we are addressing those issues.
what Peter was talking about is, you can override the
subclassResponsibility, just like you did for the doesNotUnderstand method.
There is no need to override every senders of "self subclassResponsibility".
For example, just delegate to the implementation of doesNotUnderstand
subclassResponsibility
^ self
doesNotUnderstand: (Message selector: thisContext sender selector
arguments: thisContext sender arguments)

Which event should I use just before a page is shown on browser on Plone to trigger a subscriber?

I want to create a subscriber that gets triggered when the user tries to access the resource (which is a custom content-type). So, the object is not being added, modified, nothing, is just being traversed. Something like a Zope View Event.
So, basically, suppose a custom content type has a custom workflow (two states: private and viewed). The initial state is private. This content type is only going to be created programatically, using _createObjectByType by anonymous users. Suppose an object called myobjet was added, programatically, to the root folder of my Plone site.
What I want is: when the user access
http://localhost:8080/Plone/myobject
...it automatically changes the state of the workflow of this object to viewed. The url http://localhost:8080/Plone/myobject is going to be a custom view, not the default base_edit.
Which event should I use? I tried IEndRequestEvent and IBeforeTraverseEvent from this list and none of them work: the handler is not being called for my custom object interface.
I've tried other events with my custom object interface (like IObjectEditedEvent), and, for this event, my handler is called when I edit an object that implements the interface. But using IEndRequestEvent and IBeforeTraverseEvent doesn't call the handler.
IEndRequestEvent and IBeforeTraverseEvent only work when I set the subscriber to all interfaces:
<subscriber
for="*
zope.app.publication.interfaces.IBeforeTraverseEvent"
handler=".subscriber.myhandler"
/>
And when I make myhandler print the object and the event in this situation, it shows:
<PloneSite at Plone>
<zope.app.publication.interfaces.BeforeTraverseEvent object at 0xd52618c>
If the solution is to write an event myself, is there an easy tutorial for this?
You might want to have a look at http://pypi.python.org/pypi/plone.validatehook.
Make sure you bind the event to the right interface. If you bind it to "Interface" (as described on the plone.validatehook pypi page) the event will get called for every single request. In order to restrict the event to contentish objects you can do the following:
from Products.CMFCore.interfaces import IContentish
#adapter(IContentish, IPostValidationEvent)
def RedirectMember(object, event):
...
(Edit: I removed my first answer because it didn't work)
Not sure what this subscriber is supposed to do, but if the object is not being modified, added or whatsoever than I must suspect it will just be viewed...so why not just use the __call__ method of the items view (or the __update__ method if you are using five.grok/dexterity)?

How can I pass a checkbox by reference?

I've run into what seems to be an odd quirk with VB6. I'm passing a checkbox to a method with the signature MyMethod(ByRef object) and calling it as myClass.MyMethod chkMyCheckbox. VB6, however, refuses to pass the checkbox itself, but instead passes a reference to 1 to my method. I'm guessing that this has something to do with how VB6 specifies an object's default properties. How can I get the entire object to be passed, not just .Value? I cannot turn off default properties, as a large amount of the legacy code relies heavily on them.
As you can see, ChkCalFault is a Checkbox and not an integer, but is being evaluated and passed as its integer value. (Which is in this screenshot 0.)
I can't see what your trying to do with the code so I apologize if this is off-base, but would modifying your methods signature to
MyMethod(ByRef MyCheckBox as CheckBox)
work for you? If not, the undocumented VarPtr will get the address of your checkbox object, but I don't know if that points you in the right direction either.

How can I react meaningfully to a changeAttributes: delegation pass-through from WebView?

WebView supports, through the WebEditingDelegate, a mechanism for the delegate to implement custom behavior for a variety of actions the WebView (or the private WebHTMLView) receives. When an action such as:
-(void)changeAttributes:(id)sender
is received in WebHTMLView, it is passed through to the delegate method:
-(BOOL)webView:(WebView *)webView doCommandBySelector:(SEL)command
Unfortunately, the mechanism does not provide for conveyance of the "sender" in the original action method.
For the vast majority of actions, the sender is unimportant, but for changeAttributes, and changeFont, for example, the contract requires that "sender" be called by the recipient in order to e.g. convertAttributes: or convertFont:.
For the changeFont case, it turns out that calling [[NSFontManager sharedFontManager] convertFont:] is sufficient, as coincidentally this is what the sender is.
In the changeAttributes case, in particular when strikethrough is changed, the sender may be a private class "NSFontEffectsBox" which presumably corresponds to the subsection of the font panel that is responsible for changing strikethrough/etc settings.
Unfortunately, calling [[NSFontManager sharedFontManager] convertAttributes:] does NOT obtain the expected attribute changes. This leaves a delegate who is interested in implementing this method meaningfully in a bit of a conundrum:
WebKit does not convey the sender, so the delegate can't make the contractual [sender convertAttributes:] call.
The changeAttributes: call is sent to a private WebKit class, WebHTMLView, which cannot be subclassed to, e.g., customize the behavior of changeAttributes:.
The sender for the changeAttributes: call, NSFontEffectsBox, is a private class and cannot be accessed e.g. as [NSFontEffectsBox sharedFontEffectsBox].
In short: there appears to be no way for a developer to meaningfully override the behavior of changeAttributes: for a WebView.
Any ideas?
This is an evil one. A suitably evil pair of actions (neither of them particularly clean or ideal) would be:
Do some inline assembler to look back up the stack to read the sender argument from the caller's stack (or the caller's caller, as the case should be). This of course assumes that the sender is placed on the stack and not in %eax when the call to WebHTMLView was made. That will always apply to PowerPC code however, so it's likely a non-starter there.
Put a category on WebHTMLView with a method named something like __my_evil_hacky_nasty_ugly_changeAttributes_thing: and at runtime use method_exchangeImplementations() from the ObjC runtime to swap your category's implementation with theirs. Your method becomes changeAttributes: and theirs becomes __my_evil_hacky_nasty_ugly_changeAttributes_thing:, which you can then call to pass on the original call.
As I said, neither is particularly ideal, but the second has the advantage of full runtime support (i.e. the runtime is explicitly designed to let you do this), and since you're looking up the class and methods at runtime, it's failure-tolerant. Failure in this case gets you back to square one however.
Really it needs a bug logged against WebKit to have them pass on the sender to make it meaningful at all. Your overridden version could potentially look for a method -(BOOL)webView:(WebView*)webView doCommandBySelector:(SEL)selector sender:(id)sender and call that if found, otherwise just call through to the original method. This is what Apple's code should be doing, TBH.
Have you looked at the source code?
WebHTMLView.mm
I don't see how -changeAttributes: is calling -webView:doCommandBySelector:, as within this class it's only called inside its own -doCommandBySelector: method.
- (void)changeAttributes:(id)sender
{
[self _applyStyleToSelection:[self _styleForAttributeChange:sender] withUndoAction:EditActionChangeAttributes];
}
- (void)doCommandBySelector:(SEL)aSelector
{
…
if (![[webView _editingDelegateForwarder] webView:webView doCommandBySelector:aSelector] && coreFrame) {
…
}
Also, why can't you subclass WebHTMLView? Is it because of the Mac App Store restrictions on API? Does WebKit count as private? I thought it was Open Source.
-Wil

Resources