[Mono-winforms-list] XplatUIOSX.cs

kangaroo grompf@sublimeintervention.com
Fri, 3 Dec 2004 17:19:32 -0500


--Apple-Mail-2--748879518
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed

I spent some time today hacking on some POC code that XplatUIOSX will 
be possible with a working quartz backend.

Attached to this mail (just for tracking purposes) is a small piece of 
C# code that will:

Create a Carbon window
Start an event loop
Handle the events (only mousedown is being handled for now)
Exit if you click on the window.

Anyone who wants to try this on OSX please know that my patch to 
mono-codeman.c sent to m-d-l today needs to be applied for this to 
work.

This doesn't really "do" anything; other than prove we can create the 
window and capture events.  A good starting point for anyone else 
digging into this more.

If I have time over the next few weeks I'll start translating this into 
a real XplatUIOSX.cs with the proper calls etc in preparation for a 
quartz backend,

-kangaroo

--Apple-Mail-2--748879518
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream;
	x-unix-mode=0644;
	name="CarbonWindow.cs"
Content-Disposition: attachment;
	filename=CarbonWindow.cs

using System;
using System.Runtime.InteropServices;

public enum EventKind : ushort {
	nullEvent = 0,
	mouseDown = 1,
	mouseUp = 2,
	keyDown = 3,
	keyUp = 4,
	autoKey = 5,
	updateEvt = 6,
	diskEvt = 7,
	activateEvt = 8,
	osEvt = 15,
	kHighLevelEvent = 23
}

public enum EventMask {
	mDownMask = 1 << EventKind.mouseDown,
	mUpMask = 1 << EventKind.mouseUp,
	keyDownMask = 1 << EventKind.keyDown,
	keyUpMask = 1 << EventKind.keyUp,
	autoKeyMask = 1 << EventKind.autoKey,
	updateMask = 1 << EventKind.updateEvt,
	diskMask = 1 << EventKind.diskEvt,
	activMask = 1 << EventKind.activateEvt,
	highLevelEventMask = 0x0400,
	osMask = 1 << EventKind.osEvt,
	everyEvent = 0xFFFF
}
public enum EventModifiers {
	activeFlagBit = 0,
	btnStateBit = 7,
	cmdKeyBit = 8,
	shiftKeyBit = 9,
	alphaLockBit = 10,
	optionKeyBit = 11,
	controlKeyBit = 12,
	rightShiftKeyBit = 13,
	rightOptionKeyBit = 14,
	rightControlKeyBit = 15
}
public struct Point {
	short    v;
	short    h;
}
public struct EventRecord {
	public EventKind         what;
	public UInt32            message;
	public UInt32            when;
	public Point             where;
	public EventModifiers    modifiers;
}
public struct Rect 
{
	short top;
	short left;
	short bottom;
	short right;
}

public struct EventTypeSpec 
{
	public EventClass eventClass;
	public UInt32 eventKind;
}

public enum EventClass : uint
{
	kEventClassMouse,
	kEventClassKeyboard,
	kEventClassTextInput,
	kEventClassApplication,
	kEventClassAppleEvent,
	kEventClassMenu,
	kEventClassWindow = 2003398244,
	kEventClassControl,
	kEventClassCommand,
	kEventClassTablet,
	kEventClassVolume,
	kEventClassAppearance,
	kEventClassService,
	kEventClassToolbar,
	kEventClassToolbarItem,
	kEventClassAccessibility
}

public enum OSStatus 
{
	noErr = 0,
	paramErr = -50,
	memFullErr = -108,
	resNotFound = -192,
	errInvalidWindowPtr = -5600,
	errUnsupportedWindowAttributesForClass = -5601,
	errWindowDoesNotHaveProxy = -5602,
	errInvalidWindowProperty = -5603,
	errWindowPropertyNotFound = -5604,
	errUnrecognizedWindowClass = -5605,
	errCorruptWindowDescription = -5606,
	errUserWantsToDragWindow = -5607,
	errWindowsAlreadyInitialized = -5608,
	errFloatingWindowsNotInitialized = -5609
}

public enum WindowClass : uint 
{
	kAlertWindowClass = 1,
	kMovableAlertWindowClass = 2,
	kModalWindowClass = 3,
	kMovableModalWindowClass = 4,
	kFloatingWindowClass = 5,
	kDocumentWindowClass = 6,
	kUtilityWindowClass = 8,
	kHelpWindowClass = 10,
	kSheetWindowClass = 11,
	kToolbarWindowClass = 12,
	kPlainWindowClass = 13,
	kOverlayWindowClass = 14,
	kSheetAlertWindowClass = 15,
	kAltPlainWindowClass = 16,
	kDrawerWindowClass = 20,
	kAllWindowClasses = 0xFFFFFFFF
}

