5
// Michael Hutchinson <mhutchinson@novell.com>
6
// Geoff Norton <gnorton@novell.com>
8
// Copyright (c) 2009 Novell, Inc. (http://www.novell.com)
10
// Permission is hereby granted, free of charge, to any person obtaining a copy
11
// of this software and associated documentation files (the "Software"), to deal
12
// in the Software without restriction, including without limitation the rights
13
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
// copies of the Software, and to permit persons to whom the Software is
15
// furnished to do so, subject to the following conditions:
17
// The above copyright notice and this permission notice shall be included in
18
// all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29
using System.Runtime.InteropServices;
30
using System.Collections.Generic;
31
using System.Diagnostics;
33
namespace OSXIntegration.Framework
35
internal delegate CarbonEventHandlerStatus EventDelegate (IntPtr callRef, IntPtr eventRef, IntPtr userData);
36
internal delegate CarbonEventHandlerStatus AEHandlerDelegate (IntPtr inEvnt, IntPtr outEvt, uint refConst);
38
internal static class Carbon
40
public const string CarbonLib = "/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon";
42
[DllImport (CarbonLib)]
43
public static extern IntPtr GetApplicationEventTarget ();
45
[DllImport (CarbonLib)]
46
public static extern IntPtr GetControlEventTarget (IntPtr control);
48
[DllImport (CarbonLib)]
49
public static extern IntPtr GetWindowEventTarget (IntPtr window);
51
[DllImport (CarbonLib)]
52
public static extern IntPtr GetMenuEventTarget (IntPtr menu);
54
[DllImport (CarbonLib)]
55
public static extern CarbonEventClass GetEventClass (IntPtr eventref);
57
[DllImport (CarbonLib)]
58
public static extern uint GetEventKind (IntPtr eventref);
60
#region Event handler installation
62
[DllImport (CarbonLib)]
63
static extern EventStatus InstallEventHandler (IntPtr target, EventDelegate handler, uint count,
64
CarbonEventTypeSpec [] types, IntPtr user_data, out IntPtr handlerRef);
66
[DllImport (CarbonLib)]
67
public static extern EventStatus RemoveEventHandler (IntPtr handlerRef);
69
public static IntPtr InstallEventHandler (IntPtr target, EventDelegate handler, CarbonEventTypeSpec [] types)
72
CheckReturn (InstallEventHandler (target, handler, (uint)types.Length, types, IntPtr.Zero, out handlerRef));
76
public static IntPtr InstallEventHandler (IntPtr target, EventDelegate handler, CarbonEventTypeSpec type)
78
return InstallEventHandler (target, handler, new CarbonEventTypeSpec[] { type });
81
public static IntPtr InstallApplicationEventHandler (EventDelegate handler, CarbonEventTypeSpec [] types)
83
return InstallEventHandler (GetApplicationEventTarget (), handler, types);
86
public static IntPtr InstallApplicationEventHandler (EventDelegate handler, CarbonEventTypeSpec type)
88
return InstallEventHandler (GetApplicationEventTarget (), handler, new CarbonEventTypeSpec[] { type });
93
#region Event parameter extraction
95
[DllImport (CarbonLib)]
96
public static extern EventStatus GetEventParameter (IntPtr eventRef, CarbonEventParameterName name, CarbonEventParameterType desiredType,
97
out CarbonEventParameterType actualType, uint size, ref uint outSize, ref IntPtr outPtr);
99
public static IntPtr GetEventParameter (IntPtr eventRef, CarbonEventParameterName name, CarbonEventParameterType desiredType)
101
CarbonEventParameterType actualType;
103
IntPtr val = IntPtr.Zero;
104
CheckReturn (GetEventParameter (eventRef, name, desiredType, out actualType, (uint)IntPtr.Size, ref outSize, ref val));
108
[DllImport (CarbonLib)]
109
static extern EventStatus GetEventParameter (IntPtr eventRef, CarbonEventParameterName name, CarbonEventParameterType desiredType,
110
out CarbonEventParameterType actualType, uint size, ref uint outSize, IntPtr dataBuffer);
112
[DllImport (CarbonLib)]
113
static extern EventStatus GetEventParameter (IntPtr eventRef, CarbonEventParameterName name, CarbonEventParameterType desiredType,
114
uint zero, uint size, uint zero2, IntPtr dataBuffer);
116
public static T GetEventParameter<T> (IntPtr eventRef, CarbonEventParameterName name, CarbonEventParameterType desiredType) where T : struct
118
int len = Marshal.SizeOf (typeof (T));
119
IntPtr bufferPtr = Marshal.AllocHGlobal (len);
120
CheckReturn (GetEventParameter (eventRef, name, desiredType, 0, (uint)len, 0, bufferPtr));
121
T val = (T)Marshal.PtrToStructure (bufferPtr, typeof (T));
122
Marshal.FreeHGlobal (bufferPtr);
128
#region Sending events
130
[DllImport (CarbonLib)]
131
static extern EventStatus SendEventToEventTarget (IntPtr eventRef, IntPtr eventTarget);
133
[DllImport (CarbonLib)]
134
static extern EventStatus CreateEvent (IntPtr allocator, CarbonEventClass classID, uint kind, double eventTime,
135
CarbonEventAttributes flags, out IntPtr eventHandle);
137
[DllImport (CarbonLib)]
138
static extern void ReleaseEvent (IntPtr eventHandle);
140
static EventStatus SendApplicationEvent (CarbonEventClass classID, uint kind, CarbonEventAttributes flags)
143
EventStatus s = CreateEvent (IntPtr.Zero, classID, kind, 0, flags, out eventHandle);
144
if (s != EventStatus.Ok)
146
s = SendEventToEventTarget (eventHandle, GetApplicationEventTarget ());
147
ReleaseEvent (eventHandle);
151
[DllImport (CarbonLib)]
152
public static extern CarbonEventHandlerStatus ProcessHICommand (ref CarbonHICommand command);
156
#region Error checking
158
public static void CheckReturn (EventStatus status)
160
int intStatus = (int) status;
162
throw new EventStatusException (status);
165
public static void CheckReturn (int osErr)
168
string s = GetMacOSStatusCommentString (osErr);
169
throw new SystemException ("Unexpected OS error code " + osErr + ": " + s);
173
[DllImport (CarbonLib)]
174
static extern string GetMacOSStatusCommentString (int osErr);
178
#region Char code conversion
180
internal static int ConvertCharCode (string fourcc)
182
Debug.Assert (fourcc != null);
183
Debug.Assert (fourcc.Length == 4);
184
return (fourcc[3]) | (fourcc[2] << 8) | (fourcc[1] << 16) | (fourcc[0] << 24);
187
internal static string UnConvertCharCode (int i)
189
return new string (new char[] {
191
(char)(0xFF & (i >> 16)),
192
(char)(0xFF & (i >> 8)),
199
#region Navigation services
201
[DllImport (CarbonLib)]
202
static extern NavStatus NavDialogSetFilterTypeIdentifiers (IntPtr getFileDialogRef, IntPtr typeIdentifiersCFArray);
205
[DllImport (CarbonLib)]
206
static extern NavEventUPP NewNavEventUPP (NavEventProc userRoutine);
208
[DllImport (CarbonLib)]
209
static extern NavObjectFilterUPP NewNavObjectFilterUPP (NavObjectFilterProc userRoutine);
211
[DllImport (CarbonLib)]
212
static extern NavPreviewUPP NewNavPreviewUPP (NavPreviewProc userRoutine);
214
delegate void NavEventProc (NavEventCallbackMessage callBackSelector, ref NavCBRec callBackParms, IntPtr callBackUD);
216
delegate bool NavObjectFilterProc (ref AEDesc theItem, IntPtr info, IntPtr callBackUD, NavFilterModes filterMode);
218
delegate bool NavPreviewProc (ref NavCBRec callBackParms, IntPtr callBackUD);
220
[DllImport (CarbonLib)]
221
static extern void DisposeNavEventUPP (NavEventUPP userUPP);
223
[DllImport (CarbonLib)]
224
static extern void DisposeNavObjectFilterUPP (NavObjectFilterUPP userUPP);
226
[DllImport (CarbonLib)]
227
static extern void DisposeNavPreviewUPP (NavPreviewUPP userUPP);
231
#region Internal Mac API for setting process name
233
[DllImport (CarbonLib)]
234
static extern int GetCurrentProcess (out ProcessSerialNumber psn);
236
[DllImport (CarbonLib)]
237
static extern int CPSSetProcessName (ref ProcessSerialNumber psn, string name);
239
public static void SetProcessName (string name)
242
ProcessSerialNumber psn;
243
if (GetCurrentProcess (out psn) == 0)
244
CPSSetProcessName (ref psn, name);
245
} catch {} //EntryPointNotFoundException?
248
struct ProcessSerialNumber {
255
public static Dictionary<string,int> GetFileListFromEventRef (IntPtr eventRef)
257
AEDesc list = GetEventParameter<AEDesc> (eventRef, CarbonEventParameterName.DirectObject, CarbonEventParameterType.AEList);
261
SelectionRange range = GetEventParameter<SelectionRange> (eventRef, CarbonEventParameterName.AEPosition, CarbonEventParameterType.Char);
262
line = range.lineNum+1;
266
var arr = AppleEvent.GetListFromAEDesc<string,FSRef> (ref list, CoreFoundation.FSRefToString,
267
(OSType)(int)CarbonEventParameterType.FSRef);
268
var files = new Dictionary<string,int> ();
269
foreach (var s in arr) {
270
if (!string.IsNullOrEmpty (s))
275
CheckReturn ((int)AppleEvent.AEDisposeDesc (ref list));
279
public static IList<string> GetUrlListFromEventRef (IntPtr eventRef)
281
AEDesc list = GetEventParameter<AEDesc> (eventRef, CarbonEventParameterName.DirectObject, CarbonEventParameterType.AEList);
283
return AppleEvent.GetUtf8StringListFromAEDesc (ref list, true);
285
Carbon.CheckReturn ((int)AppleEvent.AEDisposeDesc (ref list));
290
[StructLayout(LayoutKind.Sequential, Pack = 2, Size = 80)]
293
//this is an 80-char opaque byte array
297
[StructLayout(LayoutKind.Sequential)]
298
struct SelectionRange
300
public short unused1; // 0 (not used)
301
public short lineNum; // line to select (<0 to specify range)
302
public int startRange; // start of selection range (if line < 0)
303
public int endRange; // end of selection range (if line < 0)
304
public int unused2; // 0 (not used)
305
public int theDate; // modification date/time
308
internal enum CarbonEventHandlerStatus //this is an OSStatus
312
UserCancelled = -128,
315
internal enum CarbonEventParameterName : uint
317
DirectObject = 757935405, // '----'
318
AEPosition = 1802530675, // 'kpos'
321
internal enum CarbonEventParameterType : uint
323
HICommand = 1751346532, // 'hcmd'
324
MenuRef = 1835363957, // 'menu'
325
WindowRef = 2003398244, // 'wind'
326
Char = 1413830740, // 'TEXT'
327
UInt32 = 1835100014, // 'magn'
328
UnicodeText = 1970567284, // 'utxt'
329
AEList = 1818850164, // 'list'
330
WildCard = 707406378, // '****'
331
FSRef = 1718841958, // 'fsrf'
334
internal enum CarbonEventClass : uint
336
Mouse = 1836021107, // 'mous'
337
Keyboard = 1801812322, // 'keyb'
338
TextInput = 1952807028, // 'text'
339
Application = 1634758764, // 'appl'
340
RemoteAppleEvent = 1701867619, //'eppc' //remote apple event?
341
Menu = 1835363957, // 'menu'
342
Window = 2003398244, // 'wind'
343
Control = 1668183148, // 'cntl'
344
Command = 1668113523, // 'cmds'
345
Tablet = 1952607348, // 'tblt'
346
Volume = 1987013664, // 'vol '
347
Appearance = 1634758765, // 'appm'
348
Service = 1936028278, // 'serv'
349
Toolbar = 1952604530, // 'tbar'
350
ToolbarItem = 1952606580, // 'tbit'
351
Accessibility = 1633903461, // 'acce'
352
HIObject = 1751740258, // 'hiob'
353
AppleEvent = 1634039412, // 'aevt'
354
Internet = 1196773964, // 'GURL'
357
public enum CarbonCommandID : uint
359
OK = 1869291552, // 'ok '
360
Cancel = 1852797985, // 'not!'
361
Quit = 1903520116, // 'quit'
362
Undo = 1970168943, // 'undo'
363
Redo = 1919247471, // 'redo'
364
Cut = 1668641824, // 'cut '
365
Copy = 1668247673, // 'copy'
366
Paste = 1885434740, // 'past'
367
Clear = 1668048225, // 'clea',
368
SelectAll = 1935764588, // 'sall',
369
Preferences = 1886545254, //'pref'
370
About = 1633841013, // 'abou'
371
New = 1852143392, // 'new ',
372
Open = 1869636974, // 'open'
373
Close = 1668050803, // 'clos'
374
Save = 1935767141, // 'save',
375
SaveAs = 1937138035, // 'svas'
376
Revert = 1920365172, // 'rvrt'
377
Print = 1886547572, // 'prnt'
378
PageSetup = 1885431653, // 'page',
379
AppHelp = 1634233456, //'ahlp'
381
//menu manager handles these automatically
383
Hide = 1751737445, // 'hide'
384
HideOthers = 1751737455, // 'hido'
385
ShowAll = 1936220524, // 'shal'
386
ZoomWindow = 2054123373, // 'zoom'
387
MinimizeWindow = 1835626089, // 'mini'
388
MinimizeAll = 1835626081, // 'mina'
389
MaximizeAll = 1835104353, // 'maxa'
390
ArrangeInFront = 1718775412, // 'frnt'
391
BringAllToFront = 1650881140, // 'bfrt'
392
SelectWindow = 1937205614, // 'swin'
393
RotateWindowsForward = 1919906935, // 'rotw'
394
RotateWindowsBackward = 1919906914, // 'rotb'
395
RotateFloatingWindowsForward = 1920231031, // 'rtfw'
396
RotateFloatingWindowsBackward = 1920231010, // 'rtfb'
398
//created automatically -- used for inserting before/after the default window list
399
WindowListSeparator = 2003592310, // 'wldv'
400
WindowListTerminator = 2003596148, // 'wlst'
403
internal enum CarbonEventCommand : uint
409
internal enum CarbonEventMenu : uint
413
ChangeTrackingMode = 3,
420
internal enum CarbonEventAttributes : uint
423
UserEvent = (1 << 0),
427
internal enum CarbonEventApple
429
OpenApplication = 1868656752, // 'oapp'
430
ReopenApplication = 1918988400, //'rapp'
431
OpenDocuments = 1868853091, // 'odoc'
432
PrintDocuments = 188563030, // 'pdoc'
433
OpenContents = 1868787566, // 'ocon'
434
QuitApplication = 1903520116, // 'quit'
435
ShowPreferences = 1886545254, // 'pref'
436
ApplicationDied = 1868720500, // 'obit'
437
GetUrl = 1196773964, // 'GURL'
440
[StructLayout(LayoutKind.Sequential, Pack = 2)]
441
struct CarbonEventTypeSpec
443
public CarbonEventClass EventClass;
444
public uint EventKind;
446
public CarbonEventTypeSpec (CarbonEventClass eventClass, UInt32 eventKind)
448
this.EventClass = eventClass;
449
this.EventKind = eventKind;
452
public CarbonEventTypeSpec (CarbonEventMenu kind) : this (CarbonEventClass.Menu, (uint) kind)
456
public CarbonEventTypeSpec (CarbonEventCommand kind) : this (CarbonEventClass.Command, (uint) kind)
461
public CarbonEventTypeSpec (CarbonEventApple kind) : this (CarbonEventClass.AppleEvent, (uint) kind)
465
public static implicit operator CarbonEventTypeSpec (CarbonEventMenu kind)
467
return new CarbonEventTypeSpec (kind);
470
public static implicit operator CarbonEventTypeSpec (CarbonEventCommand kind)
472
return new CarbonEventTypeSpec (kind);
475
public static implicit operator CarbonEventTypeSpec (CarbonEventApple kind)
477
return new CarbonEventTypeSpec (kind);
481
class EventStatusException : SystemException
483
public EventStatusException (EventStatus status)
488
public EventStatus StatusCode {
493
enum EventStatus // this is an OSStatus
498
EventAlreadyPostedErr = -9860,
499
EventTargetBusyErr = -9861,
500
EventClassInvalidErr = -9862,
501
EventClassIncorrectErr = -9864,
502
EventHandlerAlreadyInstalledErr = -9866,
503
EventInternalErr = -9868,
504
EventKindIncorrectErr = -9869,
505
EventParameterNotFoundErr = -9870,
506
EventNotHandledErr = -9874,
507
EventLoopTimedOutErr = -9875,
508
EventLoopQuitErr = -9876,
509
EventNotInQueueErr = -9877,
510
EventHotKeyExistsErr = -9878,
511
EventHotKeyInvalidErr = -9879,
514
[StructLayout(LayoutKind.Explicit)]
515
struct CarbonHICommand //technically HICommandExtended, but they're compatible
518
CarbonHICommandAttributes attributes;
532
public CarbonHICommand (uint commandID, HIMenuItem item)
534
windowRef = controlRef = IntPtr.Zero;
535
this.commandID = commandID;
536
this.menuItem = item;
537
this.attributes = CarbonHICommandAttributes.FromMenu;
540
public CarbonHICommandAttributes Attributes { get { return attributes; } }
541
public uint CommandID { get { return commandID; } }
542
public IntPtr ControlRef { get { return controlRef; } }
543
public IntPtr WindowRef { get { return windowRef; } }
544
public HIMenuItem MenuItem { get { return menuItem; } }
546
public bool IsFromMenu {
547
get { return attributes == CarbonHICommandAttributes.FromMenu; }
550
public bool IsFromControl {
551
get { return attributes == CarbonHICommandAttributes.FromControl; }
554
public bool IsFromWindow {
555
get { return attributes == CarbonHICommandAttributes.FromWindow; }
559
[StructLayout(LayoutKind.Sequential, Pack = 2)]
565
public HIMenuItem (IntPtr menuRef, ushort index)
568
this.menuRef = menuRef;
571
public IntPtr MenuRef { get { return menuRef; } }
572
public ushort Index { get { return index; } }
576
enum CarbonHICommandAttributes : uint
579
FromControl = 1 << 1,
583
[StructLayout(LayoutKind.Sequential, Pack = 2)]
584
struct FileTranslationSpec
586
uint componentSignature; // OSType
587
IntPtr translationSystemInfo; // void*
592
[StructLayout(LayoutKind.Sequential, Pack = 2)]
595
uint format; // FileType
597
TranslationAttributes flags;
598
uint catInfoType; // OSType
599
uint catInfoCreator; // OSType
607
get { return Value; }
610
public OSType (int value)
615
public OSType (string fourcc)
617
value = Carbon.ConvertCharCode (fourcc);
620
public static explicit operator OSType (string fourcc)
622
return new OSType (fourcc);
625
public static implicit operator int (OSType o)
630
public static implicit operator OSType (int i)
632
return new OSType (i);