How to avoid Cocoa "error beep" when pressing a key ?

Mac OSX specific forum
Niffo
Enthusiast
Enthusiast
Posts: 504
Joined: Tue Jan 31, 2006 9:43 am
Location: France

How to avoid Cocoa "error beep" when pressing a key ?

Post by Niffo »

In my application i need to detect keyboard keyDown and keyUp whatever the gadget who has the focus and even when there is no gadget on the Window. For that, i use Cocoa "subclassing". Bellow is my working code.

BUT i want Cocoa not to emit an "error beep" each time a key is pressed (PB Keyboard Shortcuts are not usable in my case).
I have read that it is needed to subclass the NSView to return YES to the "performKeyEquivalent:" event to avoid the "error beep" from Cocoa when pressing a key :
http://stackoverflow.com/questions/8869 ... -in-nsview
But i don't know how to do it in PB. Can some Cocoa guru help me ?

Code: Select all

EnableExplicit

#NSKeyDown                   = 10
#NSKeyUp                     = 11
#NSFlagsChanged              = 12

ImportC "" ;{
   sel_registerName(str.p-ascii)
   class_addMethod(class, selector, imp, types.p-ascii)
EndImport ;}

ProcedureC OS_CallBackEventsHandler(obj, sel, notification)
   Define sharedApplication = CocoaMessage(0, 0, "NSApplication sharedApplication")
   Define currentEvent = CocoaMessage(0, sharedApplication, "currentEvent")
   Define Object = CocoaMessage(0, currentEvent, "window")
   Static lastEvent

   If currentEvent = lastEvent : ProcedureReturn : EndIf
   lastEvent = currentEvent

   If currentEvent
      Select CocoaMessage(0, currentEvent, "type")
         Case #NSKeyDown
            Debug "KeyDown : keyCode = " + CocoaMessage(0, currentEvent, "keyCode")
            Define Long = CocoaMessage(0, currentEvent, "characters")
            CocoaMessage(@Long, Long, "UTF8String")
            Debug "KeyDown : keyChar = " + Asc(PeekS(Long, -1, #PB_UTF8))
          
         Case #NSKeyUp
            Debug "KeyUp : keyCode = " + CocoaMessage(0, currentEvent, "keyCode")
          
         Case #NSFlagsChanged ; SHIFT, CMD, ALT, CTRL, CAPS
            Debug "Flags : " + Bin(CocoaMessage(0, currentEvent, "modifierFlags"))
         
      EndSelect
   EndIf
EndProcedure

OpenWindow(0, 100, 100, 300, 200, "Test")

Define notificationCenter = CocoaMessage(0, 0, "NSNotificationCenter defaultCenter")
Define appDelegate = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
Define delegateClass = CocoaMessage(0, appDelegate, "class")
Define selector = sel_registerName("EventsHandlerCallback:") ; Necessary ?
class_addMethod(delegateClass, selector, @OS_CallBackEventsHandler(), "v@:@")
CocoaMessage(0, notificationCenter, "addObserver:", appDelegate, "selector:", selector, "name:", #Null, "object:", WindowID(0))

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Last edited by Niffo on Thu Oct 22, 2015 5:53 pm, edited 1 time in total.
Niffo
empty
User
User
Posts: 27
Joined: Sat Apr 12, 2014 11:31 am

Re: How to avoid Cocoa "error beep" when pressing a key ?

Post by empty »

You need to override performKeyEquivalent and return 1 to avoid the message sound.
Be aware though that this overridden method applies to ALL windows you create in the application, unless you subclass a specific window during runtime. See my post in the tips and tricks thread. The function "SubclassGadget" is aimed at Gadgets only, so you would need to replace GadgetID() with WindowID().

Code: Select all

EnableExplicit

#NSKeyDown                   = 10
#NSKeyUp                     = 11
#NSFlagsChanged              = 12

ImportC "" ;{
   sel_registerName(str.p-ascii)
   class_addMethod(class, selector, imp, types.p-ascii)
EndImport ;}

ProcedureC FlagsChanged(Sender, sel, event)
  Debug "Flags : " + Bin(CocoaMessage(0, Event, "modifierFlags"))
  
EndProcedure


ProcedureC PerformKeyEquivalent(Sender, sel, event)
  
  Static lastEvent
  Protected currentevent = event
   Protected result = #YES  
   If currentEvent = lastEvent : ProcedureReturn result : EndIf
   lastEvent = currentEvent

   If currentEvent
      Select CocoaMessage(0, currentEvent, "type")
         Case #NSKeyDown
            Debug "KeyDown : keyCode = " + CocoaMessage(0, currentEvent, "keyCode")
            Define Long = CocoaMessage(0, currentEvent, "characters")
            CocoaMessage(@Long, Long, "UTF8String")
            Debug "KeyDown : keyChar = " + Asc(PeekS(Long, -1, #PB_UTF8))
         
         Case #NSKeyUp
            Debug "KeyUp : keyCode = " + CocoaMessage(0, currentEvent, "keyCode")
         
     ;    Case #NSFlagsChanged ; SHIFT, CMD, ALT, CTRL, CAPS
     ;       Debug "Flags : " + Bin(CocoaMessage(0, currentEvent, "modifierFlags"))
         
      EndSelect
    EndIf
  
  ProcedureReturn result
EndProcedure


OpenWindow(0, 100, 100, 300, 200, "Test")


Define class = CocoaMessage(0, WindowID(0), "class")
Define selector = sel_registerName("performKeyEquivalent:") 
class_addMethod(class, selector, @PerformKeyEquivalent(), "v@:@")
selector = sel_registerName("flagsChanged:") 
class_addMethod(class, selector, @FlagsChanged(), "v@:@")


Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Niffo
Enthusiast
Enthusiast
Posts: 504
Joined: Tue Jan 31, 2006 9:43 am
Location: France

Re: How to avoid Cocoa "error beep" when pressing a key ?

Post by Niffo »

Thank you VERY much for this very clear sample code "Empty" ! And thank you too for your sample in "[PB Cocoa] Methods, Tips & Tricks".
Niffo
empty
User
User
Posts: 27
Joined: Sat Apr 12, 2014 11:31 am

Re: How to avoid Cocoa "error beep" when pressing a key ?

Post by empty »

You're welcome :)
Post Reply