How to handle keyboard short cuts ( shortcuts like Command + control )? - cocoa

How can I get the keyCode for a particular combination in KeyDown? What would be the keyCode for Control + Option + A. or Command + Control +Shift +X?

[NSEvent modifierFlags] will return a bitmask of the modifier keys that are currently down (http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/Reference/Reference.html)

Related

Why is this functionKey selected when I press F1, F2, etc?

I am reading the keyboard shortcuts typed inside a NSTextField.
When I press, for example, shift + option + F2, this method
class func convertToString(event:NSEvent) -> String {
var shortcut = ""
let intersection = event.modifierFlags.intersection(.deviceIndependentFlagsMask)
if intersection.contains(.control) {
shortcut.append("^ ")
}
if intersection.contains(.option) {
shortcut.append("⌥ ")
}
if intersection.contains(.command) {
shortcut.append("⌘ ")
}
if intersection.contains(.shift) {
shortcut.append("⇧ ")
}
if intersection.contains(.function) {
shortcut.append("fn ")
}
let character = keysCodesToCharacters[event.keyCode]!
shortcut.append(character)
return shortcut
}
will evaluate true for
if intersection.contains(.function)
In theory this tests for the function key but the most strange part is that event.keycode comes as 120 that corresponds to F2.
So I don't need to do this test at all to test for the function keys F1 to F12.
The big question is: what is the purpose of this .function. What is this testing?
I thought of the fn keys on the mac keyboard but these keys are not detectable and when I press any key from F1 to F12, this method gives me the keycode of the key plus this function true.
What I mean is this: when I press F2, for example, I receive event.keycode, meaning that F2 was pressed and also functionKey (63) as true? Why the redundancy?
Apple's documentation isn't what is used to be.
If the documentation doesn't help, check the header. Copied from NSEvents.h:
NSEventModifierFlagFunction = 1 << 23, // Set if any function key is pressed.
NSEventModifierFlagFunction was NSFunctionKeyMask, documentation:
NSFunctionKeyMask
Set if any function key is pressed. The function keys include the F keys at the top of most keyboards (F1, F2, and so on) and the navigation keys in the center of most keyboards (Help, Forward Delete, Home, End, Page Up, Page Down, and the arrow keys).
Apparently the .function flag is also set when the fn-key is pressed (on my Apple keyboard, my Logitech keyboard handles the fn-key internally).

Local NSEvent Monitor yields incorrect keycode

I'm using a local monitor to observe key events. However, I get an incorrect keycode when the modifiers ⌥ and ⌘ are active and the key with code 42 is pressed simultaneously. The keyCode in the event is 8, which is C on my keyboard. The event monitor is used within a subclass of NSTextField to intercept key events.
This is the only case where I get an incorrect keycode so far. I also tried using a CGEventTap to reproduce this, but the keyCode is always correct using a CGEventTap.
Has anybody ever experienced this? Is this a known bug?
import Foundation
import Cocoa
class FooTextField : NSTextField {
func initMonitor() {
NSEvent.addLocalMonitorForEvents(matching: [.keyUp, .keyDown, .flagsChanged], handler: onKeyEvent)
}
private func onKeyEvent(_ e: NSEvent) -> NSEvent? {
//prints 8 when key with keycode 42 is pressed and (⌥,⌘) are active.
//the textfield seems to receives the correct keycode since a # appears for German keyboards
print(e.keyCode)
return e
}
}

AutoHotKey: Toggle RAlt to Mouse Hotkey with Another Hotkey

