EventHandler to detect key presses and mouse clicks

Mac OSX specific forum
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: EventHandler to detect key presses and mouse clicks

Post by wilbert »

jesperbrannmark wrote:Its really tricky to understand this.. and why didn't Apple just choose to use Purebasic to begin with instead of fiddling with this Xcode beast?
It's not really tricky. It may just be a bit hard to understand if you are just starting out with Cocoa functionality :wink:
Why Apple didn't just choose PureBasic. Very good question :)

Anyway ... does this help you out ?

Code: Select all

#NSLeftMouseUp        = 2
#NSRightMouseUp       = 4
#NSMouseMoved         = 5
#NSKeyDown            = 10
#NSKeyUp              = 11
#NSScrollWheel        = 22

#NSAlphaShiftKeyMask = 1 << 16
#NSShiftKeyMask      = 1 << 17
#NSControlKeyMask    = 1 << 18
#NSAlternateKeyMask  = 1 << 19
#NSCommandKeyMask    = 1 << 20

EnableExplicit

Global sharedApplication = CocoaMessage(0, 0, "NSApplication sharedApplication")
Define currentEvent, type, modifierFlags, keyCode
Define clickCount, location.NSPoint, deltaX.CGFloat, deltaY.CGFloat
Define Event

If OpenWindow(0, 0, 0, 320, 170, "Events example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  EditorGadget(0, 10, 10, 300, 100, #PB_Editor_ReadOnly)
  
  Repeat
    
    Event = WaitWindowEvent()
    currentEvent = CocoaMessage(0, sharedApplication, "currentEvent")
    If currentEvent
      type = CocoaMessage(0, currentEvent, "type")
      modifierFlags = CocoaMessage(0, currentEvent, "modifierFlags")
      
      ClearGadgetItems(0)
      
      ; mouse events
      
      If type = #NSLeftMouseUp
        clickCount = CocoaMessage(0, currentEvent, "clickCount")
        SetGadgetText(0, "Left mouse " + Str(clickCount) + "x clicked")
      EndIf
      
      If type = #NSRightMouseUp
        clickCount = CocoaMessage(0, currentEvent, "clickCount")
        SetGadgetText(0, "Right mouse " + Str(clickCount) + "x clicked")
      EndIf
      
      If type = #NSMouseMoved
        CocoaMessage(@location, currentEvent, "locationInWindow")
        SetGadgetText(0, "Mouse moved to (" + StrF(location\x, 1) + "," + StrF(WindowHeight(0)-location\y, 1) + ")"); use WindowHeight() to flip y coordinate
      EndIf
      
      If type = #NSScrollWheel
        CocoaMessage(@deltaX, currentEvent, "deltaX")
        CocoaMessage(@deltaY, currentEvent, "deltaY")
        SetGadgetText(0, "Mouse wheel delta (" + StrF(deltaX, 1) + "," + StrF(deltaY, 1) + ")")
      EndIf
      
      ; keyboard events
      
      If type = #NSKeyDown
        keyCode = CocoaMessage(0, currentEvent, "keyCode")
        SetGadgetText(0, "Key down with code : " + Str(keyCode))
      EndIf
      
      If type = #NSKeyUp
        keyCode = CocoaMessage(0, currentEvent, "keyCode")
        SetGadgetText(0, "Key up with code : " + Str(keyCode))
      EndIf
      
      ; key modifiers
      
      If modifierFlags & #NSAlphaShiftKeyMask  
        AddGadgetItem(0, -1, "Caps lock is on")
      Else
        AddGadgetItem(0, -1, "Caps lock is off")
      EndIf
      If modifierFlags & #NSShiftKeyMask
        AddGadgetItem(0, -1, "Shift key is pressed")
      EndIf
      If modifierFlags & #NSControlKeyMask
        AddGadgetItem(0, -1, "Ctrl key is pressed")
      EndIf
      If modifierFlags & #NSAlternateKeyMask
        AddGadgetItem(0, -1, "Alt key is pressed")
      EndIf
      If modifierFlags & #NSCommandKeyMask
        AddGadgetItem(0, -1, "Cmd key is pressed")
      EndIf
      
    EndIf
    
  Until Event = #PB_Event_CloseWindow
EndIf
Niffo
Enthusiast
Enthusiast
Posts: 504
Joined: Tue Jan 31, 2006 9:43 am
Location: France

Re: EventHandler to detect key presses and mouse clicks

Post by Niffo »

In this last sample code, when you press a key, Cocoa triggers an audible error beep if no "keyboard gadget" has the focus.
Do you know how to avoid this ?
I have found an equivalent request on the web but how to implement the proposed solution in PB ?

http://stackoverflow.com/questions/1351 ... error-beep
Niffo
User avatar
Shardik
Addict
Addict
Posts: 2060
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: EventHandler to detect key presses and mouse clicks

Post by Shardik »

Niffo wrote:In this last sample code, when you press a key, Cocoa triggers an audible error beep if no "keyboard gadget" has the focus.
Do you know how to avoid this ?
A solution to this problem is very easy: simply insert the following line behind the definition of the EditorGadget in wilbert's last code example:

Code: Select all

  CocoaMessage(0, WindowID(0), "makeFirstResponder:", GadgetID(0))
Niffo
Enthusiast
Enthusiast
Posts: 504
Joined: Tue Jan 31, 2006 9:43 am
Location: France

Re: EventHandler to detect key presses and mouse clicks

Post by Niffo »

Thank you very much, it works like a charm when there is a gadget on the window !
But do you have a solution if there is no gadget on the window ?
Last edited by Niffo on Tue Jul 08, 2014 3:11 pm, edited 2 times in total.
Niffo
User avatar
glomph
User
User
Posts: 48
Joined: Tue Apr 27, 2010 1:43 am
Location: St. Elsewhere / Germany
Contact:

Re: EventHandler to detect key presses and mouse clicks

Post by glomph »

I really would like to know it too.
User avatar
Piero
Addict
Addict
Posts: 923
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: EventHandler to detect key presses and mouse clicks

Post by Piero »

I put together what I found on Forum (and added something…)

Code: Select all

EnableExplicit
; #NSLeftMouseUp ; #NSRightMouseUp ; #NSMouseMoved ; #NSScrollWheel ; …
Global keyTime, lastKeyTime = -99999 ; for doublecommand

Procedure.s modifierFlagsInfo(modifierFlags)
   Protected r1.s, flags
   flags = modifierFlags & $FFFF0000
   If modifierFlags & #NSCommandKeyMask
      r1 + "Command "
   EndIf
   If modifierFlags & #NSControlKeyMask
      r1 + "Control "
   EndIf
   If modifierFlags & #NSAlternateKeyMask
      r1 + "Alt "
   EndIf
   If modifierFlags & #NSShiftKeyMask
      r1 + "Shift "
   EndIf
   If modifierFlags & #NSAlphaShiftKeyMask
      r1 + "Caps Lock "
   EndIf
   If modifierFlags & #NSFunctionKeyMask
      if not modifierFlags & #NSNumericPadKeyMask ; for arrow keys…
         r1 + "fn "
      EndIf
   EndIf
   ProcedureReturn r1
EndProcedure

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

Macro Print(s)
   AddGadgetItem(0, -1, s)
   SetGadgetState(0, CountGadgetItems(0)-1)
   SetGadgetState(0, -1)
EndMacro

Procedure PrintKey(Ev.s, CurEv)
   Print(Ev + ": keyCode = " + CocoaMessage(0, CurEv, "keyCode"))
   Define Long = CocoaMessage(0, CurEv, "characters")
   CocoaMessage(@Long, Long, "UTF8String")
   Print(Ev + ": keyChar = " + Chr(Asc(PeekS(Long, -1, #PB_UTF8))))
   Protected modkeys.s = modifierFlagsInfo(CocoaMessage(0, CurEv, "modifierFlags"))
   if modkeys : Print("Modifiers: " + modkeys) : EndIf
   Print("")
EndProcedure

ProcedureC OS_CallBackEventsHandler(obj, sel, notification)
   Define sharedApplication = CocoaMessage(0, 0, "NSApplication sharedApplication")
   Define currentEvent = CocoaMessage(0, sharedApplication, "currentEvent")
   Static lastEvent
   If currentEvent = lastEvent : ProcedureReturn : EndIf
   lastEvent = currentEvent
   If currentEvent
      Select CocoaMessage(0, currentEvent, "type")
         Case #NSKeyDown
            PrintKey("Key Down", currentEvent)
         Case #NSKeyUp
            PrintKey("Key Up", currentEvent)
         Case #NSLeftMouseUp
            Debug "NSLeftMouseUp" ; whole window
         Case #NSFlagsChanged ; SHIFT, CMD, ALT, CTRL, CAPS, fn…
            If (CocoaMessage(0, currentEvent, "modifierFlags") & $FFFF0000) = #NSCommandKeyMask
               keyTime = ElapsedMilliseconds()
               If keyTime - lastKeyTime < DoubleClickTime()
                  Print("Double Command!") : Print("")
               EndIf
               lastKeyTime = keyTime
            EndIf
      EndSelect
   EndIf
EndProcedure

ProcedureC PerformKeyEquivalent(Sender, sel, event)
   ProcedureReturn #YES ; avoid beeps
EndProcedure

OpenWindow(0, 0, 0, 300, 300, "Keys Info")
ListViewGadget(0, 5, 5, 290, 290)

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:")
class_addMethod(delegateClass, selector, @OS_CallBackEventsHandler(), "v@:@")
CocoaMessage(0, notificationCenter, "addObserver:", appDelegate, "selector:", selector, "name:", #Null, "object:", WindowID(0))
; avoid beeps
Define class = CocoaMessage(0, WindowID(0), "class")
Define selector = sel_registerName("performKeyEquivalent:") 
class_addMethod(class, selector, @PerformKeyEquivalent(), "v@:@")

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow ; or EventMenu() = #PB_Menu_Quit
Post Reply