I tried to simulate keypress by Xlib, but I can't find out where Fn key was defined in " keysymdef.h ".
If it really wasn't defined in Xlib, are there any workarounds for it ?
Fn works differently from modifiers such as Shift: it's typically caught inside the keyboard controller or in the BIOS, and the combined (Fn + other) keypress is sent over the bus as a single signal. That means that X11, or the OS for that matter, doesn't even get to see that Fn was pressed.
Related
I'm curious if it's possible to detect when the "fn" key is pressed on a mac keyboard, either when it's used on its own or when used in combination with another key. Is there a way to do that? I'm open to using any sort of method, including undocumented Apple APIs if necessary.
All keyboard NSEvents will have NSEventModifierFlagFunction (NSEvent.ModifierFlags.function in Swift) in their .modifierFlags when the Fn key is down.
To test for Fn on its own rather than in combination with some other keyboard event, it appears that when the Fn key is depressed or released, an NSEvent gets sent with type NSFlagsChanged (NSEvent.EventType.flagsChanged in Swift).
I am in the process of creating a 2D tile-based platform game for Mac OSX in swift. I have come across problems with the controls when more than one key is pushed at a time. For example; if 'D' makes the character move to the right, and 'W' makes him jump; if I hold 'D' to make the character run, then tap 'W' to make him jump, he will stop once he lands. The only way for him to continue to move to the right is to retouch 'D' again, which is certainly undesirable. It appears as though when the 'W' key is pressed, it cancels the 'D' keyDown event. If anyone has any suggestions on how I can make it so that multiple keys can be pressed without canceling other similar events I sure would appreciate it.
This is how my KeyDown events looks:
func returnChar(theEvent: NSEvent!) -> Character?{
let s: String = theEvent.characters!
for char in s {
return char}
return nil
}
override func keyDown(theEvent: NSEvent) {
let s: String = String(self.returnChar(theEvent)!)
switch(s){
case "w":
player.jump()
case "s":
// nothing yet
case "d":
player.moveLeftOrRight(CGVector(dx: 1.0, dy: 0.0))
case "a":
player.moveLeftOrRight(CGVector(dx: -1.0, dy: 0.0))
default:
println("default")
}
}
The repeated keydown events that occur when a key is held down are generated by the keyboard hardware. On the PC, the protocol definition says:
If you press a key, its make code is sent to the computer. When you press and hold down a key, that key becomes typematic, which means the keyboard will keep sending that key's make code until the key is released or another key is pressed. To verify this, open a text editor and hold down the "A" key. ... Typematic data is not buffered within the keyboard. In the case where more than one key is held down, only the last key pressed becomes typematic. Typematic repeat then stops when that key is released, even though other keys may be held down.
Since both PCs and Macs can use the same USB keyboards (modulo some key remapping), I'm pretty sure they both use the same protocol.
In the case you describe, the problem occurs because even though you're holding down D, when you hit W, the keyboard stops repeating the D key. The sequence of events is:
Keydown D
Keydown D
...
Keydown W
Keyup W
and at this point the keyboard events stop. Notice that the Keyup D has not occurred, so you actually know that the D key is still down, but now it is up to you to simulate the repeated keypresses.
I suggest you research how to disable autorepeat altogether in the keyboard hardware (or just ignore the key repeat events) and generate the desired game behavior yourself. You could easily do this by tracking the state of each key using Keydown and Keyup events, ignoring repeated Keydown.
Jim Garrison's answer seems correct. A workaround in this case, could be to have the character move right when you press the D key down, and continue to move right using a loop until the D key is released, which you can check using the func keyUp(theEvent: NSEvent)
If using SpritKit, you can do the character movement in the update method while using a bool that is set in the keyDown and keyUp method.
I have a system with no keyboard. I can connect a keyboard, but ultimately the inputs come from a custom keypad which is not a HID device, it sends serial data which I can interpret and decode to determine if the user pressed Up, Down, Left, Right, or Enter.
Right now all I have is a Fl_Window, with two Fl_Button widgets. Focus is set for one of the buttons and callbacks are defined for these buttons. I know that if I attach a real keyboard, and use the arrow keys I can change focus from button to button. I do have to hit SPACE to activate a button.
My problem is determining how to cause these key presses using code when I decode the outcome form the embedded key pad. Because in deployment, there will be no actual keyboard.
What I've tried is to invoke int Fl_Window::handle(int) and not really had success. I've also tried to invoke int Fl::handle(int, Fl_Window *) and not had success.
Here are code examples:
if((ret = Fl::handle(FL_Left, window)) == 0)
That compiles, but I find that I get zero back, implying that it did not process the event.
if((ret = Fl_Window::handle(FL_Right)) == 0)
That does not compile, informing me that it "cannot call member function virtual int Fl_Window::handle(int) without object"
I'm thinking that the "int event" actually ought to be FL_KEYDOWN.
That logic leaves me to wonder though how I "set" event_key(). For instance, there are API functions to get that when one has a handler, but I do not wish to get that; I wish to cause that event to occur.
Is my only option here to figure out how to emulate a HID or make some type of virtual HID where I then cause the keyboard events to occur?
I do not feel I require a handler function in my application, I'm fine with the default behaviors which occur and cause my callback functions to be invoked. My problem is that I can't "cause" these events to occur.
You need to assign the desired key to e_keysym, then dispatch a FL_KEYDOWN event using Fl::handle_(). (Fl::handle() will not generate the followup FL_SHORTCUT event.)
Fl::e_keysym = FL_Left;
Fl::handle_(FL_KEYDOWN, window);
// sleep() and/or Fl::wait() as appropriate
Fl::handle_(FL_KEYUP, window);
i need to know what key code of Command button in mac keyboard, do somebody know how to get it programmatically?
can i get the key code if user tap button Command + X (cut shortcut)? thank you for the suggestion
I'm going to assume here that you're dealing with NSEvents generated by the AppKit framework.
In NSEvent's documentation, take a look at the modifierFlags method.
And the flag you're lookng for is specifically the NSCommandKeyMask.
Now, to get it, if you have a NSView view in focus... it inherits from NSResponder. One of the methods in NSResponder is keyDown. So add a keyDown method to your subclassed view and the parameter it takes is a NSEvent. And that is how you would get your command button key.
BTW & FYI, if you just want to get the command key by itself (which is what I suspect), that's a bigger trick and I'm not sure if it's possible with AppKit. Because the command key, like the control and shift keys, are modifier keys and that means when events get generated, NSEvent is expecting two keys to be pressed at the same time (e.g. Command + Q for Quit, Control + C for interrupt, Shift + A for capital A).
I develop an application on Mac using cocoa. I need to handle cmd + period(.) keyboard event as a command I designed. But now the cmd + period(.) keyboard event does not well handled as I expected.
In the cocoa keyEvent handle process, if the application object processes a key event and it turns out not to be a key equivalent or a key interface control event, it then sends it to the key window in a sendEvent: message. The window object invokes the keyDown: method in the first responder. My handle for cmd + period(.) is in keyDown: method.
But the problem is that Mac treates cmd + period(.) key the same as Escape key. The key window first searches the view hierarchy for a view whose key equivalent is Escape or Command-., whichever was entered. But none of these views handles the key equivalent, then a cancel: action message is sent to the first responder in the responder chain.
So cmd + period(.) is handled as a cancel operation before it reaches keyDown: method.
Can anyone have some idea to solve this problem. And make the cmd + period(.) be handled as I expected but as cancel command. Thank you.
What is more, it is better not handle the cmd + period(.) when do the key equivalent check(performkeyEquivalent).
If you want to override the default handling, you need to catch the keyboard event earlier in the chain. For example, subclass NSWindow and override -sendEvent, or even more thorough, subclass NSApplication and override -nextEventMatchingMask (all events will pass through this function).