I'm trying to create a Hotkey (Win+Shift+Q) that toggles on/off another Hotkey that changes the right Alt key to a left mouse click; however, I can't get it to work.
Expected Behavior:
Pressing Windows+Shift+Q will initially toggle the Right-Alt key to act as a left mouse click.
Pressing Windows+Shift+Q again will toggle the Right-Alt key back to acting as a Right-Alt key.
Pressing Windows+Shift+Q again will revert to the left-click behavior (see #1). And so on.
Here's the most current iteration of my code:
Hotkey, RAlt, MyClick, On
#+Q:: ;Win+Shift+Q :: ::Right-Alt acts as a left mouse button click
switch := !switch
MsgBox %switch%
Hotkey RAlt, % (switch ? "Off": "On")
Return
MyClick:
MouseClick
Return
When I run my script I get the following error after clicking OK on the MsgBox and the script quits:
Error: Nonexistent hotkey
Specifically: RAlt
Line#
141: Hotkey,RAlt,MyClick,On
143: switch:=!switch
144: MsgBox %switch%
-->145: Hotkey RAlt, % (switch ? "Off": "On")
146: Return
149: MouseClick
150: Return
The current thread will exit.
Most of the other posts that might relate (Can AutoHotKey toggle keymapping?, Autohotkey: Toggle a set of keybinds on and off) only deal with key to key mapping and not key to mouse mapping. I can't tell if that is the cause of my issues or not.
Previously I had this, but the Win+Shift+Q didn't toggle the behavior, RAlt always acted as a left-click so I commented it out:
#+Q:: ;Win+Shift+Q :: ::Right-Alt acts as a left mouse button click
RAlt::LButton
;Hotkey, RAlt, Toggle ;Does not work for some reason
int += 1
test := mod(int, 2) = 0
if (test) {
msgbox on
Hotkey, RAlt, On
}
else {
msgbox off
Hotkey, leftClick, Off
}
Return
I'll also add that I would like this behavior across Windows, not just a single application (which also seems to be a topic in other posts that allows for the #IfWinActive-type suggestions/solutions).
I tried your current iteration of code in AutoHotkey v1.1.13.01 Unicode 32-bit and I don't have any errors after pressing OK on the message box, the script works as advertised.
Try updating your AutoHotkey version here: http://ahkscript.org/download/ and see if the problem persists.
bState:=False
#If bState
RAlt::Click
#If
#+vk51:: ; win + shift + q
KeyWait, vk51
TrayTip, % "state of switch", % (bState:=!bState) ? "on":"off"
Return

How to convert a selection to lowercase or uppercase in Sublime Text

I have several strings selected in a file in Sublime Text and I want to convert them all to lowercase.
How can I convert them all to lowercase in Sublime Text?
From the Sublime Text docs for Windows/Linux:
Keypress Command
Ctrl + K, Ctrl + U Transform to Uppercase
Ctrl + K, Ctrl + L Transform to Lowercase
and for Mac:
Keypress Command
cmd + KU Transform to Uppercase
cmd + KL Transform to Lowercase
Also note that Ctrl + Shift + p in Windows (⌘ + Shift + p in a Mac) brings up the Command Palette where you can search for these and other commands. It looks like this:
For Windows:
Ctrl+K,Ctrl+U for UPPERCASE.
Ctrl+K,Ctrl+L for lowercase.
Method 1 (Two keys pressed at a time)
Press Ctrl and hold.
Now press K, release K while holding Ctrl. (Do not release the Ctrl key)
Immediately, press U (for uppercase) OR L (for lowercase) with Ctrl still being pressed, then release all pressed keys.
Method 2 (3 keys pressed at a time)
Press Ctrl and hold.
Now press K.
Without releasing Ctrl and K, immediately press U (for uppercase) OR L (for lowercase) and release all pressed keys.
Please note: If you press and hold Ctrl+K for more than two seconds it will start deleting text so try to be quick with it.
I use the above shortcuts, and they work on my Windows system.
As a bonus for setting up a Title Case shortcut key Ctrl+kt (while holding Ctrl, press k and t), go to Preferences --> Keybindings-User
If you have a blank file open and close with the square brackets:
[ { "keys": ["ctrl+k", "ctrl+t"], "command": "title_case" } ]
Otherwise if you already have stuff in there, just make sure if it comes after another command to prepend a comma "," and add:
{ "keys": ["ctrl+k", "ctrl+t"], "command": "title_case" }
For Windows OS
For Uppercase
CTRL + K + U
For Lowercase
CTRL + K + L
For others needing a key binding:
{ "keys": ["ctrl+="], "command": "upper_case" },
{ "keys": ["ctrl+-"], "command": "lower_case" }

Distinguish between left and right shift keys using RAWINPUT

RAWINPUT provides two flags (RI_KEY_E0 and RI_KEY_E1) to check whether the left or right version of a key is pressed. This works great for CTRL, but not for left and right shift. In fact, the flags are the same for both, and the VKey is also the same (VK_SHIFT). How can I find out which shift was pressed? I'm working on Windows 7. Interestingly, the flags/vkey values are exactly the same no matter which shift key I'm pressing.
Windows 7, and I only get VK_SHIFT, never the L/R variants
Which is part of the explanation why this doesn't work the way you think it should do. There's ancient history behind this. The keyboard controller was redesigned for the IBM AT, again for the Enhanced keyboard. It started sending out 0xe0 and 0xe1 prefixes for keys that were added to the keyboard layout. Like the right Ctrl and Alt keys.
But keyboards always had two shift keys. The original IBM PC didn't consider them special keys, they simply have a different scan code. Which was maintained in later updates. Accordingly, you don't get the RI_KEY_E0 or E1 flags for them. You have to distinguish them by the RAWKEYBOARD.MakeCode value. The left shift key has makecode 0x2a, the right key is 0x36.
Note that the left Ctrl and Alt keys don't have the flags either. They match the corresponding keys on the old PC keyboard layout. The description of the flags in the MSDN Library article is not very accurate.
You can distinguish left-right SHIFT/CONTROL/ALT VK codes like this:
case WM_INPUT:
{
HRAWINPUT dataHandle = reinterpret_cast<HRAWINPUT>(lParam);
RAWINPUT input;
UINT size = sizeof(input);
::GetRawInputData(dataHandle, RID_INPUT, &input, &size, sizeof(RAWINPUTHEADER));
if (input.header.dwType != RIM_TYPEKEYBOARD)
break;
const RAWKEYBOARD& keyboard = input.data.keyboard;
// Ignore key overrun state
if (keyboard.MakeCode == KEYBOARD_OVERRUN_MAKE_CODE)
return;
// Ignore keys not mapped to any VK code
// This effectively filters out scan code pre/postfix for some keys like PrintScreen.
if (keyboard.VKey >= 0xff/*VK__none_*/)
return;
uint16_t scanCode = keyboard.MakeCode;
// Scan codes could contain 0xe0 or 0xe1 one-byte prefix.
// See https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf
scanCode |= (keyboard.Flags & RI_KEY_E0) ? 0xe000 : 0;
scanCode |= (keyboard.Flags & RI_KEY_E1) ? 0xe100 : 0;
uint16_t vkCode = keyboard.VKey;
switch (vkCode)
{
case VK_SHIFT: // -> VK_LSHIFT or VK_RSHIFT
case VK_CONTROL: // -> VK_LCONTROL or VK_RCONTROL
case VK_MENU: // -> VK_LMENU or VK_RMENU
vkCode = LOWORD(MapVirtualKeyW(scanCode, MAPVK_VSC_TO_VK_EX));
break;
}
//...
return 0;
}
This code should work at least from Vista.
But please note that gamedev programmers are usually manually mapping scancodes to internal game engine specific keycodes - because VK codes are tend to change on different keyboard layouts. For example if you use usual VK_W/VK_A/VK_S/VK_D for movement in QWERTY layout - it could turn into VK_Z/VK_Q/VK_S/VK_D in AZERTY keyboard layout. VK codes are primarily handy in Win32 GUI programming.
You can grab decent scancode<->USB HID Usage conversion table here: https://source.chromium.org/chromium/chromium/src/+/main:ui/events/keycodes/dom/dom_code_data.inc

Resources