filename | src/drivers/video_osx.m |
changeset | 964:f2f3c7612d06 |
next | 1010:a506a2f66180 |
author | nkeynes |
date | Thu Jan 15 04:15:11 2009 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Add support for the Intel ICC compiler (C only, icc doesn't support Obj-C) - Rename Obj-C source to .m - Separate paths.c into paths_unix.c and paths_osx.m - Add configuration detection of ICC, along with specific opt flags |
file | annotate | diff | log | raw |
nkeynes@964 | 1 | /** |
nkeynes@964 | 2 | * $Id$ |
nkeynes@964 | 3 | * |
nkeynes@964 | 4 | * The OS/X side of the video support (responsible for actually displaying / |
nkeynes@964 | 5 | * rendering frames) |
nkeynes@964 | 6 | * |
nkeynes@964 | 7 | * Copyright (c) 2008 Nathan Keynes. |
nkeynes@964 | 8 | * |
nkeynes@964 | 9 | * This program is free software; you can redistribute it and/or modify |
nkeynes@964 | 10 | * it under the terms of the GNU General Public License as published by |
nkeynes@964 | 11 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@964 | 12 | * (at your option) any later version. |
nkeynes@964 | 13 | * |
nkeynes@964 | 14 | * This program is distributed in the hope that it will be useful, |
nkeynes@964 | 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@964 | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@964 | 17 | * GNU General Public License for more details. |
nkeynes@964 | 18 | */ |
nkeynes@964 | 19 | |
nkeynes@964 | 20 | #include <stdlib.h> |
nkeynes@964 | 21 | #include <string.h> |
nkeynes@964 | 22 | #include "lxdream.h" |
nkeynes@964 | 23 | #include "display.h" |
nkeynes@964 | 24 | #include "dckeysyms.h" |
nkeynes@964 | 25 | #include "cocoaui/cocoaui.h" |
nkeynes@964 | 26 | #include "drivers/video_nsgl.h" |
nkeynes@964 | 27 | #include "drivers/video_gl.h" |
nkeynes@964 | 28 | #include "pvr2/pvr2.h" |
nkeynes@964 | 29 | #import <AppKit/AppKit.h> |
nkeynes@964 | 30 | |
nkeynes@964 | 31 | #include "mac_keymap.h" |
nkeynes@964 | 32 | |
nkeynes@964 | 33 | #define MOUSE_X_SCALE 5 |
nkeynes@964 | 34 | #define MOUSE_Y_SCALE 5 |
nkeynes@964 | 35 | |
nkeynes@964 | 36 | static gboolean video_osx_init(); |
nkeynes@964 | 37 | static void video_osx_shutdown(); |
nkeynes@964 | 38 | static void video_osx_display_blank( uint32_t colour ); |
nkeynes@964 | 39 | static uint16_t video_osx_resolve_keysym( const gchar *keysym ); |
nkeynes@964 | 40 | static uint16_t video_osx_keycode_to_dckeysym(uint16_t keycode); |
nkeynes@964 | 41 | static gchar *video_osx_keycode_to_keysym(uint16_t keycode); |
nkeynes@964 | 42 | |
nkeynes@964 | 43 | struct display_driver display_osx_driver = { |
nkeynes@964 | 44 | "osx", |
nkeynes@964 | 45 | N_("OS X Cocoa GUI-based OpenGL driver"), |
nkeynes@964 | 46 | video_osx_init, video_osx_shutdown, |
nkeynes@964 | 47 | video_osx_resolve_keysym, |
nkeynes@964 | 48 | video_osx_keycode_to_dckeysym, |
nkeynes@964 | 49 | video_osx_keycode_to_keysym, |
nkeynes@964 | 50 | NULL, NULL, NULL, NULL, NULL, |
nkeynes@964 | 51 | NULL, |
nkeynes@964 | 52 | video_osx_display_blank, NULL }; |
nkeynes@964 | 53 | |
nkeynes@964 | 54 | |
nkeynes@964 | 55 | static NSView *video_view = NULL; |
nkeynes@964 | 56 | int video_width = 640; |
nkeynes@964 | 57 | int video_height = 480; |
nkeynes@964 | 58 | |
nkeynes@964 | 59 | #define MAX_MASK_KEYCODE 128 |
nkeynes@964 | 60 | |
nkeynes@964 | 61 | @interface LxdreamOSXView : LxdreamVideoView |
nkeynes@964 | 62 | { |
nkeynes@964 | 63 | int flagsMask[MAX_MASK_KEYCODE]; |
nkeynes@964 | 64 | } |
nkeynes@964 | 65 | @end |
nkeynes@964 | 66 | |
nkeynes@964 | 67 | @implementation LxdreamVideoView |
nkeynes@964 | 68 | - (void)setIsGrabbed: (BOOL)grabbed |
nkeynes@964 | 69 | { |
nkeynes@964 | 70 | isGrabbed = grabbed; |
nkeynes@964 | 71 | } |
nkeynes@964 | 72 | - (void) setDelegate: (id)other |
nkeynes@964 | 73 | { |
nkeynes@964 | 74 | delegate = other; |
nkeynes@964 | 75 | } |
nkeynes@964 | 76 | - (id)delegate |
nkeynes@964 | 77 | { |
nkeynes@964 | 78 | return delegate; |
nkeynes@964 | 79 | } |
nkeynes@964 | 80 | @end |
nkeynes@964 | 81 | |
nkeynes@964 | 82 | @implementation LxdreamOSXView |
nkeynes@964 | 83 | //-------------------------------------------------------------------- |
nkeynes@964 | 84 | - (id)initWithFrame: (NSRect)contentRect |
nkeynes@964 | 85 | { |
nkeynes@964 | 86 | if( [super initWithFrame: contentRect] != nil ) { |
nkeynes@964 | 87 | int i; |
nkeynes@964 | 88 | isGrabbed = NO; |
nkeynes@964 | 89 | for( i=0; i<MAX_MASK_KEYCODE; i++ ) { |
nkeynes@964 | 90 | flagsMask[i] = 0; |
nkeynes@964 | 91 | } |
nkeynes@964 | 92 | return self; |
nkeynes@964 | 93 | } |
nkeynes@964 | 94 | return nil; |
nkeynes@964 | 95 | } |
nkeynes@964 | 96 | - (BOOL)requestGrab |
nkeynes@964 | 97 | { |
nkeynes@964 | 98 | if( delegate && [delegate respondsToSelector: @selector(viewRequestedGrab:)] ) |
nkeynes@964 | 99 | return [delegate performSelector: @selector(viewRequestedGrab:) withObject: self] != nil; |
nkeynes@964 | 100 | return NO; |
nkeynes@964 | 101 | } |
nkeynes@964 | 102 | - (BOOL)requestUngrab |
nkeynes@964 | 103 | { |
nkeynes@964 | 104 | if( delegate && [delegate respondsToSelector: @selector(viewRequestedUngrab:)] ) |
nkeynes@964 | 105 | return [delegate performSelector: @selector(viewRequestedUngrab:) withObject: self] != nil; |
nkeynes@964 | 106 | return NO; |
nkeynes@964 | 107 | } |
nkeynes@964 | 108 | - (BOOL)isOpaque |
nkeynes@964 | 109 | { |
nkeynes@964 | 110 | return YES; |
nkeynes@964 | 111 | } |
nkeynes@964 | 112 | - (BOOL)acceptsFirstResponder |
nkeynes@964 | 113 | { |
nkeynes@964 | 114 | return YES; |
nkeynes@964 | 115 | } |
nkeynes@964 | 116 | - (BOOL)isFlipped |
nkeynes@964 | 117 | { |
nkeynes@964 | 118 | return YES; |
nkeynes@964 | 119 | } |
nkeynes@964 | 120 | //-------------------------------------------------------------------- |
nkeynes@964 | 121 | - (void)drawRect: (NSRect) rect |
nkeynes@964 | 122 | { |
nkeynes@964 | 123 | NSSize size = [self frame].size; |
nkeynes@964 | 124 | if( video_width != size.width || video_height != size.height ) { |
nkeynes@964 | 125 | video_width = size.width; |
nkeynes@964 | 126 | video_height = size.height; |
nkeynes@964 | 127 | video_nsgl_update(); |
nkeynes@964 | 128 | } |
nkeynes@964 | 129 | pvr2_redraw_display(); |
nkeynes@964 | 130 | } |
nkeynes@964 | 131 | - (void)keyDown: (NSEvent *) event |
nkeynes@964 | 132 | { |
nkeynes@964 | 133 | if( ![event isARepeat] ) { |
nkeynes@964 | 134 | input_event_keydown( NULL, [event keyCode]+1, 1 ); |
nkeynes@964 | 135 | } |
nkeynes@964 | 136 | } |
nkeynes@964 | 137 | - (void)keyUp: (NSEvent *) event |
nkeynes@964 | 138 | { |
nkeynes@964 | 139 | input_event_keyup( NULL, [event keyCode]+1, 1 ); |
nkeynes@964 | 140 | } |
nkeynes@964 | 141 | - (void)flagsChanged: (NSEvent *) event |
nkeynes@964 | 142 | { |
nkeynes@964 | 143 | int keycode = [event keyCode]; |
nkeynes@964 | 144 | if( ([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask) ) { |
nkeynes@964 | 145 | [self requestUngrab]; |
nkeynes@964 | 146 | } |
nkeynes@964 | 147 | |
nkeynes@964 | 148 | if( flagsMask[keycode] == 0 ) { |
nkeynes@964 | 149 | input_event_keydown( NULL, keycode+1, 1 ); |
nkeynes@964 | 150 | flagsMask[keycode] = 1; |
nkeynes@964 | 151 | } else { |
nkeynes@964 | 152 | input_event_keyup( NULL, keycode+1, 1 ); |
nkeynes@964 | 153 | flagsMask[keycode] = 0; |
nkeynes@964 | 154 | } |
nkeynes@964 | 155 | } |
nkeynes@964 | 156 | - (void)emitMouseDownEvent: (NSEvent *)event button: (int)button |
nkeynes@964 | 157 | { |
nkeynes@964 | 158 | if( isGrabbed ) { |
nkeynes@964 | 159 | input_event_mousedown( button, 0, 0, FALSE ); |
nkeynes@964 | 160 | } else { |
nkeynes@964 | 161 | NSPoint pt = [event locationInWindow]; |
nkeynes@964 | 162 | int x = (int)pt.x; |
nkeynes@964 | 163 | int y = video_height - (int)pt.y; |
nkeynes@964 | 164 | gl_window_to_system_coords(&x,&y); |
nkeynes@964 | 165 | input_event_mousedown( button, x, y, TRUE ); |
nkeynes@964 | 166 | } |
nkeynes@964 | 167 | } |
nkeynes@964 | 168 | - (void)emitMouseUpEvent: (NSEvent *)event button: (int)button |
nkeynes@964 | 169 | { |
nkeynes@964 | 170 | if( isGrabbed ) { |
nkeynes@964 | 171 | input_event_mouseup( button, 0, 0, FALSE ); |
nkeynes@964 | 172 | } else { |
nkeynes@964 | 173 | NSPoint pt = [event locationInWindow]; |
nkeynes@964 | 174 | int x = (int)pt.x; |
nkeynes@964 | 175 | int y = video_height - (int)pt.y; |
nkeynes@964 | 176 | gl_window_to_system_coords(&x,&y); |
nkeynes@964 | 177 | input_event_mouseup( button, x, y, TRUE ); |
nkeynes@964 | 178 | } |
nkeynes@964 | 179 | } |
nkeynes@964 | 180 | - (void)emitMouseMoveEvent: (NSEvent *)event |
nkeynes@964 | 181 | { |
nkeynes@964 | 182 | if( isGrabbed ) { |
nkeynes@964 | 183 | input_event_mousemove( [event deltaX] * MOUSE_X_SCALE, [event deltaY] * MOUSE_Y_SCALE, FALSE ); |
nkeynes@964 | 184 | } else { |
nkeynes@964 | 185 | NSPoint pt = [event locationInWindow]; |
nkeynes@964 | 186 | int x = (int)pt.x; |
nkeynes@964 | 187 | int y = video_height - (int)pt.y; |
nkeynes@964 | 188 | gl_window_to_system_coords(&x,&y); |
nkeynes@964 | 189 | input_event_mousemove( x, y, TRUE ); |
nkeynes@964 | 190 | } |
nkeynes@964 | 191 | } |
nkeynes@964 | 192 | - (void)mouseExited: (NSEvent *)event |
nkeynes@964 | 193 | { |
nkeynes@964 | 194 | if( !isGrabbed ) { |
nkeynes@964 | 195 | input_event_mousemove( -1, -1, TRUE ); |
nkeynes@964 | 196 | } |
nkeynes@964 | 197 | } |
nkeynes@964 | 198 | |
nkeynes@964 | 199 | - (void)mouseDown: (NSEvent *) event |
nkeynes@964 | 200 | { |
nkeynes@964 | 201 | // If using grab but not grabbed yet, the first click should be consumed |
nkeynes@964 | 202 | // by the grabber. In all other circumstances we process normally. |
nkeynes@964 | 203 | if( isGrabbed || ![self requestGrab] ) { |
nkeynes@964 | 204 | [self emitMouseDownEvent: event button: 0]; |
nkeynes@964 | 205 | } |
nkeynes@964 | 206 | } |
nkeynes@964 | 207 | - (void)mouseUp: (NSEvent *)event |
nkeynes@964 | 208 | { |
nkeynes@964 | 209 | [self emitMouseUpEvent: event button: 0]; |
nkeynes@964 | 210 | } |
nkeynes@964 | 211 | |
nkeynes@964 | 212 | - (void)rightMouseDown: (NSEvent *) event |
nkeynes@964 | 213 | { |
nkeynes@964 | 214 | [self emitMouseDownEvent: event button: 1]; |
nkeynes@964 | 215 | } |
nkeynes@964 | 216 | - (void)rightMouseUp: (NSEvent *)event |
nkeynes@964 | 217 | { |
nkeynes@964 | 218 | [self emitMouseUpEvent: event button: 1]; |
nkeynes@964 | 219 | } |
nkeynes@964 | 220 | - (void)otherMouseDown: (NSEvent *) event |
nkeynes@964 | 221 | { |
nkeynes@964 | 222 | [self emitMouseDownEvent: event button: [event buttonNumber]]; |
nkeynes@964 | 223 | } |
nkeynes@964 | 224 | - (void)otherMouseUp: (NSEvent *) event |
nkeynes@964 | 225 | { |
nkeynes@964 | 226 | [self emitMouseUpEvent: event button: [event buttonNumber]]; |
nkeynes@964 | 227 | } |
nkeynes@964 | 228 | - (void)mouseMoved: (NSEvent *) event |
nkeynes@964 | 229 | { |
nkeynes@964 | 230 | [self emitMouseMoveEvent: event]; |
nkeynes@964 | 231 | } |
nkeynes@964 | 232 | - (void)mouseDragged: (NSEvent *) event |
nkeynes@964 | 233 | { |
nkeynes@964 | 234 | [self emitMouseMoveEvent: event]; |
nkeynes@964 | 235 | } |
nkeynes@964 | 236 | - (void)rightMouseDragged: (NSEvent *) event |
nkeynes@964 | 237 | { |
nkeynes@964 | 238 | [self emitMouseMoveEvent: event]; |
nkeynes@964 | 239 | } |
nkeynes@964 | 240 | - (void)otherMouseDragged: (NSEvent *) event |
nkeynes@964 | 241 | { |
nkeynes@964 | 242 | [self emitMouseMoveEvent: event]; |
nkeynes@964 | 243 | } |
nkeynes@964 | 244 | |
nkeynes@964 | 245 | @end |
nkeynes@964 | 246 | |
nkeynes@964 | 247 | NSView *video_osx_create_drawable() |
nkeynes@964 | 248 | { |
nkeynes@964 | 249 | NSRect contentRect = {{0,0},{640,480}}; |
nkeynes@964 | 250 | video_view = [[LxdreamOSXView alloc] initWithFrame: contentRect]; |
nkeynes@964 | 251 | [video_view setAutoresizingMask: (NSViewWidthSizable|NSViewHeightSizable)]; |
nkeynes@964 | 252 | return video_view; |
nkeynes@964 | 253 | } |
nkeynes@964 | 254 | |
nkeynes@964 | 255 | static gboolean video_osx_init() |
nkeynes@964 | 256 | { |
nkeynes@964 | 257 | if( video_view == NULL ) { |
nkeynes@964 | 258 | return FALSE; |
nkeynes@964 | 259 | } |
nkeynes@964 | 260 | if( !video_nsgl_init_driver(video_view, &display_osx_driver) ) { |
nkeynes@964 | 261 | return FALSE; |
nkeynes@964 | 262 | } |
nkeynes@964 | 263 | pvr2_setup_gl_context(); |
nkeynes@964 | 264 | return TRUE; |
nkeynes@964 | 265 | } |
nkeynes@964 | 266 | |
nkeynes@964 | 267 | static void video_osx_shutdown() |
nkeynes@964 | 268 | { |
nkeynes@964 | 269 | } |
nkeynes@964 | 270 | |
nkeynes@964 | 271 | static void video_osx_display_blank( uint32_t colour ) |
nkeynes@964 | 272 | { |
nkeynes@964 | 273 | } |
nkeynes@964 | 274 | |
nkeynes@964 | 275 | static int mac_keymap_cmp(const void *a, const void *b) |
nkeynes@964 | 276 | { |
nkeynes@964 | 277 | const gchar *key = a; |
nkeynes@964 | 278 | const struct mac_keymap_struct *kb = b; |
nkeynes@964 | 279 | return strcasecmp(key, kb->name); |
nkeynes@964 | 280 | } |
nkeynes@964 | 281 | |
nkeynes@964 | 282 | static uint16_t video_osx_resolve_keysym( const gchar *keysym ) |
nkeynes@964 | 283 | { |
nkeynes@964 | 284 | struct mac_keymap_struct *result = bsearch( keysym, mac_keysyms, mac_keysym_count, sizeof(struct mac_keymap_struct), mac_keymap_cmp ); |
nkeynes@964 | 285 | if( result == NULL ) { |
nkeynes@964 | 286 | return 0; |
nkeynes@964 | 287 | } else { |
nkeynes@964 | 288 | return result->keycode + 1; |
nkeynes@964 | 289 | } |
nkeynes@964 | 290 | } |
nkeynes@964 | 291 | |
nkeynes@964 | 292 | static uint16_t video_osx_keycode_to_dckeysym(uint16_t keycode) |
nkeynes@964 | 293 | { |
nkeynes@964 | 294 | if( keycode < 1 || keycode > 128 ) { |
nkeynes@964 | 295 | return DCKB_NONE; |
nkeynes@964 | 296 | } else { |
nkeynes@964 | 297 | return mac_keycode_to_dckeysym[keycode-1]; |
nkeynes@964 | 298 | } |
nkeynes@964 | 299 | } |
nkeynes@964 | 300 | |
nkeynes@964 | 301 | static gchar *video_osx_keycode_to_keysym(uint16_t keycode) |
nkeynes@964 | 302 | { |
nkeynes@964 | 303 | if( keycode < 1 || keycode > 128 ) { |
nkeynes@964 | 304 | return NULL; |
nkeynes@964 | 305 | } else { |
nkeynes@964 | 306 | return g_strdup(mac_keysyms_by_keycode[keycode-1]); |
nkeynes@964 | 307 | } |
nkeynes@964 | 308 | } |
.