How do I allow ⌘V into NSTextField without having a Menu? - cocoa

I've removed the menu from my cocoa app, all of the interaction should happen from within a status item, that links to a menu, that links to different NSPanels. But this seems to have removed the ability to ⌘C or ⌘V within a NSTextField. Is there a way to add this back without having to have a standard menu included with my app?

Even if your app is a faceless background app, so it never shows a menu bar, you should still have a full main menu because that's what provides all of the default actions (and enables the user to redefine the key commands if they so choose). If you remove the main menu, you have to reimplement everything in it, including anything Apple adds in the future, in code.
And I'd especially warn you against trying to handle keyboard shortcuts yourself. That's damned tricky. A lot of applications get it wrong, causing us Dvorak users (among others) to curse their developers.

I assume you can just implement the actions originally connected to the menu items in a keyDown event. Check out this page for details: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/HandlingKeyEvents/HandlingKeyEvents.html
Just have it respond to cmd-v with paste:, and cmd-C with copy:
Edit: Though I have to agree with Peter, you really should have a main menu...

Related

overriding system-wide (Windows) key shortcuts in Qt app

Ctrl+Escape is a global Windows shortcut for opening main system menu. But I would like my Qt application to use this shortcut without triggering Windows main menu. I know it is probably a bad idea to override system shortcuts in general, but I would like to use this shortcut is a very limited use case.
This usecase is as follows. I have a popup window containing several rows or items. This window is opened by Ctrl+Tab and while the user holds Ctrl and keep pressing Tab, the current rows are cycled through. When the user releases Ctrl, the current row is used for some operation... But sometimes it happens that user presses Ctrl+Tab and then realizes he does not want to continue. He usually presses Escape while still holding Ctrl. And then it triggers Windows system menu and normal user gets confused, choleric user get angry... which is a bad thing. In other words I would like to be able to close the popup window when user presses Ctrl+Escape. How to do that? It is even possible?
If I write the code using this shortcut like any other short, it does not work and it always triggers Windows main menu.
As I understand it, Qt will typically not receive the key event if the underlying window system has intercepted it. For example even QtCreator cannot override system-wide shortcuts.
This question is almost a duplicate of: C++/Qt Global Hotkeys
While that question is asking specifically to capture shortcuts in a hidden/background application, I think the basic concept is the same -- capture shortcuts before the window system processes them.
From that answer, UGlobalHotkey seems pretty good, and the How to use System-Wide Hotkeys in your Qt application blog post could be useful for your limited-use case (but read the comments on that blog post about fixing the example).
Also found:
https://github.com/mitei/qglobalshortcut
https://github.com/Skycoder42/QHotkey (looks like a more detailed version of above)

Status Item blocking the main thread (NSMenu blocking NSSpeechRecognizer from detecting sound)

I have a NSMenu coming down under a NSStatusItem. I also have a NSSpeechRecognizer. When the NSMenu is open, the speech recognizer does not function properly. It will constantly show that it's receiving sound, until I close the menu. I need it to detect sound properly even while the menu is open.
How can I make the speech recognizer detect sound even while the menu is open? Does it need to become a "first responder" and take precedence over the menu?
I tried setting [speechRecognizer setListensInForegroundOnly: NO] and it still won't work.
If you don't understand, I am more than happy to provide clarification.
Here are some similar situations, but I don't yet fully understand.
The problem is most likely that the menu is running a modal run loop as long as it is open (for the purposes of tracking the mouse, etc...) and this is blocking the NSSpeechRecognizer's ability to function normally.
You can confirm this by bringing up the menu and then pausing into the debugger. You'll likely see two run loops; the outer, normal, one and one deeper down the stack that is running the modal loop.
In general, this is kind of an odd thing to do from a user interaction perspective. The whole point of a pop-up menu is to offer the user some commands that will be done after the corresponding menu item is selected.
If you really need "click this thing and recognize voice", I'd recommend a button that, maybe, pops up a bit of UI and then interacts with the speech recognizer without using a menu?

How can I add custom menu item to window system menu under X?

