Cocoa: What NSTextView the insertion point is currently blinking in? - cocoa

Given an NSApp object (aka [NSApplication sharedApplication]), how can I get the currently active NSTextView, where the insertion point is blinking right now (if there is one)? :-)
I can go [[NSApp keyWindow] contentView] and try traversing the whole view hierarchy, but that seems too hard. Ideal code would be: [NSApp focusedTextView].
I tryed firstResponder for an app and a window, and also fieldEditor:forObject:, but this does not return anything interesting (at least, to me).
By the way, if anybody knows how to get the system wide current text view, that would be even cooler (Accessibility APIs won’t work: it won’t return a Cocoa NSTextView).
Thanks

The -firstResponder function returns the field editor. So if you want the real view you might need to check the first responder's delegate to get to it. Also see field editor for details.
There is probably no way to get it system wide as a NSTextViews since that object is in general in a different process space.

By the way, if anybody knows how to get the system wide current text view, that would be even cooler (Accessibility APIs won’t work: it won’t return a Cocoa NSTextView).
Not possible. NSTextViews are per-process; you can't get a proxy to an NSTextView from another process without that other process serving it up through an NSConnection. You're just going to have to use Accessibility.
On the bright side, using Accessibility means your app should (in theory) also work with Carbon apps that use MLTE/HITextView.

Related

Focus wrongly preserved by Lion

