1 /* 2 * Copyright (c) 2011, 2014, 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 46 @interface NSWindow (External) 47 48 - (void)_startLiveResize; 49 - (void)_endLiveResize; 50 51 @end 52 53 @implementation GlassWindow (Java) 54 55 #pragma mark --- Callbacks 56 57 - (void)_sendJavaWindowMoveToAnotherScreenEventIfNeeded 58 { 59 NSScreen *newScreen = [self->nsWindow screen]; 60 61 // Update only if the newScreen isn't nil 62 if (self->currentScreen != newScreen && newScreen != nil) 63 { 64 self->currentScreen = newScreen; 65 66 GET_MAIN_JENV; 67 (*env)->CallVoidMethod(env, jWindow, jWindowNotifyMoveToAnotherScreen, createJavaScreen(env, newScreen)); 68 } 69 } 70 71 - (void)_sendJavaWindowMoveEventForFrame:(NSRect)frame 72 { 73 if (self->suppressWindowMoveEvent == NO) 74 { 75 self->lastReportedLocation = frame.origin; 76 77 GET_MAIN_JENV; 78 (*env)->CallVoidMethod(env, jWindow, jWindowNotifyMove, (int)frame.origin.x, (int)frame.origin.y); 79 [self _sendJavaWindowMoveToAnotherScreenEventIfNeeded]; 80 } 81 } 82 83 - (void)_sendJavaWindowResizeEvent:(int)type forFrame:(NSRect)frame 84 { 85 if (self->suppressWindowResizeEvent == NO) 86 { 87 GET_MAIN_JENV; 88 (*env)->CallVoidMethod(env, jWindow, jWindowNotifyResize, type, (int)frame.size.width, (int)frame.size.height); 89 [self _sendJavaWindowMoveToAnotherScreenEventIfNeeded]; 90 } 91 } 92 93 #pragma mark --- Additions 94 95 - (id)_initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle screen:(NSScreen *)screen jwindow:(jobject)jwindow jIsChild:(jboolean)jIsChild 96 { 97 self = [super init]; 98 if (self == nil) { 99 return nil; 100 } 101 102 if (jIsChild == JNI_FALSE) { 103 if (windowStyle & (NSUtilityWindowMask | NSNonactivatingPanelMask)) { 104 self->nsWindow = [[GlassWindow_Panel alloc] initWithDelegate:self 105 frameRect:contentRect 106 styleMask:windowStyle 107 screen:screen]; 108 } else { 109 self->nsWindow = [[GlassWindow_Normal alloc] initWithDelegate:self 110 frameRect:contentRect 111 styleMask:windowStyle 112 screen:screen]; 113 } 114 } else { 115 GlassEmbeddedWindow *ewindow = [[GlassEmbeddedWindow alloc] initWithDelegate:self 116 frameRect:contentRect 117 styleMask:windowStyle 118 screen:screen]; 119 if (ewindow) { 120 ewindow->parent = nil; 121 ewindow->child = nil; 122 123 self->nsWindow = ewindow; 124 } 125 } 126 127 if (self->nsWindow == nil) { 128 NSLog(@"Unable to create GlassWindow_Normal or GlassWindow_Panel"); 129 return nil; 130 } 131 132 self->jWindow = jwindow; 133 134 self->isFocusable = YES; 135 self->isEnabled = YES; 136 self->currentScreen = screen; 137 138 self->suppressWindowMoveEvent = NO; 139 self->suppressWindowResizeEvent = NO; 140 141 self->isClosed = NO; 142 143 // This is surely can't be a real location, which indicates 144 // we've never sent a MOVE event to Java yet. 145 self->lastReportedLocation.x = self->lastReportedLocation.y = FLT_MAX; 146 147 CGFloat x = 0.0f; 148 CGFloat y = [screen frame].size.height - [screen visibleFrame].size.height; 149 CGFloat w = [self->nsWindow frame].size.width; 150 CGFloat h = [self->nsWindow frame].size.height; 151 [self _setFlipFrame:NSMakeRect(x, y, w, h) display:YES animate:NO]; 152 153 //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:nil]; 154 //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidMiniaturizeNotification object:nil]; 155 156 return self; 157 } 158 159 - (NSWindow*)_getCurrentWindow 160 { 161 return self->fullscreenWindow ? self->fullscreenWindow : self->nsWindow; 162 } 163 164 - (void)_ungrabFocus 165 { 166 NSWindow *window = [self _getCurrentWindow]; 167 168 if (s_grabWindow != window) { 169 return; 170 } 171 172 GET_MAIN_JENV; 173 (*env)->CallVoidMethod(env, self->jWindow, jWindowNotifyFocusUngrab); 174 175 s_grabWindow = nil; 176 } 177 178 + (void)_resetGrab 179 { 180 if (s_grabWindow && [[s_grabWindow delegate] isKindOfClass:[GlassWindow class]]) { 181 GlassWindow * window = (GlassWindow*)[s_grabWindow delegate]; 182 [window _ungrabFocus]; 183 } 184 s_grabWindow = nil; // unconditionally 185 } 186 187 - (void)_checkUngrab 188 { 189 if (!s_grabWindow) { 190 return; 191 } 192 193 // If this window doesn't belong to an owned windows hierarchy that 194 // holds the grab currently, then the grab should be released. 195 for (NSWindow * window = self->nsWindow; window; window = [window parentWindow]) { 196 if (window == s_grabWindow) { 197 return; 198 } 199 } 200 201 [GlassWindow _resetGrab]; 202 } 203 204 - (void)_grabFocus 205 { 206 NSWindow *window = [self _getCurrentWindow]; 207 208 if (s_grabWindow == window) { 209 return; 210 } 211 212 [GlassWindow _resetGrab]; 213 s_grabWindow = window; 214 } 215 216 - (void)_setResizable 217 { 218 NSUInteger mask = [self->nsWindow styleMask]; 219 if ((mask & NSResizableWindowMask) != 0) 220 { 221 if (self->isDecorated == YES) 222 { 223 mask &= ~(NSUInteger)NSResizableWindowMask; 224 [self->nsWindow setStyleMask: mask]; 225 [self->nsWindow setShowsResizeIndicator:NO]; 226 227 NSButton *zoomButton = [self->nsWindow standardWindowButton:NSWindowZoomButton]; 228 [zoomButton setEnabled:NO]; 229 } 230 self->isResizable = NO; 231 } 232 else 233 { 234 if (self->isDecorated == YES) 235 { 236 mask |= NSResizableWindowMask; 237 [self->nsWindow setStyleMask: mask]; 238 [self->nsWindow setShowsResizeIndicator:YES]; 239 240 NSButton *zoomButton = [self->nsWindow standardWindowButton:NSWindowZoomButton]; 241 [zoomButton setEnabled:YES]; 242 } 243 self->isResizable = YES; 244 } 245 } 246 247 - (NSRect)_constrainFrame:(NSRect)frame 248 { 249 NSSize minSize = [self->nsWindow minSize]; 250 NSSize maxSize = [self->nsWindow maxSize]; 251 NSSize size = frame.size; 252 253 NSRect constrained = frame; 254 { 255 if (size.width < minSize.width) 256 { 257 constrained.size.width = minSize.width; 258 } 259 else if (size.width > maxSize.width) 260 { 261 constrained.size.width = maxSize.width; 262 } 263 264 if (size.height < minSize.height) 265 { 266 constrained.size.height = minSize.height; 267 } 268 else if (size.height > maxSize.height) 269 { 270 constrained.size.height = maxSize.height; 271 } 272 } 273 return constrained; 274 } 275 276 - (void)_setVisible 277 { 278 LOG("_setVisible: focusable %d enabled %d", self->isFocusable, self->isEnabled); 279 280 if (self->isFocusable == YES && self->isEnabled == YES) 281 { 282 [self->nsWindow makeMainWindow]; 283 [self->nsWindow makeKeyAndOrderFront:nil]; 284 } 285 else 286 { 287 [self->nsWindow orderFront:nil]; 288 } 289 290 if ((self->owner != nil) && ([self->nsWindow parentWindow] == nil)) 291 { 292 [self->owner addChildWindow:self->nsWindow ordered:NSWindowAbove]; 293 } 294 } 295 296 - (void)_setWindowFrameWithRect:(NSRect)rect withDisplay:(jboolean)display withAnimate:(jboolean)animate 297 { 298 NSRect frame = [self _constrainFrame:rect]; 299 [self _setFlipFrame:frame display:(BOOL)display animate:(BOOL)animate]; 300 301 } 302 303 - (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 304 { 305 NSPoint origin = [self _flipFrame].origin; 306 NSSize size = [self->nsWindow frame].size; 307 NSSize sizeForClient = [NSWindow frameRectForContentRect:NSMakeRect(0.0, 0.0, cw > 0 ? cw : 0.0, ch > 0 ? ch : 0.0) styleMask:[self->nsWindow styleMask]].size; 308 309 jint newX = xSet == JNI_TRUE ? x : (jint)origin.x; 310 jint newY = ySet == JNI_TRUE ? y : (jint)origin.y; 311 312 jint newW = (w > 0) ? w : (cw > 0) ? (jint)sizeForClient.width : (jint)size.width; 313 jint newH = (h > 0) ? h : (ch > 0) ? (jint)sizeForClient.height : (jint)size.height; 314 315 [self _setWindowFrameWithRect:NSMakeRect(newX, newY, newW, newH) withDisplay:JNI_TRUE withAnimate:JNI_FALSE]; 316 } 317 318 - (void)_restorePreZoomedRect 319 { 320 [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]; 321 [self _sendJavaWindowMoveEventForFrame:[self _flipFrame]]; 322 [self _sendJavaWindowResizeEvent:com_sun_glass_events_WindowEvent_RESTORE forFrame:[self _flipFrame]]; 323 } 324 325 - (NSScreen*)_getScreen 326 { 327 NSScreen *screen = [self->nsWindow screen]; 328 if (screen == nil) 329 { 330 screen = self->currentScreen; 331 } 332 if (screen == nil) 333 { 334 screen = [[NSScreen screens] objectAtIndex: 0]; 335 } 336 return screen; 337 } 338 339 #pragma mark --- Flip 340 341 - (void)_setFlipFrame:(NSRect)frameRect display:(BOOL)displayFlag animate:(BOOL)animateFlag 342 { 343 //NSLog(@"_setFlipFrame: %.2f,%.2f %.2fx%.2f", frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); 344 NSScreen * screen = [[NSScreen screens] objectAtIndex: 0]; 345 NSRect screenFrame = screen.frame; 346 //NSLog(@" screenFrame: %.2f,%.2f %.2fx%.2f", screenFrame.origin.x, screenFrame.origin.y, screenFrame.size.width, screenFrame.size.height); 347 348 frameRect.origin.y = screenFrame.size.height - frameRect.size.height - frameRect.origin.y; 349 //NSLog(@" set to frameRect:%.2f,%.2f %.2fx%.2f", frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); 350 351 [self->nsWindow setFrame:frameRect display:displayFlag animate:animateFlag]; 352 353 //frameRect = [self _flipFrame]; 354 //NSLog(@" _flipFrame:%.2f,%.2f %.2fx%.2f", frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); 355 //frameRect = [super frame]; 356 //NSLog(@" frame:%.2f,%.2f %.2fx%.2f", frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); 357 } 358 359 - (NSRect)_flipFrame 360 { 361 NSScreen * screen = [[NSScreen screens] objectAtIndex: 0]; 362 NSRect screenFrame = screen.frame; 363 364 NSRect frame = [self->nsWindow frame]; 365 //NSLog(@"_flipFrame: v.s.h=%.2f f.s.h=%.2f f.o.y=%.2f", screenFrame.size.height, frame.size.height, frame.origin.y); 366 frame.origin.y = screenFrame.size.height - frame.size.height - frame.origin.y; 367 //NSLog(@" result: f.o.y=%.2f", frame.origin.y); 368 369 //NSLog(@"_flipFrame: %.2f,%.2f %.2fx%.2f", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height); 370 return frame; 371 } 372 373 @end