filename | src/cocoaui/cocoa_win.m |
changeset | 1098:4f2750753a6c |
prev | 1028:f99eeaf084c2 |
next | 1298:d0eb2307b847 |
author | nkeynes |
date | Wed Feb 15 17:54:51 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Use GL_TEXTURE_2D instead of GL_TEXTURE_RECTANGLE_ARB for frame buffers, for systems that don't provide the latter (and there's not really much difference anyway). Add macro wrangling for GL_DEPTH24_STENCIL8 format |
file | annotate | diff | log | raw |
nkeynes@964 | 1 | /** |
nkeynes@964 | 2 | * $Id$ |
nkeynes@964 | 3 | * |
nkeynes@964 | 4 | * Construct and maintain the main window under cocoa. |
nkeynes@964 | 5 | * |
nkeynes@964 | 6 | * Copyright (c) 2008 Nathan Keynes. |
nkeynes@964 | 7 | * |
nkeynes@964 | 8 | * This program is free software; you can redistribute it and/or modify |
nkeynes@964 | 9 | * it under the terms of the GNU General Public License as published by |
nkeynes@964 | 10 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@964 | 11 | * (at your option) any later version. |
nkeynes@964 | 12 | * |
nkeynes@964 | 13 | * This program is distributed in the hope that it will be useful, |
nkeynes@964 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@964 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@964 | 16 | * GNU General Public License for more details. |
nkeynes@964 | 17 | */ |
nkeynes@964 | 18 | |
nkeynes@964 | 19 | #include "cocoaui/cocoaui.h" |
nkeynes@964 | 20 | #include "lxdream.h" |
nkeynes@964 | 21 | #include "dreamcast.h" |
nkeynes@964 | 22 | #include "gdrom/gdrom.h" |
nkeynes@964 | 23 | #include <ApplicationServices/ApplicationServices.h> |
nkeynes@1028 | 24 | #include <Carbon/Carbon.h> |
nkeynes@964 | 25 | |
nkeynes@964 | 26 | @interface NSWindow (OSX10_5_and_later) |
nkeynes@964 | 27 | #ifndef CGFLOAT_DEFINED |
nkeynes@964 | 28 | # ifdef __LP64__ |
nkeynes@964 | 29 | typedef double CGFloat; |
nkeynes@964 | 30 | # else |
nkeynes@964 | 31 | typedef float CGFloat; |
nkeynes@964 | 32 | # endif |
nkeynes@964 | 33 | #endif |
nkeynes@964 | 34 | - (void)setAutorecalculatesContentBorderThickness:(BOOL)b forEdge:(NSRectEdge)e; |
nkeynes@964 | 35 | - (void)setContentBorderThickness:(CGFloat)b forEdge:(NSRectEdge)e; |
nkeynes@964 | 36 | @end |
nkeynes@964 | 37 | |
nkeynes@964 | 38 | |
nkeynes@964 | 39 | #if NSAppKitVersionNumber > NSAppKitVersionNumber10_4 |
nkeynes@964 | 40 | |
nkeynes@964 | 41 | #endif |
nkeynes@964 | 42 | |
nkeynes@964 | 43 | #define STATUSBAR_HEIGHT 25 |
nkeynes@964 | 44 | #define STATUS_TEXT_HEIGHT 22 |
nkeynes@964 | 45 | |
nkeynes@964 | 46 | @interface LxdreamToolbarDelegate : NSObject { |
nkeynes@964 | 47 | NSArray *identifiers; |
nkeynes@964 | 48 | NSArray *defaults; |
nkeynes@964 | 49 | NSDictionary *items; |
nkeynes@964 | 50 | } |
nkeynes@964 | 51 | - (NSToolbarItem *) createToolbarItem: (NSString *)id label: (NSString *) label |
nkeynes@964 | 52 | tooltip: (NSString *)tooltip |
nkeynes@964 | 53 | icon: (NSString *)icon action: (SEL) action; |
nkeynes@964 | 54 | @end |
nkeynes@964 | 55 | |
nkeynes@964 | 56 | @implementation LxdreamToolbarDelegate |
nkeynes@964 | 57 | - (id) init |
nkeynes@964 | 58 | { |
nkeynes@964 | 59 | NSToolbarItem *mount = [self createToolbarItem: @"GdromMount" label: @"Open Image" |
nkeynes@964 | 60 | tooltip: @"Mount a cdrom disc" icon: @"tb-cdrom" |
nkeynes@964 | 61 | action: @selector(mount_action:)]; |
nkeynes@964 | 62 | NSToolbarItem *reset = [self createToolbarItem: @"Reset" label: @"Reset" |
nkeynes@964 | 63 | tooltip: @"Reset dreamcast" icon: @"tb-reset" |
nkeynes@964 | 64 | action: @selector(reset_action:)]; |
nkeynes@964 | 65 | NSToolbarItem *pause = [self createToolbarItem: @"Pause" label: @"Pause" |
nkeynes@964 | 66 | tooltip: @"Pause dreamcast" icon: @"tb-pause" |
nkeynes@964 | 67 | action: @selector(pause_action:)]; |
nkeynes@964 | 68 | NSToolbarItem *run = [self createToolbarItem: @"Run" label: @"Resume" |
nkeynes@964 | 69 | tooltip: @"Resume" icon: @"tb-run" |
nkeynes@964 | 70 | action: @selector(run_action:)]; |
nkeynes@964 | 71 | NSToolbarItem *load = [self createToolbarItem: @"LoadState" label: @"Load State..." |
nkeynes@964 | 72 | tooltip: @"Load an lxdream save state" icon: @"tb-load" |
nkeynes@964 | 73 | action: @selector(load_action:)]; |
nkeynes@964 | 74 | NSToolbarItem *save = [self createToolbarItem: @"SaveState" label: @"Save State..." |
nkeynes@964 | 75 | tooltip: @"Create an lxdream save state" icon: @"tb-save" |
nkeynes@964 | 76 | action: @selector(save_action:)]; |
nkeynes@964 | 77 | NSToolbarItem *prefs = [self createToolbarItem: @"Preferences" label: @"Preferences..." |
nkeynes@964 | 78 | tooltip: @"Edit preferences" icon: @"tb-preferences" |
nkeynes@964 | 79 | action: @selector(preferences_action:)]; |
nkeynes@964 | 80 | [pause setEnabled: NO]; |
nkeynes@964 | 81 | identifiers = |
nkeynes@964 | 82 | [NSArray arrayWithObjects: @"GdromMount", @"Reset", @"Pause", @"Run", @"LoadState", @"SaveState", @"Preferences", nil ]; |
nkeynes@964 | 83 | defaults = |
nkeynes@964 | 84 | [NSArray arrayWithObjects: @"GdromMount", @"Reset", @"Pause", @"Run", |
nkeynes@964 | 85 | NSToolbarSeparatorItemIdentifier, @"LoadState", @"SaveState", |
nkeynes@964 | 86 | NSToolbarFlexibleSpaceItemIdentifier, @"Preferences", nil ]; |
nkeynes@964 | 87 | NSArray *values = [NSArray arrayWithObjects: mount, reset, pause, run, load, save, prefs, nil ]; |
nkeynes@964 | 88 | items = [NSDictionary dictionaryWithObjects: values forKeys: identifiers]; |
nkeynes@964 | 89 | return self; |
nkeynes@964 | 90 | } |
nkeynes@964 | 91 | |
nkeynes@964 | 92 | - (NSToolbarItem *) createToolbarItem: (NSString *)id label: (NSString *) label |
nkeynes@964 | 93 | tooltip: (NSString *)tooltip icon: (NSString *)icon action: (SEL) action |
nkeynes@964 | 94 | { |
nkeynes@964 | 95 | NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier: id]; |
nkeynes@964 | 96 | [item setLabel: label]; |
nkeynes@964 | 97 | [item setToolTip: tooltip]; |
nkeynes@964 | 98 | [item setTarget: [NSApp delegate]]; |
nkeynes@964 | 99 | NSString *iconFile = [[NSBundle mainBundle] pathForResource:icon ofType:@"png"]; |
nkeynes@964 | 100 | NSImage *image = [[NSImage alloc] initWithContentsOfFile: iconFile]; |
nkeynes@964 | 101 | [item setImage: image]; |
nkeynes@964 | 102 | [item setAction: action]; |
nkeynes@964 | 103 | return item; |
nkeynes@964 | 104 | } |
nkeynes@964 | 105 | |
nkeynes@964 | 106 | - (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar |
nkeynes@964 | 107 | { |
nkeynes@964 | 108 | return identifiers; |
nkeynes@964 | 109 | } |
nkeynes@964 | 110 | |
nkeynes@964 | 111 | - (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar |
nkeynes@964 | 112 | { |
nkeynes@964 | 113 | return defaults; |
nkeynes@964 | 114 | } |
nkeynes@964 | 115 | |
nkeynes@964 | 116 | - (NSArray *)toolbarSelectableItemIdentifiers: (NSToolbar *)toolbar |
nkeynes@964 | 117 | { |
nkeynes@964 | 118 | return [NSArray arrayWithObjects: @"Pause", @"Run", nil]; |
nkeynes@964 | 119 | } |
nkeynes@964 | 120 | |
nkeynes@964 | 121 | - (NSToolbarItem *) toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier |
nkeynes@964 | 122 | willBeInsertedIntoToolbar:(BOOL)flag |
nkeynes@964 | 123 | { |
nkeynes@964 | 124 | return [items objectForKey: itemIdentifier]; |
nkeynes@964 | 125 | } |
nkeynes@964 | 126 | @end |
nkeynes@964 | 127 | |
nkeynes@964 | 128 | @implementation LxdreamMainWindow |
nkeynes@964 | 129 | - (id)initWithContentRect:(NSRect)videoRect |
nkeynes@964 | 130 | { |
nkeynes@964 | 131 | NSRect contentRect = NSMakeRect(videoRect.origin.x,videoRect.origin.y, |
nkeynes@964 | 132 | videoRect.size.width,videoRect.size.height+STATUSBAR_HEIGHT); |
nkeynes@964 | 133 | if( [super initWithContentRect: contentRect |
nkeynes@964 | 134 | styleMask: ( NSTitledWindowMask | NSClosableWindowMask | |
nkeynes@964 | 135 | NSMiniaturizableWindowMask | NSResizableWindowMask | |
nkeynes@964 | 136 | NSUnifiedTitleAndToolbarWindowMask ) |
nkeynes@964 | 137 | backing: NSBackingStoreBuffered defer: NO ] == nil ) { |
nkeynes@964 | 138 | return nil; |
nkeynes@964 | 139 | } else { |
nkeynes@964 | 140 | useGrab = NO; |
nkeynes@964 | 141 | isGrabbed = NO; |
nkeynes@964 | 142 | video = (LxdreamVideoView *)video_osx_create_drawable(); |
nkeynes@964 | 143 | [video setFrameOrigin: NSMakePoint(0.0,STATUSBAR_HEIGHT)]; |
nkeynes@964 | 144 | [video setDelegate: self]; |
nkeynes@964 | 145 | |
nkeynes@964 | 146 | status = |
nkeynes@964 | 147 | [[NSTextField alloc] initWithFrame: NSMakeRect(0.0,0.0,videoRect.size.width,STATUS_TEXT_HEIGHT)]; |
nkeynes@964 | 148 | [status setStringValue: @"Idle"]; |
nkeynes@964 | 149 | [status setEditable: NO]; |
nkeynes@964 | 150 | [status setDrawsBackground: NO]; |
nkeynes@964 | 151 | [status setBordered: NO]; |
nkeynes@964 | 152 | [[self contentView] addSubview: video]; |
nkeynes@964 | 153 | [[self contentView] addSubview: status]; |
nkeynes@964 | 154 | [self makeFirstResponder: video]; |
nkeynes@964 | 155 | |
nkeynes@964 | 156 | if( [self respondsToSelector:@selector(setAutorecalculatesContentBorderThickness:forEdge:)] ) |
nkeynes@964 | 157 | [self setAutorecalculatesContentBorderThickness: NO forEdge: NSMinYEdge ]; |
nkeynes@964 | 158 | if( [self respondsToSelector:@selector(setContentBorderThickness:forEdge:)] ) |
nkeynes@964 | 159 | [self setContentBorderThickness: STATUSBAR_HEIGHT forEdge: NSMinYEdge]; |
nkeynes@964 | 160 | |
nkeynes@964 | 161 | // Share the app delegate for the purposes of keeping it in one place |
nkeynes@964 | 162 | [self setDelegate: [NSApp delegate]]; |
nkeynes@964 | 163 | [self setContentMinSize: contentRect.size]; |
nkeynes@964 | 164 | [self setAcceptsMouseMovedEvents: YES]; |
nkeynes@964 | 165 | [self updateTitle]; |
nkeynes@964 | 166 | |
nkeynes@964 | 167 | NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier: @"LxdreamToolbar"]; |
nkeynes@964 | 168 | [toolbar setDelegate: [[LxdreamToolbarDelegate alloc] init]]; |
nkeynes@964 | 169 | [toolbar setDisplayMode: NSToolbarDisplayModeIconOnly]; |
nkeynes@964 | 170 | [toolbar setSizeMode: NSToolbarSizeModeSmall]; |
nkeynes@964 | 171 | [toolbar setSelectedItemIdentifier: @"Pause"]; |
nkeynes@964 | 172 | [self setToolbar: toolbar]; |
nkeynes@964 | 173 | return self; |
nkeynes@964 | 174 | } |
nkeynes@964 | 175 | } |
nkeynes@964 | 176 | |
nkeynes@964 | 177 | - (void)updateTitle |
nkeynes@964 | 178 | { |
nkeynes@964 | 179 | NSString *title; |
nkeynes@964 | 180 | const char *disc_title = gdrom_get_current_disc_title(); |
nkeynes@964 | 181 | if( disc_title == NULL ) { |
nkeynes@1098 | 182 | title = [NSString stringWithFormat: @"%s - <no disc>", lxdream_package_name]; |
nkeynes@964 | 183 | } else { |
nkeynes@964 | 184 | title = [NSString stringWithFormat: @"%s - %s", lxdream_package_name, disc_title]; |
nkeynes@964 | 185 | } |
nkeynes@964 | 186 | [self setTitle: title]; |
nkeynes@964 | 187 | } |
nkeynes@964 | 188 | |
nkeynes@964 | 189 | - (void)setStatusText: (const gchar *)text |
nkeynes@964 | 190 | { |
nkeynes@964 | 191 | if( isGrabbed ) { |
nkeynes@964 | 192 | gchar buf[128]; |
nkeynes@964 | 193 | snprintf( buf, sizeof(buf), "%s %s", text, _("(Press <ctrl><alt> to release grab)") ); |
nkeynes@964 | 194 | NSString *s = [NSString stringWithUTF8String: buf]; |
nkeynes@964 | 195 | [status setStringValue: s]; |
nkeynes@964 | 196 | } else { |
nkeynes@964 | 197 | NSString *s = [NSString stringWithUTF8String: text]; |
nkeynes@964 | 198 | [status setStringValue: s]; |
nkeynes@964 | 199 | } |
nkeynes@964 | 200 | } |
nkeynes@964 | 201 | - (void)setRunning:(BOOL)isRunning |
nkeynes@964 | 202 | { |
nkeynes@964 | 203 | if( isRunning ) { |
nkeynes@964 | 204 | [[self toolbar] setSelectedItemIdentifier: @"Run"]; |
nkeynes@964 | 205 | [self setStatusText: _("Running")]; |
nkeynes@964 | 206 | } else { |
nkeynes@964 | 207 | [[self toolbar] setSelectedItemIdentifier: @"Pause"]; |
nkeynes@964 | 208 | [self setStatusText: _("Stopped")]; |
nkeynes@964 | 209 | } |
nkeynes@964 | 210 | } |
nkeynes@1028 | 211 | - (BOOL)isFullscreen |
nkeynes@1028 | 212 | { |
nkeynes@1028 | 213 | return isFullscreen; |
nkeynes@1028 | 214 | } |
nkeynes@1028 | 215 | - (void)setFullscreen:(BOOL)full |
nkeynes@1028 | 216 | { |
nkeynes@1028 | 217 | if( full != isFullscreen ) { |
nkeynes@1028 | 218 | isFullscreen = full; |
nkeynes@1028 | 219 | |
nkeynes@1028 | 220 | if( full ) { |
nkeynes@1028 | 221 | savedFrame = [self frame]; |
nkeynes@1028 | 222 | SetSystemUIMode( kUIModeAllHidden, 0 ); |
nkeynes@1028 | 223 | NSRect screenRect = [[NSScreen mainScreen] frame]; |
nkeynes@1028 | 224 | screenRect.size.height += STATUSBAR_HEIGHT; |
nkeynes@1028 | 225 | screenRect.origin.y -= STATUSBAR_HEIGHT; |
nkeynes@1028 | 226 | NSRect targetRect = [self frameRectForContentRect: screenRect]; |
nkeynes@1028 | 227 | [self setFrame: targetRect display: YES]; |
nkeynes@1028 | 228 | } else { |
nkeynes@1028 | 229 | SetSystemUIMode( kUIModeNormal, 0 ); |
nkeynes@1028 | 230 | [self setFrame: savedFrame display: YES]; |
nkeynes@1028 | 231 | } |
nkeynes@1028 | 232 | } |
nkeynes@1028 | 233 | } |
nkeynes@964 | 234 | - (BOOL)isGrabbed |
nkeynes@964 | 235 | { |
nkeynes@964 | 236 | return isGrabbed; |
nkeynes@964 | 237 | } |
nkeynes@964 | 238 | - (void)setIsGrabbed:(BOOL)grab |
nkeynes@964 | 239 | { |
nkeynes@964 | 240 | if( grab != isGrabbed ) { |
nkeynes@964 | 241 | isGrabbed = grab; |
nkeynes@964 | 242 | [self setRunning: dreamcast_is_running() ? YES : NO]; |
nkeynes@964 | 243 | |
nkeynes@964 | 244 | if( isGrabbed ) { |
nkeynes@964 | 245 | [NSCursor hide]; |
nkeynes@964 | 246 | CGAssociateMouseAndMouseCursorPosition(NO); |
nkeynes@964 | 247 | } else { |
nkeynes@964 | 248 | [NSCursor unhide]; |
nkeynes@964 | 249 | CGAssociateMouseAndMouseCursorPosition(YES); |
nkeynes@964 | 250 | } |
nkeynes@964 | 251 | [video setIsGrabbed: isGrabbed]; |
nkeynes@964 | 252 | } |
nkeynes@964 | 253 | } |
nkeynes@964 | 254 | - (void)setUseGrab:(BOOL)grab |
nkeynes@964 | 255 | { |
nkeynes@964 | 256 | if( grab != useGrab ) { |
nkeynes@964 | 257 | if( !grab && isGrabbed ) { |
nkeynes@964 | 258 | [self setIsGrabbed: NO]; |
nkeynes@964 | 259 | } |
nkeynes@964 | 260 | useGrab = grab; |
nkeynes@964 | 261 | } |
nkeynes@964 | 262 | } |
nkeynes@964 | 263 | |
nkeynes@964 | 264 | - (id)viewRequestedGrab: (id)sender |
nkeynes@964 | 265 | { |
nkeynes@964 | 266 | if( useGrab ) { |
nkeynes@964 | 267 | [self setIsGrabbed: YES]; |
nkeynes@964 | 268 | } |
nkeynes@964 | 269 | return useGrab ? self : nil; |
nkeynes@964 | 270 | } |
nkeynes@964 | 271 | - (id)viewRequestedUngrab: (id)sender |
nkeynes@964 | 272 | { |
nkeynes@964 | 273 | [self setIsGrabbed: NO]; |
nkeynes@964 | 274 | return useGrab ? self : nil; |
nkeynes@964 | 275 | } |
nkeynes@1028 | 276 | - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)aScreen |
nkeynes@1028 | 277 | { |
nkeynes@1028 | 278 | return frameRect; |
nkeynes@1028 | 279 | } |
nkeynes@964 | 280 | @end |
nkeynes@964 | 281 | |
nkeynes@964 | 282 | LxdreamMainWindow *cocoa_gui_create_main_window() |
nkeynes@964 | 283 | { |
nkeynes@964 | 284 | NSRect contentRect = {{0,0},{640,480}}; |
nkeynes@964 | 285 | return [[LxdreamMainWindow alloc] initWithContentRect: contentRect]; |
nkeynes@964 | 286 | } |
.