NSEvent otherEventWithType too many parameters?

Mac OSX specific forum
Rinzwind
Enthusiast
Enthusiast
Posts: 638
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

NSEvent otherEventWithType too many parameters?

Post by Rinzwind »

Code: Select all

#NSSystemDefined = 14

#KMUTE			= 7 ;#define	NX_KEYTYPE_MUTE			7

Procedure MediaKeyPress(k1)
  Protected p.NSPoint, flags, data1, data2
  
  flags = $a00 ;down
  data1 = (k1 << 16) | ($a << 8) ;down
  CocoaMessage(0, 0, "NSEvent otherEventWithType:", NSSystemDefined, "location:@", @p, "modifierFlags:", flags, "timestamp:", 0, "windowNumber:", 0, "context:", 0, "subtype:", 8, "data1:", data1, "data2:", -1)
  flags = $b00 ;up
  data1 = (k1 << 16) | ($b << 8) ;up
  CocoaMessage(0, 0, "NSEvent otherEventWithType:", NSSystemDefined, "location:@", @p, "modifierFlags:", flags, "timestamp:", 0, "windowNumber:", 0, "context:", 0, "subtype:", 8, "data1:", data1, "data2:", -1)
EndProcedure


MediaKeyPress(#KMUTE)
Nogo... too many parameters for CocoaMessage because it has a buildin max of 7 in total.. (need 9 here...)
https://developer.apple.com/documentati ... guage=objc

I guess not possible then. Just asking to be sure... Just playing around with media keys...
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: NSEvent otherEventWithType too many parameters?

Post by wilbert »

Rinzwind wrote:I guess not possible then. Just asking to be sure... Just playing around with media keys...
No, not possible with CocoaMessage.
If you really need the functionality you can work around it but that's less easy.
Windows (x64)
Raspberry Pi OS (Arm64)
Justin
Addict
Addict
Posts: 830
Joined: Sat Apr 26, 2003 2:49 pm

Re: NSEvent otherEventWithType too many parameters?

Post by Justin »

Once I had to use that function and I did something like this, I am on a VM so I don't know if it really works although the function returns a value.

Code: Select all

EnableExplicit

PrototypeC NSEventOtherEventWithTypeProto(class.i, sel.i, type.i, locx.f, locy.f, flags.i, time.d, wNum.i, gctx.i, subtype.w, data1.i, data2.i)

Global.i NSEventClass, NSEventOtherEventWithTypeSel
Global.NSEventOtherEventWithTypeProto NSEventOtherEventWithTypeImp

Macro NSEventOtherEventWithType(iType, ptLocation, iFlags, dTime, iWinNum, iGctx, wSubtype, iData1, iData2)
	NSEventOtherEventWithTypeImp(NSEventClass, NSEventOtherEventWithTypeSel, iType, ptLocation\x, ptLocation\y, iFlags, dTime, iWinNum, iGctx, wSubtype, iData1, iData2)
EndMacro

Procedure	LoadNSEventFunctions()	
	NSEventClass = CocoaMessage(0, 0, "NSEvent class")
	NSEventOtherEventWithTypeSel = sel_registerName_("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:")
	NSEventOtherEventWithTypeImp = method_getImplementation_(class_getClassMethod_(NSEventClass, NSEventOtherEventWithTypeSel))
EndProcedure

;- START
#NSSystemDefined = 14
#KMUTE         = 7

Procedure MediaKeyPress(k1)
  Protected p.NSPoint, flags, data1, data2
  
  flags = $a00 ;down
  data1 = (k1 << 16) | ($a << 8) ;down
  NSEventOtherEventWithType(#NSSystemDefined, @p, flags, 0, 0, 0, 8, data1, -1)
  flags = $b00 ;up
  data1 = (k1 << 16) | ($b << 8) ;up
  NSEventOtherEventWithType(#NSSystemDefined, @p, flags, 0, 0, 0, 8, data1, -1)
EndProcedure

LoadNSEventFunctions()

MediaKeyPress(#KMUTE)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: NSEvent otherEventWithType too many parameters?

Post by wilbert »

Justin wrote:Once I had to use that function and I did something like this
Using a method implementation pointer with a prototype is indeed a way to do it.
But inside the prototype, it's best to type locx and locy as CGFloat.
For the x64 version of PureBasic, .f is wrong since CGFloat is a double .d on x64.
Windows (x64)
Raspberry Pi OS (Arm64)
Justin
Addict
Addict
Posts: 830
Joined: Sat Apr 26, 2003 2:49 pm

Re: NSEvent otherEventWithType too many parameters?

Post by Justin »

Ok i will change it when i can. Does the Media function acrually work? Is there another way to do it?
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: NSEvent otherEventWithType too many parameters?

Post by wilbert »

Justin wrote:Does the Media function acrually work?
If it is supposed to mute all sounds system wide, I can't get it to work so far :(
Besides creating an event, you also have to post the event but even that doesn't seem to help.

Another way to call the function is yo use NSInvocation, which is what CocoaMessage does internally.
But that's a lot more work.
Windows (x64)
Raspberry Pi OS (Arm64)
Justin
Addict
Addict
Posts: 830
Joined: Sat Apr 26, 2003 2:49 pm

Re: NSEvent otherEventWithType too many parameters?

Post by Justin »

Just translated this code to simulate system hot keys from stack overflow and it works. Like I said I can't test the mute key.

https://stackoverflow.com/questions/107 ... de-hotkeys

Code: Select all

;https://stackoverflow.com/questions/10734349/simulate-keypress-for-system-wide-hotkeys

;Simulate keypress for system wide hotkeys
;Brings spotlight search.

EnableExplicit

#kCGEventFlagMaskCommand = $00100000

Define.i src, cmdd, cmdu, spcd, spcu, loc

src = CGEventsourceCreate_(#kCGEventSourceStateHIDSystemState)

cmdd = CGEventCreateKeyboardEvent_(src, $38, #True)
cmdu = CGEventCreateKeyboardEvent_(src, $38, #False)
spcd = CGEventCreateKeyboardEvent_(src, $31, #True)
spcu = CGEventCreateKeyboardEvent_(src, $31, #False)

CGEventSetFlags_(spcd, #kCGEventFlagMaskCommand)
CGEventSetFlags_(spcu, #kCGEventFlagMaskCommand)

loc = #kCGHIDEventTap ;kCGSessionEventTap also works
CGEventPost_(loc, cmdd)
CGEventPost_(loc, spcd)
CGEventPost_(loc, spcu)
CGEventPost_(loc, cmdu)

;Put a delay, spotlight search disapears when losing focus after program exits.
Delay(2000)

CFRelease_(cmdd)
CFRelease_(cmdu)
CFRelease_(spcd)
CFRelease_(spcu)
CFRelease_(src)  
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: NSEvent otherEventWithType too many parameters?

Post by wilbert »

Justin wrote:Just translated this code to simulate system hot keys from stack overflow and it works.
Nothing happens if I run your code (macOS 10.15.2)
Windows (x64)
Raspberry Pi OS (Arm64)
Justin
Addict
Addict
Posts: 830
Joined: Sat Apr 26, 2003 2:49 pm

Re: NSEvent otherEventWithType too many parameters?

Post by Justin »

Does the spotlight search appear if you press cmd+space?
Maybe the shortcuts change from Mac OS version, try the code with a shortcut that works on your system.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: NSEvent otherEventWithType too many parameters?

Post by wilbert »

Justin wrote:Does the spotlight search appear if you press cmd+space?
Yes, it does.
But not with the code you posted.
Maybe something has changed when it comes to permissions.
Windows (x64)
Raspberry Pi OS (Arm64)
Justin
Addict
Addict
Posts: 830
Joined: Sat Apr 26, 2003 2:49 pm

Re: NSEvent otherEventWithType too many parameters?

Post by Justin »

The cmd key code was wrong from SO but not sure is the problem, try this one, pressing the test button simulates cmd+tab to switch to the next app, the pb ide in my case.

Code: Select all

;https://stackoverflow.com/questions/10734349/simulate-keypress-for-system-wide-hotkeys

;Simulate keypress for system wide hotkeys

EnableExplicit

#kCGEventFlagMaskCommand = $00100000
#kVK_Tab                       = $30
#kVK_Space                     = $31
#kVK_Command                   = $37
#kVK_ANSI_Comma                = $2B
#kVK_Return                    =  $24
#kVK_ANSI_G                    = $05

Define.i src, cmdd, cmdu, spcd, spcu, loc, keyd, keyu, retd, retu, ev, btn

src = CGEventsourceCreate_(#kCGEventSourceStateHIDSystemState)

cmdd = CGEventCreateKeyboardEvent_(src, #kVK_Command, #True)
cmdu = CGEventCreateKeyboardEvent_(src, #kVK_Command, #False)

keyd = CGEventCreateKeyboardEvent_(src, #kVK_Tab, #True)
keyu = CGEventCreateKeyboardEvent_(src, #kVK_Tab, #False)
; retd = CGEventCreateKeyboardEvent_(src, #kVK_Return, #True)
; retu = CGEventCreateKeyboardEvent_(src, #kVK_Return, #False)

CGEventSetFlags_(keyd, #kCGEventFlagMaskCommand)
CGEventSetFlags_(keyu, #kCGEventFlagMaskCommand)

;kCGSessionEventTap
loc = #kCGHIDEventTap 

OpenWindow(0, 10, 10, 500, 400, "", #PB_Window_SystemMenu)
btn = ButtonGadget(0, 10, 10, 80, 30, "Test")
Repeat
	ev = WaitWindowEvent()
	Select ev
		Case #PB_Event_Gadget
			;cmd+tab to switch app
			CGEventPost_(loc, keyd)
			CGEventPost_(loc, keyu)
			CGEventPost_(loc, cmdu)
	EndSelect
Until ev = #PB_Event_CloseWindow


; CFRelease_(cmdd)
; CFRelease_(cmdu)
; CFRelease_(keyd)
; CFRelease_(keyu)
; CFRelease_(src)  
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: NSEvent otherEventWithType too many parameters?

Post by wilbert »

No difference.

After some reading ...
On macOS 10.15 it seems you have to give an app permission to monitor system wide keyboard input in system preferences > privacy settings.
Windows (x64)
Raspberry Pi OS (Arm64)
Justin
Addict
Addict
Posts: 830
Joined: Sat Apr 26, 2003 2:49 pm

Re: NSEvent otherEventWithType too many parameters?

Post by Justin »

I upgraded to Catalina and after pressing the button a message showed up to let the app grant access, in
System Preferences - Security & Privacy - Privacy - Accessibility add the app to the list and works as expected.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: NSEvent otherEventWithType too many parameters?

Post by wilbert »

Justin wrote:I upgraded to Catalina and after pressing the button a message showed up to let the app grant access, in
System Preferences - Security & Privacy - Privacy - Accessibility add the app to the list and works as expected.
You are right. Simulating mute also works fine now.

Code: Select all

PrototypeC NSEventOtherEventWithTypeProto(obj, sel, type, locx.CGFloat, locy.CGFloat, flags, time.d, wNum, ctx, subtype.w, d1, d2)

Global NSEventClass, NSEventOtherEventWithTypeSel, NSEventOtherEventWithTypeImp.NSEventOtherEventWithTypeProto

NSEventClass = CocoaMessage(0, 0, "NSEvent class")
NSEventOtherEventWithTypeSel = sel_registerName_("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:")
NSEventOtherEventWithTypeImp = method_getImplementation_(class_getClassMethod_(NSEventClass, NSEventOtherEventWithTypeSel))

#NSEventTypeSystemDefined = 14
#NX_KEYTYPE_MUTE = 7

Procedure MediaKeyPress(k)
  
  Protected NSEvent
  
  NSEvent = NSEventOtherEventWithTypeImp(NSEventClass, NSEventOtherEventWithTypeSel, #NSEventTypeSystemDefined, 0, 0, 
                                         $a00, 0, 0, 0, 8, (k << 16) | $a00, -1)
  CGEventPost_(0, CocoaMessage(0, NSEvent, "CGEvent"))
  
  NSEvent = NSEventOtherEventWithTypeImp(NSEventClass, NSEventOtherEventWithTypeSel, #NSEventTypeSystemDefined, 0, 0, 
                                         $b00, 0, 0, 0, 8, (k << 16) | $b00, -1)
  CGEventPost_(0, CocoaMessage(0, NSEvent, "CGEvent"))
  
EndProcedure

MediaKeyPress(#NX_KEYTYPE_MUTE)
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply