Page 1 of 2

Re: EventHandler to detect key presses and mouse clicks

Posted: Sun Oct 21, 2012 6:20 pm
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

Re: EventHandler to detect key presses and mouse clicks

Posted: Thu Apr 24, 2014 9:25 am
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

Re: EventHandler to detect key presses and mouse clicks

Posted: Sat May 10, 2014 10:26 pm
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))

Re: EventHandler to detect key presses and mouse clicks

Posted: Fri May 23, 2014 1:58 pm
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 ?

Re: EventHandler to detect key presses and mouse clicks

Posted: Fri May 23, 2014 7:59 pm
by glomph
I really would like to know it too.

Re: EventHandler to detect key presses and mouse clicks

Posted: Wed May 01, 2024 8:07 pm
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