/*************************************************************************** PluginWindowController.m The big bad boy that controls/creates the game window, the openGLView, and communicates with PCSX itself PeopsOpenGPU Created by Gil Pedersen on Tue April 12 2004. Copyright (c) 2004 Gil Pedersen. ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. See also the license.txt file for * * additional informations. * * * ***************************************************************************/ #import "PluginWindowController.h" #import "PluginWindow.h" #import "Carbon/Carbon.h" #include // OpenGL needed for "externals.h" #include "externals.h" #undef BOOL // not sure why these aren't class or instance variables... NSWindow *gameWindow; PluginWindowController *gameController; NSRect windowFrame; NSRect windowDefaultRect; // default window size (needed to go back into window mode) @implementation PluginWindowController + (id)openGameView { // create a window for the GPU and return // the controller that controls it if (gameWindow == nil) { if (gameController == nil) { gameController = [[PluginWindowController alloc] initWithWindowNibName:@"NetSfPeopsOpenGLGPUInterface"]; } gameWindow = [gameController window]; } else { NSLog(@"Well, we have a game window open already, which is kinda bad."); abort(); return nil; } [gameWindow setBackgroundColor: [NSColor blackColor]]; windowFrame.size.width=iResX; windowFrame.size.height=iResY; if (windowFrame.size.width != 0) [gameWindow setFrame:windowFrame display:NO]; [gameWindow center]; windowDefaultRect = [gameWindow frame]; [gameWindow makeKeyAndOrderFront:nil]; [gameController showWindow:nil]; NSOpenGLView* glInstance = [gameController getOpenGLView]; [glInstance setFrameSize: windowDefaultRect.size]; [glInstance reshape]; // [glView update]; CGDirectDisplayID display = (CGDirectDisplayID)[[[[gameWindow screen] deviceDescription] objectForKey:@"NSScreenNumber"] longValue]; if (CGDisplayIsCaptured(display)) { [gameController setFullscreen:YES]; } return gameController; } - (PluginGLView *)getOpenGLView { return (PluginGLView *)glView; } - (void) cureAllIlls { // try to reset the GPU without discarding textures, etc. // when a resize takes place, all hell breaks loose, so // this is necessarily ugly. // all this should be in draw.c, actually // needed, but I don't know what it's for... rRatioRect.left = rRatioRect.top=0; rRatioRect.right = iResX; rRatioRect.bottom = iResY; [[glView openGLContext] makeCurrentContext]; glFlush(); glFinish(); glViewport(rRatioRect.left, // init viewport by ratio rect iResY-(rRatioRect.top+rRatioRect.bottom), rRatioRect.right, rRatioRect.bottom); glScissor(0, 0, iResX, iResY); // init clipping (fullscreen) glEnable(GL_SCISSOR_TEST); glMatrixMode(GL_PROJECTION); // init projection with psx resolution glLoadIdentity(); glOrtho(0,PSXDisplay.DisplayMode.x, PSXDisplay.DisplayMode.y, 0, -1, 1); CreateScanLines(); // if(bKeepRatio) SetAspectRatio(); // set ratio glFlush(); glFinish(); [NSOpenGLContext clearCurrentContext]; [glView reshape]; // to get rid of fuglies on screen // GLinitialize(); // blunt instrument method of setting a proper state. } - (void)dealloc { windowFrame = [[self window] frame]; [super dealloc]; } // forget keyDownEvents - (void)keyDown:(NSEvent *)theEvent { // Not required any more } - (void)mouseDown:(NSEvent *)theEvent { if ([self fullscreen]) { [self setFullscreen:NO]; } } - (BOOL)fullscreen { return inFullscreen; } - (void)setFullscreen:(BOOL)flag { // this is called by cocoa, not the main PSX thread. // Messing with the opengl context is a Bad Thing. // Therefore, just set a global flag, and // wait around for a frame until // gpu.c calls fullscreenswap() from // the right thread if ([self fullscreen] == flag) return; if (flag) bChangeWinMode = 2; else bChangeWinMode = 1; } - (void)performFullscreenSwap { // ah, that's better. We are called from the main PSX thread // after a screen update, so we're clean. // bChangeWinMode is a global set from PSX int flag = bChangeWinMode - 1; // 1 = go to window, 2 = go to fullscreen bChangeWinMode = 0; // this is our flag that launched us, so 0 now NSWindow *window = [self window]; NSScreen *screen = [window screen]; CGDirectDisplayID display = (CGDirectDisplayID)[[[screen deviceDescription] objectForKey:@"NSScreenNumber"] longValue]; NSRect newPlace; if (flag){ [window setLevel: NSScreenSaverWindowLevel]; newPlace = NSMakeRect(0,0,CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display)); CGDisplayHideCursor(display); CGAssociateMouseAndMouseCursorPosition(NO); } else{ [window setLevel: NSNormalWindowLevel]; newPlace = windowDefaultRect; CGDisplayShowCursor(display); CGAssociateMouseAndMouseCursorPosition(YES); } int proportionalWidth, proportionalHeight; [window setFrame:newPlace display:true]; // assume square pixel ratio on the monitor if ((newPlace.size.width*3)/4 <= newPlace.size.height) { // is window skinnier than it needs to be? proportionalHeight = (newPlace.size.width*3)/4; // then shrink the content height (letterbox) proportionalWidth = newPlace.size.width; // and conform to width } else { proportionalWidth = (newPlace.size.height*4)/3; proportionalHeight = newPlace.size.height; } NSRect fitToWindow = NSMakeRect( (newPlace.size.width - proportionalWidth)/2, (newPlace.size.height - proportionalHeight)/2, proportionalWidth, proportionalHeight); [glView setFrame:fitToWindow]; [glView reshape]; iResX = proportionalWidth; iResY = proportionalHeight; if (flag) inFullscreen = TRUE; else inFullscreen = FALSE; [self cureAllIlls]; // do some fixin' return; } - (BOOL)windowShouldZoom:(NSWindow *)sender toFrame:(NSRect)newFrame { [self setFullscreen:YES]; return NO; } - (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)proposedFrameSize { // we don't bother return proposedFrameSize; if (!(([sender resizeFlags] & NSShiftKeyMask) == NSShiftKeyMask)) { NSRect oldSize = [sender frame]; NSRect viewSize = [glView frame]; float xDiff = NSWidth(oldSize) - NSWidth(viewSize); float yDiff = NSHeight(oldSize) - NSHeight(viewSize); //if ((proposedFrameSize.height / proposedFrameSize.width) < (3.0/4.0)) // proposedFrameSize.height = ((proposedFrameSize.width - xDiff) * 3.0) / 4.0 + yDiff; //else proposedFrameSize.width = ((proposedFrameSize.height - yDiff) * 4.0) / 3.0 + xDiff; } return proposedFrameSize; } - (void)windowWillMiniaturize:(NSNotification *)aNotification { [[NSNotificationCenter defaultCenter] postNotificationName:@"emuWindowWantPause" object:self]; } - (void)windowDidDeminiaturize:(NSNotification *)aNotification { [[NSNotificationCenter defaultCenter] postNotificationName:@"emuWindowWantResume" object:self]; } //- (void)windowDidBecomeMain:(NSNotification *)aNotification /*- (void)windowDidBecomeKey:(NSNotification *)aNotification { if (iWindowMode==0) { [self setFullscreen:YES]; } }*/ - (BOOL)windowShouldClose:(id)sender { /* if (fullWindow) { return NO; } */ // NSLog(@"windowShouldClose: We're closing the window"); [[NSNotificationCenter defaultCenter] postNotificationName:@"emuWindowDidClose" object:self]; [gameController autorelease]; gameController = nil; gameWindow = nil; return YES; } @end void ChangeWindowMode(void) { // glue from PSX thread. Globals are already set [ gameController performFullscreenSwap]; }