I would like to add my custom command, to a window system menu (the one usually on the left top on titlebar, usually containing Minimize, Maximize and so on), and respond to it in my application.
In ms windows one can do
HMENU hMenu = GetSystemMenu(hwnd, false);
AppendMenu(hMenu, MF_STRING, ...)
Is something like this possible under X11? If not a general method maybe a solution for some specific window manager?
Ok, after your last edit, what I understand is that you want to add your custom menu to the menu that's on the window decoration, which is controlled by the Window Manager.
I don't think that's possible, although I'm not sure. I believe you should read the ICCCM and the EWMH to find if this is possible or not:
http://en.wikipedia.org/wiki/Inter-Client_Communication_Conventions_Manual
http://en.wikipedia.org/wiki/Extended_Window_Manager_Hints
Or you can send an email to wm-spec-list asking:
http://mail.gnome.org/mailman/listinfo/wm-spec-list
Also, adding an option there makes it quite hidden, doesn't it? I guess most people don't ever click that menu... I don't even think that menu exists on all the possible Window Managers. You should really try to put your menu inside your application's Window instead of the Window Manager's decoration. Some environments don't even have Window Managers: what would your users do in this case?
Note that some applications (like the Chromium browser) don't use the Window Manager decorations: they implement their own decoration, they implement their own close/maximize/minimize buttons. This way, they have complete control over all the decoration buttons and menus, but their decoration doesn't have the same "look and feel" of the rest of the desktop. You could think about doing this, but I wouldn't encourage that... You should probably put your menu somewhere else (where it's not that hidden...).
You mean you want to add your app to the system menu?
I believe most modern desktop environments implement the XDG Menu Standard:
http://standards.freedesktop.org/menu-spec/menu-spec-latest.html
You'll have to learn other standards too probably:
http://standards.freedesktop.org/
They're all somehow short, so they won't consume more than some hours to read and learn.

Is there a way to make changes to the titlebar with GTK2?

I have a desktop application written in Ruby that is using GTK2. It's just a small test application to play with GTK2, but I'm having problems achieving what I want to do. Is there any way using GTK2 to get at the titlebar (apart from setting the title), specifically to either add a button to it (beside the min/max/etc, B in the below diagram) or to add an option to the menu that pops up when you click the icon on the titlebar (A in the below diagram)?
I'm thinking there might not be because GTK is meant to work with many many different window managers, but I just wondered if there was. As a side question, what event does clicking the 'cross' button fire? At the moment if the user clicks that the window disappears but the program doesn't end - I need to capture that event and quit the program.
Thanks for any help, including hitting me over the head and telling me how silly I am.
Note that this is possible in GTK 3.10 and up, by using gtk_window_set_titlebar(). It replaces the window manager's title bar with a custom one. GtkHeaderBar is a good custom title bar class to use.
You can't, however, make it look just like the window manager would, because you won't know which window manager the user is running.
No, the title bar is owned by the window manager and you will typically not have direct access to it.
When the user tries to close the window by clicking the window manager's button, the window will receive the delete event.

How do I get keyboard events in an NSStatusWindowLevel window while my application is not frontmost?

After creating a translucent window (based on example code by Matt Gemmell) I want to get keyboard events in this window. It seems that there are only keyboard events when my application is the active application while I want keyboard events even when my application isn't active but the window is visible.
Basically I want behavior like that provided by the Quicksilver application (by blacktree).
Does anybody have any hints on how to do this?
There are two options:
Use GetEventMonitorTarget() with a tacked-on Carbon run loop to grab keyboard events. Sample code is available on this page at CocoaDev.
Register an event trap with CGEventTapCreate. Sample code can be found in this thread from the Apple developer mailing list.
Edit: Note that these methods only work if you check off “Enable access for assistive devices” in the Universal Access preference pane.
A simpler route that may work better for you is to make your app background-only. The discussion on CocoaDev of the LSUIElement plist key explains how to set it up. Basically, your application will not appear in the dock or the app switcher, and will not replace the current application's menu bar when activated. From a user perspective it's never the 'active' application, but any windows you open can get activated and respond to events normally. The only caveat is that you'll never get to show your menu bar, so you'll probably have to set up an NSStatusItem (one of those icon menus that show up on the right side of the menu bar) to control (i.e. quit, bring up prefs, etc.) your application.
Edit: I completely forgot about the Non-Activating Panel checkbox in Interface Builder. You need to use an NSPanel instead of an NSWindow to get this choice. This setting lets your panel accept clicks and keyboard input without activating your application. I'm betting that some mix of this setting and the Carbon Hot Keys API is what QuickSilver is using for their UI.
Update:
Apple actually seems to have changed everything again starting with 10.5 BTW (I recently upgraded and my sample code did not work as before).
Now you can indeed only capture keydown events setting up an event tap if you are either root or assistive devices are enabled, regardless on which level you plan to capture and regardless if you selected to capture (which allows you to modify and even discard events) or to be listen only. You can still get information when flags have changed (actually even change these) and other events, but keydown under no other circumstances.
However, using the carbon event handler and the method RegisterEventHotKey() allows you to register a hotkey and you'll get notified when it is pressed, you neither need to be root for that nor do you need anything like assistive devices enabled. I think Quicksilver is probably doing it that way.

Resources