1 /*
   2  * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #import "common.h"
  27 #import "com_sun_glass_events_ViewEvent.h"
  28 #import "com_sun_glass_events_WindowEvent.h"
  29 #import "com_sun_glass_ui_Window.h"
  30 #import "com_sun_glass_ui_Window_Level.h"
  31 #import "com_sun_glass_ui_mac_MacWindow.h"
  32 
  33 #import "GlassMacros.h"
  34 #import "GlassWindow.h"
  35 #import "GlassTouches.h"
  36 #import "GlassWindow+Java.h"
  37 #import "GlassWindow+Overrides.h"
  38 #import "GlassViewDelegate.h"
  39 #import "GlassApplication.h"
  40 #import "GlassScreen.h"
  41 
  42 #import <AppKit/NSGraphics.h> // NSBeep();
  43 
  44 @implementation GlassWindow (Overrides)
  45 
  46 - (void)dealloc
  47 {
  48     assert(pthread_main_np() == 1);
  49     JNIEnv *env = jEnv;
  50     if (env != NULL)
  51     {
  52         (*env)->DeleteGlobalRef(env, self->jWindow);
  53         GLASS_CHECK_EXCEPTION(env);
  54     }
  55 
  56     self->jWindow = NULL;
  57 
  58     [super dealloc];
  59 }
  60 
  61 #pragma mark --- Delegate
  62 
  63 - (void)windowDidBecomeKey:(NSNotification *)notification
  64 {
  65     if (self->fullscreenWindow)
  66     {
  67         return;
  68     }
  69 
  70     GET_MAIN_JENV;
  71     if (!self->isEnabled)
  72     {
  73         NSBeep();
  74         (*env)->CallVoidMethod(env, self->jWindow, jWindowNotifyFocusDisabled);
  75         return;
  76     }
  77 
  78     (*env)->CallVoidMethod(env, self->jWindow, jWindowNotifyFocus, com_sun_glass_events_WindowEvent_FOCUS_GAINED);
  79 
  80     if (self->menubar != nil)
  81     {
  82         [NSApp setMainMenu:self->menubar->menu];
  83     }
  84     [[NSApp mainMenu] update];
  85 }
  86 
  87 - (void)windowDidResignKey:(NSNotification *)notification
  88 {
  89     if (self->fullscreenWindow)
  90     {
  91         return;
  92     }
  93 
  94     [self _ungrabFocus];
  95 
  96     GET_MAIN_JENV;
  97     (*env)->CallVoidMethod(env, self->jWindow, jWindowNotifyFocus, com_sun_glass_events_WindowEvent_FOCUS_LOST);
  98 }
  99 
 100 - (void)windowWillClose:(NSNotification *)notification
 101 {
 102     // Unparent self. Otherwise the code hangs
 103     if ([self->nsWindow parentWindow])
 104     {
 105         [[self->nsWindow parentWindow] removeChildWindow:self->nsWindow];
 106     }
 107 
 108     // Finally, close owned windows to mimic MS Windows behavior
 109     NSArray *children = [self->nsWindow childWindows];
 110     for (NSUInteger i=0; i<[children count]; i++)
 111     {
 112         NSWindow *child = (NSWindow*)[children objectAtIndex:i];
 113         [child close];
 114     }
 115 
 116     // Call the notification method
 117     assert(pthread_main_np() == 1);
 118     JNIEnv *env = jEnv;
 119     if (env != NULL) {
 120         (*env)->CallVoidMethod(env, self->jWindow, jWindowNotifyDestroy);
 121     }
 122 }
 123 
 124 - (void)windowWillMove:(NSNotification *)notification
 125 {
 126     //NSLog(@"windowWillMove");
 127 }
 128 
 129 - (void)windowDidMove:(NSNotification *)notification
 130 {
 131     //NSLog(@"windowDidMove");
 132     [self _sendJavaWindowMoveEventForFrame:[self _flipFrame]];
 133 }
 134 
 135 - (void)windowDidChangeBackingProperties:(NSNotification *)notification
 136 {
 137     // The spec for [NSWindow backingScaleFactor] only mentions 1.0 and 2.0
 138     // whereas NSScreen's one is more generic. So use the latter.
 139     if ([self->nsWindow screen]) {
 140         CGFloat scale = GetScreenScaleFactor([self->nsWindow screen]);
 141         [self->view notifyScaleFactorChanged:scale];
 142         [self _sendJavaWindowNotifyScaleChanged:scale];
 143     }
 144 
 145     // Screen.notifySettingsChanged() calls Window.setScreen(), and the latter
 146     // generates the Window.EventHandler.handleScreenChangedEvent notification.
 147 }
 148 
 149 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
 150 {
 151     //NSLog(@"windowWillResize");
 152     return proposedFrameSize;
 153 }
 154 
 155 - (void)windowDidResize:(NSNotification *)notification
 156 {
 157     //NSLog(@"windowDidResize");
 158     NSRect frame = [self _flipFrame];
 159 
 160     if ((int)self->lastReportedLocation.x != (int)frame.origin.x ||
 161             (int)self->lastReportedLocation.y != (int)frame.origin.y)
 162     {
 163         [self _sendJavaWindowMoveEventForFrame:frame];
 164 
 165         // Refetch the frame since it might've been modified due to the previous call
 166         frame = [self _flipFrame];
 167     }
 168 
 169     [self _sendJavaWindowResizeEvent:com_sun_glass_events_WindowEvent_RESIZE forFrame:frame];
 170 }
 171 
 172 - (void)windowDidMiniaturize:(NSNotification *)notification
 173 {
 174     [self _sendJavaWindowResizeEvent:com_sun_glass_events_WindowEvent_MINIMIZE forFrame:[self _flipFrame]];
 175 }
 176 
 177 - (void)windowDidDeminiaturize:(NSNotification *)notification
 178 {
 179     [self _sendJavaWindowResizeEvent:com_sun_glass_events_WindowEvent_RESTORE forFrame:[self _flipFrame]];
 180 }
 181 
 182 - (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame
 183 {
 184     GET_MAIN_JENV;
 185 
 186     if ([window isZoomed]) {
 187         return NO;
 188     }
 189 
 190     (*env)->CallVoidMethod(env, jWindow, jWindowNotifyResize, com_sun_glass_events_WindowEvent_MAXIMIZE, (int)newFrame.size.width, (int)newFrame.size.height);
 191 
 192     return YES;
 193 }
 194 
 195 - (void)windowWillEnterFullScreen:(NSNotification *)notification
 196 {
 197     //NSLog(@"windowWillEnterFullScreen");
 198 }
 199 
 200 - (void)windowDidEnterFullScreen:(NSNotification *)notification
 201 {
 202     //NSLog(@"windowDidEnterFullScreen");
 203     [(GlassViewDelegate*)[self->view delegate] sendJavaFullScreenEvent:YES withNativeWidget:YES];
 204     [GlassApplication leaveFullScreenExitingLoopIfNeeded];
 205 }
 206 
 207 - (void)windowWillExitFullScreen:(NSNotification *)notification
 208 {
 209     //NSLog(@"windowWillExitFullScreen");
 210 }
 211 - (void)windowDidExitFullScreen:(NSNotification *)notification
 212 {
 213     //NSLog(@"windowDidExitFullScreen");
 214     [(GlassViewDelegate*)[self->view delegate] sendJavaFullScreenEvent:NO withNativeWidget:YES];
 215     [GlassApplication leaveFullScreenExitingLoopIfNeeded];
 216 }
 217 
 218 - (BOOL)windowShouldClose:(NSNotification *)notification
 219 {
 220     if (self->isEnabled)
 221     {
 222         GET_MAIN_JENV;
 223         (*env)->CallVoidMethod(env, jWindow, jWindowNotifyClose);
 224     }
 225 
 226     // it's up to app to decide if the window should be closed
 227     return FALSE;
 228 }
 229 
 230 #pragma mark --- Title Icon
 231 
 232 - (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu
 233 {
 234     return NO;
 235 }
 236 
 237 - (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard
 238 {
 239     return NO;
 240 }
 241 
 242 @end