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.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         [self->view notifyScaleFactorChanged:GetScreenScaleFactor([self->nsWindow screen])];
 141     }
 142 
 143     // Screen.notifySettingsChanged() calls Window.setScreen(), and the latter
 144     // generates the Window.EventHandler.handleScreenChangedEvent notification.
 145 }
 146 
 147 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
 148 {
 149     //NSLog(@"windowWillResize");
 150     return proposedFrameSize;
 151 }
 152 
 153 - (void)windowDidResize:(NSNotification *)notification
 154 {
 155     //NSLog(@"windowDidResize");
 156     NSRect frame = [self _flipFrame];
 157 
 158     if ((int)self->lastReportedLocation.x != (int)frame.origin.x ||
 159             (int)self->lastReportedLocation.y != (int)frame.origin.y)
 160     {
 161         [self _sendJavaWindowMoveEventForFrame:frame];
 162 
 163         // Refetch the frame since it might've been modified due to the previous call
 164         frame = [self _flipFrame];
 165     }
 166 
 167     [self _sendJavaWindowResizeEvent:com_sun_glass_events_WindowEvent_RESIZE forFrame:frame];
 168 }
 169 
 170 - (void)windowDidMiniaturize:(NSNotification *)notification
 171 {
 172     [self _sendJavaWindowResizeEvent:com_sun_glass_events_WindowEvent_MINIMIZE forFrame:[self _flipFrame]];
 173 }
 174 
 175 - (void)windowDidDeminiaturize:(NSNotification *)notification
 176 {
 177     [self _sendJavaWindowResizeEvent:com_sun_glass_events_WindowEvent_RESTORE forFrame:[self _flipFrame]];
 178 }
 179 
 180 - (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame
 181 {
 182     GET_MAIN_JENV;
 183     (*env)->CallVoidMethod(env, jWindow, jWindowNotifyResize, com_sun_glass_events_WindowEvent_MAXIMIZE, (int)newFrame.size.width, (int)newFrame.size.height);
 184     
 185     return YES;
 186 }
 187 
 188 - (void)windowWillEnterFullScreen:(NSNotification *)notification
 189 {
 190     //NSLog(@"windowWillEnterFullScreen");
 191 }
 192 
 193 - (void)windowDidEnterFullScreen:(NSNotification *)notification
 194 {
 195     //NSLog(@"windowDidEnterFullScreen");
 196     [(GlassViewDelegate*)[self->view delegate] sendJavaFullScreenEvent:YES withNativeWidget:YES];
 197     [GlassApplication leaveFullScreenExitingLoopIfNeeded];
 198 }
 199 
 200 - (void)windowWillExitFullScreen:(NSNotification *)notification
 201 {
 202     //NSLog(@"windowWillExitFullScreen");
 203 }
 204 - (void)windowDidExitFullScreen:(NSNotification *)notification 
 205 {
 206     //NSLog(@"windowDidExitFullScreen");
 207     [(GlassViewDelegate*)[self->view delegate] sendJavaFullScreenEvent:NO withNativeWidget:YES];
 208     [GlassApplication leaveFullScreenExitingLoopIfNeeded];
 209 }
 210 
 211 - (BOOL)windowShouldClose:(NSNotification *)notification
 212 {
 213     if (self->isEnabled)
 214     {
 215         GET_MAIN_JENV;
 216         (*env)->CallVoidMethod(env, jWindow, jWindowNotifyClose);
 217     }
 218     
 219     // it's up to app to decide if the window should be closed
 220     return FALSE;
 221 }
 222 
 223 #pragma mark --- Title Icon
 224 
 225 - (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu
 226 {
 227     return NO;
 228 }
 229 
 230 - (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard
 231 {
 232     return NO;
 233 }
 234 
 235 @end