1 /*
   2  * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #import "common.h"
  27 #import "com_sun_glass_events_ViewEvent.h"
  28 #import "com_sun_glass_events_WindowEvent.h"
  29 #import "com_sun_glass_ui_Window.h"
  30 #import "com_sun_glass_ui_Window_Level.h"
  31 #import "com_sun_glass_ui_mac_MacWindow.h"
  32 
  33 #import "GlassMacros.h"
  34 #import "GlassWindow.h"
  35 #import "GlassWindow+Java.h"
  36 #import "GlassWindow+Overrides.h"
  37 #import "GlassEmbeddedWindow+Overrides.h"
  38 #import "GlassView.h"
  39 #import "GlassScreen.h"
  40 #import "GlassTouches.h"
  41 #import "GlassApplication.h"
  42 #import "GlassLayer3D.h"
  43 #import "GlassHelper.h"
  44 
  45 //#include <stdio.h>
  46 //#include <stdarg.h>
  47 //
  48 //void glass_logf(char *fmt, ...) {
  49 //    va_list argp;
  50 //    va_start(argp, fmt);
  51 //    FILE *f = fopen("/tmp/glass.log", "a");
  52 //    vfprintf(f, fmt, argp);
  53 //    fclose(f);
  54 //}
  55 //
  56 //void Sys_out_sprintf(JNIEnv *env, char *fmt, ...) {
  57 //    va_list argp;
  58 //    va_start(argp, fmt);
  59 //    char buffer[4096];
  60 //    vsprintf(buffer, fmt, argp);
  61 ////    glass_logf("str = %s", buffer);
  62 ////    return;
  63 //    jclass sysClass = (*env)->FindClass(env, "java/lang/System");
  64 //    if (!sysClass) { glass_logf("Null finding System class\n"); return; }
  65 //    jclass psClass = (*env)->FindClass(env, "java/io/PrintStream");
  66 //    if (!psClass) { glass_logf("Null finding PrintStream class\n"); return; }
  67 //    jfieldID outField = (*env)->GetStaticFieldID(env, sysClass, "out", "Ljava/io/PrintStream;");
  68 //    if (!outField) { glass_logf("Null finding System.out field\n"); return; }
  69 //    jmethodID printMethod = (*env)->GetMethodID(env, psClass, "print", "(Ljava/lang/String;)V");
  70 //    if (!printMethod) { glass_logf("Null finding print method\n"); return; }
  71 //    jobject outStream = (*env)->GetStaticObjectField(env, sysClass, outField);
  72 //    if (!outStream) { glass_logf("Null getting System.out object\n"); return; }
  73 //    jstring theString = (*env)->NewStringUTF(env, buffer);
  74 //    if (!theString) { glass_logf("Null creating String object\n"); return; }
  75 //    (*env)->CallVoidMethod(env, outStream, printMethod, theString);
  76 //    (*env)->DeleteLocalRef(env, theString);
  77 //}
  78 
  79 //#define VERBOSE
  80 #ifndef VERBOSE
  81     #define LOG(MSG, ...)
  82 #else
  83     #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__);
  84 #endif
  85 
  86 #define BROWSER_PARENT_ID -1L
  87 
  88 #pragma mark --- Internal utilities
  89 
  90 static inline GlassWindow *getGlassWindow(JNIEnv *env, jlong jPtr)
  91 {
  92     assert(jPtr != 0L);
  93 
  94     NSWindow * nsWindow = (NSWindow*)jlong_to_ptr(jPtr);
  95     return (GlassWindow*)[nsWindow delegate];
  96 }
  97 
  98 static inline NSView<GlassView> *getMacView(JNIEnv *env, jobject jview)
  99 {
 100     if (jview != NULL)
 101     {
 102         jfieldID jfID = (*env)->GetFieldID(env, jViewClass, "ptr", "J");
 103         GLASS_CHECK_EXCEPTION(env);
 104         return (NSView<GlassView>*)jlong_to_ptr((*env)->GetLongField(env, jview, jfID));
 105     }
 106     else
 107     {
 108         return nil;
 109     }
 110 }
 111 
 112 // --------------------------------------------------------------------------------------
 113 // NSWindow/NSPanel descendants implementation
 114 #define GLASS_NS_WINDOW_IMPLEMENTATION                                                  \
 115 - (id)initWithDelegate:(GlassWindow*)delegate                                           \
 116              frameRect:(NSRect)rect                                                     \
 117              styleMask:(NSUInteger)styleMask                                            \
 118                 screen:(NSScreen*)screen                                                \
 119 {                                                                                       \
 120     self->gWindow = delegate; /* must be done before calling [super init...] */         \
 121     self = [super initWithContentRect:rect                                              \
 122                             styleMask:styleMask                                         \
 123                               backing:NSBackingStoreBuffered                            \
 124                                 defer:NO                                                \
 125                                screen:screen];                                          \
 126                                                                                         \
 127     if (self == nil) {                                                                  \
 128         return nil;                                                                     \
 129     }                                                                                   \
 130                                                                                         \
 131     [self setDelegate:delegate];                                                        \
 132     [self setAcceptsMouseMovedEvents:NO];                                               \
 133     [self setShowsResizeIndicator:NO];                                                  \
 134     [self setAllowsConcurrentViewDrawing:YES];                                          \
 135                                                                                         \
 136     [self setReleasedWhenClosed:YES];                                                   \
 137                                                                                         \
 138     return self;                                                                        \
 139 }                                                                                       \
 140                                                                                         \
 141 - (void)dealloc                                                                         \
 142 {                                                                                       \
 143     id window = self->gWindow;                                                          \
 144     LOG("dealloc window: %p", window);                                                  \
 145     [super dealloc];                                                                    \
 146     [window release];                                                                   \
 147 }                                                                                       \
 148                                                                                         \
 149 - (void)close                                                                           \
 150 {                                                                                       \
 151     self->gWindow->isClosed = YES;                                                      \
 152     [self->gWindow close];                                                              \
 153     LOG("gWindow close: %p", self->gWindow);                                            \
 154     [super close];                                                                      \
 155     LOG("super close");                                                                 \
 156 }                                                                                       \
 157 /* super calls NSWindow on the next run-loop pass when NSWindow could be released */    \
 158 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent                                        \
 159 {                                                                                       \
 160     [self retain];                                                                      \
 161     BOOL result = [super performKeyEquivalent:theEvent];                                \
 162     result = result || self->gWindow->isClosed;                                         \
 163     [self release];                                                                     \
 164     return result;                                                                      \
 165 }                                                                                       \
 166 - (BOOL)canBecomeMainWindow                                                             \
 167 {                                                                                       \
 168     return [self->gWindow canBecomeMainWindow];                                         \
 169 }                                                                                       \
 170 - (BOOL)canBecomeKeyWindow                                                              \
 171 {                                                                                       \
 172     return [self->gWindow canBecomeKeyWindow];                                          \
 173 }                                                                                       \
 174 - (void)setHidesOnDeactivate:(BOOL)hideOnDeactivate                                     \
 175 {                                                                                       \
 176     [super setHidesOnDeactivate:NO];                                                    \
 177 }                                                                                       \
 178 - (BOOL)hidesOnDeactivate                                                               \
 179 {                                                                                       \
 180     return [self->gWindow hidesOnDeactivate];                                           \
 181 }                                                                                       \
 182 - (BOOL)worksWhenModal                                                                  \
 183 {                                                                                       \
 184     return [self->gWindow worksWhenModal];                                              \
 185 }                                                                                       \
 186 - (void)setBackgroundColor:(NSColor *)color                                             \
 187 {                                                                                       \
 188     [super setBackgroundColor:[self->gWindow setBackgroundColor:color]];                \
 189 }                                                                                       \
 190 - (NSButton *)standardWindowButton:(NSWindowButton)type                                 \
 191 {                                                                                       \
 192     NSButton* button = [super standardWindowButton:type];                               \
 193     switch (type)                                                                       \
 194     {                                                                                   \
 195         case NSWindowDocumentIconButton:                                                \
 196             [button setAcceptsTouchEvents:NO];                                          \
 197             [button setAction:nil];                                                     \
 198             [button setEnabled:NO];                                                     \
 199             break;                                                                      \
 200     }                                                                                   \
 201     return button;                                                                      \
 202 }                                                                                       \
 203 - (void)sendEvent:(NSEvent *)event                                                      \
 204 {                                                                                       \
 205     /* Local copy of the id keeps the retain/release calls balanced. */                 \
 206     id view = [self->gWindow->view retain];                                             \
 207     [self->gWindow sendEvent:event];                                                    \
 208     [super sendEvent:event];                                                            \
 209     [view release];                                                                     \
 210 }
 211 
 212 @implementation GlassWindow_Normal
 213 GLASS_NS_WINDOW_IMPLEMENTATION
 214 @end
 215 
 216 @implementation GlassWindow_Panel
 217 GLASS_NS_WINDOW_IMPLEMENTATION
 218 
 219 - (void)setWorksWhenModal:(BOOL)worksWhenModal
 220 {
 221     [super setWorksWhenModal:NO];
 222 }
 223 
 224 - (BOOL)accessibilityIsIgnored
 225 {
 226     /* In JavaFX NSPanels are used to implement PopupWindows,
 227      * which are used by ContextMenu.  In Accessibility, for a
 228      * menu to work as expected, the window has to be ignored.
 229      * Note that asking the children of the window is
 230      * very important in this context. It ensures that all
 231      * descendants created.  Without it, the menu  will
 232      * not be seen by the assistive technology.
 233      */
 234     __block BOOL ignored = [super accessibilityIsIgnored];
 235     NSArray* children = [self accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
 236     if (children) {
 237         [children enumerateObjectsUsingBlock: ^(id child, NSUInteger index, BOOL *stop) {
 238             NSString* role = [child accessibilityAttributeValue: NSAccessibilityRoleAttribute];
 239             if ([NSAccessibilityMenuRole isEqualToString: role]) {
 240                 ignored = YES;
 241                 *stop = YES;
 242             }
 243             /* Tooltips are exposed by AXHelp attribute and there is no API in Mac
 244              * to represent the tooltip window.
 245              * Nonetheless, the window must be ignored to prevent interfering with
 246              * VoiceOver focus.
 247              */
 248             if ([@"AXJFXTOOLTIP" isEqualToString: role]) {
 249                 ignored = YES;
 250                 *stop = YES;
 251             }
 252         }];
 253     }
 254     return ignored;
 255 }
 256 
 257 - (id)accessibilityAttributeValue:(NSString *)attribute
 258 {
 259     /*
 260     * The default value of AXRoleDescription for a NSPanel is 'system dialog'.
 261     * While this is correct for an average cocoa application it is not appropriate
 262     * for JFX, where all NSPanels are decoration-less windows used to implement
 263     * tooltip, context menus, combo boxes, etc.
 264     */
 265     if ([NSAccessibilityRoleDescriptionAttribute isEqualToString: attribute]) {
 266         return @"";
 267     }
 268     return [super accessibilityAttributeValue: attribute];
 269 }
 270 
 271 @end
 272 // --------------------------------------------------------------------------------------
 273 
 274 
 275 @implementation GlassWindow
 276 
 277 - (void)setFullscreenWindow:(NSWindow*)fsWindow
 278 {
 279     if (self->fullscreenWindow == fsWindow) {
 280         return;
 281     }
 282 
 283     [self _ungrabFocus];
 284 
 285     NSWindow *from, *to;
 286     from = self->fullscreenWindow ? self->fullscreenWindow : self->nsWindow;
 287     to = fsWindow ? fsWindow : self->nsWindow;
 288 
 289     NSArray * children = [from childWindows];
 290     for (NSUInteger i=0; i<[children count]; i++)
 291     {
 292         NSWindow *child = (NSWindow*)[children objectAtIndex:i];
 293         if ([[child delegate] isKindOfClass: [GlassWindow class]]) {
 294             [from removeChildWindow: child];
 295             [to addChildWindow:child ordered:NSWindowAbove];
 296         }
 297     }
 298 
 299     self->fullscreenWindow = fsWindow;
 300 
 301     GET_MAIN_JENV;
 302     (*env)->CallVoidMethod(env, self->jWindow, jWindowNotifyDelegatePtr, ptr_to_jlong(fsWindow));
 303     GLASS_CHECK_EXCEPTION(env);
 304 }
 305 
 306 - (void)close
 307 {
 308     [self _ungrabFocus];
 309 }
 310 
 311 - (void)sendEvent:(NSEvent *)event
 312 {
 313     if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown)
 314     {
 315         NSPoint p = [NSEvent mouseLocation];
 316         NSRect frame = [self->nsWindow frame];
 317         NSRect contentRect = [self->nsWindow contentRectForFrameRect:frame];
 318 
 319         if (p.y >= (frame.origin.y + contentRect.size.height))
 320         {
 321             // Click to the titlebar
 322             [self _ungrabFocus];
 323         }
 324 
 325         [self _checkUngrab];
 326     }
 327 }
 328 
 329 // Window vs Panel API
 330 - (BOOL)canBecomeMainWindow
 331 {
 332     if (!self->isEnabled)
 333     {
 334         // We'll send FOCUS_DISABLED
 335         return YES;
 336     }
 337     return self->isFocusable;
 338 }
 339 
 340 // Window vs Panel API
 341 - (BOOL)hidesOnDeactivate
 342 {
 343     return NO;
 344 }
 345 
 346 // Window vs Panel API
 347 - (BOOL)worksWhenModal
 348 {
 349     return NO;
 350 }
 351 
 352 - (BOOL)canBecomeKeyWindow
 353 {
 354     if (!self->isEnabled)
 355     {
 356         // We'll send FOCUS_DISABLED
 357         return YES;
 358     }
 359     return self->isFocusable;
 360 }
 361 
 362 - (NSColor*)setBackgroundColor:(NSColor *)color
 363 {
 364     if (self->isTransparent == NO)
 365     {
 366         // allow color if we're opaque
 367         return color;
 368     }
 369     else
 370     {
 371         // for transparent window, ignore and set to clear color
 372         // FIXME: do we want to store the background color in case we switch to non-transparent mode?
 373         return [NSColor clearColor];
 374     }
 375 }
 376 
 377 
 378 @end
 379 
 380 #pragma mark --- GlassEmbeddedWindow
 381 
 382 static NSMutableArray * embeddedWindowsList = nil;
 383 
 384 @implementation GlassEmbeddedWindow
 385 
 386 - (id)initWithDelegate:(GlassWindow*)delegate
 387              frameRect:(NSRect)rect
 388              styleMask:(NSUInteger)styleMask
 389                 screen:(NSScreen*)screen
 390 {
 391     self = [super initWithDelegate:delegate frameRect:rect styleMask:styleMask screen:screen];
 392     if (self == nil) {
 393         return nil;
 394     }
 395 
 396     if (embeddedWindowsList == nil) {
 397         embeddedWindowsList = [[NSMutableArray alloc] initWithCapacity: 4];
 398     }
 399     [embeddedWindowsList addObject:self]; // retains 'self'
 400 
 401     return self;
 402 }
 403 
 404 - (void)close
 405 {
 406     if (embeddedWindowsList) {
 407         [embeddedWindowsList removeObject:self]; // releases 'self'
 408         if ([embeddedWindowsList count] == 0) {
 409             [embeddedWindowsList release];
 410             embeddedWindowsList = nil;
 411         }
 412     }
 413     [super close];
 414 }
 415 
 416 + (BOOL)exists:(GlassEmbeddedWindow*)window
 417 {
 418     if (embeddedWindowsList && window) {
 419         return [embeddedWindowsList indexOfObjectIdenticalTo:window] != NSNotFound;
 420     }
 421     return NO;
 422 }
 423 
 424 - (void)setFullscreenWindow:(NSWindow*)fsWindow
 425 {
 426     if (self->parent != nil)
 427     {
 428         BOOL fullscreen = (fsWindow != nil);
 429 
 430         CALayer *layer = [self->gWindow->view layer];
 431         if ([layer isKindOfClass:[GlassLayer3D class]] == YES)
 432         {
 433             [((CAOpenGLLayer*)layer) setAsynchronous:fullscreen];
 434 
 435             layer = [self->parent->gWindow->view layer];
 436             if ([layer isKindOfClass:[GlassLayer3D class]] == YES)
 437             {
 438                 [((CAOpenGLLayer*)layer) setAsynchronous:!fullscreen];
 439             }
 440         }
 441 
 442         self->fullscreenWindow = fsWindow;
 443     }
 444 }
 445 
 446 - (void)sendEvent:(NSEvent *)theEvent
 447 {
 448     BOOL fullscreen = (self->fullscreenWindow != nil);
 449     if (fullscreen == NO)
 450     {
 451         [super sendEvent:theEvent];
 452     }
 453     else
 454     {
 455         [self->fullscreenWindow sendEvent:theEvent];
 456     }
 457 }
 458 
 459 
 460 @end
 461 
 462 #pragma mark --- Dispatcher
 463 
 464 // TODO: re-implement using Obj-C blocks ?
 465 static jlong _createWindowCommonDo(JNIEnv *env, jobject jWindow, jlong jOwnerPtr, jlong jScreenPtr, jint jStyleMask, jboolean jIsChild)
 466 {
 467     GlassWindow *window = nil;
 468 
 469     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 470     {
 471         NSUInteger styleMask = NSBorderlessWindowMask;
 472         // only titled windows get title
 473         if ((jStyleMask&com_sun_glass_ui_Window_TITLED) != 0)
 474         {
 475             styleMask = styleMask|NSTitledWindowMask;
 476         }
 477 
 478         bool isUtility = (jStyleMask & com_sun_glass_ui_Window_UTILITY) != 0;
 479         bool isPopup = (jStyleMask & com_sun_glass_ui_Window_POPUP) != 0;
 480 
 481         // only nontransparent windows get decorations
 482         if ((jStyleMask&com_sun_glass_ui_Window_TRANSPARENT) == 0)
 483         {
 484             if ((jStyleMask&com_sun_glass_ui_Window_CLOSABLE) != 0)
 485             {
 486                 styleMask = styleMask|NSClosableWindowMask;
 487             }
 488 
 489             if (((jStyleMask&com_sun_glass_ui_Window_MINIMIZABLE) != 0) ||
 490                 ((jStyleMask&com_sun_glass_ui_Window_MAXIMIZABLE) != 0))
 491             {
 492                 // on Mac OS X there is one set for min/max buttons,
 493                 // so if clients requests either one, we turn them both on
 494                 styleMask = styleMask|NSMiniaturizableWindowMask;
 495             }
 496 
 497             if ((jStyleMask&com_sun_glass_ui_Window_UNIFIED) != 0) {
 498                 styleMask = styleMask|NSTexturedBackgroundWindowMask;
 499             }
 500 
 501             if (isUtility)
 502             {
 503                 styleMask = styleMask | NSUtilityWindowMask | NSNonactivatingPanelMask;
 504             }
 505         }
 506 
 507         if (isPopup)
 508         {
 509             // can receive keyboard input without activating the owning application
 510             styleMask = styleMask|NSNonactivatingPanelMask;
 511         }
 512 
 513         // initial size must be 0x0 otherwise we don't get resize update if the initial size happens to be the exact same size as the later programatical one!
 514         CGFloat x = 0.0f;
 515         CGFloat y = 0.0f;
 516         CGFloat w = 0.0f;
 517         CGFloat h = 0.0f;
 518 
 519         NSScreen *screen = (NSScreen*)jlong_to_ptr(jScreenPtr);
 520         window = [[GlassWindow alloc] _initWithContentRect:NSMakeRect(x, y, w, h) styleMask:styleMask screen:screen jwindow:jWindow jIsChild:jIsChild];
 521 
 522         if ((jStyleMask & com_sun_glass_ui_Window_UNIFIED) != 0) {
 523             //Prevent the textured effect from disappearing on border thickness recalculation
 524             [window->nsWindow setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge];
 525         }
 526 
 527         if ((jStyleMask & com_sun_glass_ui_Window_UTILITY) != 0) {
 528             [[window->nsWindow standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
 529             [[window->nsWindow standardWindowButton:NSWindowZoomButton] setHidden:YES];
 530             if (!jOwnerPtr) {
 531                 [window->nsWindow setLevel:NSNormalWindowLevel];
 532             }
 533         }
 534 
 535         if (jIsChild == JNI_FALSE)
 536         {
 537             if (jOwnerPtr != 0L)
 538             {
 539                 window->owner = getGlassWindow(env, jOwnerPtr)->nsWindow; // not retained (use weak reference?)
 540             }
 541         }
 542         else
 543         {
 544             if ((jOwnerPtr != 0L) && (jOwnerPtr != BROWSER_PARENT_ID))
 545             {
 546                 GlassEmbeddedWindow *parent = getGlassEmbeddedWindow(env, jOwnerPtr);
 547                 GlassEmbeddedWindow *ewindow = (GlassEmbeddedWindow*)window->nsWindow;
 548                 parent->child = ewindow; // not retained (use weak reference?)
 549 
 550                 ewindow->parent = parent; // not retained (use weak reference?)
 551             }
 552         }
 553         window->isResizable = NO;
 554         window->isDecorated = (jStyleMask&com_sun_glass_ui_Window_TITLED) != 0;
 555         /* 10.7 full screen window support */
 556         if ([NSWindow instancesRespondToSelector:@selector(toggleFullScreen:)]) {
 557             NSWindowCollectionBehavior behavior = [window->nsWindow collectionBehavior];
 558             if (!isPopup && !isUtility && !window->owner)
 559             {
 560                 // Only ownerless windows should have the Full Screen Toggle control
 561                 behavior |= (1 << 7) /* NSWindowCollectionBehaviorFullScreenPrimary */;
 562             }
 563             else
 564             {
 565                 // Other windows are only allowed to be shown together with a primary
 566                 // full screen window
 567                 behavior |= (1 << 8) /* NSWindowCollectionBehaviorFullScreenAuxiliary */;
 568             }
 569             [window->nsWindow setCollectionBehavior: behavior];
 570         }
 571 
 572         window->isTransparent = (jStyleMask & com_sun_glass_ui_Window_TRANSPARENT) != 0;
 573         if (window->isTransparent == YES)
 574         {
 575             [window->nsWindow setBackgroundColor:[NSColor clearColor]];
 576             [window->nsWindow setHasShadow:NO];
 577             [window->nsWindow setOpaque:NO];
 578         }
 579         else
 580         {
 581             [window->nsWindow setHasShadow:YES];
 582             [window->nsWindow setOpaque:YES];
 583         }
 584 
 585         window->fullscreenWindow = nil;
 586 
 587         window->isSizeAssigned = NO;
 588         window->isLocationAssigned = NO;
 589 
 590         if (jIsChild == JNI_TRUE && jOwnerPtr != 0L && jOwnerPtr != BROWSER_PARENT_ID
 591             && [window->nsWindow isKindOfClass:[GlassEmbeddedWindow class]])
 592         {
 593             GlassEmbeddedWindow* parent = ((GlassEmbeddedWindow*)window->nsWindow)->parent;
 594             if ([GlassEmbeddedWindow exists:parent])
 595             {
 596                 window->isLocationAssigned = YES;
 597                 NSScreen *pscreen = [[NSScreen screens] objectAtIndex:0];
 598                 NSRect screenFrame = pscreen.frame;
 599                 NSRect frameRect = parent.frame;
 600                 int invy = (int)round(screenFrame.size.height - frameRect.size.height - frameRect.origin.y);
 601                 [window _setBounds:(int)round(frameRect.origin.x)
 602                                  y:invy
 603                               xSet:YES ySet:YES w:0 h:0 cw:0 ch:0];
 604             }
 605         }
 606     }
 607     [pool drain];
 608 
 609     GLASS_CHECK_EXCEPTION(env);
 610 
 611     return ptr_to_jlong(window->nsWindow);
 612 }
 613 
 614 static jlong _createWindowCommon
 615 (JNIEnv *env, jobject jWindow, jlong jOwnerPtr, jlong jScreenPtr, jint jStyleMask, jboolean jIsChild)
 616 {
 617     LOG("_createWindowCommon");
 618 
 619     jlong value = 0L;
 620 
 621     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 622     GLASS_POOL_ENTER;
 623     {
 624         jobject jWindowRef = (*env)->NewGlobalRef(env, jWindow);
 625         value = _createWindowCommonDo(env, jWindowRef, jOwnerPtr, jScreenPtr, jStyleMask, jIsChild);
 626     }
 627     GLASS_POOL_EXIT;
 628     GLASS_CHECK_EXCEPTION(env);
 629 
 630     LOG("   window: %p", value);
 631     return value;
 632 }
 633 
 634 #pragma mark --- JNI
 635 
 636 /*
 637  * Class:     com_sun_glass_ui_mac_MacWindow
 638  * Method:    _initIDs
 639  * Signature: ()V
 640  */
 641 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1initIDs
 642 (JNIEnv *env, jclass jClass)
 643 {
 644     LOG("Java_com_sun_glass_ui_mac_MacWindow__1initIDs");
 645 
 646     if (jWindowClass == NULL)
 647     {
 648         jWindowClass = (*env)->NewGlobalRef(env, jClass);
 649     }
 650 
 651     if (jMenuBarDelegateClass == NULL)
 652     {
 653         jMenuBarDelegateClass = (*env)->NewGlobalRef(env, [GlassHelper ClassForName:"com.sun.glass.ui.mac.MacMenuBarDelegate" withEnv:env]);
 654     }
 655 
 656     if (jViewClass == NULL)
 657     {
 658         jViewClass = (*env)->NewGlobalRef(env, [GlassHelper ClassForName:"com.sun.glass.ui.View" withEnv:env]);
 659     }
 660 
 661     if (jScreenClass == NULL)
 662     {
 663         jScreenClass = (*env)->NewGlobalRef(env, [GlassHelper ClassForName:"com.sun.glass.ui.Screen" withEnv:env]);
 664     }
 665 
 666     if (jWindowNotifyMove == NULL)
 667     {
 668         jWindowNotifyMove = (*env)->GetMethodID(env, jWindowClass, "notifyMove", "(IIZ)V");
 669         if ((*env)->ExceptionCheck(env)) return;
 670     }
 671 
 672     if (jWindowNotifyResize == NULL)
 673     {
 674         jWindowNotifyResize = (*env)->GetMethodID(env, jWindowClass, "notifyResize", "(III)V");
 675         if ((*env)->ExceptionCheck(env)) return;
 676     }
 677 
 678     if (jWindowNotifyMoveToAnotherScreen == NULL)
 679     {
 680         jWindowNotifyMoveToAnotherScreen = (*env)->GetMethodID(env, jWindowClass, "notifyMoveToAnotherScreen", "(Lcom/sun/glass/ui/Screen;)V");
 681         if ((*env)->ExceptionCheck(env)) return;
 682     }
 683 
 684     if (jWindowNotifyScaleChanged == NULL)
 685     {
 686         jWindowNotifyScaleChanged = (*env)->GetMethodID(env, jWindowClass, "notifyScaleChanged", "(FFFF)V");
 687         if ((*env)->ExceptionCheck(env)) return;
 688     }
 689 
 690     if (jWindowNotifyClose == NULL)
 691     {
 692         jWindowNotifyClose = (*env)->GetMethodID(env, jWindowClass, "notifyClose", "()V");
 693         if ((*env)->ExceptionCheck(env)) return;
 694     }
 695 
 696     if (jWindowNotifyFocus == NULL)
 697     {
 698         jWindowNotifyFocus = (*env)->GetMethodID(env, jWindowClass, "notifyFocus", "(I)V");
 699         if ((*env)->ExceptionCheck(env)) return;
 700     }
 701 
 702     if (jWindowNotifyFocusUngrab == NULL)
 703     {
 704         jWindowNotifyFocusUngrab = (*env)->GetMethodID(env, jWindowClass, "notifyFocusUngrab", "()V");
 705         if ((*env)->ExceptionCheck(env)) return;
 706     }
 707 
 708     if (jWindowNotifyFocusDisabled == NULL)
 709     {
 710         jWindowNotifyFocusDisabled = (*env)->GetMethodID(env, jWindowClass, "notifyFocusDisabled", "()V");
 711         if ((*env)->ExceptionCheck(env)) return;
 712     }
 713 
 714     if (jWindowNotifyDestroy == NULL)
 715     {
 716         jWindowNotifyDestroy = (*env)->GetMethodID(env, jWindowClass, "notifyDestroy", "()V");
 717         if ((*env)->ExceptionCheck(env)) return;
 718     }
 719 
 720     if (jWindowNotifyDelegatePtr == NULL)
 721     {
 722         jWindowNotifyDelegatePtr = (*env)->GetMethodID(env, jWindowClass, "notifyDelegatePtr", "(J)V");
 723     }
 724 }
 725 
 726 /*
 727  * Class:     com_sun_glass_ui_mac_MacWindow
 728  * Method:    _createWindow
 729  * Signature: (JJI)J
 730  */
 731 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacWindow__1createWindow
 732 (JNIEnv *env, jobject jWindow, jlong jOwnerPtr, jlong jScreenPtr, jint jStyleMask)
 733 {
 734     LOG("Java_com_sun_glass_ui_mac_MacWindow__1createWindow");
 735 
 736     return _createWindowCommon(env, jWindow, jOwnerPtr, jScreenPtr, jStyleMask, JNI_FALSE);
 737 }
 738 
 739 /*
 740  * Class:     com_sun_glass_ui_mac_MacWindow
 741  * Method:    _createChildWindow
 742  * Signature: (J)J
 743  */
 744 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacWindow__1createChildWindow
 745 (JNIEnv *env, jobject jWindow, jlong jOwnerPtr)
 746 {
 747     LOG("Java_com_sun_glass_ui_mac_MacWindow__1createChildWindow");
 748     LOG("   owner: %p", jOwnerPtr);
 749 
 750     jlong jScreenPtr = 0L;
 751     jint jStyleMask = NSBorderlessWindowMask;
 752     if (jOwnerPtr == BROWSER_PARENT_ID)
 753     {
 754         LOG("       case PARENT (PLUGIN)");
 755         // special case: embedded window for plugin (the container which will hold the child window)
 756     }
 757     else
 758     {
 759         LOG("       case CHILD (EMBEDDED)");
 760         // special case: embedded window for plugin (the actual plugin window with remote layer)
 761         // jOwnerPtr must be a valid GlassEmbeddedWindow instance
 762         if (![GlassEmbeddedWindow exists:(GlassEmbeddedWindow*)jlong_to_ptr(jOwnerPtr)]) {
 763             return (jlong)0;
 764         }
 765     }
 766 
 767     return _createWindowCommon(env, jWindow, jOwnerPtr, jScreenPtr, jStyleMask, JNI_TRUE);
 768 }
 769 
 770 /*
 771  * Class:     com_sun_glass_ui_mac_MacWindow
 772  * Method:    _setLevel
 773  * Signature: (JI)V
 774  */
 775 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setLevel
 776 (JNIEnv *env, jobject jWindow, jlong jPtr, jint jLevel)
 777 {
 778     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setLevel");
 779     if (!jPtr) return;
 780 
 781     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 782     GLASS_POOL_ENTER;
 783     {
 784         GlassWindow *window = getGlassWindow(env, jPtr);
 785         NSInteger level = NSNormalWindowLevel;
 786         switch (jLevel)
 787         {
 788             case com_sun_glass_ui_Window_Level_FLOATING:
 789                 level = NSFloatingWindowLevel;
 790                 break;
 791             case com_sun_glass_ui_Window_Level_TOPMOST:
 792                 level = NSScreenSaverWindowLevel;
 793                 break;
 794         }
 795         [window->nsWindow setLevel:level];
 796     }
 797     GLASS_POOL_EXIT;
 798     GLASS_CHECK_EXCEPTION(env);
 799 }
 800 
 801 /*
 802  * Class:     com_sun_glass_ui_mac_MacWindow
 803  * Method:    _setFocusable
 804  * Signature: (Z)V
 805  */
 806 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setFocusable
 807 (JNIEnv *env, jobject jWindow, jlong jPtr, jboolean isFocusable)
 808 {
 809     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setCanBecomeActive");
 810     if (!jPtr) return;
 811 
 812     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 813     GLASS_POOL_ENTER;
 814     {
 815         GlassWindow *window = getGlassWindow(env, jPtr);
 816         window->isFocusable = (isFocusable==JNI_TRUE);
 817     }
 818     GLASS_POOL_EXIT;
 819     GLASS_CHECK_EXCEPTION(env);
 820 }
 821 
 822 /*
 823  * Class:     com_sun_glass_ui_mac_MacWindow
 824  * Method:    _setEnabled
 825  * Signature: (JZ)V
 826  */
 827 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setEnabled
 828 (JNIEnv *env, jobject jwindow, jlong jPtr, jboolean isEnabled)
 829 {
 830     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setEnabled");
 831     if (!jPtr) return;
 832 
 833     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 834     GLASS_POOL_ENTER;
 835     {
 836         GlassWindow *window = getGlassWindow(env, jPtr);
 837         window->isEnabled = (BOOL)isEnabled;
 838         NSButton *zoomButton = [window->nsWindow standardWindowButton:NSWindowZoomButton];
 839         if ((window->isEnabled) && (window->isResizable)){
 840             [window->nsWindow setStyleMask: window->enabledStyleMask];
 841             if (window->enabledStyleMask & NSResizableWindowMask) {
 842                 [zoomButton setEnabled:YES];
 843             }
 844         }
 845         else if((window->isEnabled) && (!window->isResizable)){
 846             [window->nsWindow setStyleMask:
 847                 (window->enabledStyleMask & ~(NSUInteger) NSResizableWindowMask)];
 848             [zoomButton setEnabled:NO];
 849         }
 850         else{
 851             window->enabledStyleMask = [window->nsWindow styleMask];
 852             [window->nsWindow setStyleMask:
 853                 (window->enabledStyleMask & ~(NSUInteger)(NSMiniaturizableWindowMask | NSResizableWindowMask))];
 854             [zoomButton setEnabled:NO];
 855         }
 856     }
 857     GLASS_POOL_EXIT;
 858     GLASS_CHECK_EXCEPTION(env);
 859 }
 860 
 861 /*
 862  * Class:     com_sun_glass_ui_mac_MacWindow
 863  * Method:    _setAlpha
 864  * Signature: (F)V
 865  */
 866 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setAlpha
 867 (JNIEnv *env, jobject jWindow, jlong jPtr, jfloat jAlpha)
 868 {
 869     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setAlpha");
 870     if (!jPtr) return;
 871 
 872     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 873     GLASS_POOL_ENTER;
 874     {
 875         GlassWindow *window = getGlassWindow(env, jPtr);
 876         [window->nsWindow setAlphaValue:jAlpha];
 877     }
 878     GLASS_POOL_EXIT;
 879     GLASS_CHECK_EXCEPTION(env);
 880 }
 881 
 882 /*
 883  * Class:     com_sun_glass_ui_mac_MacWindow
 884  * Method:    _setBackground
 885  * Signature: (JFFF)Z
 886  */
 887 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setBackground
 888 (JNIEnv *env, jobject jWindow, jlong jPtr, jfloat r, jfloat g, jfloat b)
 889 {
 890     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setBackground");
 891     if (!jPtr) return JNI_FALSE;
 892 
 893     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 894     GLASS_POOL_ENTER;
 895     {
 896         GlassWindow *window = getGlassWindow(env, jPtr);
 897         [window->nsWindow setBackgroundColor:[NSColor colorWithCalibratedRed:r green:g blue:b alpha:1.0f]];
 898     }
 899     GLASS_POOL_EXIT;
 900     GLASS_CHECK_EXCEPTION(env);
 901 
 902     return JNI_TRUE; // gznote: remove this return value if unused
 903 }
 904 
 905 /*
 906  * Class:     com_sun_glass_ui_mac_MacWindow
 907  * Method:    _setView
 908  * Signature: (J)Z
 909  */
 910 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setView
 911 (JNIEnv *env, jobject jWindow, jlong jPtr, jobject jview)
 912 {
 913     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setView");
 914     LOG("   window: %p", jPtr);
 915     LOG("   view: %p", getMacView(env, jview));
 916     if (!jPtr) return JNI_FALSE;
 917 
 918     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 919     GLASS_POOL_ENTER;
 920     {
 921         GlassWindow *window = getGlassWindow(env, jPtr);
 922 
 923         // We don't support changing views in the FS mode because
 924         // by Glass design the FS functionality belongs to the View.
 925         // Also, this leads to a crash on the Mac
 926         if ([window->nsWindow styleMask] & (1 << 14)/*NSFullScreenWindowMask*/) {
 927             [window->nsWindow performSelector:@selector(toggleFullScreen:) withObject:nil];
 928 
 929             // Wait until the FS mode has really exited
 930             [GlassApplication enterFullScreenExitingLoop];
 931         }
 932 
 933         NSView<GlassView> *oldView = window->view;
 934         window->view = getMacView(env, jview);
 935         //NSLog(@"        window: %@", window);
 936         //NSLog(@"                frame: %.2f,%.2f %.2fx%.2f", [window frame].origin.x, [window frame].origin.y, [window frame].size.width, [window frame].size.height);
 937         //NSLog(@"        view: %@", window->view);
 938         //NSLog(@"                frame: %.2f,%.2f %.2fx%.2f", [window->view frame].origin.x, [window->view frame].origin.y, [window->view frame].size.width, [window->view frame].size.height);
 939 
 940         // Make sure we synchronize scale factors to the new view as any
 941         // dynamic updates might have happened when we had the old view
 942         // and/or we may have been set visible before we had a view and
 943         // missed the initial notification.
 944         if ([window->nsWindow screen]) {
 945             [window->view notifyScaleFactorChanged:GetScreenScaleFactor([window->nsWindow screen])];
 946         }
 947 
 948         if (oldView && oldView != window->view) {
 949             [[oldView delegate] resetMouseTracking];
 950         }
 951 
 952         if (window->view != nil)
 953         {
 954             CALayer *layer = [window->view layer];
 955             if (([layer isKindOfClass:[CAOpenGLLayer class]] == YES) &&
 956                 (([window->nsWindow styleMask] & NSTexturedBackgroundWindowMask) == NO))
 957             {
 958                 [((CAOpenGLLayer*)layer) setOpaque:[window->nsWindow isOpaque]];
 959             }
 960 
 961             window->suppressWindowMoveEvent = YES; // RT-11215
 962             {
 963                 NSRect viewFrame = [window->view frame];
 964                 if ((viewFrame.size.width != 0.0f) && (viewFrame.size.height != 0.0f))
 965                 {
 966                     NSRect windowFrame = [window->nsWindow frameRectForContentRect:viewFrame];
 967                     windowFrame.origin.x = [window->nsWindow frame].origin.x;
 968                     windowFrame.origin.y = [window->nsWindow frame].origin.y;
 969                     [window _setWindowFrameWithRect:NSMakeRect(windowFrame.origin.x, windowFrame.origin.y, windowFrame.size.width, windowFrame.size.height) withDisplay:JNI_TRUE withAnimate:JNI_FALSE];
 970                 }
 971 
 972                 [window->nsWindow setContentView:[window->view superview]]; // use our superview not ourselves!
 973                 [window->nsWindow setInitialFirstResponder:window->view];
 974                 [window->nsWindow makeFirstResponder:window->view];
 975             }
 976             window->suppressWindowMoveEvent = NO;
 977         }
 978         else
 979         {
 980             [window->nsWindow performSelectorOnMainThread:@selector(setContentView:) withObject:nil waitUntilDone:YES];
 981         }
 982     }
 983     GLASS_POOL_EXIT;
 984     GLASS_CHECK_EXCEPTION(env);
 985 
 986     return JNI_TRUE; // gznote: remove this return value if unused
 987 }
 988 
 989 /*
 990  * Class:     com_sun_glass_ui_mac_MacWindow
 991  * Method:    _setMenubar
 992  * Signature: (Lcom/sun/glass/ui/mac/MacMenubarDelegate;)V
 993  */
 994 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setMenubar
 995 (JNIEnv *env, jobject jWindow, jlong jPtr, jlong jMenubarPtr)
 996 {
 997     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setMenubar");
 998     if (!jPtr) return JNI_FALSE;
 999 
1000     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1001     GLASS_POOL_ENTER;
1002     {
1003         GlassWindow *window = getGlassWindow(env, jPtr);
1004         window->menubar = (GlassMenubar*)jlong_to_ptr(jMenubarPtr);
1005         [NSApp setMainMenu:window->menubar->menu];
1006         [[NSApp mainMenu] update];
1007     }
1008     GLASS_POOL_EXIT;
1009     GLASS_CHECK_EXCEPTION(env);
1010 
1011     return JNI_TRUE; // gznote: remove this return value if unused
1012 }
1013 
1014 /*
1015  * Class:     com_sun_glass_ui_mac_MacWindow
1016  * Method:    _close
1017  * Signature: ()V
1018  */
1019 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1close
1020 (JNIEnv *env, jclass cls, jlong jPtr)
1021 {
1022     LOG("Java_com_sun_glass_ui_mac_MacWindow__1close");
1023     if (!jPtr) return JNI_FALSE;
1024 
1025     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1026     GLASS_POOL_ENTER;
1027     {
1028         GlassWindow *window = getGlassWindow(env, jPtr);
1029         // this call will always close the window
1030         // without calling the windowShouldClose
1031 
1032         // RT-39813 When closing a window as the result of a global right-click
1033         //          mouse event outside the bounds of the window, using an immediate
1034         //          [window->nsWindow close] crashes the JDK as the AppKit at this
1035         //          point still has another [NSWindow _resignKeyFocus] from the
1036         //          right-click handling in [NSApplication sendEvent].  This defers
1037         //          the close until the [NSWindow _resignKeyFocus] can be performed.
1038 
1039         [window->nsWindow performSelectorOnMainThread:@selector(close) withObject:nil waitUntilDone:NO];
1040 
1041         // The NSWindow will be automatically released after closing
1042         // The GlassWindow is released in the [NSWindow dealloc] override
1043     }
1044     GLASS_POOL_EXIT;
1045     GLASS_CHECK_EXCEPTION(env);
1046 
1047     return JNI_TRUE; // gznote: remove this return value if unused
1048 }
1049 
1050 /*
1051  * Class:     com_sun_glass_ui_mac_MacWindow
1052  * Method:    _requestFocus
1053  * Signature: (J)Z
1054  */
1055 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1requestFocus
1056 (JNIEnv *env, jobject jWindow, jlong jPtr)
1057 {
1058     LOG("Java_com_sun_glass_ui_mac_MacWindow__1requestFocus");
1059     if (!jPtr) return JNI_FALSE;
1060 
1061     jboolean focused = JNI_FALSE;
1062 
1063     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1064     GLASS_POOL_ENTER;
1065     {
1066         GlassWindow *window = getGlassWindow(env, jPtr);
1067 
1068         if ([window->nsWindow isVisible])
1069         {
1070             [window->nsWindow makeMainWindow];
1071             [window->nsWindow makeKeyAndOrderFront:window->nsWindow];
1072             [window->nsWindow orderFrontRegardless];
1073         }
1074 
1075         focused = [window->nsWindow isKeyWindow] ? JNI_TRUE : JNI_FALSE;
1076     }
1077     GLASS_POOL_EXIT;
1078     GLASS_CHECK_EXCEPTION(env);
1079 
1080     return focused;
1081 }
1082 
1083 /*
1084  * Class:     com_sun_glass_ui_mac_MacWindow
1085  * Method:    _grabFocus
1086  * Signature: (J)Z
1087  */
1088 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1grabFocus
1089 (JNIEnv *env, jobject jThis, jlong jPtr)
1090 {
1091     LOG("Java_com_sun_glass_ui_mac_MacWindow__1grabFocus");
1092     if (!jPtr) return JNI_FALSE;
1093 
1094     jboolean ret = JNI_FALSE;
1095 
1096     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1097     GLASS_POOL_ENTER;
1098     {
1099         GlassWindow * window = getGlassWindow(env, jPtr);
1100         //TODO: full screen
1101         [window _grabFocus];
1102         ret = JNI_TRUE;
1103     }
1104     GLASS_POOL_EXIT;
1105     GLASS_CHECK_EXCEPTION(env);
1106 
1107     return ret;
1108 }
1109 
1110 /*
1111  * Class:     com_sun_glass_ui_mac_MacWindow
1112  * Method:    _ungrabFocus
1113  * Signature: (J)V
1114  */
1115 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1ungrabFocus
1116 (JNIEnv *env, jobject jThis, jlong jPtr)
1117 {
1118     LOG("Java_com_sun_glass_ui_mac_MacWindow__1ungrabFocus");
1119     if (!jPtr) return;
1120 
1121     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1122     GLASS_POOL_ENTER;
1123     {
1124         GlassWindow * window = getGlassWindow(env, jPtr);
1125         //TODO; full screen
1126         [window _ungrabFocus];
1127     }
1128     GLASS_POOL_EXIT;
1129     GLASS_CHECK_EXCEPTION(env);
1130 }
1131 
1132 /*
1133  * Class:     com_sun_glass_ui_mac_MacWindow
1134  * Method:    _maximize
1135  * Signature: (JZZ)V
1136  */
1137 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1maximize
1138 (JNIEnv *env, jobject jWindow, jlong jPtr, jboolean maximize, jboolean isZoomed)
1139 {
1140     LOG("Java_com_sun_glass_ui_mac_MacWindow__1maximize");
1141     if (!jPtr) return JNI_FALSE;
1142 
1143     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1144     GLASS_POOL_ENTER;
1145     {
1146         GlassWindow *window = getGlassWindow(env, jPtr);
1147         window->suppressWindowResizeEvent = YES;
1148 
1149         if ((maximize == JNI_TRUE) && (isZoomed == JNI_FALSE))
1150         {
1151             window->preZoomedRect = [window->nsWindow frame];
1152 
1153             if ([window->nsWindow styleMask] != NSBorderlessWindowMask)
1154             {
1155                 [window->nsWindow zoom:nil];
1156                 // windowShouldZoom will be called automatically in this case
1157             }
1158             else
1159             {
1160                 NSRect visibleRect = [[window _getScreen] visibleFrame];
1161                 [window _setWindowFrameWithRect:NSMakeRect(visibleRect.origin.x, visibleRect.origin.y, visibleRect.size.width, visibleRect.size.height) withDisplay:JNI_TRUE withAnimate:JNI_TRUE];
1162 
1163                 // calling windowShouldZoom will send Java maximize event
1164                 [window windowShouldZoom:window->nsWindow toFrame:[window->nsWindow frame]];
1165             }
1166         }
1167         else if ((maximize == JNI_FALSE) && (isZoomed == JNI_TRUE))
1168         {
1169             [window _restorePreZoomedRect];
1170         }
1171 
1172         window->suppressWindowResizeEvent = NO;
1173     }
1174     GLASS_POOL_EXIT;
1175     GLASS_CHECK_EXCEPTION(env);
1176 
1177     return JNI_TRUE; // gznote: remove this return value if unused
1178 }
1179 
1180 /*
1181  * Class:     com_sun_glass_ui_mac_MacWindow
1182  * Method:    _setBounds
1183  * Signature: (JIIZZIIIIFF)V
1184  */
1185 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setBounds2
1186 (JNIEnv *env, jobject jWindow, jlong jPtr,
1187  jint x, jint y, jboolean xSet, jboolean ySet,
1188  jint w, jint h, jint cw, jint ch, jfloat xGravity, jfloat yGravity)
1189 {
1190     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setBounds");
1191     LOG("   x,y: %d,%d", x, y);
1192     LOG("   xSet,ySet: %d,%d", xSet, ySet);
1193     LOG("   xGravity,yGravity: %.2f,%.2f", xGravity, yGravity);
1194     LOG("   w x h: %dx%d", w, h);
1195     LOG("   cw x ch: %dx%d", cw, ch);
1196     if (!jPtr) return;
1197 
1198     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1199     GLASS_POOL_ENTER;
1200     {
1201         GlassWindow *window = getGlassWindow(env, jPtr);
1202         if (xSet || ySet) window->isLocationAssigned = YES;
1203         if (w > 0 || h > 0 || cw > 0 || ch > 0) window->isSizeAssigned = YES;
1204         [window _setBounds:x y:y xSet:xSet ySet:ySet w:w h:h cw:cw ch:ch];
1205     }
1206     GLASS_POOL_EXIT;
1207     GLASS_CHECK_EXCEPTION(env);
1208 }
1209 
1210 /*
1211  * Class:     com_sun_glass_ui_mac_MacWindow
1212  * Method:    _setMinimumSize
1213  * Signature: (JII)Z
1214  */
1215 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setMinimumSize
1216 (JNIEnv *env, jobject jWindow, jlong jPtr, jint jW, jint jH)
1217 {
1218     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setMinimumSize");
1219     if (!jPtr) return JNI_FALSE;
1220 
1221     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1222     GLASS_POOL_ENTER;
1223     {
1224         GlassWindow *window = getGlassWindow(env, jPtr);
1225         [window->nsWindow setMinSize:NSMakeSize(jW, jH)];
1226     }
1227     GLASS_POOL_EXIT;
1228     GLASS_CHECK_EXCEPTION(env);
1229 
1230     return JNI_TRUE; // gznote: remove this return value if unused
1231 }
1232 
1233 /*
1234  * Class:     com_sun_glass_ui_mac_MacWindow
1235  * Method:    _setMaximumSize
1236  * Signature: (JII)Z
1237  */
1238 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setMaximumSize
1239 (JNIEnv *env, jobject jWindow, jlong jPtr, jint jW, jint jH)
1240 {
1241     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setMaximumSize");
1242     if (!jPtr) return JNI_FALSE;
1243 
1244     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1245     GLASS_POOL_ENTER;
1246     {
1247         GlassWindow *window = getGlassWindow(env, jPtr);
1248         [window->nsWindow setMaxSize:NSMakeSize(jW == -1 ? FLT_MAX : (CGFloat)jW,
1249                                                 jH == -1 ? FLT_MAX : (CGFloat)jH)];
1250     }
1251     GLASS_POOL_EXIT;
1252     GLASS_CHECK_EXCEPTION(env);
1253 
1254     return JNI_TRUE; // gznote: remove this return value if unused
1255 }
1256 
1257 /*
1258  * Class:     com_sun_glass_ui_mac_MacWindow
1259  * Method:    _setResizable
1260  * Signature: (Z)Z
1261  */
1262 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setResizable
1263 (JNIEnv *env, jobject jWindow, jlong jPtr, jboolean jResizable)
1264 {
1265     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setResizable");
1266     if (!jPtr) return JNI_FALSE;
1267 
1268     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1269     GLASS_POOL_ENTER;
1270     {
1271         GlassWindow *window = getGlassWindow(env, jPtr);
1272         if (window->isResizable != jResizable)
1273         {
1274             [window performSelectorOnMainThread:@selector(_setResizable) withObject:nil waitUntilDone:YES];
1275         }
1276     }
1277     GLASS_POOL_EXIT;
1278     GLASS_CHECK_EXCEPTION(env);
1279 
1280     return JNI_TRUE;
1281 }
1282 
1283 /*
1284  * Class:     com_sun_glass_ui_mac_MacWindow
1285  * Method:    _setVisible
1286  * Signature: (Z)Z
1287  */
1288 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setVisible
1289 (JNIEnv *env, jobject jWindow, jlong jPtr, jboolean jVisible)
1290 {
1291     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setVisible: %d", jVisible);
1292     LOG("   window: %p", jPtr);
1293     if (!jPtr) return JNI_FALSE;
1294 
1295     jboolean now = JNI_FALSE;
1296 
1297     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1298     GLASS_POOL_ENTER;
1299     {
1300         GlassWindow *window = getGlassWindow(env, jPtr);
1301         if (jVisible == JNI_TRUE)
1302         {
1303             if (!window->isLocationAssigned) {
1304                 [window _setBounds:0 y:0 xSet:JNI_TRUE ySet:JNI_TRUE w:-1 h:-1 cw:-1 ch:-1];
1305             }
1306             if (!window->isSizeAssigned) {
1307                 [window _setBounds:0 y:0 xSet:JNI_FALSE ySet:JNI_FALSE w:320 h:200 cw:-1 ch:-1];
1308             }
1309             [window _setVisible];
1310         }
1311         else
1312         {
1313             [window _ungrabFocus];
1314             if (window->owner != nil)
1315             {
1316                 LOG("   removeChildWindow: %p", window);
1317                 [window->owner removeChildWindow:window->nsWindow];
1318             }
1319             [window->nsWindow orderOut:window->nsWindow];
1320         }
1321         now = [window->nsWindow isVisible] ? JNI_TRUE : JNI_FALSE;
1322 
1323         // RT-22502 temp workaround: bring plugin window in front of a browser
1324         if (now == YES)
1325         {
1326             static BOOL isBackgroundOnlyAppChecked = NO;
1327             static BOOL isBackgroundOnlyApp = NO;
1328             if (isBackgroundOnlyAppChecked == NO)
1329             {
1330                 isBackgroundOnlyAppChecked = YES;
1331 
1332                 ProcessSerialNumber psn;
1333                 if (GetCurrentProcess(&psn) == noErr)
1334                 {
1335                     ProcessInfoRec info;
1336                     memset(&info, 0x00, sizeof(ProcessInfoRec));
1337                     GetProcessInformation(&psn, &info);
1338                     isBackgroundOnlyApp = ((modeOnlyBackground&info.processMode) == modeOnlyBackground);
1339                 }
1340             }
1341             if (isBackgroundOnlyApp == YES)
1342             {
1343                 [window->nsWindow performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES];
1344             }
1345         }
1346     }
1347     GLASS_POOL_EXIT;
1348     GLASS_CHECK_EXCEPTION(env);
1349 
1350     return now;
1351 }
1352 
1353 /*
1354  * Class:     com_sun_glass_ui_mac_MacWindow
1355  * Method:    _setTitle
1356  * Signature: (Ljava/lang/String;)Z
1357  */
1358 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setTitle
1359 (JNIEnv *env, jobject jWindow, jlong jPtr, jstring jTitle)
1360 {
1361     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setTitle");
1362     LOG("   window: %p", jPtr);
1363     if (!jPtr) return JNI_FALSE;
1364 
1365     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1366     GLASS_POOL_ENTER;
1367     {
1368         GlassWindow *window = getGlassWindow(env, jPtr);
1369 
1370         NSString *title = [GlassHelper nsStringWithJavaString:jTitle withEnv:env];
1371         LOG("   title: %s", [title UTF8String]);
1372         [window->nsWindow setTitle:title];
1373     }
1374     GLASS_POOL_EXIT;
1375     GLASS_CHECK_EXCEPTION(env);
1376 
1377     return JNI_TRUE; // gnote: remove this return value if unused
1378 }
1379 
1380 /*
1381  * Class:     com_sun_glass_ui_mac_MacWindow
1382  * Method:    _minimize
1383  * Signature: (Z)V
1384  */
1385 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1minimize
1386 (JNIEnv *env, jobject jWindow, jlong jPtr, jboolean jMiniaturize)
1387 {
1388     LOG("Java_com_sun_glass_ui_mac_MacWindow__1minimize");
1389     if (!jPtr) return JNI_FALSE;
1390 
1391     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1392     GLASS_POOL_ENTER;
1393     {
1394         GlassWindow *window = getGlassWindow(env, jPtr);
1395 
1396         if (jMiniaturize == JNI_TRUE)
1397         {
1398             [window->nsWindow miniaturize:nil];
1399         }
1400         else
1401         {
1402             [window->nsWindow deminiaturize:nil];
1403         }
1404     }
1405     GLASS_POOL_EXIT;
1406     GLASS_CHECK_EXCEPTION(env);
1407 
1408     return JNI_TRUE; // gnote: remove this return value if unused
1409 }
1410 
1411 /*
1412  * Class:     com_sun_glass_ui_mac_MacWindow
1413  * Method:    _setIcon
1414  * Signature: (JLjava/nio/ByteBuffer;II)V
1415  */
1416 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setIcon
1417 (JNIEnv *env, jobject jWindow, jlong jPtr, jobject iconBuffer, jint jWidth, jint jHeight)
1418 {
1419     LOG("Java_com_sun_glass_ui_mac_MacWindow__1setIcon");
1420     if (!jPtr) return;
1421 
1422     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1423     GLASS_POOL_ENTER;
1424     {
1425         GlassWindow *window = getGlassWindow(env, jPtr);
1426 
1427         if (iconBuffer)
1428         {
1429             NSImage *image = nil;
1430 
1431             image = getImage(
1432                         (*env)->GetDirectBufferAddress(env, iconBuffer),
1433                         jHeight, jWidth, 0);
1434 
1435             if (image != nil) {
1436                 // need an explicit window title for the rest of the code to work
1437                 if ([window->nsWindow title] == nil)
1438                 {
1439                     [window->nsWindow setTitle:@"Untitled"];
1440                 }
1441 
1442                 // http://www.cocoabuilder.com/archive/cocoa/199554-nswindow-title-bar-icon-without-representedurl.html
1443                 [window->nsWindow setRepresentedURL:[NSURL fileURLWithPath:[window->nsWindow title]]];
1444                 [[window->nsWindow standardWindowButton:NSWindowDocumentIconButton] setImage:image];
1445                 [image release];
1446             } else {
1447                 [[window->nsWindow standardWindowButton:NSWindowDocumentIconButton] setImage:nil];
1448             }
1449         } else {
1450             [[window->nsWindow standardWindowButton:NSWindowDocumentIconButton] setImage:nil];
1451         }
1452     }
1453     GLASS_POOL_EXIT;
1454     GLASS_CHECK_EXCEPTION(env);
1455 }
1456 
1457 /*
1458  * Class:     com_sun_glass_ui_mac_MacWindow
1459  * Method:    _toFront
1460  * Signature: (J)V
1461  */
1462 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1toFront
1463 (JNIEnv *env, jobject jWindow, jlong jPtr)
1464 {
1465     LOG("Java_com_sun_glass_ui_mac_MacWindow__1toFront");
1466     LOG("   window: %p", jPtr);
1467     if (!jPtr) return;
1468 
1469     GLASS_POOL_ENTER;
1470     {
1471         GlassWindow *window = getGlassWindow(env, jPtr);
1472         [window->nsWindow orderFrontRegardless];
1473     }
1474     GLASS_POOL_EXIT;
1475     GLASS_CHECK_EXCEPTION(env);
1476 }
1477 
1478 /*
1479  * Class:     com_sun_glass_ui_mac_MacWindow
1480  * Method:    _toBack
1481  * Signature: (J)V
1482  */
1483 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1toBack
1484 (JNIEnv *env, jobject jWindow, jlong jPtr)
1485 {
1486     LOG("Java_com_sun_glass_ui_mac_MacWindow__1toBack");
1487     if (!jPtr) return;
1488 
1489     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1490     GLASS_POOL_ENTER;
1491     {
1492         GlassWindow *window = getGlassWindow(env, jPtr);
1493         [window->nsWindow orderBack:nil];
1494     }
1495     GLASS_POOL_EXIT;
1496     GLASS_CHECK_EXCEPTION(env);
1497 }
1498 
1499 
1500 /*
1501  * Class:     com_sun_glass_ui_mac_MacWindow
1502  * Method:    _enterModal
1503  * Signature: (J)V
1504  */
1505 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1enterModal
1506 (JNIEnv *env, jobject jWindow, jlong jPtr)
1507 {
1508     LOG("Java_com_sun_glass_ui_mac_MacWindow__1enterModal");
1509     if (!jPtr) return;
1510 
1511     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1512     GLASS_POOL_ENTER;
1513     {
1514         GlassWindow *window = getGlassWindow(env, jPtr);
1515         [NSApp runModalForWindow:window->nsWindow];
1516     }
1517     GLASS_POOL_EXIT;
1518     GLASS_CHECK_EXCEPTION(env);
1519 }
1520 
1521 /*
1522  * Class:     com_sun_glass_ui_mac_MacWindow
1523  * Method:    _enterModalWithWindow
1524  * Signature: (JJ)V
1525  */
1526 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1enterModalWithWindow
1527 (JNIEnv *env, jobject jWindow, jlong jDialogPtr, jlong jWindowPtr)
1528 {
1529     LOG("Java_com_sun_glass_ui_mac_MacWindow__1enterModalWithWindow");
1530 
1531     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1532     GLASS_POOL_ENTER;
1533     {
1534         //GlassWindow *window = getGlassWindow(env, jDialogPtr);
1535         // TODO: implement _enterModalWithWindow
1536     }
1537     GLASS_POOL_EXIT;
1538     GLASS_CHECK_EXCEPTION(env);
1539 }
1540 
1541 /*
1542  * Class:     com_sun_glass_ui_mac_MacWindow
1543  * Method:    _exitModal
1544  * Signature: (J)V
1545  */
1546 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1exitModal
1547 (JNIEnv *env, jobject jWindow, jlong jPtr)
1548 {
1549     LOG("Java_com_sun_glass_ui_mac_MacWindow__1exitModal");
1550     if (!jPtr) return;
1551 
1552     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1553     GLASS_POOL_ENTER;
1554     {
1555         GlassWindow *window = getGlassWindow(env, jPtr);
1556         [NSApp stop:window->nsWindow];
1557     }
1558     GLASS_POOL_EXIT;
1559     GLASS_CHECK_EXCEPTION(env);
1560 }
1561 
1562 /*
1563  * Class:     com_sun_glass_ui_mac_MacWindow
1564  * Method:    _getEmbeddedX
1565  * Signature: (J)I
1566  */
1567 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_mac_MacWindow__1getEmbeddedX
1568 (JNIEnv *env, jobject jWindow, jlong jPtr)
1569 {
1570     LOG("Java_com_sun_glass_ui_mac_MacWindow__1getEmbeddedX");
1571     if (!jPtr) return 0;
1572 
1573     jint x = 0;
1574 
1575     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1576     GLASS_POOL_ENTER;
1577     {
1578         GlassEmbeddedWindow *window = getGlassEmbeddedWindow(env, jPtr);
1579         x = (int)round([window frame].origin.x);
1580     }
1581     GLASS_POOL_EXIT;
1582     GLASS_CHECK_EXCEPTION(env);
1583 
1584     return x;
1585 }
1586 
1587 /*
1588  * Class:     com_sun_glass_ui_mac_MacWindow
1589  * Method:    _getEmbeddedY
1590  * Signature: (J)I
1591  */
1592 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_mac_MacWindow__1getEmbeddedY
1593 (JNIEnv *env, jobject jWindow, jlong jPtr)
1594 {
1595     LOG("Java_com_sun_glass_ui_mac_MacWindow__1getEmbeddedY");
1596     if (!jPtr) return 0;
1597 
1598     jint y = 0;
1599 
1600     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
1601     GLASS_POOL_ENTER;
1602     {
1603         GlassEmbeddedWindow *window = getGlassEmbeddedWindow(env, jPtr);
1604         NSRect frameRect = [window frame];
1605 
1606         // flip y coordinate
1607         NSScreen *screen = [[NSScreen screens] objectAtIndex:0];
1608         NSRect screenFrame = screen.frame;
1609         y = (int)round(screenFrame.size.height - frameRect.size.height - frameRect.origin.y);
1610     }
1611     GLASS_POOL_EXIT;
1612     GLASS_CHECK_EXCEPTION(env);
1613 
1614     return y;
1615 }