public enum WindowAttributes : uint
{
	kWindowNoAttributes = 0,
	kWindowCloseBoxAttribute = (1L << 0),
	kWindowHorizontalZoomAttribute = (1L << 1),
	kWindowVerticalZoomAttribute = (1L << 2),
	kWindowFullZoomAttribute = (kWindowVerticalZoomAttribute | kWindowHorizontalZoomAttribute),
	kWindowCollapseBoxAttribute = (1L << 3),
	kWindowResizableAttribute = (1L << 4),
	kWindowSideTitlebarAttribute = (1L << 5),
	kWindowToolbarButtonAttribute = (1L << 6),
	kWindowMetalAttribute = (1L << 8),
	kWindowNoUpdatesAttribute = (1L << 16),
	kWindowNoActivatesAttribute = (1L << 17),
	kWindowOpaqueForEventsAttribute = (1L << 18),
	kWindowCompositingAttribute = (1L << 19),
	kWindowNoShadowAttribute = (1L << 21),
	kWindowHideOnSuspendAttribute = (1L << 24),
	kWindowStandardHandlerAttribute = (1L << 25),
	kWindowHideOnFullScreenAttribute = (1L << 26),
	kWindowInWindowMenuAttribute = (1L << 27),
	kWindowLiveResizeAttribute = (1L << 28),
	kWindowIgnoreClicksAttribute = (1L << 29),
	kWindowNoConstrainAttribute = (1L << 31),
	kWindowStandardDocumentAttributes = (kWindowCloseBoxAttribute | kWindowFullZoomAttribute | kWindowCollapseBoxAttribute | kWindowResizableAttribute),
	kWindowStandardFloatingAttributes = (kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute)
}

public class CarbonTest
{
	private static bool stop = false;
	Rect r;
	OSStatus status;
	IntPtr window;
	delegate int EventHandler (IntPtr inCallRef, IntPtr inEvent, IntPtr userData);

	public CarbonTest ()
	{
	}

	public static int HandleEvent (EventRecord eventRecord)
	{
		switch (eventRecord.what)
		{
			case EventKind.mouseDown:
				Console.WriteLine ("mdown");
				stop = true;
				break;
			default:
				Console.WriteLine ("unknown event: {0}", eventRecord.what);
				break;
		}
		return 1;
	}
	public int WindowEventHandler (IntPtr inCallRef, IntPtr inEvent, IntPtr userData)
	{
		Console.WriteLine ("Received an event!");
		QuitApplicationEventLoop();
		return (int)OSStatus.noErr;
	}

	public void NewWindow ()
	{
		SetRect (ref r, 30, 60, 30 + 400, 60 + 400);
		status = CreateNewWindow (WindowClass.kDocumentWindowClass,
					  WindowAttributes.kWindowStandardHandlerAttribute,
					  ref r,
					  ref window);
		Console.WriteLine ("CNWINDOW: {0}", status);
		EventTypeSpec [] windowEvents = new EventTypeSpec [2];
		windowEvents [0] = new EventTypeSpec ();
		windowEvents [0].eventClass = EventClass.kEventClassWindow; 
		windowEvents [0].eventKind = 2;
		windowEvents [1] = new EventTypeSpec ();
		windowEvents [1].eventClass = EventClass.kEventClassWindow; 
		windowEvents [1].eventKind = 2;
		EventHandler evtHandler = new EventHandler (WindowEventHandler);
		IntPtr uppHandler = NewEventHandlerUPP (evtHandler);
		Console.WriteLine ("UPP Handler: {0} {0:x}", (int)uppHandler);
//		status = InstallEventHandler (GetWindowEventTarget (window), uppHandler, GetEventTypeCount (windowEvents), windowEvents, window, IntPtr.Zero);
		Console.WriteLine ("EVT HANDLER: {0}", status);
		ShowWindow (window);
		Console.WriteLine ("WINDOW RENDERED");

	}

	public uint GetEventTypeCount (EventTypeSpec [] windowEvents)
	{
		return (uint)windowEvents.Length;
	}

	static void Main (string[] args)
	{
		CarbonTest t = new CarbonTest ();
		t.NewWindow ();
		Console.WriteLine ("INTO EVENT LOOP");
		//RunApplicationEventLoop ();
		while (!stop)
		{
			Console.WriteLine ("looping...");
			EventRecord eventRecord = new EventRecord ();
			if (WaitNextEvent (EventMask.everyEvent, ref eventRecord, 1000, IntPtr.Zero)) {
				Console.WriteLine ("\tgot an event...");
				HandleEvent (eventRecord);
				Console.WriteLine ("\thandled an event...");
			}
		}
		Console.WriteLine ("siyanora!");
	}
	
	[DllImport ("/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/ApplicationServices")]
	static extern void SetRect (ref Rect r, short left, short top, short right, short bottom);
	[DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
	static extern OSStatus CreateNewWindow (WindowClass klass, WindowAttributes attributes, ref Rect r, ref IntPtr window);
	[DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
	static extern void ShowWindow (IntPtr window);
	[DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
	static extern OSStatus InstallEventHandler (IntPtr window, IntPtr handlerProc, uint numtypes, EventTypeSpec [] typeList, IntPtr userData, IntPtr handlerRef);
	[DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
	static extern IntPtr GetWindowEventTarget (IntPtr window);
	[DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
	static extern IntPtr NewEventHandlerUPP (EventHandler handler);
	[DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
	static extern bool WaitNextEvent (EventMask eventMask, ref EventRecord eventRecrod, uint sleep, IntPtr mouseRgn);
	[DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
	static extern void RunApplicationEventLoop ();
	[DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
	static extern void QuitApplicationEventLoop ();
}

--Apple-Mail-2--748879518--