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

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).

Related

AutoHotKey If Key pressed while win11 TaskView is open syntax

I've recently been using Gnome 41.5 and fell in love with the way the Activities menu works
So I am trying to use AHK to create a script that when I press the windows key it opens Task View - then if Task View is open and I start to type, (to search for an application) I want AHK to open the start menu so that I can utilize its search function
My rough outline for how I imagine it would work below - I've been trying to learn but got stuck here
Lwin::
Send, #{Tab}
if (""taskview is open"" + ""any char pressed"") {
Send, Rctrl + Esc
}
In the future I'd love to have the start button just appear on the Task View screen so that it's almost just like Gnome
i wanted to do the same thing and got this so far, i like how this works tbh, but you might wanna add RWin as well (i don't have it, so i didn't)
before task view appears the start menu flashes shortly, but the activation timing keeps shortcuts working without opening task view, so it's a good tradeoff imo.
;couldn't check these names bc the names are different based on system language
;double click on the script in the task tray and hit CTRL+K to figure out the correct name
taskView := "Task View" ;these 2 names are guesses
search := "Search"
;----------------------------------------------------------------------
;Hotkey function hotkeys have to be created first
Hotkey, ~*LButton, mousedown, off
Hotkey, ~*RButton, mousedown, off
Hotkey, ~*MButton, mousedown, off
Hotkey, ~LWin, showTask
;checks every half second if you're in task view to activate the key logging
SetTimer, taskInput, 500
return
showTask:
;prevent repeats
keywait, LWin
;cancel if a different key got pressed while win was held down
if (A_PriorKey != "LWin") {
return
}
if WinActive(taskView){
sleep 1
send {Esc}
return
}
else send #{tab}
taskInput:
if (!WinActive(taskView)){
return
}
Mouse_Flag = 0
Hotkey, ~*LButton, on
Hotkey, ~*RButton, on
Hotkey, ~*MButton, on
;wait for any key
Input, key, L1 V, {VK0E}{LWin}{RWin}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{BS}{Pause} ;excluded: {LControl}{RControl}{LAlt}{RAlt}{LShift}{RShift}{CapsLock}{NumLock}{PrintScreen}{Left}{Right}{Up}{Down}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}
if WinActive(taskView){
if (key = LWin) {
keywait, LWin
sleep 1
send {Esc}
}
else if (Mouse_Flag || key = Chr(27)) { ;chr 27 = blank space character, matches some characters specified in the any key input check, notably Esc
;nothing/return
}
else {
;open search
send #s
WinWaitActive %search%
if("LWin" != A_PriorKey && key != A_PriorKey){ ;slight fix if you type very fast and the letters get jumbled bc winwaitactive takes too long
send {BS}
send {%key%}
send {%A_PriorKey%}
}
else send {%key%}
}
}
Hotkey, ~*LButton, off
Hotkey, ~*RButton, off
Hotkey, ~*MButton, off
Return
mousedown:
Mouse_Flag = 1
sendevent, {Blind}{VK0E} ;unused virtual key
return

AutoHotkey key shortcuts with disabling Alt key

