diff dwt/widgets/Shell.d @ 45:d8635bb48c7c

Merge with SWT 3.5
author Jacob Carlborg <doob@me.com>
date Mon, 01 Dec 2008 17:07:00 +0100
parents 642f460a0908
children cfa563df4fdd
line wrap: on
line diff
--- a/dwt/widgets/Shell.d	Tue Oct 21 15:20:04 2008 +0200
+++ b/dwt/widgets/Shell.d	Mon Dec 01 17:07:00 2008 +0100
@@ -1,5 +1,5 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2007 IBM Corporation and others.
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *     IBM Corporation - initial API and implementation
  *     
  * Port to the D programming language:
- *     Jacob Carlborg <jacob.carlborg@gmail.com>
+ *     Jacob Carlborg <doob@me.com>
  *******************************************************************************/
 module dwt.widgets.Shell;
 
@@ -21,9 +21,14 @@
 import dwt.graphics.Point;
 import dwt.graphics.Rectangle;
 import dwt.graphics.Region;
-import dwt.internal.cocoa.NSEvent;
+import dwt.internal.Callback;
+import dwt.internal.cocoa.NSApplication;
+import dwt.internal.cocoa.NSBezierPath;
+import dwt.internal.cocoa.NSColor;
+import dwt.internal.cocoa.NSGraphicsContext;
 import dwt.internal.cocoa.NSPoint;
 import dwt.internal.cocoa.NSRect;
+import dwt.internal.cocoa.NSScreen;
 import dwt.internal.cocoa.NSScrollView;
 import dwt.internal.cocoa.NSSize;
 import dwt.internal.cocoa.NSString;
@@ -32,6 +37,7 @@
 import dwt.internal.cocoa.OS;
 import dwt.internal.cocoa.SWTWindow;
 import dwt.internal.cocoa.SWTWindowDelegate;
+import dwt.internal.cocoa.id;
 
 import dwt.dwthelper.utils;
 import dwt.internal.cocoa.NSInteger;
@@ -144,14 +150,17 @@
  *
  * @see Decorations
  * @see DWT
+ * @see <a href="http://www.eclipse.org/swt/snippets/#shell">Shell snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
  */
 public class Shell : Decorations {
     NSWindow window;
     SWTWindowDelegate windowDelegate;
+    NSBezierPath regionPath;
     bool opened, moved, resized, fullScreen;
 //  bool resized, moved, drawing, reshape, update, deferDispose, active, disposed, opened, fullScreen;
     Control lastActive;
-    Region region;
     Rectangle normalBounds;
 
     static int DEFAULT_CLIENT_WIDTH = -1;
@@ -381,10 +390,48 @@
     this (parent !is null ? parent.display : null, parent, style, null, false);
 }
 
-public static Shell internal_new (Display display, objc.id handle) {
+/**  
+ * Invokes platform specific functionality to allocate a new shell
+ * that is not embedded.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Shell</code>. It is marked public only so that it
+ * can be shared within the packages provided by DWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param display the display for the shell
+ * @param handle the handle for the shell
+ * @return a new shell object containing the specified display and handle
+ * 
+ * @since 3.3
+ */
     return new Shell (display, null, DWT.NO_TRIM, handle, false);
 }
 
+/**  
+ * Invokes platform specific functionality to allocate a new shell
+ * that is 'embedded'.  In this case, the handle represents an NSView
+ * that acts as an embedded DWT Shell in an AWT Canvas.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Shell</code>. It is marked public only so that it
+ * can be shared within the packages provided by DWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param display the display for the shell
+ * @param handle the handle for the shell
+ * @return a new shell object containing the specified display and handle
+ * 
+ * @since 3.5
+ */
+public static Shell cocoa_new (Display display, int /*long*/ handle) {
+    return new Shell (display, null, DWT.NO_TRIM, handle, true);
+}
+
 static int checkStyle (int style) {
     style = Decorations.checkStyle (style);
     style &= ~DWT.TRANSPARENT;
@@ -396,6 +443,12 @@
     return bits;
 }
 
