00001 #region License
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #endregion
00027
00028 using System;
00029 using System.Collections.Generic;
00030 using System.ComponentModel;
00031 using System.Diagnostics;
00032 using System.Drawing;
00033 using System.Text;
00034
00035 namespace OpenTK.Platform.MacOS
00036 {
00037 using Carbon;
00038 using Graphics;
00039
00040 class CarbonGLNative : INativeWindow
00041 {
00042 #region Fields
00043
00044 CarbonWindowInfo window;
00045 CarbonInput mInputDriver;
00046
00047 static MacOSKeyMap Keymap = new MacOSKeyMap();
00048
00049 IntPtr uppHandler;
00050
00051 string title = "OpenTK Window";
00052 Rectangle bounds, clientRectangle;
00053 Rectangle windowedBounds;
00054 bool mIsDisposed = false;
00055 bool mExists = true;
00056 DisplayDevice mDisplayDevice;
00057
00058 WindowAttributes mWindowAttrib;
00059 WindowClass mWindowClass;
00060 WindowPositionMethod mPositionMethod = WindowPositionMethod.CenterOnMainScreen;
00061 int mTitlebarHeight;
00062 private WindowBorder windowBorder = WindowBorder.Resizable;
00063 private WindowState windowState = WindowState.Normal;
00064
00065 static Dictionary<IntPtr, WeakReference> mWindows = new Dictionary<IntPtr, WeakReference>();
00066
00067 KeyPressEventArgs mKeyPressArgs = new KeyPressEventArgs((char)0);
00068
00069 bool mMouseIn = false;
00070 bool mIsActive = false;
00071
00072 Icon mIcon;
00073
00074 #endregion
00075
00076 #region AGL Device Hack
00077
00078 static internal Dictionary<IntPtr, WeakReference> WindowRefMap { get { return mWindows; } }
00079 internal DisplayDevice TargetDisplayDevice { get { return mDisplayDevice; } }
00080
00081 #endregion
00082
00083 #region Constructors
00084
00085 static CarbonGLNative()
00086 {
00087 Application.Initialize();
00088 }
00089
00090 CarbonGLNative()
00091 : this(WindowClass.Document,
00092 WindowAttributes.StandardDocument |
00093 WindowAttributes.StandardHandler |
00094 WindowAttributes.InWindowMenu |
00095 WindowAttributes.LiveResize)
00096 { }
00097
00098
00099 CarbonGLNative(WindowClass @class, WindowAttributes attrib)
00100 {
00101 mWindowClass = @class;
00102 mWindowAttrib = attrib;
00103 }
00104
00105 public CarbonGLNative(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
00106 {
00107 CreateNativeWindow(WindowClass.Document,
00108 WindowAttributes.StandardDocument | WindowAttributes.StandardHandler |
00109 WindowAttributes.InWindowMenu | WindowAttributes.LiveResize,
00110 new Rect((short)x, (short)y, (short)width, (short)height));
00111
00112 mDisplayDevice = device;
00113 }
00114
00115 #endregion
00116
00117 #region IDisposable
00118
00119 public void Dispose()
00120 {
00121 Dispose(true);
00122 GC.SuppressFinalize(this);
00123 }
00124
00125 protected virtual void Dispose(bool disposing)
00126 {
00127 if (mIsDisposed)
00128 return;
00129
00130 Debug.Print("Disposing of CarbonGLNative window.");
00131
00132 API.DisposeWindow(window.WindowRef);
00133
00134 mIsDisposed = true;
00135 mExists = false;
00136
00137 if (disposing)
00138 {
00139 mWindows.Remove(window.WindowRef);
00140
00141 window.Dispose();
00142 window = null;
00143 }
00144
00145 DisposeUPP();
00146
00147 }
00148
00149 ~CarbonGLNative()
00150 {
00151 Dispose(false);
00152 }
00153
00154 #endregion
00155
00156 #region Private Members
00157
00158 void DisposeUPP()
00159 {
00160 if (uppHandler != IntPtr.Zero)
00161 {
00162
00163
00164 }
00165
00166 uppHandler = IntPtr.Zero;
00167 }
00168
00169 void CreateNativeWindow(WindowClass @class, WindowAttributes attrib, Rect r)
00170 {
00171 Debug.Print("Creating window...");
00172 Debug.Indent();
00173
00174 IntPtr windowRef = API.CreateNewWindow(@class, attrib, r);
00175 API.SetWindowTitle(windowRef, title);
00176
00177 window = new CarbonWindowInfo(windowRef, true, false);
00178
00179 SetLocation(r.X, r.Y);
00180 SetSize(r.Width, r.Height);
00181
00182 Debug.Unindent();
00183 Debug.Print("Created window.");
00184
00185 mWindows.Add(windowRef, new WeakReference(this));
00186
00187 LoadSize();
00188
00189 Rect titleSize = API.GetWindowBounds(window.WindowRef, WindowRegionCode.TitleBarRegion);
00190 mTitlebarHeight = titleSize.Height;
00191
00192 Debug.Print("Titlebar size: {0}", titleSize);
00193
00194 ConnectEvents();
00195
00196 System.Diagnostics.Debug.Print("Attached window events.");
00197 }
00198
00199 void ConnectEvents()
00200 {
00201 mInputDriver = new CarbonInput();
00202
00203 EventTypeSpec[] eventTypes = new EventTypeSpec[]
00204 {
00205 new EventTypeSpec(EventClass.Window, WindowEventKind.WindowClose),
00206 new EventTypeSpec(EventClass.Window, WindowEventKind.WindowClosed),
00207 new EventTypeSpec(EventClass.Window, WindowEventKind.WindowBoundsChanged),
00208 new EventTypeSpec(EventClass.Window, WindowEventKind.WindowActivate),
00209 new EventTypeSpec(EventClass.Window, WindowEventKind.WindowDeactivate),
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 };
00224
00225 MacOSEventHandler handler = EventHandler;
00226 uppHandler = API.NewEventHandlerUPP(handler);
00227
00228 API.InstallWindowEventHandler(window.WindowRef, uppHandler, eventTypes, window.WindowRef, IntPtr.Zero);
00229
00230 Application.WindowEventHandler = this;
00231 }
00232
00233 void Activate()
00234 {
00235 API.SelectWindow(window.WindowRef);
00236 }
00237
00238 void Show()
00239 {
00240 IntPtr parent = IntPtr.Zero;
00241
00242 API.ShowWindow(window.WindowRef);
00243 API.RepositionWindow(window.WindowRef, parent, WindowPositionMethod);
00244 API.SelectWindow(window.WindowRef);
00245 }
00246
00247 void Hide()
00248 {
00249 API.HideWindow(window.WindowRef);
00250 }
00251
00252 internal void SetFullscreen(AglContext context)
00253 {
00254 windowedBounds = bounds;
00255
00256 int width, height;
00257
00258 context.SetFullScreen(window, out width, out height);
00259
00260 Debug.Print("Prev Size: {0}, {1}", Width, Height);
00261 clientRectangle.Size = new Size(width, height);
00262 Debug.Print("New Size: {0}, {1}", Width, Height);
00263
00264
00265 bounds = mDisplayDevice.Bounds;
00266
00267
00268 windowState = WindowState.Fullscreen;
00269 }
00270
00271 internal void UnsetFullscreen(AglContext context)
00272 {
00273 context.UnsetFullScreen(window);
00274
00275 Debug.Print("Telling Carbon to reset window state to " + windowState.ToString());
00276 SetCarbonWindowState();
00277
00278 SetSize((short)windowedBounds.Width, (short)windowedBounds.Height);
00279 }
00280
00281 bool IsDisposed
00282 {
00283 get { return mIsDisposed; }
00284 }
00285
00286 WindowPositionMethod WindowPositionMethod
00287 {
00288 get { return mPositionMethod; }
00289 set { mPositionMethod = value; }
00290 }
00291
00292 internal OSStatus DispatchEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData)
00293 {
00294 switch (evt.EventClass)
00295 {
00296 case EventClass.Window:
00297 return ProcessWindowEvent(inCaller, inEvent, evt, userData);
00298
00299 case EventClass.Mouse:
00300 return ProcessMouseEvent(inCaller, inEvent, evt, userData);
00301
00302 case EventClass.Keyboard:
00303 return ProcessKeyboardEvent(inCaller, inEvent, evt, userData);
00304
00305 default:
00306 return OSStatus.EventNotHandled;
00307 }
00308 }
00309
00310 protected static OSStatus EventHandler(IntPtr inCaller, IntPtr inEvent, IntPtr userData)
00311 {
00312
00313
00314 if (mWindows.ContainsKey(userData) == false)
00315 return OSStatus.EventNotHandled;
00316
00317 WeakReference reference = mWindows[userData];
00318
00319
00320 if (reference.IsAlive == false)
00321 {
00322 mWindows.Remove(userData);
00323 return OSStatus.EventNotHandled;
00324 }
00325
00326 CarbonGLNative window = (CarbonGLNative)reference.Target;
00327 EventInfo evt = new EventInfo(inEvent);
00328
00329
00330
00331 if (window == null)
00332 {
00333 Debug.WriteLine("Window for event not found.");
00334 return OSStatus.EventNotHandled;
00335 }
00336
00337 switch (evt.EventClass)
00338 {
00339 case EventClass.Window:
00340 return window.ProcessWindowEvent(inCaller, inEvent, evt, userData);
00341
00342 case EventClass.Mouse:
00343 return window.ProcessMouseEvent(inCaller, inEvent, evt, userData);
00344
00345 case EventClass.Keyboard:
00346 return window.ProcessKeyboardEvent(inCaller, inEvent, evt, userData);
00347
00348 default:
00349 return OSStatus.EventNotHandled;
00350 }
00351 }
00352
00353 private OSStatus ProcessKeyboardEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData)
00354 {
00355 System.Diagnostics.Debug.Assert(evt.EventClass == EventClass.Keyboard);
00356 MacOSKeyCode code = (MacOSKeyCode)0;
00357 char charCode = '\0';
00358
00359
00360
00361 switch (evt.KeyboardEventKind)
00362 {
00363 case KeyboardEventKind.RawKeyDown:
00364 case KeyboardEventKind.RawKeyRepeat:
00365 case KeyboardEventKind.RawKeyUp:
00366 GetCharCodes(inEvent, out code, out charCode);
00367 mKeyPressArgs.KeyChar = charCode;
00368 break;
00369 }
00370
00371 switch (evt.KeyboardEventKind)
00372 {
00373 case KeyboardEventKind.RawKeyRepeat:
00374 InputDriver.Keyboard[0].KeyRepeat = true;
00375 goto case KeyboardEventKind.RawKeyDown;
00376
00377 case KeyboardEventKind.RawKeyDown:
00378 OnKeyPress(mKeyPressArgs);
00379 InputDriver.Keyboard[0][Keymap[code]] = true;
00380 return OSStatus.NoError;
00381
00382 case KeyboardEventKind.RawKeyUp:
00383 InputDriver.Keyboard[0][Keymap[code]] = false;
00384
00385 return OSStatus.NoError;
00386
00387 case KeyboardEventKind.RawKeyModifiersChanged:
00388 ProcessModifierKey(inEvent);
00389 return OSStatus.NoError;
00390
00391 default:
00392 return OSStatus.EventNotHandled;
00393 }
00394
00395
00396 }
00397
00398 private OSStatus ProcessWindowEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData)
00399 {
00400 System.Diagnostics.Debug.Assert(evt.EventClass == EventClass.Window);
00401
00402 switch (evt.WindowEventKind)
00403 {
00404 case WindowEventKind.WindowClose:
00405 CancelEventArgs cancel = new CancelEventArgs();
00406 OnClosing(cancel);
00407
00408 if (cancel.Cancel)
00409 return OSStatus.NoError;
00410 else
00411 return OSStatus.EventNotHandled;
00412
00413 case WindowEventKind.WindowClosed:
00414 mExists = false;
00415 OnClosed();
00416
00417 return OSStatus.NoError;
00418
00419 case WindowEventKind.WindowBoundsChanged:
00420 int thisWidth = Width;
00421 int thisHeight = Height;
00422
00423 LoadSize();
00424
00425 if (thisWidth != Width || thisHeight != Height)
00426 OnResize();
00427
00428 return OSStatus.EventNotHandled;
00429
00430 case WindowEventKind.WindowActivate:
00431 OnActivate();
00432 return OSStatus.EventNotHandled;
00433
00434 case WindowEventKind.WindowDeactivate:
00435 OnDeactivate();
00436 return OSStatus.EventNotHandled;
00437
00438 default:
00439 Debug.Print("{0}", evt);
00440
00441 return OSStatus.EventNotHandled;
00442 }
00443 }
00444 protected OSStatus ProcessMouseEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData)
00445 {
00446 System.Diagnostics.Debug.Assert(evt.EventClass == EventClass.Mouse);
00447 MouseButton button = MouseButton.Primary;
00448 HIPoint pt = new HIPoint();
00449 HIPoint screenLoc = new HIPoint();
00450
00451 OSStatus err = API.GetEventMouseLocation(inEvent, out screenLoc);
00452
00453 if (this.windowState == WindowState.Fullscreen)
00454 {
00455 pt = screenLoc;
00456 }
00457 else
00458 {
00459 err = API.GetEventWindowMouseLocation(inEvent, out pt);
00460 }
00461
00462 if (err != OSStatus.NoError)
00463 {
00464
00465 if (err != OSStatus.EventParameterNotFound)
00466 {
00467 throw new MacOSException(err);
00468 }
00469 }
00470
00471 Point mousePosInClient = new Point((int)pt.X, (int)pt.Y);
00472 if (this.windowState != WindowState.Fullscreen)
00473 {
00474 mousePosInClient.Y -= mTitlebarHeight;
00475 }
00476
00477
00478 IntPtr thisEventWindow;
00479 API.GetEventWindowRef(inEvent, out thisEventWindow);
00480 CheckEnterLeaveEvents(thisEventWindow, mousePosInClient);
00481
00482 switch (evt.MouseEventKind)
00483 {
00484 case MouseEventKind.MouseDown:
00485 button = API.GetEventMouseButton(inEvent);
00486
00487 switch (button)
00488 {
00489 case MouseButton.Primary:
00490 InputDriver.Mouse[0][OpenTK.Input.MouseButton.Left] = true;
00491 break;
00492
00493 case MouseButton.Secondary:
00494 InputDriver.Mouse[0][OpenTK.Input.MouseButton.Right] = true;
00495 break;
00496
00497 case MouseButton.Tertiary:
00498 InputDriver.Mouse[0][OpenTK.Input.MouseButton.Middle] = true;
00499 break;
00500 }
00501
00502
00503 return OSStatus.NoError;
00504
00505 case MouseEventKind.MouseUp:
00506 button = API.GetEventMouseButton(inEvent);
00507
00508 switch (button)
00509 {
00510 case MouseButton.Primary:
00511 InputDriver.Mouse[0][OpenTK.Input.MouseButton.Left] = false;
00512 break;
00513
00514 case MouseButton.Secondary:
00515 InputDriver.Mouse[0][OpenTK.Input.MouseButton.Right] = false;
00516 break;
00517
00518 case MouseButton.Tertiary:
00519 InputDriver.Mouse[0][OpenTK.Input.MouseButton.Middle] = false;
00520 break;
00521 }
00522
00523 button = API.GetEventMouseButton(inEvent);
00524
00525 return OSStatus.NoError;
00526
00527 case MouseEventKind.WheelMoved:
00528
00529 int delta = API.GetEventMouseWheelDelta(inEvent) / 3;
00530
00531 InputDriver.Mouse[0].Wheel += delta;
00532
00533 return OSStatus.NoError;
00534
00535 case MouseEventKind.MouseMoved:
00536 case MouseEventKind.MouseDragged:
00537
00538
00539
00540 if (this.windowState == WindowState.Fullscreen)
00541 {
00542 if (mousePosInClient.X != InputDriver.Mouse[0].X ||
00543 mousePosInClient.Y != InputDriver.Mouse[0].Y)
00544 {
00545 InputDriver.Mouse[0].Position = mousePosInClient;
00546 }
00547 }
00548 else
00549 {
00550
00551 if (pt.Y < 0)
00552 return OSStatus.EventNotHandled;
00553
00554 if (mousePosInClient.X != InputDriver.Mouse[0].X ||
00555 mousePosInClient.Y != InputDriver.Mouse[0].Y)
00556 {
00557 InputDriver.Mouse[0].Position = mousePosInClient;
00558 }
00559 }
00560
00561 return OSStatus.EventNotHandled;
00562
00563 default:
00564 Debug.Print("{0}", evt);
00565
00566 return OSStatus.EventNotHandled;
00567 }
00568 }
00569
00570 private void CheckEnterLeaveEvents(IntPtr eventWindowRef, Point pt)
00571 {
00572 if (window == null)
00573 return;
00574
00575 bool thisIn = eventWindowRef == window.WindowRef;
00576
00577 if (pt.Y < 0)
00578 thisIn = false;
00579
00580 if (thisIn != mMouseIn)
00581 {
00582 mMouseIn = thisIn;
00583
00584 if (mMouseIn)
00585 OnMouseEnter();
00586 else
00587 OnMouseLeave();
00588 }
00589 }
00590
00591 private static void GetCharCodes(IntPtr inEvent, out MacOSKeyCode code, out char charCode)
00592 {
00593 code = API.GetEventKeyboardKeyCode(inEvent);
00594 charCode = API.GetEventKeyboardChar(inEvent);
00595 }
00596 private void ProcessModifierKey(IntPtr inEvent)
00597 {
00598 MacOSKeyModifiers modifiers = API.GetEventKeyModifiers(inEvent);
00599
00600 bool caps = (modifiers & MacOSKeyModifiers.CapsLock) != 0 ? true : false;
00601 bool control = (modifiers & MacOSKeyModifiers.Control) != 0 ? true : false;
00602 bool command = (modifiers & MacOSKeyModifiers.Command) != 0 ? true : false;
00603 bool option = (modifiers & MacOSKeyModifiers.Option) != 0 ? true : false;
00604 bool shift = (modifiers & MacOSKeyModifiers.Shift) != 0 ? true : false;
00605
00606 Debug.Print("Modifiers Changed: {0}", modifiers);
00607
00608 Input.KeyboardDevice keyboard = InputDriver.Keyboard[0];
00609
00610 if (keyboard[OpenTK.Input.Key.AltLeft] ^ option)
00611 keyboard[OpenTK.Input.Key.AltLeft] = option;
00612
00613 if (keyboard[OpenTK.Input.Key.ShiftLeft] ^ shift)
00614 keyboard[OpenTK.Input.Key.ShiftLeft] = shift;
00615
00616 if (keyboard[OpenTK.Input.Key.WinLeft] ^ command)
00617 keyboard[OpenTK.Input.Key.WinLeft] = command;
00618
00619 if (keyboard[OpenTK.Input.Key.ControlLeft] ^ control)
00620 keyboard[OpenTK.Input.Key.ControlLeft] = control;
00621
00622 if (keyboard[OpenTK.Input.Key.CapsLock] ^ caps)
00623 keyboard[OpenTK.Input.Key.CapsLock] = caps;
00624
00625 }
00626
00627 Rect GetRegion()
00628 {
00629 Rect retval = API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
00630
00631 return retval;
00632 }
00633
00634 void SetLocation(short x, short y)
00635 {
00636 if (windowState == WindowState.Fullscreen)
00637 return;
00638
00639 API.MoveWindow(window.WindowRef, x, y, false);
00640 }
00641
00642 void SetSize(short width, short height)
00643 {
00644 if (WindowState == WindowState.Fullscreen)
00645 return;
00646
00647
00648
00649
00650 width -= (short)(bounds.Width - clientRectangle.Width);
00651 height -= (short)(bounds.Height - clientRectangle.Height);
00652
00653 API.SizeWindow(window.WindowRef, width, height, true);
00654 }
00655
00656 void SetClientSize(short width, short height)
00657 {
00658 if (WindowState == WindowState.Fullscreen)
00659 return;
00660
00661 API.SizeWindow(window.WindowRef, width, height, true);
00662 }
00663
00664 protected void OnResize()
00665 {
00666 LoadSize();
00667
00668 if (Resize != null)
00669 {
00670 Resize(this, EventArgs.Empty);
00671 }
00672 }
00673
00674 private void LoadSize()
00675 {
00676 if (WindowState == WindowState.Fullscreen)
00677 return;
00678
00679 Rect r = API.GetWindowBounds(window.WindowRef, WindowRegionCode.StructureRegion);
00680 bounds = new Rectangle(r.X, r.Y, r.Width, r.Height);
00681
00682 r = API.GetWindowBounds(window.WindowRef, WindowRegionCode.GlobalPortRegion);
00683 clientRectangle = new Rectangle(0, 0, r.Width, r.Height);
00684 }
00685
00686 #endregion
00687
00688 #region INativeWindow Members
00689
00690 public void ProcessEvents()
00691 {
00692 Application.ProcessEvents();
00693 }
00694
00695 public Point PointToClient(Point point)
00696 {
00697 IntPtr handle = window.WindowRef;
00698
00699 Rect r = Carbon.API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
00700 Debug.Print("Rect: {0}", r);
00701
00702 return new Point(point.X - r.X, point.Y - r.Y);
00703 }
00704 public Point PointToScreen(Point point)
00705 {
00706 IntPtr handle = window.WindowRef;
00707
00708 Rect r = Carbon.API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
00709 Debug.Print("Rect: {0}", r);
00710
00711 return new Point(point.X + r.X, point.Y + r.Y);
00712 }
00713
00714 public bool Exists
00715 {
00716 get { return mExists; }
00717 }
00718
00719 public IWindowInfo WindowInfo
00720 {
00721 get { return window; }
00722 }
00723
00724 public bool IsIdle
00725 {
00726 get { return true; }
00727 }
00728
00729 public OpenTK.Input.IInputDriver InputDriver
00730 {
00731 get
00732 {
00733 return mInputDriver;
00734 }
00735 }
00736
00737
00738 public Icon Icon
00739 {
00740 get { return mIcon; }
00741 set {
00742 SetIcon(value);
00743 }
00744 }
00745
00746 private void SetIcon(Icon icon)
00747 {
00748
00749
00750
00751 if (icon == null)
00752 {
00753 API.RestoreApplicationDockTileImage();
00754 }
00755 else
00756 {
00757 Bitmap bitmap;
00758 int size;
00759 IntPtr[] data;
00760 int index;
00761
00762 bitmap = new Bitmap(128, 128);
00763 using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap))
00764 {
00765 g.DrawImage(icon.ToBitmap(), 0, 0, 128, 128);
00766 }
00767 index = 0;
00768 size = bitmap.Width * bitmap.Height;
00769 data = new IntPtr[size];
00770
00771 for (int y = 0; y < bitmap.Height; y++)
00772 {
00773 for (int x = 0; x < bitmap.Width; x++)
00774 {
00775 int pixel = bitmap.GetPixel(x, y).ToArgb();
00776 if (BitConverter.IsLittleEndian)
00777 {
00778 byte a = (byte)((pixel >> 24) & 0xFF);
00779 byte r = (byte)((pixel >> 16) & 0xFF);
00780 byte g = (byte)((pixel >> 8) & 0xFF);
00781 byte b = (byte)(pixel & 0xFF);
00782 data[index++] = (IntPtr)(a + (r << 8) + (g << 16) + (b << 24));
00783 }
00784 else
00785 {
00786 data[index++] = (IntPtr)pixel;
00787 }
00788 }
00789 }
00790
00791 IntPtr provider = API.CGDataProviderCreateWithData(IntPtr.Zero, data, size * 4, IntPtr.Zero);
00792 IntPtr image = API.CGImageCreate(128, 128, 8, 32, 4 * 128, API.CGColorSpaceCreateDeviceRGB(), 4, provider, IntPtr.Zero, 0, 0);
00793 API.SetApplicationDockTileImage(image);
00794 }
00795 }
00796
00797 public string Title
00798 {
00799 get
00800 {
00801 return title;
00802 }
00803 set
00804 {
00805 API.SetWindowTitle(window.WindowRef, value);
00806 title = value;
00807 }
00808 }
00809
00810 public bool Visible
00811 {
00812 get { return API.IsWindowVisible(window.WindowRef); }
00813 set
00814 {
00815 if (value && Visible == false)
00816 Show();
00817 else
00818 Hide();
00819 }
00820 }
00821
00822 public bool Focused
00823 {
00824 get { return this.mIsActive; }
00825 }
00826
00827 public Rectangle Bounds
00828 {
00829 get
00830 {
00831
00832 return bounds;
00833 }
00834 set
00835 {
00836 Location = value.Location;
00837 Size = value.Size;
00838 }
00839 }
00840
00841 public Point Location
00842 {
00843 get
00844 {
00845 return Bounds.Location;
00846 }
00847 set
00848 {
00849 SetLocation((short)value.X, (short)value.Y);
00850 }
00851 }
00852
00853 public Size Size
00854 {
00855 get
00856 {
00857 return bounds.Size;
00858 }
00859 set
00860 {
00861 SetSize((short)value.Width, (short)value.Height);
00862 }
00863 }
00864
00865 public int Width
00866 {
00867 get { return ClientRectangle.Width; }
00868 set { SetClientSize((short)value, (short)Height); }
00869 }
00870
00871 public int Height
00872 {
00873 get { return ClientRectangle.Height; }
00874 set { SetClientSize((short)Width, (short)value); }
00875 }
00876
00877 public int X
00878 {
00879 get
00880 {
00881 return ClientRectangle.X;
00882 }
00883 set
00884 {
00885 Location = new Point(value, Y);
00886 }
00887 }
00888
00889 public int Y
00890 {
00891 get
00892 {
00893 return ClientRectangle.Y;
00894 }
00895 set
00896 {
00897 Location = new Point(X, value);
00898 }
00899 }
00900
00901 public Rectangle ClientRectangle
00902 {
00903 get
00904 {
00905 return clientRectangle;
00906 }
00907 set
00908 {
00909
00910
00911 ClientSize = value.Size;
00912 }
00913 }
00914
00915 public Size ClientSize
00916 {
00917 get
00918 {
00919 return clientRectangle.Size;
00920 }
00921 set
00922 {
00923 API.SizeWindow(window.WindowRef, (short)value.Width, (short)value.Height, true);
00924 OnResize();
00925 }
00926 }
00927
00928 public void Close()
00929 {
00930 CancelEventArgs e = new CancelEventArgs();
00931 OnClosing(e);
00932
00933 if (e.Cancel)
00934 return;
00935
00936 OnClosed();
00937
00938 Dispose();
00939 }
00940
00941 public WindowState WindowState
00942 {
00943 get
00944 {
00945 if (windowState == WindowState.Fullscreen)
00946 return WindowState.Fullscreen;
00947
00948 if (Carbon.API.IsWindowCollapsed(window.WindowRef))
00949 return WindowState.Minimized;
00950
00951 if (Carbon.API.IsWindowInStandardState(window.WindowRef))
00952 {
00953 return WindowState.Maximized;
00954 }
00955
00956 return WindowState.Normal;
00957 }
00958 set
00959 {
00960 if (value == WindowState)
00961 return;
00962
00963 Debug.Print("Switching window state from {0} to {1}", WindowState, value);
00964 WindowState oldState = WindowState;
00965
00966 windowState = value;
00967
00968 if (oldState == WindowState.Fullscreen)
00969 {
00970 window.GoWindowedHack = true;
00971
00972
00973
00974 return;
00975 }
00976
00977 if (oldState == WindowState.Minimized)
00978 {
00979 API.CollapseWindow(window.WindowRef, false);
00980 }
00981
00982 SetCarbonWindowState();
00983 }
00984 }
00985
00986 private void SetCarbonWindowState()
00987 {
00988 CarbonPoint idealSize;
00989
00990 switch (windowState)
00991 {
00992 case WindowState.Fullscreen:
00993 window.GoFullScreenHack = true;
00994
00995 break;
00996
00997 case WindowState.Maximized:
00998
00999
01000
01001 idealSize = new CarbonPoint(9000, 9000);
01002 API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomOut, ref idealSize);
01003 break;
01004
01005 case WindowState.Normal:
01006 if (WindowState == WindowState.Maximized)
01007 {
01008 idealSize = new CarbonPoint();
01009 API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomIn, ref idealSize);
01010 }
01011 break;
01012
01013 case WindowState.Minimized:
01014 API.CollapseWindow(window.WindowRef, true);
01015
01016 break;
01017 }
01018
01019
01020 OnWindowStateChanged();
01021
01022 OnResize();
01023 }
01024
01025 public WindowBorder WindowBorder
01026 {
01027 get
01028 {
01029 return windowBorder;
01030 }
01031 set
01032 {
01033 if (windowBorder == value)
01034 return;
01035
01036 windowBorder = value;
01037
01038 if (windowBorder == WindowBorder.Resizable)
01039 {
01040 API.ChangeWindowAttributes(window.WindowRef, WindowAttributes.Resizable | WindowAttributes.FullZoom,
01041 WindowAttributes.NoAttributes);
01042 }
01043 else if (windowBorder == WindowBorder.Fixed)
01044 {
01045 API.ChangeWindowAttributes(window.WindowRef, WindowAttributes.NoAttributes,
01046 WindowAttributes.Resizable | WindowAttributes.FullZoom);
01047 }
01048
01049 if (WindowBorderChanged != null)
01050 WindowBorderChanged(this, EventArgs.Empty);
01051 }
01052 }
01053
01054 #region --- Event wrappers ---
01055
01056 private void OnKeyPress(KeyPressEventArgs keyPressArgs)
01057 {
01058 if (KeyPress != null)
01059 KeyPress(this, keyPressArgs);
01060 }
01061
01062
01063 private void OnWindowStateChanged()
01064 {
01065 if (WindowStateChanged != null)
01066 WindowStateChanged(this, EventArgs.Empty);
01067 }
01068
01069 protected virtual void OnClosing(CancelEventArgs e)
01070 {
01071 if (Closing != null)
01072 Closing(this, e);
01073 }
01074
01075 protected virtual void OnClosed()
01076 {
01077 if (Closed != null)
01078 Closed(this, EventArgs.Empty);
01079 }
01080
01081
01082 private void OnMouseLeave()
01083 {
01084 if (MouseLeave != null)
01085 MouseLeave(this, EventArgs.Empty);
01086 }
01087
01088 private void OnMouseEnter()
01089 {
01090 if (MouseEnter != null)
01091 MouseEnter(this, EventArgs.Empty);
01092 }
01093
01094 private void OnActivate()
01095 {
01096 mIsActive = true;
01097 if (FocusedChanged != null)
01098 FocusedChanged(this, EventArgs.Empty);
01099 }
01100 private void OnDeactivate()
01101 {
01102 mIsActive = false;
01103 if (FocusedChanged != null)
01104 FocusedChanged(this, EventArgs.Empty);
01105 }
01106
01107 #endregion
01108
01109 public event EventHandler<EventArgs> Idle;
01110 public event EventHandler<EventArgs> Load;
01111 public event EventHandler<EventArgs> Unload;
01112 public event EventHandler<EventArgs> Move;
01113 public event EventHandler<EventArgs> Resize;
01114 public event EventHandler<CancelEventArgs> Closing;
01115 public event EventHandler<EventArgs> Closed;
01116 public event EventHandler<EventArgs> Disposed;
01117 public event EventHandler<EventArgs> IconChanged;
01118 public event EventHandler<EventArgs> TitleChanged;
01119 public event EventHandler<EventArgs> ClientSizeChanged;
01120 public event EventHandler<EventArgs> VisibleChanged;
01121 public event EventHandler<EventArgs> WindowInfoChanged;
01122 public event EventHandler<EventArgs> FocusedChanged;
01123 public event EventHandler<EventArgs> WindowBorderChanged;
01124 public event EventHandler<EventArgs> WindowStateChanged;
01125 public event EventHandler<KeyPressEventArgs> KeyPress;
01126 public event EventHandler<EventArgs> MouseEnter;
01127 public event EventHandler<EventArgs> MouseLeave;
01128
01129 #endregion
01130 }
01131 }