setup
AutoHotkey v 1.1.32.00 on Windows 10 (current version) with US keyboard layout.
goal
Extending the US keyboard layout with non-existing keys by using key shortcuts with the right Alt key = RAlt. Therefore, the RAlt key should be disabled completely and only be used for the new shortcuts (the left Alt key = LAlt remains for program menu jumps and similar things).
Examples:
RAlt and a pressed together should print ä (a special German letter)
RAlt and y pressed together should print ¥ (the Japanese currency Yen).
first working attempt
#MenuMaskKey vkFF
key_map_lower := {a: "ä", y: "¥"}
RAlt::
for key in key_map_lower {
Hotkey, $%key%, hotkey_label_lower, On
}
return
RAlt Up::
for key in key_map_lower {
Hotkey, $%key%, Off
}
return
hotkey_label_lower:
Send, % key_map_lower[SubStr(A_ThisHotkey, 2)]
return
This works fine, no problems so far.
problem
The combination RAlt+a=ä prints only the lowercase German special letter, but there is also a equivalent in uppercase. Therefore, a new rule is needed like so: RAlt+Shift+a=Ä.
My attempt for this:
#MenuMaskKey vkFF
; lowercase letters
key_map_lower := {a: "ä", y: "¥"}
RAlt::
for key in key_map_lower {
Hotkey, $%key%, hotkey_label_lower, On
}
return
RAlt Up::
for key in key_map_lower {
Hotkey, $%key%, Off
}
return
hotkey_label_lower:
Send, % key_map_lower[SubStr(A_ThisHotkey, 2)]
return
; capital/uppercase letters
key_map_upper := {a: "Ä"}
RAlt & +::
for key in key_map_upper {
Hotkey, $%key%, hotkey_label_upper, On
}
return
RAlt & + Up::
for key in key_map_upper {
Hotkey, $%key%, Off
}
return
hotkey_label_upper:
Send, % key_map_upper[SubStr(A_ThisHotkey, 2)]
return
But this only works for lowercase letters as before. The uppercase letters do not appear.
alternative attempt
RAlt::
Hotkey, a, label_a, On
Hotkey, y, label_y, On
Hotkey, +a, label_a_, On
return
RAlt Up::
Hotkey, a, label_a, Off
Hotkey, y, label_y, Off
Hotkey, +a, label_a_, Off
return
label_a:
Send, ä
return
label_y:
Send, ¥
return
label_a_:
Send, Ä
return
This works for lowercase and also uppercase. But the uppercase only work when pressing RAlt before Shift. When pressing first Shift and then RAlt, the window menu gets focused.
question
How can either
the second script be fixed so that it is not important whether to press Shift or RAlt first?
Or how to fix the first script in order to work and also ignoring the order of RAlt and Shift?
The first attempt is more compact and more robust I guess because of less redundantly and also less lines.
(Also I think both attempts does not have any beauty in code at all, but combining lowercase and uppercase in one data structure in the first attempt only caused even more problems. With this doubling at least the lowercase letters work. But I am thankful for all optimizations as well.)
additional question
I also want to map RAlt+`=°
This is possible in the second attempt because the label are manually assigned. But with the first attempt this is not possible. So this is a next problem with the first attempt.
additional
In some sources they use >! for RAlt, but no luck with this either.
sources
original source on autohotkey.com and some discussions about RAlt key combinations here.
Does this work for your purposes?
*RAlt::
Hotkey, *a, label_a, On
Hotkey, y, label_y, On
return
*RAlt Up::
Hotkey, *a, label_a, Off
Hotkey, y, label_y, Off
return
label_a:
if(GetKeyState("Shift", "P")) {
Send, Ä
} else {
Send, ä
}
return
label_y:
Send, ¥
return
The '*', wildcard, lets the hotkey fire even if extra modifiers are being held down. The inside the label it checks if the shift is pressed down or not.

Replacing the ESC button on a NSTouchBar

I am building a NSTouchBar for my app using storyboard.
I want to replace the ESC button with something else.
As usual, there is no doc telling you how to do that.
I have searched the web and I have found vague informations like
You can change the content of "esc" to something else, though, like
"done" or anything, even an icon, by using
escapeKeyReplacementItemIdentifier with the NSTouchBarItem.
But this is too vague to understand.
Any ideas?
This is what I did so far.
I have added a button to NSTouchBar on storyboard and changed its identifier to newESC. I added this line programmatically:
self.touchBar.escapeKeyReplacementItemIdentifier = #"newESC";
When I run the App the ESC key is now invisible but still occupies its space on the bar. The button that was supposed to replace it, appears next to it. So that bar that was
`ESC`, `NEW_ESC`, `BUTTON1`, `BUTTON2`, ...
is now
`ESC` (invisible), `NEW_ESC`, `BUTTON1`, `BUTTON2`, ...
The old ESC is still occupying its space on the bar.
This is done by creating a touch bar item, let's say a NSCustomTouchBarItem containing a NSButton, and associating this item with its own identifier.
Then with another identifier you do your usual logic but you add the previously created identifier as the ESC replacement.
Quick example in Swift:
func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItemIdentifier) -> NSTouchBarItem? {
switch identifier {
case NSTouchBarItemIdentifier.identifierForESCItem:
let item = NSCustomTouchBarItem(identifier: identifier)
let button = NSButton(title: "Button!", target: self, action: #selector(escTapped))
item.view = button
return item
case NSTouchBarItemIdentifier.yourUsualIdentifier:
let item = NSCustomTouchBarItem(identifier: identifier)
item.view = NSTextField(labelWithString: "Example")
touchBar.escapeKeyReplacementItemIdentifier = .identifierForESCItem
return item
default:
return nil
}
}
func escTapped() {
// do additional logic when user taps ESC (optional)
}
I also suggest making an extension (category) for the identifiers, it avoids making typos with string literals:
#available(OSX 10.12.2, *)
extension NSTouchBarItemIdentifier {
static let identifierForESCItem = NSTouchBarItemIdentifier("com.yourdomain.yourapp.touchBar.identifierForESCItem")
static let yourUsualIdentifier = NSTouchBarItemIdentifier("com.yourdomain.yourapp.touchBar.yourUsualIdentifier")
}

How to make a message box appear after pressing a key

I'm currently playing around in Visual Basic 6.0 and wondered how can you cause a message box or some other code to appear/activate when the user presses a specific key on the keyboard like F1 or F2.
Use the Form_KeyDown(Keycode, Shift) method in your form:
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyF1 Then
//do something here if F1 key is pressed
//or call a method
End If
End Sub
Also, you might also want to set the KeyPreview property to true for your form.

theEvent charactersIgnoringModifiers - Get characters without modifiers

Im trying to implement a keyboard class in my game that has two modes. The game mode takes input that uses lowercase, unmodified keys (unmodified meaning if I type a '0' with the shift it still returns '0' instead of ')'). I have tracked it down as far as using the charactersIgnoringModifiers method of the NSEvent class but this method excludes all the modifier keys except for the shift key.
You can use -[NSEvent keyCode] and then translate the key code to a character without using any modifiers. Doing the latter is easier said than done. Here's a long mailing list thread on the techniques and gotchas.
The best option I could find so far for ignoring the <Shift> modifier is by using NSEvent.characters(byApplyingModifiers:) with a modifier that doesn't change the key glyph, i.e. .numericPad:
func onKeyDown(event: NSEvent) {
let characters = event.characters(byApplyingModifiers: .numericPad)
print("Key pressed: \(characters)")
}
Ideally you'd be able to pass in a mask that represents no modifiers at all, but the API doesn't seem to support it.
For completeness, here's how you could start writing a function that takes a UInt16 (CGKeyCode) and returns a string representation according to the user's keyboard:
func keyCodeToString(code: UInt16) -> String {
switch code {
// Keys that are the same across keyboards
// TODO: Fill in the rest
case 0x7A: return "<F1>"
case 0x24: return "<Enter>"
case 0x35: return "<Escape>"
// Keys that change between keyboards
default:
let cgEvent = CGEvent(keyboardEventSource: nil, virtualKey: code, keyDown: true)!
let nsEvent = NSEvent(cgEvent: cgEvent)!
let characters = nsEvent.characters(byApplyingModifiers: .numericPad)
return String(characters?.uppercased() ?? "<KeyCode: \(code)>")
}
}
The goal being for the F1 key to display <F1>, but the ";" key to display ; on US keyboards but Ñ on Spanish keyboards.

Resources