+bool accessibilityIsIgnored(int /*long*/ id, int /*long*/ sel) {
+    // The content view of a shell is always ignored.
+    if (id is view.id) return true;
+    return super.accessibilityIsIgnored(id, sel);
+}
+
 /**
  * Adds the listener to the collection of listeners who will
  * be notified when operations are performed on the receiver,
@@ -435,10 +488,19 @@
     }
 }
 
+bool canBecomeKeyWindow (int /*long*/ id, int /*long*/ sel) {
+    if (window.styleMask () is OS.NSBorderlessWindowMask) return true;
+    return super.canBecomeKeyWindow (id, sel);
+}
+
 void checkOpen () {
     if (!opened) resized = false;
 }
 
+void clearLevel() {
+    window.setLevel(0); 
+}
+
 /**
  * Requests that the window manager close the receiver in
  * the same way it would be closed when the user clicks on
@@ -473,51 +535,116 @@
     rect.y = trim.y;
     rect.width = trim.width;
     rect.height = trim.height;
-    rect = NSWindow.static_frameRectForContentRect_styleMask_(rect, window.styleMask());
-    return new Rectangle (cast(int)rect.x, cast(int)rect.y, cast(int)rect.width, cast(int)rect.height);
+    NSWindow myWindow = (window !is null ? window : view.window());
+    rect = myWindow.frameRectForContentRect(rect);
 }
 
 void createHandle () {
-    state |= CANVAS;// | GRAB | HIDDEN;
-    if (window !is null) {
-        view = window.contentView();
-        return;
-    } else {
-        SWTWindow swtWindow = cast(SWTWindow) (new SWTWindow ()).alloc ();
-        swtWindow.setTag(jniRef);
-        window = cast(NSWindow)swtWindow;
-        NSRect rect = NSRect();
-        dwt.widgets.Monitor.Monitor monitor = getMonitor ();
-        Rectangle clientArea = monitor.getClientArea ();
-        rect.width = clientArea.width * 5 / 8;
-        rect.height = clientArea.height * 5 / 8;
+    state |= HIDDEN;
+    if (window is null) {
+        window = (NSWindow) new SWTWindow ().alloc ();
         NSUInteger styleMask = NSBorderlessWindowMask;
         if ((style & DWT.NO_TRIM) is 0) {
-            styleMask = OS.NSTitledWindowMask;
+            if ((style & DWT.TITLE) !is 0) styleMask |= OS.NSTitledWindowMask;
             if ((style & DWT.CLOSE) !is 0) styleMask |= NSClosableWindowMask;
             if ((style & DWT.MIN) !is 0) styleMask |= NSMiniaturizableWindowMask;
             if ((style & DWT.MAX) !is 0) styleMask |= NSResizableWindowMask;
             if ((style & DWT.RESIZE) !is 0) styleMask |= NSResizableWindowMask;
         }
-        window = window.initWithContentRect_styleMask_backing_defer_(rect, styleMask, NSBackingStoreBuffered, false);
-        display.cascade = window.cascadeTopLeftFromPoint(display.cascade);
+        NSScreen screen = null;
+        NSScreen primaryScreen = new NSScreen(NSScreen.screens().objectAtIndex(0));
+        if (parent !is null) screen = parent.getShell().window.screen();
+        if (screen is null) screen = primaryScreen;
+        window = window.initWithContentRect(new NSRect(), styleMask, OS.NSBackingStoreBuffered, false, screen);
+        if ((style & (DWT.NO_TRIM | DWT.BORDER | DWT.SHELL_TRIM)) is 0) {
+            window.setHasShadow (true);
+        }
+        display.cascadeWindow(window, screen);
+        NSRect screenFrame = screen.frame();
+        float /*double*/ width = screenFrame.width * 5 / 8, height = screenFrame.height * 5 / 8;;
+        NSRect frame = window.frame();
+        NSRect primaryFrame = primaryScreen.frame();
+        frame.y = primaryFrame.height - ((primaryFrame.height - (frame.y + frame.height)) + height);
+        frame.width = width;
+        frame.height = height;
+        window.setFrame(frame, false);
         if ((style & DWT.ON_TOP) !is 0) {
-            window.setLevel(OS.NSFloatingWindowLevel);
+            window.setLevel(OS.NSStatusWindowLevel);
+        }
+        super.createHandle ();
+        topView ().setHidden (true);
+    } else {
+//      OS.object_setClass (window.id, OS.objc_getClass("SWTWindow"));
+        state &= ~HIDDEN;
+        //TODO - get the content of the foreign window instead of creating it
+        super.createHandle ();
+        style |= DWT.NO_BACKGROUND;
+    }
+    window.setAcceptsMouseMovedEvents(true);
+    windowDelegate = (SWTWindowDelegate)new SWTWindowDelegate().alloc().init();
+    window.setDelegate(windowDelegate);
+    window.disableCursorRects();
+    id id = window.fieldEditor (true, null);
+    if (id !is null) {
+        OS.object_setClass (id.id, OS.objc_getClass ("SWTEditorView"));
+    }
+}
+
+/*
+* Feature in Cocoa.  An NSWindow that is the child window of another NSWindow
+* will track the movement of its parent window. The work around is to adjust
+* the window's level.  
+*/
+void fixLevel() {
+    Shell topShell = this;
+    while (topShell.parent !is null) {
+        if (topShell.parent !is null) topShell = (Shell) topShell.parent;
+    }
+    Shell[] shells = display.getShells ();
+    for (int i = 0; i < shells.length; i++) {
+        Shell shell = shells [i];
+        if ((shell.style & DWT.ON_TOP) is 0) {
+            int level = 0;
+            Shell pShell = shell;
+            while (pShell.parent !is null) {
+                pShell = (Shell) pShell.parent;
+                level++;
+            }
+            int newLevel = pShell is topShell ? level : 0;
+            newLevel = Math.min (newLevel, OS.NSModalPanelWindowLevel - 1);
+            shell.window.setLevel (newLevel);
         }
     }
-    
-    (cast(Composite)this).createHandle (null);
-    
-    window.setContentView (topView());
-    windowDelegate = cast(SWTWindowDelegate)(new SWTWindowDelegate()).alloc().init();
-    windowDelegate.setTag(jniRef);
-    window.setDelegate(windowDelegate);
+}
+
+void deregister () {
+    super.deregister ();
+    if (window !is null) display.removeWidget (window);
+    if (windowDelegate !is null) display.removeWidget (windowDelegate);
 }
 
 void destroyWidget () {
     NSWindow window = this.window;
+    Display display = this.display;
     releaseHandle ();
-    if (window !is null) window.close();
+    if (window !is null) {
+        window.close();
+    }
+    //If another shell is not going to become active, clear the menu bar.
+    if (!display.isDisposed () && display.getShells ().length is 0) {
+        display.setMenuBar (null);
+    }
+}
+
+void drawWidget (int /*long*/ id, NSRect rect) {
+    if (regionPath !is null && background is null) {
+        NSGraphicsContext context = NSGraphicsContext.currentContext();
+        context.saveGraphicsState();
+        NSColor.windowBackgroundColor().setFill();
+        NSBezierPath.fillRect(rect);
+        context.restoreGraphicsState();
+    }
+    super.drawWidget (id, rect);
 }
 
 Control findBackgroundControl () {
@@ -534,43 +661,7 @@
 
 void fixShell (Shell newShell, Control control) {
     if (this is newShell) return;
-//  if (control is lastActive) setActiveControl (null);
-}
-
-void flagsChanged(objc.id theEvent) {
-    Display display = this.display;
-    NSEvent nsEvent = new NSEvent(theEvent);
-    NSUInteger modifiers = nsEvent.modifierFlags();
-    int lastModifiers = display.lastModifiers;
-//  int chord = OS.GetCurrentEventButtonState ();
-    int type = DWT.KeyUp;   
-    if ((modifiers & OS.NSAlphaShiftKeyMask) !is 0 && (lastModifiers & OS.NSAlphaShiftKeyMask) is 0) type = DWT.KeyDown;
-    if ((modifiers & OS.NSAlternateKeyMask) !is 0 && (lastModifiers & OS.NSAlternateKeyMask) is 0) type = DWT.KeyDown;
-    if ((modifiers & OS.NSShiftKeyMask) !is 0 && (lastModifiers & OS.NSShiftKeyMask) is 0) type = DWT.KeyDown;
-    if ((modifiers & OS.NSControlKeyMask) !is 0 && (lastModifiers & OS.NSControlKeyMask) is 0) type = DWT.KeyDown;
-    if ((modifiers & OS.NSCommandKeyMask) !is 0 && (lastModifiers & OS.NSCommandKeyMask) is 0) type = DWT.KeyDown;
-    Control target = display.getFocusControl();
-    if (type is DWT.KeyUp && (modifiers & OS.NSAlphaShiftKeyMask) is 0 && (lastModifiers & OS.NSAlphaShiftKeyMask) !is 0) {
-        if (target !is null) {
-            Event event = new Event ();
-            event.keyCode = DWT.CAPS_LOCK;
-    //      setInputState (event, DWT.KeyDown, chord, modifiers);
-            (cast(Widget)target).sendKeyEvent (DWT.KeyDown, event);
-        }
-    }
-    Event event = new Event ();
-//  setInputState (event, type, chord, modifiers);
-    if (event.keyCode is 0 && event.character is 0) return;
-    bool result = (cast(Widget)this).sendKeyEvent (type, event);
-    if (type is DWT.KeyDown && (modifiers & OS.NSAlphaShiftKeyMask) !is 0 && (lastModifiers & OS.NSAlphaShiftKeyMask) is 0) {
-        if (target !is null) {
-            event = new Event ();
-            event.keyCode = DWT.CAPS_LOCK;
-    //      setInputState (event, DWT.KeyUp, chord, modifiers);
-            (cast(Widget)target).sendKeyEvent (DWT.KeyUp, event);
-        }
-    }
-    display.lastModifiers = modifiers;
+    if (control is lastActive) setActiveControl (null);
 }
 
 /**
@@ -596,27 +687,50 @@
  */
 public void forceActive () {
     checkWidget ();
-    if (!isVisible ()) return;
-//  OS.SelectWindow (shellHandle);
-//  OS.SetFrontProcessWithOptions (new int [] {0, OS.kCurrentProcess}, OS.kSetFrontProcessFrontWindowOnly);
+    if (!isVisible()) return;
+    if (window is null) return;
+    window.makeKeyAndOrderFront (null);
+    NSApplication application = NSApplication.sharedApplication ();
+    application.activateIgnoringOtherApps (true);
 }
 
+/**
+ * Returns the receiver's alpha value. The alpha value
+ * is between 0 (transparent) and 255 (opaque).
+ *
+ * @return the alpha value
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * 
+ * @since 3.4
+ */
 public int getAlpha () {
     checkWidget ();
-    return cast(int)(window.alphaValue() * 255);
+    // TODO: Should we support embedded frame alpha?
+    if (window is null) return 255;
 }
 
 public Rectangle getBounds () {
     checkWidget();
-    NSRect frame = window.frame ();
-    return new Rectangle (cast(int)frame.x, cast(int) frame.y, cast(int) frame.width, cast(int) frame.height);
+    NSRect frame = (window is null ? view.frame() : window.frame());
+    GCFloat y = display.getPrimaryFrame().height - cast(int)(frame.y + frame.height);
+    return new Rectangle (cast(int)frame.x, cast(int)y, cast(int)frame.width, cast(int)frame.height);
 }
 
 public Rectangle getClientArea () {
     checkWidget();
     //TODO why super implementation fails
-    NSRect rect = window.contentRectForFrameRect_(window.frame());
-    int width = cast(int)rect.width, height = cast(int)rect.height;
+    if (window is null) {
+        // In embedded frames, the whole view is the client area.
+        NSRect rect = view.frame();
+        int width = (int)rect.width, height = (int)rect.height;
+        return new Rectangle (0, 0, width, height);
+    }
+
+    NSRect rect = window.contentRectForFrameRect(window.frame());
     if (scrollView !is null) {
         NSSize size = NSSize();
         size.width = width;
@@ -628,11 +742,24 @@
     return new Rectangle (0, 0, width, height);
 }
 
-int getDrawCount (int control) {
-    if (!isTrimHandle (control)) return drawCount;
-    return 0;
+NSBezierPath getClipping() {
+    return regionPath;
 }
 
+/**
+ * Returns <code>true</code> if the receiver is currently
+ * in fullscreen state, and false otherwise. 
+ * <p>
+ *
+ * @return the fullscreen state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
 public bool getFullScreen () {
     checkWidget();
     return fullScreen;
@@ -662,8 +789,10 @@
 
 public Point getLocation () {
     checkWidget();
-    NSRect frame = window.frame ();
-    return new Point (cast(int) frame.x, cast(int) frame.y);
+    // TODO: frame is relative to superview. What does getLocation mean in the embedded case?
+    NSRect frame = (window !is null ? window.frame() : view.frame());
+    float /*double*/ y = display.getPrimaryFrame().height - (int)(frame.y + frame.height);
+    return new Point ((int)frame.x, (int)y);
 }
 
 public bool getMaximized () {
@@ -672,6 +801,34 @@
     return !fullScreen && super.getMaximized ();
 }
 
+Shell getModalShell () {
+    Shell shell = null;
+    Shell [] modalShells = display.modalShells;
+    if (modalShells !is null) {
+        int bits = DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL;
+        int index = modalShells.length;
+        while (--index >= 0) {
+            Shell modal = modalShells [index];
+            if (modal !is null) {
+                if ((modal.style & bits) !is 0) {
+                    Control control = this;
+                    while (control !is null) {
+                        if (control is modal) break;
+                        control = control.parent;
+                    }
+                    if (control !is modal) return modal;
+                    break;
+                }
+                if ((modal.style & DWT.PRIMARY_MODAL) !is 0) {
+                    if (shell is null) shell = getShell ();
+                    if (modal.parent is shell) return modal;
+                }
+            }
+        }
+    }
+    return null;
+}
+
 public bool getMinimized () {
     checkWidget();
     if (!getVisible ()) return super.getMinimized ();
@@ -773,15 +930,19 @@
 
 public Point getSize () {
     checkWidget();
-    NSRect frame = window.frame ();
+    NSRect frame = (window !is null ? window.frame() : view.frame());
     return new Point (cast(int) frame.width, cast(int) frame.height);
 }
 
+float getThemeAlpha () {
+    return 1;
+}
+
 bool hasBorder () {
     return false;
 }
 
-void helpRequested(int theEvent) {
+void helpRequested(int /*long*/ id, int /*long*/ sel, int /*long*/ theEvent) {
     Control control = display.getFocusControl();
     while (control !is null) {
         if (control.hooks (DWT.Help)) {
@@ -806,6 +967,21 @@
     return getVisible ();
 }
 
+bool makeFirstResponder (int /*long*/ id, int /*long*/ sel, int /*long*/ notification) {
+    if (display.focusControl is null) display.focusControl = display.getFocusControl ();
+    bool result = super.makeFirstResponder(id, sel, notification);
+    if (result) {
+        Control newFocus = display.getFocusControl ();
+        if (newFocus !is null && newFocus !is display.focusControl) {
+            Control oldFocus = display.focusControl;
+            display.focusControl = newFocus;
+            if (oldFocus !is null && !oldFocus.isDisposed ()) oldFocus.sendFocusEvent (DWT.FocusOut, false);
+            if (newFocus !is null && !newFocus.isDisposed ()) newFocus.sendFocusEvent (DWT.FocusIn, false);
+        }
+    }
+    return result;
+}
+
 /**
  * Moves the receiver to the top of the drawing order for
  * the display on which it was created (so that all other
@@ -829,6 +1005,12 @@
  */
 public void open () {
     checkWidget();
+    int mask = DWT.PRIMARY_MODAL | DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL;
+    if ((style & mask) !is 0) {
+        display.setModalShell (this);
+    } else {
+        updateModal ();
+    }
     setWindowVisible (true, true);
     if (isDisposed ()) return;
 //  if (active) {
@@ -856,6 +1038,12 @@
     return false;
 }
 
+void register () {
+    super.register ();
+    if (window !is null) display.addWidget (window, this);
+    if (windowDelegate !is null) display.addWidget (windowDelegate, this);
+}
+
 void releaseChildren (bool destroy) {
     Shell [] shells = getShells ();
     for (int i=0; i<shells.length; i++) {
@@ -868,7 +1056,7 @@
 }
 
 void releaseHandle () {
-    window.setDelegate(null);
+    if (window !is null) window.setDelegate(null);
     if (windowDelegate !is null) windowDelegate.release();
     windowDelegate = null;
     super.releaseHandle ();
@@ -881,8 +1069,11 @@
 
 void releaseWidget () {
     super.releaseWidget ();
+    display.clearModal (this);
 //  disposed = true;
     lastActive = null;
+    if (regionPath !is null) regionPath.release();
+    regionPath = null;
 }
 
 /**
@@ -935,9 +1126,10 @@
  * @see Shell#setActive
  */
 public void setActive () {
+    if (window is null) return; 
     checkWidget ();
-    if (!isVisible ()) return;
-//  OS.SelectWindow (shellHandle);
+    if (!isVisible()) return;
+    window.makeKeyAndOrderFront (null);
 }
 
 void setActiveControl (Control control) {
@@ -977,41 +1169,49 @@
     }
 }
 
+/**
+ * Sets the receiver's alpha value which must be
+ * between 0 (transparent) and 255 (opaque).
+ * <p>
+ * This operation requires the operating system's advanced
+ * widgets subsystem which may not be available on some
+ * platforms.
+ * </p>
+ * @param alpha the alpha value
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * 
+ * @since 3.4
+ */
 public void setAlpha (int alpha) {
+    if (window is null) return; 
     checkWidget ();
     alpha &= 0xFF;
     window.setAlphaValue (alpha / 255f);
 }
 
-int setBounds (int x, int y, int width, int height, bool move, bool resize) {
-//  if (fullScreen) setFullScreen (false);
-    if (move && resize) {
-        NSRect rect = NSRect ();
-        rect.x = x;
-        //TODO - get the screen for the point
-        int screenHeight = cast(int) window.screen().frame().height;
-        rect.y = screenHeight - y;
-        rect.width = width;
-        rect.height = height;
-        window.setFrame_display_(rect, false);
-    } else {
-        if (move) {
-            NSPoint point = NSPoint();
-            point.x = x;
-            //TODO - get the screen for the point
-            int screenHeight = cast(int) window.screen().frame().height;
-            point.y = screenHeight - y;
-            window.setFrameTopLeftPoint (point);
-        } else {
-            if (resize) {
-                NSRect rect = window.frame();
-                rect.width = width;
-                rect.height = height;
-                window.setFrame_display_(rect, false);
-            }
-        }
+void setBounds (int x, int y, int width, int height, bool move, bool resize) {
+    // Embedded Shells are not resizable.
+    if (window is null) return;
+    if (fullScreen) setFullScreen (false);
+    int screenHeight = (int) display.getPrimaryFrame().height;
+    NSRect frame = window.frame();
+    if (!move) {
+        x = (int)frame.x;
+        y = screenHeight - (int)(frame.y + frame.height);
     }
-    return 0;
+    if (!resize) {
+        width = (int)frame.width;
+        height = (int)frame.height;
+    }
+    frame.x = x;
+    frame.y = screenHeight - (int)(y + height);
+    frame.width = width;
+    frame.height = height;
+    window.setFrame(frame, false);
 }
 
 public void setEnabled (bool enabled) {
@@ -1023,6 +1223,29 @@
 //  }
 }
 
+/**
+ * Sets the full screen state of the receiver.
+ * If the argument is <code>true</code> causes the receiver
+ * to switch to the full screen state, and if the argument is
+ * <code>false</code> and the receiver was previously switched
+ * into full screen state, causes the receiver to switch back
+ * to either the maximmized or normal states.
+ * <p>
+ * Note: The result of intermixing calls to <code>setFullScreen(true)</code>, 
+ * <code>setMaximized(true)</code> and <code>setMinimized(true)</code> will 
+ * vary by platform. Typically, the behavior will match the platform user's 
+ * expectations, but not always. This should be avoided if possible.
+ * </p>
+ * 
+ * @param fullScreen the new fullscreen state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
 public void setFullScreen (bool fullScreen) {
     checkWidget ();
     this.fullScreen = fullScreen; 
@@ -1204,50 +1427,93 @@
 public void setRegion (Region region) {
     checkWidget ();
     if ((style & DWT.NO_TRIM) is 0) return;
+    if (window is null) return;
     if (region !is null && region.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT);
-//  if (region is null) {
-//      rgnRect = null;
-//  } else {
-//      if (rgnRect is null) {
-//          rgnRect = new Rect ();
-//          OS.GetWindowBounds (shellHandle, cast(short) OS.kWindowStructureRgn, rgnRect);
-//          OS.SetRect (rgnRect, cast(short) 0, cast(short) 0, cast(short) (rgnRect.right - rgnRect.left), cast(short) (rgnRect.bottom - rgnRect.top)); 
-//      }
-//  }
-//  this.region = region;
-//  /*
-//  * Bug in the Macintosh.  Calling ReshapeCustomWindow() from a
-//  * kEventWindowDrawContent handler originating from ShowWindow()
-//  * will deadlock.  The fix is to detected this case and only call
-//  * ReshapeCustomWindow() after the default handler is done.
-//  */
-//  if (drawing) {
-//      reshape = true;
-//  } else {
-//      OS.ReshapeCustomWindow (shellHandle);
-//      redrawWidget (handle, true);
-//  }
+    this.region = region;
+    if (regionPath !is null) regionPath.release();
+    regionPath = getPath(region);
+    if (region !is null) {
+        window.setBackgroundColor(NSColor.clearColor());
+        window.setOpaque(false);
+    } else {
+        window.setBackgroundColor(NSColor.windowBackgroundColor());
+        window.setOpaque(true);
+    }
+    window.contentView().setNeedsDisplay(true);
+}
+
+NSBezierPath getPath(Region region) {
+    if (region is null) return null;
+    Callback callback = new Callback(this, "regionToRects", 4);
+    if (callback.getAddress() is 0) DWT.error(DWT.ERROR_NO_MORE_CALLBACKS);
+    NSBezierPath path = NSBezierPath.bezierPath();
+    path.retain();
+    OS.QDRegionToRects(region.handle, OS.kQDParseRegionFromTopLeft, callback.getAddress(), path.id);
+    callback.dispose();
+    if (path.isEmpty()) path.appendBezierPathWithRect(new NSRect());
+    return path;
+}
+
+int /*long*/ regionToRects(int /*long*/ message, int /*long*/ rgn, int /*long*/ r, int /*long*/ path) {
+    NSPoint pt = new NSPoint();
+    short[] rect = new short[4];
+    if (message is OS.kQDRegionToRectsMsgParse) {
+        OS.memmove(rect, r, rect.length * 2);
+        pt.x = rect[1];
+        pt.y = rect[0];
+        OS.objc_msgSend(path, OS.sel_moveToPoint_, pt);
+        pt.x = rect[3];
+        OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
+        pt.x = rect[3];
+        pt.y = rect[2];
+        OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
+        pt.x = rect[1];
+        OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
+        OS.objc_msgSend(path, OS.sel_closePath);
+    }
+    return 0;
 }
 
 public void setText (String str) {
     checkWidget();
     if (str is null) error (DWT.ERROR_NULL_ARGUMENT);
-    super.setText (str);
+    if (window is null) return;
     NSString nsStr = NSString.stringWith(str);
     window.setTitle(nsStr);
-//  str.release();
 }
 
 public void setVisible (bool visible) {
     checkWidget();
-    setWindowVisible (visible, false);
+    int mask = DWT.PRIMARY_MODAL | DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL;
+    if ((style & mask) !is 0) {
+        if (visible) {
+            display.setModalShell (this);
+        } else {
+            display.clearModal (this);
+        }
+    } else {
+        updateModal ();
+    }
+    if (window is null) {
+        super.setVisible(visible);
+    } else {
+        setWindowVisible (visible, false);
+    }
 }
 
 void setWindowVisible (bool visible, bool key) {
-    if (window.isVisible() is visible) return;
+    if (visible) {
+        if ((state & HIDDEN) is 0) return;
+        state &= ~HIDDEN;
+    } else {
+        if ((state & HIDDEN) !is 0) return;
+        state |= HIDDEN;
+    }
+    if (window !is null && (window.isVisible() is visible)) return;
     if (visible) {
         sendEvent (DWT.Show);
         if (isDisposed ()) return;
+        topView ().setHidden (false);
         if (key) {
             window.makeKeyAndOrderFront (null);
         } else {
@@ -1270,12 +1536,15 @@
         }
     } else {
         window.orderOut (null);
+        topView ().setHidden (true);
         sendEvent (DWT.Hide);
     }
 }
 
 void setZOrder () {
-//  if (scrolledHandle !is 0) OS.HIViewAddSubview (scrolledHandle, handle);
+    if (scrollView !is null) scrollView.setDocumentView (view);
+    if (window is null) return;
+    window.setContentView (scrollView !is null ? scrollView : view);
 }
 
 void setZOrder (Control control, bool above) {
@@ -1295,6 +1564,10 @@
     return true;
 }
 
+void updateModal () {
+    // do nothing
+}
+
 void updateSystemUIMode () {
     if (!getMonitor ().equals (display.getPrimaryMonitor ())) return;
     bool isActive = false;
@@ -1319,22 +1592,23 @@
 //  }
 }
 
-void windowDidBecomeKey(int notification) {
-    super.windowDidBecomeKey(notification);
+void windowDidBecomeKey(int /*long*/ id, int /*long*/ sel, int /*long*/ notification) {
+    super.windowDidBecomeKey(id, sel, notification);
     Display display = this.display;
     display.setMenuBar (menuBar);
     sendEvent (DWT.Activate);
+    fixLevel();
 //  if (!isDisposed ()) {
 //      if (!restoreFocus () && !traverseGroup (true)) setFocus ();
 //  }
 }
 
-void windowDidMove(int notification) {
+void windowDidMove(int /*long*/ id, int /*long*/ sel, int /*long*/ notification) {
     moved = true;
     sendEvent(DWT.Move);
 }
 
-void windowDidResize(int notification) {
+void windowDidResize(int /*long*/ id, int /*long*/ sel, int /*long*/ notification) {
     resized = true;
     sendEvent (DWT.Resize);
     if (isDisposed ()) return;
@@ -1344,9 +1618,9 @@
     }
 }
 
-void windowDidResignKey(int notification) {
-    super.windowDidResignKey(notification);
-    Display display = this.display;
+void windowDidResignKey(int /*long*/ id, int /*long*/ sel, int /*long*/ notification) {
+    super.windowDidResignKey(id, sel, notification);
+//  Display display = this.display;
     sendEvent (DWT.Deactivate);
     if (isDisposed ()) return;
 //  saveFocus ();
@@ -1362,34 +1636,11 @@
 //      display.ignoreFocus = false;
 //      if (!savedFocus.isDisposed ()) savedFocus.sendFocusEvent (DWT.FocusOut, false);
 //  }
-    display.setMenuBar (null);
 }
 
-bool windowShouldClose(int window) {
+bool windowShouldClose(int /*long*/ id, int /*long*/ sel, int /*long*/ window) {
     closeWidget ();
     return false;
 }
 
-void windowWillClose(int notification) {
 }
-
-void windowSendEvent(objc.id ID, objc.id event) {
-    NSEvent nsEvent = new NSEvent(event);
-    NSEventType type = nsEvent.type();
-    if (type is OS.NSKeyDown || type is OS.NSKeyUp) {
-        Control eventTarget = display.getFocusControl();
-        if (eventTarget !is null) {
-            if (type is OS.NSKeyDown) {
-                bool[] consume = new bool[1];
-                short key = nsEvent.keyCode();
-                if (eventTarget.translateTraversal(key, nsEvent, consume)) return;
-                if (consume[0]) return;
-                if (eventTarget.isDisposed()) return;
-            }
-            if (!eventTarget.sendKeyEvent(nsEvent, type is OS.NSKeyDown ? DWT.KeyDown : DWT.KeyUp)) return;
-        }
-    }
-    super.windowSendEvent(ID, event);
-}
-
-}