Make SHIFT + 3, produce `` # `not` `on OSX by code

In my British MacBook Air, # can be entered using OPT + 3. SHIFT + 3 currently produces £ . How can I redo so that SHIFT + 3 creates # ?

This question is motivated by https://apple.stackexchange.com/questions/156154/use-option-as-meta-key-with-ability-to-type-the-symbol

I think the failure is that the default parameter for the OSX Terminal application does not register OPT (which is necessary, for example, for keyboard shortcuts in the nano editor), and that if you enable the parameter to enable it, you can no longer enter # , which is usually done with OPT + 3.

I often need # when editing configuration files on a remote server in a terminal session using nano.

I believe it is possible to use Ukelele , but I would prefer a code level solution.

If I can do this by code, I found out something!

I tried to ask a more general question , but OSX has a complex mechanism for handling keystrokes. This question belongs to the first! If I can understand this, it will cover a component of a more general case.

0
source share
1 answer

This answer comes straight from Change the output of keyDown with very little adaptation:

 // compile and run from the commandline with: // clang -fobjc-arc -framework Cocoa ./foo.m -o foo // sudo ./foo #import <Foundation/Foundation.h> #import <AppKit/NSEvent.h> typedef CFMachPortRef EventTap; // - - - - - - - - - - - - - - - - - - - - - @interface KeyChanger : NSObject { @private EventTap _eventTap; CFRunLoopSourceRef _runLoopSource; CGEventRef _lastEvent; } @end // - - - - - - - - - - - - - - - - - - - - - CGEventRef _tapCallback( CGEventTapProxy proxy, CGEventType type, CGEventRef event, KeyChanger* listener ); // - - - - - - - - - - - - - - - - - - - - - @implementation KeyChanger - (BOOL)tapEvents { if (!_eventTap) { NSLog(@"Initializing an event tap."); _eventTap = CGEventTapCreate(kCGSessionEventTap, kCGTailAppendEventTap, kCGEventTapOptionDefault, CGEventMaskBit( kCGEventKeyDown ), (CGEventTapCallBack)_tapCallback, (__bridge void *)(self)); if (!_eventTap) { NSLog(@"unable to create event tap. must run as root or " "add privlidges for assistive devices to this app."); return NO; } } CGEventTapEnable(_eventTap, TRUE); return [self isTapActive]; } - (BOOL)isTapActive { return CGEventTapIsEnabled(_eventTap); } - (void)listen { if( ! _runLoopSource ) { if( _eventTap ) { //dont use [self tapActive] _runLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, _eventTap, 0); // Add to the current run loop. CFRunLoopAddSource( CFRunLoopGetCurrent(), _runLoopSource, kCFRunLoopCommonModes); NSLog(@"Registering event tap as run loop source."); CFRunLoopRun(); }else{ NSLog(@"No Event tap in place! You will need to call " "listen after tapEvents to get events."); } } } - (CGEventRef)processEvent:(CGEventRef)cgEvent { NSEvent* event = [NSEvent eventWithCGEvent:cgEvent]; NSUInteger modifiers = [event modifierFlags] & (NSCommandKeyMask | NSAlternateKeyMask | NSShiftKeyMask | NSControlKeyMask); enum { kVK_ANSI_3 = 0x14, }; // TODO: add other cases and do proper handling of case if ( //[event.characters caseInsensitiveCompare:@"3"] == NSOrderedSame event.keyCode == kVK_ANSI_3 && modifiers == NSShiftKeyMask ) { NSLog(@"Got SHIFT+3"); event = [NSEvent keyEventWithType: event.type location: NSZeroPoint modifierFlags: event.modifierFlags & ! NSShiftKeyMask timestamp: event.timestamp windowNumber: event.windowNumber context: event.context characters: @"#" charactersIgnoringModifiers: @"#" isARepeat: event.isARepeat keyCode: event.keyCode]; } _lastEvent = [event CGEvent]; CFRetain(_lastEvent); // must retain the event. will be released by the system return _lastEvent; } - (void)dealloc { if( _runLoopSource ) { CFRunLoopRemoveSource( CFRunLoopGetCurrent(), _runLoopSource, kCFRunLoopCommonModes ); CFRelease( _runLoopSource ); } if( _eventTap ) { //kill the event tap CGEventTapEnable( _eventTap, FALSE ); CFRelease( _eventTap ); } } @end // - - - - - - - - - - - - - - - - - - - - - CGEventRef _tapCallback( CGEventTapProxy proxy, CGEventType type, CGEventRef event, KeyChanger* listener ) { //Do not make the NSEvent here. //NSEvent will throw an exception if we try to make an event from the tap timout type @autoreleasepool { if( type == kCGEventTapDisabledByTimeout ) { NSLog(@"event tap has timed out, re-enabling tap"); [listener tapEvents]; return nil; } if( type != kCGEventTapDisabledByUserInput ) { return [listener processEvent:event]; } } return event; } // - - - - - - - - - - - - - - - - - - - - - int main(int argc, const char * argv[]) { @autoreleasepool { KeyChanger* keyChanger = [KeyChanger new]; [keyChanger tapEvents]; [keyChanger listen];//blocking call. } return 0; } 
0
source

Source: https://habr.com/ru/post/987431/


All Articles