1 /* 2 * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #import "common.h" 27 #import "com_sun_glass_events_ViewEvent.h" 28 #import "com_sun_glass_events_WindowEvent.h" 29 #import "com_sun_glass_ui_Window.h" 30 #import "com_sun_glass_ui_Window_Level.h" 31 #import "com_sun_glass_ui_mac_MacWindow.h" 32 33 #import "GlassMacros.h" 34 #import "GlassWindow+Java.h" 35 #import "GlassScreen.h" 36 37 //#define VERBOSE 38 #ifndef VERBOSE 39 #define LOG(MSG, ...) 40 #else 41 #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__); 42 #endif 43 44 static NSWindow *s_grabWindow = nil; 45 extern NSSize maxScreenDimensions; 46 47 @interface NSWindow (External) 48 49 - (void)_startLiveResize; 50 - (void)_endLiveResize; 51 52 @end 53 54 @implementation GlassWindow (Java) 55 56 #pragma mark --- Callbacks 57 58 - (void)_sendJavaWindowMoveToAnotherScreenEventIfNeeded 59 { 60 NSScreen *newScreen = [self->nsWindow screen]; 61 62 // Update only if the newScreen isn't nil 63 if (self->currentScreen != newScreen && newScreen != nil) 64 { 65 self->currentScreen = newScreen; 66 67 GET_MAIN_JENV; 68 (*env)->CallVoidMethod(env, jWindow, jWindowNotifyMoveToAnotherScreen, createJavaScreen(env, newScreen)); 69 } 70 } 71 72 - (void)_sendJavaWindowMoveEventForFrame:(NSRect)frame 73 { 74 if (self->suppressWindowMoveEvent == NO) 75 { 76 self->lastReportedLocation = frame.origin; 77 78 GET_MAIN_JENV; 79 80 (*env)->CallVoidMethod(env, jWindow, jWindowNotifyMove, 81 (int)frame.origin.x, (int)frame.origin.y, [self->nsWindow isZoomed]); 82 [self _sendJavaWindowMoveToAnotherScreenEventIfNeeded]; 83 } 84 } 85 86 - (void)_sendJavaWindowResizeEvent:(int)type forFrame:(NSRect)frame 87 { 88 if (self->suppressWindowResizeEvent == NO) 89 { 90 GET_MAIN_JENV; 91 (*env)->CallVoidMethod(env, jWindow, jWindowNotifyResize, 92 [self->nsWindow isZoomed] 93 ? com_sun_glass_events_WindowEvent_MAXIMIZE 94 : type, 95 (int)frame.size.width, (int)frame.size.height); 96 [self _sendJavaWindowMoveToAnotherScreenEventIfNeeded]; 97 } 98 } 99 100 #pragma mark --- Additions 101 102 - (id)_initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle screen:(NSScreen *)screen jwindow:(jobject)jwindow jIsChild:(jboolean)jIsChild 103 { 104 self = [super init]; 105 if (self == nil) { 106 return nil; 107 } 108 109 if (jIsChild == JNI_FALSE) { 110 if (windowStyle & (NSUtilityWindowMask | NSNonactivatingPanelMask)) { 111 self->nsWindow = [[GlassWindow_Panel alloc] initWithDelegate:self 112 frameRect:contentRect 113 styleMask:windowStyle 114 screen:screen]; 115 } else { 116 self->nsWindow = [[GlassWindow_Normal alloc] initWithDelegate:self 117 frameRect:contentRect 118 styleMask:windowStyle 119 screen:screen]; 120 } 121 } else { 122 GlassEmbeddedWindow *ewindow = [[GlassEmbeddedWindow alloc] initWithDelegate:self 123 frameRect:contentRect 124 styleMask:windowStyle 125 screen:screen]; 126 if (ewindow) { 127 ewindow->parent = nil; 128 ewindow->child = nil; 129 130 self->nsWindow = ewindow; 131 } 132 } 133 134 if (self->nsWindow == nil) { 135 NSLog(@"Unable to create GlassWindow_Normal or GlassWindow_Panel"); 136 return nil; 137 } 138 139 self->jWindow = jwindow; 140 141 self->isFocusable = YES; 142 self->isEnabled = YES; 143 self->currentScreen = screen; 144 145 self->suppressWindowMoveEvent = NO; 146 self->suppressWindowResizeEvent = NO; 147 148 self->isClosed = NO; 149 150 // This is surely can't be a real location, which indicates 151 // we've never sent a MOVE event to Java yet. 152 self->lastReportedLocation.x = self->lastReportedLocation.y = FLT_MAX; 153 154 CGFloat x = 0.0f; 155 CGFloat y = [screen frame].size.height - [screen visibleFrame].size.height; 156 CGFloat w = [self->nsWindow frame].size.width; 157 CGFloat h = [self->nsWindow frame].size.height; 158 [self _setFlipFrame:NSMakeRect(x, y, w, h) display:YES animate:NO]; 159 160 //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:nil]; 161 //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidMiniaturizeNotification object:nil]; 162 163 return self; 164 } 165 166 - (NSWindow*)_getCurrentWindow 167 { 168 return self->fullscreenWindow ? self->fullscreenWindow : self->nsWindow; 169 } 170 171 - (void)_ungrabFocus 172 { 173 NSWindow *window = [self _getCurrentWindow]; 174 175 if (s_grabWindow != window) { 176 return; 177 } 178 179 GET_MAIN_JENV; 180 (*env)->CallVoidMethod(env, self->jWindow, jWindowNotifyFocusUngrab); 181 182 s_grabWindow = nil; 183 } 184 185 + (void)_resetGrab 186 { 187 if (s_grabWindow && [[s_grabWindow delegate] isKindOfClass:[GlassWindow class]]) { 188 GlassWindow * window = (GlassWindow*)[s_grabWindow delegate]; 189 [window _ungrabFocus]; 190 } 191 s_grabWindow = nil; // unconditionally 192 } 193 194 - (void)_checkUngrab 195 { 196 if (!s_grabWindow) { 197 return; 198 } 199 200 // If this window doesn't belong to an owned windows hierarchy that 201 // holds the grab currently, then the grab should be released. 202 for (NSWindow * window = self->nsWindow; window; window = [window parentWindow]) { 203 if (window == s_grabWindow) { 204 return; 205 } 206 } 207 208 [GlassWindow _resetGrab]; 209 } 210 211 - (void)_grabFocus 212 { 213 NSWindow *window = [self _getCurrentWindow]; 214 215 if (s_grabWindow == window) { 216 return; 217 } 218 219 [GlassWindow _resetGrab]; 220 s_grabWindow = window; 221 } 222 223 - (void)_setResizable 224 { 225 NSUInteger mask = [self->nsWindow styleMask]; 226 if ((mask & NSResizableWindowMask) != 0) 227 { 228 if (self->isDecorated == YES) 229 { 230 mask &= ~(NSUInteger)NSResizableWindowMask; 231 [self->nsWindow setStyleMask: mask]; 232 [self->nsWindow setShowsResizeIndicator:NO]; 233 234 NSButton *zoomButton = [self->nsWindow standardWindowButton:NSWindowZoomButton]; 235 [zoomButton setEnabled:NO]; 236 } 237 self->isResizable = NO; 238 } 239 else 240 { 241 if (self->isDecorated == YES) 242 { 243 mask |= NSResizableWindowMask; 244 [self->nsWindow setStyleMask: mask]; 245 [self->nsWindow setShowsResizeIndicator:YES]; 246 247 NSButton *zoomButton = [self->nsWindow standardWindowButton:NSWindowZoomButton]; 248 [zoomButton setEnabled:YES]; 249 } 250 self->isResizable = YES; 251 } 252 } 253 254 - (NSRect)_constrainFrame:(NSRect)frame 255 { 256 NSSize minSize = [self->nsWindow minSize]; 257 NSSize maxSize = [self->nsWindow maxSize]; 258 NSSize size = frame.size; 259 260 NSRect constrained = frame; 261 { 262 if (size.width < minSize.width) 263 { 264 constrained.size.width = minSize.width; 265 } 266 else if (size.width > maxSize.width) 267 { 268 constrained.size.width = maxSize.width; 269 } 270 271 if (size.height < minSize.height) 272 { 273 constrained.size.height = minSize.height; 274 } 275 else if (size.height > maxSize.height) 276 { 277 constrained.size.height = maxSize.height; 278 } 279 } 280 return constrained; 281 } 282 283 - (void)_setVisible 284 { 285 LOG("_setVisible: focusable %d enabled %d", self->isFocusable, self->isEnabled); 286 287 if (self->isFocusable == YES && self->isEnabled == YES) 288 { 289 [self->nsWindow makeMainWindow]; 290 [self->nsWindow makeKeyAndOrderFront:nil]; 291 } 292 else 293 { 294 [self->nsWindow orderFront:nil]; 295 } 296 297 if ((self->owner != nil) && ([self->nsWindow parentWindow] == nil)) 298 { 299 [self->owner addChildWindow:self->nsWindow ordered:NSWindowAbove]; 300 } 301 // Make sure we synchronize scale factors which could have changed while 302 // we were not visible without invoking the overrides we watch. 303 if ([self->nsWindow screen] && (self->view != nil)) { 304 [self->view notifyScaleFactorChanged:GetScreenScaleFactor([self->nsWindow screen])]; 305 } 306 } 307 308 - (void)_setWindowFrameWithRect:(NSRect)rect withDisplay:(jboolean)display withAnimate:(jboolean)animate 309 { 310 NSRect frame = [self _constrainFrame:rect]; 311 [self _setFlipFrame:frame display:(BOOL)display animate:(BOOL)animate]; 312 313 } 314 315 - (void)_setBounds:(jint)x y:(jint)y xSet:(jboolean)xSet ySet:(jboolean)ySet w:(jint)w h:(jint)h cw:(jint)cw ch:(jint)ch 316 { 317 NSPoint origin = [self _flipFrame].origin; 318 NSSize size = [self->nsWindow frame].size; 319 NSSize sizeForClient = [NSWindow frameRectForContentRect:NSMakeRect(0.0, 0.0, cw > 0 ? cw : 0.0, ch > 0 ? ch : 0.0) styleMask:[self->nsWindow styleMask]].size; 320 321 jint newX = xSet == JNI_TRUE ? x : (jint)origin.x; 322 jint newY = ySet == JNI_TRUE ? y : (jint)origin.y; 323 324 jint newW = (w > 0) ? w : (cw > 0) ? (jint)sizeForClient.width : (jint)size.width; 325 jint newH = (h > 0) ? h : (ch > 0) ? (jint)sizeForClient.height : (jint)size.height; 326 327 [self _setWindowFrameWithRect:NSMakeRect(newX, newY, newW, newH) withDisplay:JNI_TRUE withAnimate:JNI_FALSE]; 328 } 329 330 - (void)_restorePreZoomedRect 331 { 332 [self _setWindowFrameWithRect:NSMakeRect(self->preZoomedRect.origin.x, self->preZoomedRect.origin.y, self->preZoomedRect.size.width, self->preZoomedRect.size.height) withDisplay:JNI_TRUE withAnimate:JNI_TRUE]; 333 [self _sendJavaWindowMoveEventForFrame:[self _flipFrame]]; 334 [self _sendJavaWindowResizeEvent:com_sun_glass_events_WindowEvent_RESTORE forFrame:[self _flipFrame]]; 335 } 336 337 - (NSScreen*)_getScreen 338 { 339 NSScreen *screen = [self->nsWindow screen]; 340 if (screen == nil) 341 { 342 screen = self->currentScreen; 343 } 344 if (screen == nil) 345 { 346 screen = [[NSScreen screens] objectAtIndex: 0]; 347 } 348 return screen; 349 } 350 351 #pragma mark --- Flip 352 353 - (void)_setFlipFrame:(NSRect)frameRect display:(BOOL)displayFlag animate:(BOOL)animateFlag 354 { 355 //NSLog(@"_setFlipFrame: %.2f,%.2f %.2fx%.2f", frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); 356 NSScreen * screen = [[NSScreen screens] objectAtIndex: 0]; 357 NSRect screenFrame = screen.frame; 358 //NSLog(@" screenFrame: %.2f,%.2f %.2fx%.2f", screenFrame.origin.x, screenFrame.origin.y, screenFrame.size.width, screenFrame.size.height); 359 360 frameRect.origin.y = screenFrame.size.height - frameRect.size.height - frameRect.origin.y; 361 //NSLog(@" set to frameRect:%.2f,%.2f %.2fx%.2f", frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); 362 363 if (frameRect.size.width > maxScreenDimensions.width) { 364 frameRect.size.width = maxScreenDimensions.width; 365 } 366 367 if (frameRect.size.height > maxScreenDimensions.height) { 368 frameRect.size.height = maxScreenDimensions.height; 369 } 370 371 [self->nsWindow setFrame:frameRect display:displayFlag animate:animateFlag]; 372 373 //frameRect = [self _flipFrame]; 374 //NSLog(@" _flipFrame:%.2f,%.2f %.2fx%.2f", frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); 375 //frameRect = [super frame]; 376 //NSLog(@" frame:%.2f,%.2f %.2fx%.2f", frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); 377 } 378 379 - (NSRect)_flipFrame 380 { 381 NSScreen * screen = [[NSScreen screens] objectAtIndex: 0]; 382 NSRect screenFrame = screen.frame; 383 384 NSRect frame = [self->nsWindow frame]; 385 //NSLog(@"_flipFrame: v.s.h=%.2f f.s.h=%.2f f.o.y=%.2f", screenFrame.size.height, frame.size.height, frame.origin.y); 386 frame.origin.y = screenFrame.size.height - frame.size.height - frame.origin.y; 387 //NSLog(@" result: f.o.y=%.2f", frame.origin.y); 388 389 //NSLog(@"_flipFrame: %.2f,%.2f %.2fx%.2f", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height); 390 return frame; 391 } 392 393 @end