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