1 /* 2 * Copyright (c) 2011, 2015, 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 default: \ 166 return button; \ 167 } \ 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 (window->isDecorated && !window->owner) 518 { 519 // Only titled 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", "(II)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 (jWindowNotifyClose == NULL) 640 { 641 jWindowNotifyClose = (*env)->GetMethodID(env, jWindowClass, "notifyClose", "()V"); 642 if ((*env)->ExceptionCheck(env)) return; 643 } 644 645 if (jWindowNotifyFocus == NULL) 646 { 647 jWindowNotifyFocus = (*env)->GetMethodID(env, jWindowClass, "notifyFocus", "(I)V"); 648 if ((*env)->ExceptionCheck(env)) return; 649 } 650 651 if (jWindowNotifyFocusUngrab == NULL) 652 { 653 jWindowNotifyFocusUngrab = (*env)->GetMethodID(env, jWindowClass, "notifyFocusUngrab", "()V"); 654 if ((*env)->ExceptionCheck(env)) return; 655 } 656 657 if (jWindowNotifyFocusDisabled == NULL) 658 { 659 jWindowNotifyFocusDisabled = (*env)->GetMethodID(env, jWindowClass, "notifyFocusDisabled", "()V"); 660 if ((*env)->ExceptionCheck(env)) return; 661 } 662 663 if (jWindowNotifyDestroy == NULL) 664 { 665 jWindowNotifyDestroy = (*env)->GetMethodID(env, jWindowClass, "notifyDestroy", "()V"); 666 if ((*env)->ExceptionCheck(env)) return; 667 } 668 669 if (jWindowNotifyDelegatePtr == NULL) 670 { 671 jWindowNotifyDelegatePtr = (*env)->GetMethodID(env, jWindowClass, "notifyDelegatePtr", "(J)V"); 672 } 673 } 674 675 /* 676 * Class: com_sun_glass_ui_mac_MacWindow 677 * Method: _createWindow 678 * Signature: (JJI)J 679 */ 680 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacWindow__1createWindow 681 (JNIEnv *env, jobject jWindow, jlong jOwnerPtr, jlong jScreenPtr, jint jStyleMask) 682 { 683 LOG("Java_com_sun_glass_ui_mac_MacWindow__1createWindow"); 684 685 return _createWindowCommon(env, jWindow, jOwnerPtr, jScreenPtr, jStyleMask, JNI_FALSE); 686 } 687 688 /* 689 * Class: com_sun_glass_ui_mac_MacWindow 690 * Method: _createChildWindow 691 * Signature: (J)J 692 */ 693 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacWindow__1createChildWindow 694 (JNIEnv *env, jobject jWindow, jlong jOwnerPtr) 695 { 696 LOG("Java_com_sun_glass_ui_mac_MacWindow__1createChildWindow"); 697 LOG(" owner: %p", jOwnerPtr); 698 699 jlong jScreenPtr = 0L; 700 jint jStyleMask = NSBorderlessWindowMask; 701 if (jOwnerPtr == BROWSER_PARENT_ID) 702 { 703 LOG(" case PARENT (PLUGIN)"); 704 // special case: embedded window for plugin (the container which will hold the child window) 705 } 706 else 707 { 708 LOG(" case CHILD (EMBEDDED)"); 709 // special case: embedded window for plugin (the actual plugin window with remote layer) 710 // jOwnerPtr must be a valid GlassEmbeddedWindow instance 711 if (![GlassEmbeddedWindow exists:(GlassEmbeddedWindow*)jlong_to_ptr(jOwnerPtr)]) { 712 return (jlong)0; 713 } 714 } 715 716 return _createWindowCommon(env, jWindow, jOwnerPtr, jScreenPtr, jStyleMask, JNI_TRUE); 717 } 718 719 /* 720 * Class: com_sun_glass_ui_mac_MacWindow 721 * Method: _setLevel 722 * Signature: (JI)V 723 */ 724 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setLevel 725 (JNIEnv *env, jobject jWindow, jlong jPtr, jint jLevel) 726 { 727 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setLevel"); 728 if (!jPtr) return; 729 730 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 731 GLASS_POOL_ENTER; 732 { 733 GlassWindow *window = getGlassWindow(env, jPtr); 734 NSInteger level = NSNormalWindowLevel; 735 switch (jLevel) 736 { 737 case com_sun_glass_ui_Window_Level_FLOATING: 738 level = NSFloatingWindowLevel; 739 break; 740 case com_sun_glass_ui_Window_Level_TOPMOST: 741 level = NSScreenSaverWindowLevel; 742 break; 743 } 744 [window->nsWindow setLevel:level]; 745 } 746 GLASS_POOL_EXIT; 747 GLASS_CHECK_EXCEPTION(env); 748 } 749 750 /* 751 * Class: com_sun_glass_ui_mac_MacWindow 752 * Method: _setFocusable 753 * Signature: (Z)V 754 */ 755 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setFocusable 756 (JNIEnv *env, jobject jWindow, jlong jPtr, jboolean isFocusable) 757 { 758 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setCanBecomeActive"); 759 if (!jPtr) return; 760 761 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 762 GLASS_POOL_ENTER; 763 { 764 GlassWindow *window = getGlassWindow(env, jPtr); 765 window->isFocusable = (isFocusable==JNI_TRUE); 766 } 767 GLASS_POOL_EXIT; 768 GLASS_CHECK_EXCEPTION(env); 769 } 770 771 /* 772 * Class: com_sun_glass_ui_mac_MacWindow 773 * Method: _setEnabled 774 * Signature: (JZ)V 775 */ 776 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setEnabled 777 (JNIEnv *env, jobject jwindow, jlong jPtr, jboolean isEnabled) 778 { 779 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setEnabled"); 780 if (!jPtr) return; 781 782 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 783 GLASS_POOL_ENTER; 784 { 785 GlassWindow *window = getGlassWindow(env, jPtr); 786 window->isEnabled = (BOOL)isEnabled; 787 788 if (!window->isEnabled) { 789 window->enabledStyleMask = [window->nsWindow styleMask]; 790 [window->nsWindow setStyleMask: (window->enabledStyleMask & ~(NSUInteger)(NSMiniaturizableWindowMask | NSResizableWindowMask))]; 791 792 //XXX: perhaps we could simply enable/disable the buttons w/o playing with the styles at all 793 NSButton *zoomButton = [window->nsWindow standardWindowButton:NSWindowZoomButton]; 794 [zoomButton setEnabled:NO]; 795 } else { 796 [window->nsWindow setStyleMask: window->enabledStyleMask]; 797 798 if (window->enabledStyleMask & NSResizableWindowMask) { 799 NSButton *zoomButton = [window->nsWindow standardWindowButton:NSWindowZoomButton]; 800 [zoomButton setEnabled:YES]; 801 } 802 } 803 } 804 GLASS_POOL_EXIT; 805 GLASS_CHECK_EXCEPTION(env); 806 } 807 808 /* 809 * Class: com_sun_glass_ui_mac_MacWindow 810 * Method: _setAlpha 811 * Signature: (F)V 812 */ 813 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setAlpha 814 (JNIEnv *env, jobject jWindow, jlong jPtr, jfloat jAlpha) 815 { 816 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setAlpha"); 817 if (!jPtr) return; 818 819 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 820 GLASS_POOL_ENTER; 821 { 822 GlassWindow *window = getGlassWindow(env, jPtr); 823 [window->nsWindow setAlphaValue:jAlpha]; 824 } 825 GLASS_POOL_EXIT; 826 GLASS_CHECK_EXCEPTION(env); 827 } 828 829 /* 830 * Class: com_sun_glass_ui_mac_MacWindow 831 * Method: _setBackground 832 * Signature: (JFFF)Z 833 */ 834 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setBackground 835 (JNIEnv *env, jobject jWindow, jlong jPtr, jfloat r, jfloat g, jfloat b) 836 { 837 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setBackground"); 838 if (!jPtr) return JNI_FALSE; 839 840 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 841 GLASS_POOL_ENTER; 842 { 843 GlassWindow *window = getGlassWindow(env, jPtr); 844 [window->nsWindow setBackgroundColor:[NSColor colorWithCalibratedRed:r green:g blue:b alpha:1.0f]]; 845 } 846 GLASS_POOL_EXIT; 847 GLASS_CHECK_EXCEPTION(env); 848 849 return JNI_TRUE; // gznote: remove this return value if unused 850 } 851 852 /* 853 * Class: com_sun_glass_ui_mac_MacWindow 854 * Method: _setView 855 * Signature: (J)Z 856 */ 857 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setView 858 (JNIEnv *env, jobject jWindow, jlong jPtr, jobject jview) 859 { 860 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setView"); 861 LOG(" window: %p", jPtr); 862 LOG(" view: %p", getMacView(env, jview)); 863 if (!jPtr) return JNI_FALSE; 864 865 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 866 GLASS_POOL_ENTER; 867 { 868 GlassWindow *window = getGlassWindow(env, jPtr); 869 870 // We don't support changing views in the FS mode because 871 // by Glass design the FS functionality belongs to the View. 872 // Also, this leads to a crash on the Mac 873 if ([window->nsWindow styleMask] & (1 << 14)/*NSFullScreenWindowMask*/) { 874 [window->nsWindow performSelector:@selector(toggleFullScreen:) withObject:nil]; 875 876 // Wait until the FS mode has really exited 877 [GlassApplication enterFullScreenExitingLoop]; 878 } 879 880 NSView<GlassView> *oldView = window->view; 881 window->view = getMacView(env, jview); 882 883 LOG("window: %@ frame: %s", window, 884 [NSStringFromRect([window->nsWindow frame]) UTF8String]); 885 LOG("view: %@ frame: %s", window->view, 886 [NSStringFromRect([window->view frame]) UTF8String]); 887 888 if (oldView && oldView != window->view) { 889 [[oldView delegate] resetMouseTracking]; 890 } 891 892 if (window->view != nil) 893 { 894 CALayer *layer = [window->view layer]; 895 if (([layer isKindOfClass:[CAOpenGLLayer class]] == YES) && 896 (([window->nsWindow styleMask] & NSTexturedBackgroundWindowMask) == NO)) 897 { 898 [((CAOpenGLLayer*)layer) setOpaque:[window->nsWindow isOpaque]]; 899 } 900 901 window->suppressWindowMoveEvent = YES; // RT-11215 902 { 903 NSRect viewFrame = [window->view frame]; 904 if ((viewFrame.size.width != 0.0f) && (viewFrame.size.height != 0.0f)) 905 { 906 NSRect windowFrame = [window->nsWindow frameRectForContentRect:viewFrame]; 907 windowFrame.origin.x = [window->nsWindow frame].origin.x; 908 windowFrame.origin.y = [window->nsWindow frame].origin.y; 909 [window _setWindowFrameWithRect:NSMakeRect(windowFrame.origin.x, windowFrame.origin.y, windowFrame.size.width, windowFrame.size.height) withDisplay:JNI_TRUE withAnimate:JNI_FALSE]; 910 } 911 912 [window->nsWindow setContentView:[window->view superview]]; // use our superview not ourselves! 913 [window->nsWindow setInitialFirstResponder:window->view]; 914 [window->nsWindow makeFirstResponder:window->view]; 915 } 916 window->suppressWindowMoveEvent = NO; 917 } 918 else 919 { 920 [window->nsWindow performSelectorOnMainThread:@selector(setContentView:) withObject:nil waitUntilDone:YES]; 921 } 922 } 923 GLASS_POOL_EXIT; 924 GLASS_CHECK_EXCEPTION(env); 925 926 return JNI_TRUE; // gznote: remove this return value if unused 927 } 928 929 /* 930 * Class: com_sun_glass_ui_mac_MacWindow 931 * Method: _setMenubar 932 * Signature: (Lcom/sun/glass/ui/mac/MacMenubarDelegate;)V 933 */ 934 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setMenubar 935 (JNIEnv *env, jobject jWindow, jlong jPtr, jlong jMenubarPtr) 936 { 937 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setMenubar"); 938 if (!jPtr) return JNI_FALSE; 939 940 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 941 GLASS_POOL_ENTER; 942 { 943 GlassWindow *window = getGlassWindow(env, jPtr); 944 window->menubar = (GlassMenubar*)jlong_to_ptr(jMenubarPtr); 945 [NSApp setMainMenu:window->menubar->menu]; 946 [[NSApp mainMenu] update]; 947 } 948 GLASS_POOL_EXIT; 949 GLASS_CHECK_EXCEPTION(env); 950 951 return JNI_TRUE; // gznote: remove this return value if unused 952 } 953 954 /* 955 * Class: com_sun_glass_ui_mac_MacWindow 956 * Method: _close 957 * Signature: ()V 958 */ 959 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1close 960 (JNIEnv *env, jclass cls, jlong jPtr) 961 { 962 LOG("Java_com_sun_glass_ui_mac_MacWindow__1close"); 963 if (!jPtr) return JNI_FALSE; 964 965 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 966 GLASS_POOL_ENTER; 967 { 968 GlassWindow *window = getGlassWindow(env, jPtr); 969 // this call will always close the window 970 // without calling the windowShouldClose 971 972 // RT-39813 When closing a window as the result of a global right-click 973 // mouse event outside the bounds of the window, using an immediate 974 // [window->nsWindow close] crashes the JDK as the AppKit at this 975 // point still has another [NSWindow _resignKeyFocus] from the 976 // right-click handling in [NSApplication sendEvent]. This defers 977 // the close until the [NSWindow _resignKeyFocus] can be performed. 978 979 [window->nsWindow performSelectorOnMainThread:@selector(close) withObject:nil waitUntilDone:NO]; 980 981 // The NSWindow will be automatically released after closing 982 // The GlassWindow is released in the [NSWindow dealloc] override 983 } 984 GLASS_POOL_EXIT; 985 GLASS_CHECK_EXCEPTION(env); 986 987 return JNI_TRUE; // gznote: remove this return value if unused 988 } 989 990 /* 991 * Class: com_sun_glass_ui_mac_MacWindow 992 * Method: _requestFocus 993 * Signature: (J)Z 994 */ 995 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1requestFocus 996 (JNIEnv *env, jobject jWindow, jlong jPtr) 997 { 998 LOG("Java_com_sun_glass_ui_mac_MacWindow__1requestFocus"); 999 if (!jPtr) return JNI_FALSE; 1000 1001 jboolean focused = JNI_FALSE; 1002 1003 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1004 GLASS_POOL_ENTER; 1005 { 1006 GlassWindow *window = getGlassWindow(env, jPtr); 1007 1008 if ([window->nsWindow isVisible]) 1009 { 1010 [window->nsWindow makeMainWindow]; 1011 [window->nsWindow makeKeyAndOrderFront:window->nsWindow]; 1012 [window->nsWindow orderFrontRegardless]; 1013 } 1014 1015 focused = [window->nsWindow isKeyWindow] ? JNI_TRUE : JNI_FALSE; 1016 } 1017 GLASS_POOL_EXIT; 1018 GLASS_CHECK_EXCEPTION(env); 1019 1020 return focused; 1021 } 1022 1023 /* 1024 * Class: com_sun_glass_ui_mac_MacWindow 1025 * Method: _grabFocus 1026 * Signature: (J)Z 1027 */ 1028 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1grabFocus 1029 (JNIEnv *env, jobject jThis, jlong jPtr) 1030 { 1031 LOG("Java_com_sun_glass_ui_mac_MacWindow__1grabFocus"); 1032 if (!jPtr) return JNI_FALSE; 1033 1034 jboolean ret = JNI_FALSE; 1035 1036 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1037 GLASS_POOL_ENTER; 1038 { 1039 GlassWindow * window = getGlassWindow(env, jPtr); 1040 //TODO: full screen 1041 [window _grabFocus]; 1042 ret = JNI_TRUE; 1043 } 1044 GLASS_POOL_EXIT; 1045 GLASS_CHECK_EXCEPTION(env); 1046 1047 return ret; 1048 } 1049 1050 /* 1051 * Class: com_sun_glass_ui_mac_MacWindow 1052 * Method: _ungrabFocus 1053 * Signature: (J)V 1054 */ 1055 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1ungrabFocus 1056 (JNIEnv *env, jobject jThis, jlong jPtr) 1057 { 1058 LOG("Java_com_sun_glass_ui_mac_MacWindow__1ungrabFocus"); 1059 if (!jPtr) return; 1060 1061 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1062 GLASS_POOL_ENTER; 1063 { 1064 GlassWindow * window = getGlassWindow(env, jPtr); 1065 //TODO; full screen 1066 [window _ungrabFocus]; 1067 } 1068 GLASS_POOL_EXIT; 1069 GLASS_CHECK_EXCEPTION(env); 1070 } 1071 1072 /* 1073 * Class: com_sun_glass_ui_mac_MacWindow 1074 * Method: _maximize 1075 * Signature: (JZZ)V 1076 */ 1077 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1maximize 1078 (JNIEnv *env, jobject jWindow, jlong jPtr, jboolean maximize, jboolean isZoomed) 1079 { 1080 LOG("Java_com_sun_glass_ui_mac_MacWindow__1maximize"); 1081 if (!jPtr) return JNI_FALSE; 1082 1083 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1084 GLASS_POOL_ENTER; 1085 { 1086 GlassWindow *window = getGlassWindow(env, jPtr); 1087 window->suppressWindowResizeEvent = YES; 1088 1089 if ((maximize == JNI_TRUE) && (isZoomed == JNI_FALSE)) 1090 { 1091 window->preZoomedRect = [window->nsWindow frame]; 1092 1093 if ([window->nsWindow styleMask] != NSBorderlessWindowMask) 1094 { 1095 [window->nsWindow zoom:nil]; 1096 // windowShouldZoom will be called automatically in this case 1097 } 1098 else 1099 { 1100 NSRect visibleRect = [[window _getScreen] visibleFrame]; 1101 [window _setWindowFrameWithRect:NSMakeRect(visibleRect.origin.x, visibleRect.origin.y, visibleRect.size.width, visibleRect.size.height) withDisplay:JNI_TRUE withAnimate:JNI_TRUE]; 1102 1103 // calling windowShouldZoom will send Java maximize event 1104 [window windowShouldZoom:window->nsWindow toFrame:[window->nsWindow frame]]; 1105 } 1106 } 1107 else if ((maximize == JNI_FALSE) && (isZoomed == JNI_TRUE)) 1108 { 1109 [window _restorePreZoomedRect]; 1110 } 1111 1112 window->suppressWindowResizeEvent = NO; 1113 } 1114 GLASS_POOL_EXIT; 1115 GLASS_CHECK_EXCEPTION(env); 1116 1117 return JNI_TRUE; // gznote: remove this return value if unused 1118 } 1119 1120 /* 1121 * Class: com_sun_glass_ui_mac_MacWindow 1122 * Method: _setBounds 1123 * Signature: (JIIZZIIIIFF)V 1124 */ 1125 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setBounds 1126 (JNIEnv *env, jobject jWindow, jlong jPtr, 1127 jint x, jint y, jboolean xSet, jboolean ySet, 1128 jint w, jint h, jint cw, jint ch, jfloat xGravity, jfloat yGravity) 1129 { 1130 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setBounds"); 1131 LOG(" x,y: %d,%d", x, y); 1132 LOG(" xSet,ySet: %d,%d", xSet, ySet); 1133 LOG(" xGravity,yGravity: %.2f,%.2f", xGravity, yGravity); 1134 LOG(" w x h: %dx%d", w, h); 1135 LOG(" cw x ch: %dx%d", cw, ch); 1136 if (!jPtr) return; 1137 1138 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1139 GLASS_POOL_ENTER; 1140 { 1141 GlassWindow *window = getGlassWindow(env, jPtr); 1142 if (xSet || ySet) window->isLocationAssigned = YES; 1143 if (w > 0 || h > 0 || cw > 0 || ch > 0) window->isSizeAssigned = YES; 1144 [window _setBounds:x y:y xSet:xSet ySet:ySet w:w h:h cw:cw ch:ch]; 1145 } 1146 GLASS_POOL_EXIT; 1147 GLASS_CHECK_EXCEPTION(env); 1148 } 1149 1150 /* 1151 * Class: com_sun_glass_ui_mac_MacWindow 1152 * Method: _setMinimumSize 1153 * Signature: (JII)Z 1154 */ 1155 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setMinimumSize 1156 (JNIEnv *env, jobject jWindow, jlong jPtr, jint jW, jint jH) 1157 { 1158 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setMinimumSize"); 1159 if (!jPtr) return JNI_FALSE; 1160 1161 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1162 GLASS_POOL_ENTER; 1163 { 1164 GlassWindow *window = getGlassWindow(env, jPtr); 1165 [window->nsWindow setMinSize:NSMakeSize(jW, jH)]; 1166 } 1167 GLASS_POOL_EXIT; 1168 GLASS_CHECK_EXCEPTION(env); 1169 1170 return JNI_TRUE; // gznote: remove this return value if unused 1171 } 1172 1173 /* 1174 * Class: com_sun_glass_ui_mac_MacWindow 1175 * Method: _setMaximumSize 1176 * Signature: (JII)Z 1177 */ 1178 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setMaximumSize 1179 (JNIEnv *env, jobject jWindow, jlong jPtr, jint jW, jint jH) 1180 { 1181 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setMaximumSize"); 1182 if (!jPtr) return JNI_FALSE; 1183 1184 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1185 GLASS_POOL_ENTER; 1186 { 1187 GlassWindow *window = getGlassWindow(env, jPtr); 1188 [window->nsWindow setMaxSize:NSMakeSize(jW == -1 ? FLT_MAX : (CGFloat)jW, 1189 jH == -1 ? FLT_MAX : (CGFloat)jH)]; 1190 } 1191 GLASS_POOL_EXIT; 1192 GLASS_CHECK_EXCEPTION(env); 1193 1194 return JNI_TRUE; // gznote: remove this return value if unused 1195 } 1196 1197 /* 1198 * Class: com_sun_glass_ui_mac_MacWindow 1199 * Method: _setResizable 1200 * Signature: (Z)Z 1201 */ 1202 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setResizable 1203 (JNIEnv *env, jobject jWindow, jlong jPtr, jboolean jResizable) 1204 { 1205 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setResizable"); 1206 if (!jPtr) return JNI_FALSE; 1207 1208 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1209 GLASS_POOL_ENTER; 1210 { 1211 GlassWindow *window = getGlassWindow(env, jPtr); 1212 if (window->isResizable != jResizable) 1213 { 1214 [window performSelectorOnMainThread:@selector(_setResizable) withObject:nil waitUntilDone:YES]; 1215 } 1216 } 1217 GLASS_POOL_EXIT; 1218 GLASS_CHECK_EXCEPTION(env); 1219 1220 return JNI_TRUE; 1221 } 1222 1223 /* 1224 * Class: com_sun_glass_ui_mac_MacWindow 1225 * Method: _setVisible 1226 * Signature: (Z)Z 1227 */ 1228 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setVisible 1229 (JNIEnv *env, jobject jWindow, jlong jPtr, jboolean jVisible) 1230 { 1231 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setVisible: %d", jVisible); 1232 LOG(" window: %p", jPtr); 1233 if (!jPtr) return JNI_FALSE; 1234 1235 jboolean now = JNI_FALSE; 1236 1237 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1238 GLASS_POOL_ENTER; 1239 { 1240 GlassWindow *window = getGlassWindow(env, jPtr); 1241 if (jVisible == JNI_TRUE) 1242 { 1243 if (!window->isLocationAssigned) { 1244 [window _setBounds:0 y:0 xSet:JNI_TRUE ySet:JNI_TRUE w:-1 h:-1 cw:-1 ch:-1]; 1245 } 1246 if (!window->isSizeAssigned) { 1247 [window _setBounds:0 y:0 xSet:JNI_FALSE ySet:JNI_FALSE w:320 h:200 cw:-1 ch:-1]; 1248 } 1249 [window _setVisible]; 1250 } 1251 else 1252 { 1253 [window _ungrabFocus]; 1254 if (window->owner != nil) 1255 { 1256 LOG(" removeChildWindow: %p", window); 1257 [window->owner removeChildWindow:window->nsWindow]; 1258 } 1259 [window->nsWindow orderOut:window->nsWindow]; 1260 } 1261 now = [window->nsWindow isVisible] ? JNI_TRUE : JNI_FALSE; 1262 1263 // RT-22502 temp workaround: bring plugin window in front of a browser 1264 if (now == YES) 1265 { 1266 static BOOL isBackgroundOnlyAppChecked = NO; 1267 static BOOL isBackgroundOnlyApp = NO; 1268 if (isBackgroundOnlyAppChecked == NO) 1269 { 1270 isBackgroundOnlyAppChecked = YES; 1271 1272 ProcessSerialNumber psn; 1273 if (GetCurrentProcess(&psn) == noErr) 1274 { 1275 ProcessInfoRec info; 1276 memset(&info, 0x00, sizeof(ProcessInfoRec)); 1277 GetProcessInformation(&psn, &info); 1278 isBackgroundOnlyApp = ((modeOnlyBackground&info.processMode) == modeOnlyBackground); 1279 } 1280 } 1281 if (isBackgroundOnlyApp == YES) 1282 { 1283 [window->nsWindow performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; 1284 } 1285 } 1286 } 1287 GLASS_POOL_EXIT; 1288 GLASS_CHECK_EXCEPTION(env); 1289 1290 return now; 1291 } 1292 1293 /* 1294 * Class: com_sun_glass_ui_mac_MacWindow 1295 * Method: _setTitle 1296 * Signature: (Ljava/lang/String;)Z 1297 */ 1298 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setTitle 1299 (JNIEnv *env, jobject jWindow, jlong jPtr, jstring jTitle) 1300 { 1301 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setTitle"); 1302 LOG(" window: %p", jPtr); 1303 if (!jPtr) return JNI_FALSE; 1304 1305 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1306 GLASS_POOL_ENTER; 1307 { 1308 GlassWindow *window = getGlassWindow(env, jPtr); 1309 1310 NSString *title = [GlassHelper nsStringWithJavaString:jTitle withEnv:env]; 1311 LOG(" title: %s", [title UTF8String]); 1312 [window->nsWindow setTitle:title]; 1313 } 1314 GLASS_POOL_EXIT; 1315 GLASS_CHECK_EXCEPTION(env); 1316 1317 return JNI_TRUE; // gnote: remove this return value if unused 1318 } 1319 1320 /* 1321 * Class: com_sun_glass_ui_mac_MacWindow 1322 * Method: _minimize 1323 * Signature: (Z)V 1324 */ 1325 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_mac_MacWindow__1minimize 1326 (JNIEnv *env, jobject jWindow, jlong jPtr, jboolean jMiniaturize) 1327 { 1328 LOG("Java_com_sun_glass_ui_mac_MacWindow__1minimize"); 1329 if (!jPtr) return JNI_FALSE; 1330 1331 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1332 GLASS_POOL_ENTER; 1333 { 1334 GlassWindow *window = getGlassWindow(env, jPtr); 1335 1336 if (jMiniaturize == JNI_TRUE) 1337 { 1338 [window->nsWindow miniaturize:nil]; 1339 } 1340 else 1341 { 1342 [window->nsWindow deminiaturize:nil]; 1343 } 1344 } 1345 GLASS_POOL_EXIT; 1346 GLASS_CHECK_EXCEPTION(env); 1347 1348 return JNI_TRUE; // gnote: remove this return value if unused 1349 } 1350 1351 /* 1352 * Class: com_sun_glass_ui_mac_MacWindow 1353 * Method: _setIcon 1354 * Signature: (JLcom/sun/glass/ui/Pixels;)V 1355 */ 1356 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setIcon 1357 (JNIEnv *env, jobject jWindow, jlong jPtr, jobject jPixels) 1358 { 1359 LOG("Java_com_sun_glass_ui_mac_MacWindow__1setIcon"); 1360 if (!jPtr) return; 1361 1362 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1363 GLASS_POOL_ENTER; 1364 { 1365 GlassWindow *window = getGlassWindow(env, jPtr); 1366 if (jPixels != NULL) 1367 { 1368 NSImage *image = nil; 1369 (*env)->CallVoidMethod(env, jPixels, jPixelsAttachData, ptr_to_jlong(&image)); 1370 if (image != nil) { 1371 // need an explicit window title for the rest of the code to work 1372 if ([window->nsWindow title] == nil) 1373 { 1374 [window->nsWindow setTitle:@"Untitled"]; 1375 } 1376 1377 // http://www.cocoabuilder.com/archive/cocoa/199554-nswindow-title-bar-icon-without-representedurl.html 1378 [window->nsWindow setRepresentedURL:[NSURL fileURLWithPath:[window->nsWindow title]]]; 1379 [[window->nsWindow standardWindowButton:NSWindowDocumentIconButton] setImage:image]; 1380 [image release]; 1381 } else { 1382 [[window->nsWindow standardWindowButton:NSWindowDocumentIconButton] setImage:nil]; 1383 } 1384 } else { 1385 [[window->nsWindow standardWindowButton:NSWindowDocumentIconButton] setImage:nil]; 1386 } 1387 } 1388 GLASS_POOL_EXIT; 1389 GLASS_CHECK_EXCEPTION(env); 1390 } 1391 1392 /* 1393 * Class: com_sun_glass_ui_mac_MacWindow 1394 * Method: _toFront 1395 * Signature: (J)V 1396 */ 1397 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1toFront 1398 (JNIEnv *env, jobject jWindow, jlong jPtr) 1399 { 1400 LOG("Java_com_sun_glass_ui_mac_MacWindow__1toFront"); 1401 LOG(" window: %p", jPtr); 1402 if (!jPtr) return; 1403 1404 GLASS_POOL_ENTER; 1405 { 1406 GlassWindow *window = getGlassWindow(env, jPtr); 1407 [window->nsWindow orderFrontRegardless]; 1408 } 1409 GLASS_POOL_EXIT; 1410 GLASS_CHECK_EXCEPTION(env); 1411 } 1412 1413 /* 1414 * Class: com_sun_glass_ui_mac_MacWindow 1415 * Method: _toBack 1416 * Signature: (J)V 1417 */ 1418 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1toBack 1419 (JNIEnv *env, jobject jWindow, jlong jPtr) 1420 { 1421 LOG("Java_com_sun_glass_ui_mac_MacWindow__1toBack"); 1422 if (!jPtr) return; 1423 1424 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1425 GLASS_POOL_ENTER; 1426 { 1427 GlassWindow *window = getGlassWindow(env, jPtr); 1428 [window->nsWindow orderBack:nil]; 1429 } 1430 GLASS_POOL_EXIT; 1431 GLASS_CHECK_EXCEPTION(env); 1432 } 1433 1434 1435 /* 1436 * Class: com_sun_glass_ui_mac_MacWindow 1437 * Method: _enterModal 1438 * Signature: (J)V 1439 */ 1440 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1enterModal 1441 (JNIEnv *env, jobject jWindow, jlong jPtr) 1442 { 1443 LOG("Java_com_sun_glass_ui_mac_MacWindow__1enterModal"); 1444 if (!jPtr) return; 1445 1446 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1447 GLASS_POOL_ENTER; 1448 { 1449 GlassWindow *window = getGlassWindow(env, jPtr); 1450 [NSApp runModalForWindow:window->nsWindow]; 1451 } 1452 GLASS_POOL_EXIT; 1453 GLASS_CHECK_EXCEPTION(env); 1454 } 1455 1456 /* 1457 * Class: com_sun_glass_ui_mac_MacWindow 1458 * Method: _enterModalWithWindow 1459 * Signature: (JJ)V 1460 */ 1461 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1enterModalWithWindow 1462 (JNIEnv *env, jobject jWindow, jlong jDialogPtr, jlong jWindowPtr) 1463 { 1464 LOG("Java_com_sun_glass_ui_mac_MacWindow__1enterModalWithWindow"); 1465 1466 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1467 GLASS_POOL_ENTER; 1468 { 1469 //GlassWindow *window = getGlassWindow(env, jDialogPtr); 1470 // TODO: implement _enterModalWithWindow 1471 } 1472 GLASS_POOL_EXIT; 1473 GLASS_CHECK_EXCEPTION(env); 1474 } 1475 1476 /* 1477 * Class: com_sun_glass_ui_mac_MacWindow 1478 * Method: _exitModal 1479 * Signature: (J)V 1480 */ 1481 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1exitModal 1482 (JNIEnv *env, jobject jWindow, jlong jPtr) 1483 { 1484 LOG("Java_com_sun_glass_ui_mac_MacWindow__1exitModal"); 1485 if (!jPtr) return; 1486 1487 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1488 GLASS_POOL_ENTER; 1489 { 1490 GlassWindow *window = getGlassWindow(env, jPtr); 1491 [NSApp stop:window->nsWindow]; 1492 } 1493 GLASS_POOL_EXIT; 1494 GLASS_CHECK_EXCEPTION(env); 1495 } 1496 1497 /* 1498 * Class: com_sun_glass_ui_mac_MacWindow 1499 * Method: _getEmbeddedX 1500 * Signature: (J)I 1501 */ 1502 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_mac_MacWindow__1getEmbeddedX 1503 (JNIEnv *env, jobject jWindow, jlong jPtr) 1504 { 1505 LOG("Java_com_sun_glass_ui_mac_MacWindow__1getEmbeddedX"); 1506 if (!jPtr) return 0; 1507 1508 jint x = 0; 1509 1510 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1511 GLASS_POOL_ENTER; 1512 { 1513 GlassEmbeddedWindow *window = getGlassEmbeddedWindow(env, jPtr); 1514 x = (int)round([window frame].origin.x); 1515 } 1516 GLASS_POOL_EXIT; 1517 GLASS_CHECK_EXCEPTION(env); 1518 1519 return x; 1520 } 1521 1522 /* 1523 * Class: com_sun_glass_ui_mac_MacWindow 1524 * Method: _getEmbeddedY 1525 * Signature: (J)I 1526 */ 1527 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_mac_MacWindow__1getEmbeddedY 1528 (JNIEnv *env, jobject jWindow, jlong jPtr) 1529 { 1530 LOG("Java_com_sun_glass_ui_mac_MacWindow__1getEmbeddedX"); 1531 if (!jPtr) return 0; 1532 1533 jint y = 0; 1534 1535 GLASS_ASSERT_MAIN_JAVA_THREAD(env); 1536 GLASS_POOL_ENTER; 1537 { 1538 GlassEmbeddedWindow *window = getGlassEmbeddedWindow(env, jPtr); 1539 NSRect frameRect = [window frame]; 1540 1541 // flip y coorindate 1542 NSScreen *screen = [[NSScreen screens] objectAtIndex:0]; 1543 NSRect screenFrame = screen.frame; 1544 y = (int)round(screenFrame.size.height - frameRect.size.height - frameRect.origin.y); 1545 } 1546 GLASS_POOL_EXIT; 1547 GLASS_CHECK_EXCEPTION(env); 1548 1549 return y; 1550 }