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