I'd really appreciate an answer to this, but can't afford a bounty (!).
Here we have a very simple GUI: the user just enters a source word and a target word in two text boxes, then presses a button. Then a lot of whirring takes place, and half a second later an answer is shown. The user goes on doing this until bored, then closes the app. Naturally, when the app restarts, the focus should be on the source, and I am hoping there is a neater way of achieving this than the one described. The commenter below has confirmed my feeling that the problem was an artefact of Lion persistence, which is a real nuisance in simple cases like this.
I set an NSTextField as First Responder (using the window's makeFirstResponder) in the awakeFromNib method of a simple 'controller' class, in a simple Cocoa application in Xcode 4.3, running under Lion.
The makeFirstResponder works fine the first time the app is loaded after reboot, but on every rerun the focus is set to the last field accessed. (I had tried connecting the window's initialFirstResponder outlet to the desired NSTextField, but got the same problem).
I fixed it finally by calling an initialisation function from the NSApplication delegate, and putting the makeFirstResponder call there.
The fix is a bit messy - I added a global variable to the controller, and initialised it to self in awakeFromNib.
I add the information that the Cocoa part of the app is simple, but the bulk of it is a mass of STL stuff in .cpp files, ported from Windows.
Deselect the "Restorable" check box in the attributes inspector for your window in IB. Of course, you then won't have the other behaviors you get with a restorable window like remembering its position and size.

Can I change NSScreen visibleframe?

I trying to create a toolbar that docks on the top of the screen below the OS X menu bar.
I would like no other application's to be able to overlap my application when they are maximized. I can get the visible frame dimensions using NSScreen's visibleframe method, but can I adjust the visibleframe to omit the size and position of my application?
The simple answer is that no, you can't. I think that the only way to change the screen's visibleRect would be to inject code into AppKit and swizzle the method.
Even then, it might not do what you want because that method might not be what Apple uses to determine the "safe area" for windows and almost certainly would not work with Carbon apps.
Nothing you do with window levels will change this.
What you could do is use the Accessibility framework to reposition windows if you detect that their frames have changed such that they overlap your toolbar window. Unfortunately, I think you might need use polling for this.
Try setting your window's level to NSDockWindowLevel.
This may not work, depending on whether the system subtracts all windows on that level or only ever the Dock's window, but it's worth a try.

Getting accented characters in a custom NSView

In Mac OSX text views, it's possible to enter accented characters with a sequence of key presses (e.g. option-e e to get e-acute). Is there a way to access this functionality in a custom NSView. In my case I have class derived from NSOpenGLView. I've implemented a responder for keyDown: so I can get the unicode characters that come from a single press, but with the sequences I just get events for the individual presses. I hoped that interpretKeyEvents: from NSResponder would help but it doesn't seem to.
I could implement it myself by copying what NSTextView does but I imagine it will be tricky, especially if people use a different keyboard setup to mine.
Calling interpretKeyEvents: is the right way to go, but you need to also implement other methods that will notify you when marked text (which I always called 'in progress text') or text to be inserted arrives in your view.
Your NSView must implement NSTextInputClient. See the Cocoa reference here. A search for some of the methods in that protocol found this chunk of code on github. which looks like a very good starting point.
For what you're asking for, it will be sufficient to test with English and at least one other Western language (French is a good one). But longer term, you'll also want to test with at least one of the Kotoeri and Hangul layouts. The code I linked to above, however, looks like it will handle the vast majority of text you can throw at it.
Hhhmm.. that sounds pretty tricky.
NSTextField does some pretty similar things as it does not have its own editing facilities but rather delegates them to the parent window's "field editor" which is an instance of an invisible NSTextView. You also get a lot of the NSTextView behavior without a window in NSText.
It might be worth checking how NSTextFields delegate to the field editor and see whether you can hook yourself into the field editor in the same way rather than doing your keyDown: events.
Another possibility could be to create an invisible NSTextView and delegate each key press to it and then display the NSTextStorage associated with it in your own view.
It sounds like you are in for a bit of pain, but that's what I would start by exploring.
Of course, I'm no Cocoa Text Subsystem wizard..
I hope this helps.

cocoa -- What is the proper way to tell an NSWindow to redisplay its contents?

According to the NSWindow Class Reference, you should "rarely need to invoke" the NSWindow methods "display" or "setViewsNeedDisplay". So what is the usual way to redisplay the window's contents?
EDIT: I am having trouble dealing with resizing events. I just want to have everything scale proportionally. See this question. As no one seems to have any ideas for using masks to get it to happen, I want to redraw the whole thing.
Jason's comment really should be an answer:
Generally you don't need to. Instead, you invalidate whatever view needs to be invalidated for whatever reason within the window.
In addition to that comment, I'd add that you might want to explain why you feel you need to do this. While there are sometimes perfectly valid reasons to force the whole window to redraw, they are rare and you should suspect You're Doing It Wrong™.
Use this method to flag subviews for redisplay:
- setNeedsDisplay:YES

Getting rid of the focus rect on an NSCell. Only shows up when right clicking

I have an NSCell subclass that I do all kinds of custom drawing in. The only time things seem to be entirely out of my control is when right clicking a cell to show the associated context menu. While showing it's context menu, the table (or cell - not sure which exactly is doing this) draws a focus rect. I would like to get rid of this, or at least find a way to draw my own version of it that better fits within my interface.
I have tried about 15 different methods that seem like they could give me control over this focus rect drawing itself (various first responder methods, various drawing methods, various highlight color methods, etc.), but I have yet to find something that changes anything about it.
Screenshot of the problem: http://twitpic.com/3zx2t
I am almost annoyed enough to class-dump AppKit and try to find whatever private method it's using to draw this annoying focus rect. Nothing else I do has any effect on it. Any help here would really save both my sanity and lots of future hair pulling.
Thanks so much!
Without completely overriding your table view's -drawRect: this is the only other way I know to get rid of the context menu highlight rect.
- (void)_drawContextMenuHighlightForIndexes:(NSIndexSet *)rowIndexes clipRect:(NSRect)rect {
return;
}
This is the method, used in Leopard at least, to draw the highlight around cells that will be activated upon by a context menu. It is unfortunately called directly by NSTableView's -drawRect: method and as far as I know there is no other way to signal your disinterest in having those highlights drawn.
Of course this is private API, it may stop working in Snow Leopard, or some other release. But at worst that means that somewhere along the way the context menu highlight may start up again in your programs on newer releases or some other functionality using this method may not work later. You have been warned.
On 10.5 and later, NSTableView allows you to bring up a contextual menu on any item in the table (that is, without having the side effect of changing the selection.)
It draws that 'focus rect' to indicate which item(s) are being acted on by the contextual menu.

Resources