comparison src/video/quartz/SDL_QuartzVideo.m @ 501:74262d2647ca

Lots of cleanups by Darrell, added the ability to resize Cocoa windows.
author Sam Lantinga <slouken@libsdl.org>
date Sat, 05 Oct 2002 05:07:57 +0000
parents c335456c421d
children 2536446a92de
comparison
equal deleted inserted replaced
500:c335456c421d 501:74262d2647ca
19 Sam Lantinga 19 Sam Lantinga
20 slouken@libsdl.org 20 slouken@libsdl.org
21 */ 21 */
22 22
23 #include "SDL_QuartzVideo.h" 23 #include "SDL_QuartzVideo.h"
24
25 /* Some variables to share among files, put in device structure eventually */
26 static SDL_GrabMode currentGrabMode = SDL_GRAB_OFF;
27 static BOOL inForeground = YES;
28 static char QZ_Error[255]; /* Global error buffer to temporarily store more informative error messages */
29 24
30 /* Include files into one compile unit...break apart eventually */ 25 /* Include files into one compile unit...break apart eventually */
31 #include "SDL_QuartzWM.m" 26 #include "SDL_QuartzWM.m"
32 #include "SDL_QuartzEvents.m" 27 #include "SDL_QuartzEvents.m"
33 #include "SDL_QuartzWindow.m" 28 #include "SDL_QuartzWindow.m"
130 CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayHeight), 125 CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayHeight),
131 kCFNumberSInt32Type, &device_height); 126 kCFNumberSInt32Type, &device_height);
132 127
133 video_format->BitsPerPixel = device_bpp; 128 video_format->BitsPerPixel = device_bpp;
134 129
130 /* Set misc globals */
131 current_grab_mode = SDL_GRAB_OFF;
132 in_foreground = YES;
133
135 return 0; 134 return 0;
136 } 135 }
137 136
138 static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) { 137 static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) {
139 138
140 CFIndex num_modes; 139 CFIndex num_modes;
141 CFIndex i; 140 CFIndex i;
142 141
143 static SDL_Rect **list = NULL;
144 int list_size = 0; 142 int list_size = 0;
145 143
146 /* Any windowed mode is acceptable */ 144 /* Any windowed mode is acceptable */
147 if ( (flags & SDL_FULLSCREEN) == 0 ) 145 if ( (flags & SDL_FULLSCREEN) == 0 )
148 return (SDL_Rect**)-1; 146 return (SDL_Rect**)-1;
149 147
150 /* Free memory from previous call, if any */ 148 /* Free memory from previous call, if any */
151 if ( list != NULL ) { 149 if ( client_mode_list != NULL ) {
152 150
153 int i; 151 int i;
154 152
155 for (i = 0; list[i] != NULL; i++) 153 for (i = 0; client_mode_list[i] != NULL; i++)
156 free (list[i]); 154 free (client_mode_list[i]);
157 155
158 free (list); 156 free (client_mode_list);
159 list = NULL; 157 client_mode_list = NULL;
160 } 158 }
161 159
162 num_modes = CFArrayGetCount (mode_list); 160 num_modes = CFArrayGetCount (mode_list);
163 161
164 /* Build list of modes with the requested bpp */ 162 /* Build list of modes with the requested bpp */
189 /* Check if mode is already in the list */ 187 /* Check if mode is already in the list */
190 { 188 {
191 int i; 189 int i;
192 hasMode = SDL_FALSE; 190 hasMode = SDL_FALSE;
193 for (i = 0; i < list_size; i++) { 191 for (i = 0; i < list_size; i++) {
194 if (list[i]->w == width && list[i]->h == height) { 192 if (client_mode_list[i]->w == width &&
193 client_mode_list[i]->h == height) {
195 hasMode = SDL_TRUE; 194 hasMode = SDL_TRUE;
196 break; 195 break;
197 } 196 }
198 } 197 }
199 } 198 }
203 202
204 SDL_Rect *rect; 203 SDL_Rect *rect;
205 204
206 list_size++; 205 list_size++;
207 206
208 if (list == NULL) 207 if (client_mode_list == NULL)
209 list = (SDL_Rect**) malloc (sizeof(*list) * (list_size+1) ); 208 client_mode_list = (SDL_Rect**)
209 malloc (sizeof(*client_mode_list) * (list_size+1) );
210 else 210 else
211 list = (SDL_Rect**) realloc (list, sizeof(*list) * (list_size+1)); 211 client_mode_list = (SDL_Rect**)
212 212 realloc (client_mode_list, sizeof(*client_mode_list) * (list_size+1));
213 rect = (SDL_Rect*) malloc (sizeof(**list)); 213
214 214 rect = (SDL_Rect*) malloc (sizeof(**client_mode_list));
215 if (list == NULL || rect == NULL) { 215
216 if (client_mode_list == NULL || rect == NULL) {
216 SDL_OutOfMemory (); 217 SDL_OutOfMemory ();
217 return NULL; 218 return NULL;
218 } 219 }
219 220
220 rect->w = width; 221 rect->w = width;
221 rect->h = height; 222 rect->h = height;
222 223
223 list[list_size-1] = rect; 224 client_mode_list[list_size-1] = rect;
224 list[list_size] = NULL; 225 client_mode_list[list_size] = NULL;
225 } 226 }
226 } 227 }
227 } 228 }
228 229
229 /* Sort list largest to smallest (by area) */ 230 /* Sort list largest to smallest (by area) */
231 int i, j; 232 int i, j;
232 for (i = 0; i < list_size; i++) { 233 for (i = 0; i < list_size; i++) {
233 for (j = 0; j < list_size-1; j++) { 234 for (j = 0; j < list_size-1; j++) {
234 235
235 int area1, area2; 236 int area1, area2;
236 area1 = list[j]->w * list[j]->h; 237 area1 = client_mode_list[j]->w * client_mode_list[j]->h;
237 area2 = list[j+1]->w * list[j+1]->h; 238 area2 = client_mode_list[j+1]->w * client_mode_list[j+1]->h;
238 239
239 if (area1 < area2) { 240 if (area1 < area2) {
240 SDL_Rect *tmp = list[j]; 241 SDL_Rect *tmp = client_mode_list[j];
241 list[j] = list[j+1]; 242 client_mode_list[j] = client_mode_list[j+1];
242 list[j+1] = tmp; 243 client_mode_list[j+1] = tmp;
243 } 244 }
244 } 245 }
245 } 246 }
246 } 247 }
247 return list; 248 return client_mode_list;
248 } 249 }
249 250
250 /* Gamma functions to try to hide the flash from a rez switch */ 251 /*
251 /* Fade the display from normal to black */ 252 Gamma functions to try to hide the flash from a rez switch
252 /* Save gamma tables for fade back to normal */ 253 Fade the display from normal to black
254 Save gamma tables for fade back to normal
255 */
253 static UInt32 QZ_FadeGammaOut (_THIS, SDL_QuartzGammaTable *table) { 256 static UInt32 QZ_FadeGammaOut (_THIS, SDL_QuartzGammaTable *table) {
254 257
255 CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE], 258 CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE],
256 greenTable[QZ_GAMMA_TABLE_SIZE], 259 greenTable[QZ_GAMMA_TABLE_SIZE],
257 blueTable[QZ_GAMMA_TABLE_SIZE]; 260 blueTable[QZ_GAMMA_TABLE_SIZE];
293 } 296 }
294 297
295 return 0; 298 return 0;
296 } 299 }
297 300
298 /* Fade the display from black to normal */ 301 /*
299 /* Restore previously saved gamma values */ 302 Fade the display from black to normal
303 Restore previously saved gamma values
304 */
300 static UInt32 QZ_FadeGammaIn (_THIS, SDL_QuartzGammaTable *table) { 305 static UInt32 QZ_FadeGammaIn (_THIS, SDL_QuartzGammaTable *table) {
301 306
302 CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE], 307 CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE],
303 greenTable[QZ_GAMMA_TABLE_SIZE], 308 greenTable[QZ_GAMMA_TABLE_SIZE],
304 blueTable[QZ_GAMMA_TABLE_SIZE]; 309 blueTable[QZ_GAMMA_TABLE_SIZE];
334 } 339 }
335 340
336 static void QZ_UnsetVideoMode (_THIS) { 341 static void QZ_UnsetVideoMode (_THIS) {
337 342
338 /* Reset values that may change between switches */ 343 /* Reset values that may change between switches */
339 this->info.blit_fill = 0; 344 this->info.blit_fill = 0;
340 this->FillHWRect = NULL; 345 this->FillHWRect = NULL;
341 this->UpdateRects = NULL; 346 this->UpdateRects = NULL;
342 347 this->LockHWSurface = NULL;
348 this->UnlockHWSurface = NULL;
349
343 /* Release fullscreen resources */ 350 /* Release fullscreen resources */
344 if ( mode_flags & SDL_FULLSCREEN ) { 351 if ( mode_flags & SDL_FULLSCREEN ) {
345 352
346 SDL_QuartzGammaTable gamma_table; 353 SDL_QuartzGammaTable gamma_table;
347 int gamma_error; 354 int gamma_error;
348 NSRect screen_rect; 355 NSRect screen_rect;
349 356
350 gamma_error = QZ_FadeGammaOut (this, &gamma_table); 357 gamma_error = QZ_FadeGammaOut (this, &gamma_table);
351 358
352 /* Release the OpenGL context */ 359 /*
353 /* Do this first to avoid trash on the display before fade */ 360 Release the OpenGL context
354 if ( mode_flags & SDL_OPENGL ) 361 Do this first to avoid trash on the display before fade
362 */
363 if ( mode_flags & SDL_OPENGL ) {
364
355 QZ_TearDownOpenGL (this); 365 QZ_TearDownOpenGL (this);
356 366 CGLSetFullScreen (NULL);
357 if (mode_flags & SDL_OPENGL) 367 }
358 CGLSetFullScreen(NULL); 368
359
360 /* Restore original screen resolution/bpp */ 369 /* Restore original screen resolution/bpp */
361 CGDisplaySwitchToMode (display_id, save_mode); 370 CGDisplaySwitchToMode (display_id, save_mode);
362 CGDisplayRelease (display_id); 371 CGDisplayRelease (display_id);
363 ShowMenuBar (); 372 ShowMenuBar ();
364 373
365 /* 374 /*
366 reset the main screen's rectangle, see comment 375 Reset the main screen's rectangle
367 in QZ_SetVideoFullscreen 376 See comment in QZ_SetVideoFullscreen for why we do this
368 */ 377 */
369 screen_rect = NSMakeRect(0,0,device_width,device_height); 378 screen_rect = NSMakeRect(0,0,device_width,device_height);
370 [ [ NSScreen mainScreen ] setFrame:screen_rect ]; 379 [ [ NSScreen mainScreen ] setFrame:screen_rect ];
371 380
372 if (! gamma_error) 381 if (! gamma_error)
373 QZ_FadeGammaIn (this, &gamma_table); 382 QZ_FadeGammaIn (this, &gamma_table);
374 } 383 }
375 /* Release window mode resources */ 384 /* Release window mode resources */
376 else { 385 else {
377 if ( (mode_flags & SDL_OPENGL) == 0 ) { 386
378 UnlockPortBits ( [ window_view qdPort ] );
379 [ window_view release ];
380 }
381 [ qz_window setContentView:nil ];
382 [ qz_window setDelegate:nil ];
383 [ qz_window close ]; 387 [ qz_window close ];
384 [ qz_window release ]; 388 [ qz_window release ];
385 qz_window = nil; 389 qz_window = nil;
386 390 window_view = nil;
391
387 /* Release the OpenGL context */ 392 /* Release the OpenGL context */
388 if ( mode_flags & SDL_OPENGL ) 393 if ( mode_flags & SDL_OPENGL )
389 QZ_TearDownOpenGL (this); 394 QZ_TearDownOpenGL (this);
390 } 395 }
391 396
392 /* Restore gamma settings */ 397 /* Restore gamma settings */
393 CGDisplayRestoreColorSyncSettings (); 398 CGDisplayRestoreColorSyncSettings ();
394
395 /* Set pixels to null (so other code doesn't try to free it) */
396 if (this->screen != NULL)
397 this->screen->pixels = NULL;
398 399
399 /* Ensure the cursor will be visible and working when we quit */ 400 /* Ensure the cursor will be visible and working when we quit */
400 CGDisplayShowCursor (display_id); 401 CGDisplayShowCursor (display_id);
401 CGAssociateMouseAndMouseCursorPosition (1); 402 CGAssociateMouseAndMouseCursorPosition (1);
402 403
409 int exact_match; 410 int exact_match;
410 int gamma_error; 411 int gamma_error;
411 SDL_QuartzGammaTable gamma_table; 412 SDL_QuartzGammaTable gamma_table;
412 NSRect screen_rect; 413 NSRect screen_rect;
413 414
415 /* Destroy any previous mode */
416 if (video_set == SDL_TRUE)
417 QZ_UnsetVideoMode (this);
418
414 /* See if requested mode exists */ 419 /* See if requested mode exists */
415 mode = CGDisplayBestModeForParameters (display_id, bpp, width, 420 mode = CGDisplayBestModeForParameters (display_id, bpp, width,
416 height, &exact_match); 421 height, &exact_match);
417 422
418 /* Require an exact match to the requested mode */ 423 /* Require an exact match to the requested mode */
419 if ( ! exact_match ) { 424 if ( ! exact_match ) {
420 sprintf (QZ_Error, "Failed to find display resolution: %dx%dx%d", width, height, bpp); 425 SDL_SetError ("Failed to find display resolution: %dx%dx%d", width, height, bpp);
421 SDL_SetError (QZ_Error);
422 goto ERR_NO_MATCH; 426 goto ERR_NO_MATCH;
423 } 427 }
424 428
425 /* Fade display to zero gamma */ 429 /* Fade display to zero gamma */
426 gamma_error = QZ_FadeGammaOut (this, &gamma_table); 430 gamma_error = QZ_FadeGammaOut (this, &gamma_table);
428 /* Put up the blanking window (a window above all other windows) */ 432 /* Put up the blanking window (a window above all other windows) */
429 if ( CGDisplayNoErr != CGDisplayCapture (display_id) ) { 433 if ( CGDisplayNoErr != CGDisplayCapture (display_id) ) {
430 SDL_SetError ("Failed capturing display"); 434 SDL_SetError ("Failed capturing display");
431 goto ERR_NO_CAPTURE; 435 goto ERR_NO_CAPTURE;
432 } 436 }
433
434 437
435 /* Do the physical switch */ 438 /* Do the physical switch */
436 if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) { 439 if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) {
437 SDL_SetError ("Failed switching display resolution"); 440 SDL_SetError ("Failed switching display resolution");
438 goto ERR_NO_SWITCH; 441 goto ERR_NO_SWITCH;
444 current->flags = 0; 447 current->flags = 0;
445 current->w = width; 448 current->w = width;
446 current->h = height; 449 current->h = height;
447 current->flags |= SDL_FULLSCREEN; 450 current->flags |= SDL_FULLSCREEN;
448 current->flags |= SDL_HWSURFACE; 451 current->flags |= SDL_HWSURFACE;
449 452 current->flags |= SDL_PREALLOC;
450 this->UpdateRects = QZ_DirectUpdate; 453
451 454 this->UpdateRects = QZ_DirectUpdate;
455 this->LockHWSurface = QZ_LockHWSurface;
456 this->UnlockHWSurface = QZ_UnlockHWSurface;
457
452 /* Setup some mode-dependant info */ 458 /* Setup some mode-dependant info */
453 if ( CGSDisplayCanHWFill (display_id) ) { 459 if ( CGSDisplayCanHWFill (display_id) ) {
454 this->info.blit_fill = 1; 460 this->info.blit_fill = 1;
455 this->FillHWRect = QZ_FillHWRect; 461 this->FillHWRect = QZ_FillHWRect;
456 } 462 }
470 476
471 ctx = [ gl_context cglContext ]; 477 ctx = [ gl_context cglContext ];
472 err = CGLSetFullScreen (ctx); 478 err = CGLSetFullScreen (ctx);
473 479
474 if (err) { 480 if (err) {
475 sprintf (QZ_Error, "Error setting OpenGL fullscreen: %s", CGLErrorString(err)); 481 SDL_SetError ("Error setting OpenGL fullscreen: %s", CGLErrorString(err));
476 SDL_SetError (QZ_Error);
477 goto ERR_NO_GL; 482 goto ERR_NO_GL;
478 } 483 }
479 484
480 [ gl_context makeCurrentContext]; 485 [ gl_context makeCurrentContext];
481 486
492 /* Fade the display to original gamma */ 497 /* Fade the display to original gamma */
493 if (! gamma_error ) 498 if (! gamma_error )
494 QZ_FadeGammaIn (this, &gamma_table); 499 QZ_FadeGammaIn (this, &gamma_table);
495 500
496 /* 501 /*
497 There is a bug in Cocoa where NSScreen doesn't synchronize 502 There is a bug in Cocoa where NSScreen doesn't synchronize
498 with CGDirectDisplay, so the main screen's frame is wrong. 503 with CGDirectDisplay, so the main screen's frame is wrong.
499 As a result, coordinate translation produces wrong results. 504 As a result, coordinate translation produces incorrect results.
500 We can hack around this bug by setting the screen rect 505 We can hack around this bug by setting the screen rect
501 ourselves. This hack should be removed if/when the bug is fixed. 506 ourselves. This hack should be removed if/when the bug is fixed.
502 */ 507 */
503 screen_rect = NSMakeRect(0,0,width,height); 508 screen_rect = NSMakeRect(0,0,width,height);
504 [ [ NSScreen mainScreen ] setFrame:screen_rect ]; 509 [ [ NSScreen mainScreen ] setFrame:screen_rect ];
505 510
506 /* Save the flags to ensure correct tear-down */ 511 /* Save the flags to ensure correct tear-down */
516 } 521 }
517 522
518 static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, 523 static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
519 int height, int bpp, Uint32 flags) { 524 int height, int bpp, Uint32 flags) {
520 unsigned int style; 525 unsigned int style;
521 NSRect rect; 526 NSRect contentRect;
522 rect = NSMakeRect (0, 0, width, height);
523
524 #if 1 // FIXME - the resize button doesn't show? Also need resize events...
525 flags &= ~SDL_RESIZABLE;
526 #endif
527 /* Set the window style based on input flags */
528 if ( flags & SDL_NOFRAME ) {
529 style = NSBorderlessWindowMask;
530 } else {
531 style = NSTitledWindowMask;
532 style |= (NSMiniaturizableWindowMask | NSClosableWindowMask);
533 if ( flags & SDL_RESIZABLE )
534 style |= NSResizableWindowMask;
535 }
536
537 /* Manually create a window, avoids having a nib file resource */
538 qz_window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:rect
539 styleMask:style backing:NSBackingStoreBuffered defer:NO ];
540 if (qz_window == nil) {
541 SDL_SetError ("Could not create the Cocoa window");
542 return NULL;
543 }
544 527
545 current->flags = 0; 528 current->flags = 0;
546 current->w = width; 529 current->w = width;
547 current->h = height; 530 current->h = height;
548 531
549 [ qz_window setReleasedWhenClosed:YES ]; 532 contentRect = NSMakeRect (0, 0, width, height);
550 QZ_SetCaption(this, this->wm_title, this->wm_icon); 533
551 [ qz_window setAcceptsMouseMovedEvents:YES ]; 534 /*
552 [ qz_window setViewsNeedDisplay:NO ]; 535 Check if we should completely destroy the previous mode
553 [ qz_window center ]; 536 - If it is fullscreen
554 [ qz_window setDelegate: 537 - If it has different noframe or resizable attribute
555 [ [ [ SDL_QuartzWindowDelegate alloc ] init ] autorelease ] ]; 538 - If it is OpenGL (since gl attributes could be different)
556 539 - If new mode is OpenGL, but previous mode wasn't
557 /* For OpenGL, we set the content view to a NSOpenGLView */ 540 */
541 if (video_set == SDL_TRUE)
542 if ( (mode_flags & SDL_FULLSCREEN) ||
543 ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) ||
544 (mode_flags & SDL_OPENGL) ||
545 (flags & SDL_OPENGL) )
546 QZ_UnsetVideoMode (this);
547
548 /* Check if we should recreate the window */
549 if (qz_window == nil) {
550
551 /* Set the window style based on input flags */
552 if ( flags & SDL_NOFRAME ) {
553 style = NSBorderlessWindowMask;
554 current->flags |= SDL_NOFRAME;
555 } else {
556 style = NSTitledWindowMask;
557 style |= (NSMiniaturizableWindowMask | NSClosableWindowMask);
558 if ( flags & SDL_RESIZABLE ) {
559 style |= NSResizableWindowMask;
560 current->flags |= SDL_RESIZABLE;
561 }
562 }
563
564 /* Manually create a window, avoids having a nib file resource */
565 qz_window = [ [ SDL_QuartzWindow alloc ]
566 initWithContentRect:contentRect
567 styleMask:style
568 backing:NSBackingStoreBuffered
569 defer:NO ];
570
571 if (qz_window == nil) {
572 SDL_SetError ("Could not create the Cocoa window");
573 return NULL;
574 }
575
576 [ qz_window setReleasedWhenClosed:YES ];
577 QZ_SetCaption(this, this->wm_title, this->wm_icon);
578 [ qz_window setAcceptsMouseMovedEvents:YES ];
579 [ qz_window setViewsNeedDisplay:NO ];
580 [ qz_window center ];
581 [ qz_window setDelegate:
582 [ [ [ SDL_QuartzWindowDelegate alloc ] init ] autorelease ] ];
583 }
584 /* We already have a window, just change its size */
585 else {
586
587 [ qz_window setContentSize:contentRect.size ];
588 current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags;
589 }
590
591 /* For OpenGL, we bind the context to a subview */
558 if ( flags & SDL_OPENGL ) { 592 if ( flags & SDL_OPENGL ) {
559 593
560 if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { 594 if ( ! QZ_SetupOpenGL (this, bpp, flags) ) {
561 return NULL; 595 return NULL;
562 } 596 }
563 597
564 [ gl_context setView: [ qz_window contentView ] ]; 598 window_view = [ [ NSView alloc ] initWithFrame:contentRect ];
599 [ window_view setAutoresizingMask: NSViewMinYMargin ];
600 [ [ qz_window contentView ] addSubview:window_view ];
601 [ gl_context setView: window_view ];
602 [ window_view release ];
565 [ gl_context makeCurrentContext]; 603 [ gl_context makeCurrentContext];
566 [ qz_window makeKeyAndOrderFront:nil ]; 604 [ qz_window makeKeyAndOrderFront:nil ];
567 current->flags |= SDL_OPENGL; 605 current->flags |= SDL_OPENGL;
568 } 606 }
569 /* For 2D, we set the content view to a NSQuickDrawView */ 607 /* For 2D, we set the subview to an NSQuickDrawView */
570 else { 608 else {
571 609
572 window_view = [ [ SDL_QuartzWindowView alloc ] init ]; 610 /* Only recreate the view if it doesn't already exist */
573 [ qz_window setContentView:window_view ]; 611 if (window_view == nil) {
574 [ qz_window makeKeyAndOrderFront:nil ]; 612
575 613 window_view = [ [ SDL_QuartzWindowView alloc ] initWithFrame:contentRect ];
614 [ window_view setAutoresizingMask: NSViewMinYMargin ];
615 [ [ qz_window contentView ] addSubview:window_view ];
616 [ window_view release ];
617 [ qz_window makeKeyAndOrderFront:nil ];
618 }
619
576 LockPortBits ( [ window_view qdPort ] ); 620 LockPortBits ( [ window_view qdPort ] );
577 current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) ); 621 current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) );
578 current->pitch = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) ); 622 current->pitch = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) );
579 UnlockPortBits ( [ window_view qdPort ] ); 623 UnlockPortBits ( [ window_view qdPort ] );
580 624
581 current->flags |= SDL_SWSURFACE; 625 current->flags |= SDL_SWSURFACE;
582 current->flags |= SDL_PREALLOC; 626 current->flags |= SDL_PREALLOC;
583 current->flags |= SDL_ASYNCBLIT; 627 current->flags |= SDL_ASYNCBLIT;
584 628
585 if ( flags & SDL_NOFRAME ) 629 /* Offset below the title bar to fill the full content region */
586 current->flags |= SDL_NOFRAME; 630 current->pixels += ((int)([ qz_window frame ].size.height) - height) * current->pitch;
587 if ( flags & SDL_RESIZABLE )
588 current->flags |= SDL_RESIZABLE;
589
590 /* Offset 22 pixels down to fill the full content region */
591 if ( ! (current->flags & SDL_NOFRAME) ) {
592 current->pixels += 22 * current->pitch;
593 }
594 631
595 this->UpdateRects = QZ_UpdateRects; 632 this->UpdateRects = QZ_UpdateRects;
596 this->LockHWSurface = QZ_LockWindow; 633 this->LockHWSurface = QZ_LockWindow;
597 this->UnlockHWSurface = QZ_UnlockWindow; 634 this->UnlockHWSurface = QZ_UnlockWindow;
598 } 635 }
603 return current; 640 return current;
604 } 641 }
605 642
606 static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, 643 static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width,
607 int height, int bpp, Uint32 flags) { 644 int height, int bpp, Uint32 flags) {
608
609 if (video_set == SDL_TRUE)
610 QZ_UnsetVideoMode (this);
611 645
612 current->flags = 0; 646 current->flags = 0;
613 647
614 /* Setup full screen video */ 648 /* Setup full screen video */
615 if ( flags & SDL_FULLSCREEN ) { 649 if ( flags & SDL_FULLSCREEN ) {
694 728
695 static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) { 729 static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) {
696 #pragma unused(this,num_rects,rects) 730 #pragma unused(this,num_rects,rects)
697 } 731 }
698 732
699 /** 733 /*
700 * The obscured code is based on work by Matt Slot fprefect@ambrosiasw.com, 734 The obscured code is based on work by Matt Slot fprefect@ambrosiasw.com,
701 * who supplied sample code for Carbon. 735 who supplied sample code for Carbon.
702 **/ 736 */
703 static int QZ_IsWindowObscured (NSWindow *window) { 737 static int QZ_IsWindowObscured (NSWindow *window) {
704 738
705 //#define TEST_OBSCURED 1 739 //#define TEST_OBSCURED 1
706 740
707 #if TEST_OBSCURED 741 #if TEST_OBSCURED
708 742
709 /* In order to determine if a direct copy to the screen is possible, 743 /*
744 In order to determine if a direct copy to the screen is possible,
710 we must figure out if there are any windows covering ours (including shadows). 745 we must figure out if there are any windows covering ours (including shadows).
711 This can be done by querying the window server about the on screen 746 This can be done by querying the window server about the on screen
712 windows for their screen rectangle and window level. 747 windows for their screen rectangle and window level.
713 The procedure used below is puts accuracy before speed; however, it aims to call 748 The procedure used below is puts accuracy before speed; however, it aims to call
714 the window server the fewest number of times possible to keep things reasonable. 749 the window server the fewest number of times possible to keep things reasonable.
751 786
752 int obscured = SDL_TRUE; 787 int obscured = SDL_TRUE;
753 788
754 if ( [ window isVisible ] ) { 789 if ( [ window isVisible ] ) {
755 790
756 /* walk the window list looking for windows over top of 791 /*
757 (or casting a shadow on) ours */ 792 walk the window list looking for windows over top of
758 793 (or casting a shadow on) ours
759 /* Get a connection to the window server */ 794 */
760 /* Should probably be moved out into SetVideoMode() or InitVideo() */ 795
796 /*
797 Get a connection to the window server
798 Should probably be moved out into SetVideoMode() or InitVideo()
799 */
761 if (cgsConnection == (CGSConnectionID) -1) { 800 if (cgsConnection == (CGSConnectionID) -1) {
762 cgsConnection = (CGSConnectionID) 0; 801 cgsConnection = (CGSConnectionID) 0;
763 cgsConnection = _CGSDefaultConnection (); 802 cgsConnection = _CGSDefaultConnection ();
764 } 803 }
765 804
783 contentRect.size.height -= windowContentOffset; 822 contentRect.size.height -= windowContentOffset;
784 823
785 firstDockIcon = -1; 824 firstDockIcon = -1;
786 dockIconCacheMiss = SDL_FALSE; 825 dockIconCacheMiss = SDL_FALSE;
787 826
788 /* The first window is always an empty window with level kCGSWindowLevelTop 827 /*
789 so start at index 1 */ 828 The first window is always an empty window with level kCGSWindowLevelTop
829 so start at index 1
830 */
790 for (i = 1; i < count; i++) { 831 for (i = 1; i < count; i++) {
791 832
792 /* If we reach our window in the list, it cannot be obscured */ 833 /* If we reach our window in the list, it cannot be obscured */
793 if (windows[i] == windowNumber) { 834 if (windows[i] == windowNumber) {
794 835
854 shadowTop = 4; 895 shadowTop = 4;
855 shadowBottom = 12; 896 shadowBottom = 12;
856 } 897 }
857 else if (winLevel == kCGSWindowLevelNormal) { 898 else if (winLevel == kCGSWindowLevelNormal) {
858 899
859 /* These numbers are for foreground windows, 900 /*
860 they are too big (but will work) for background windows */ 901 These numbers are for foreground windows,
902 they are too big (but will work) for background windows
903 */
861 shadowSide = 20; 904 shadowSide = 20;
862 shadowTop = 10; 905 shadowTop = 10;
863 shadowBottom = 24; 906 shadowBottom = 24;
864 } 907 }
865 else if (winLevel == kCGSWindowLevelDock) { 908 else if (winLevel == kCGSWindowLevelDock) {
878 shadowTop = 0; 921 shadowTop = 0;
879 shadowBottom = 0; 922 shadowBottom = 0;
880 } 923 }
881 else { 924 else {
882 925
883 /* kCGSWindowLevelDockLabel, 926 /*
884 kCGSWindowLevelDock, 927 kCGSWindowLevelDockLabel,
885 kOther??? */ 928 kCGSWindowLevelDock,
929 kOther???
930 */
886 931
887 /* no shadow */ 932 /* no shadow */
888 shadowSide = 0; 933 shadowSide = 0;
889 shadowTop = 0; 934 shadowTop = 0;
890 shadowBottom = 0; 935 shadowBottom = 0;
915 #else 960 #else
916 return SDL_TRUE; 961 return SDL_TRUE;
917 #endif 962 #endif
918 } 963 }
919 964
965
920 /* Locking functions for the software window buffer */ 966 /* Locking functions for the software window buffer */
921 static int QZ_LockWindow (_THIS, SDL_Surface *surface) { 967 static int QZ_LockWindow (_THIS, SDL_Surface *surface) {
922 968
923 return LockPortBits ( [ window_view qdPort ] ); 969 return LockPortBits ( [ window_view qdPort ] );
924 } 970 }
931 static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) { 977 static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) {
932 978
933 if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) { 979 if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) {
934 QZ_GL_SwapBuffers (this); 980 QZ_GL_SwapBuffers (this);
935 } 981 }
936 else if ( [ qz_window isMiniaturized ] && 982 else if ( [ qz_window isMiniaturized ] ) {
937 ! (SDL_VideoSurface->flags & SDL_OPENGL)) { 983
938 984 /* Do nothing if miniaturized */
939 /** 985 }
940 * Set port alpha opaque so deminiaturize looks right 986
941 * This isn't so nice, but there is no
942 * initial deminatureize notification (before demini starts)
943 **/
944 QZ_SetPortAlphaOpaque ([ [ qz_window contentView ] qdPort],
945 [ qz_window styleMask ] & NSBorderlessWindowMask);
946 }
947 else if ( ! QZ_IsWindowObscured (qz_window) ) { 987 else if ( ! QZ_IsWindowObscured (qz_window) ) {
948 988
949 /* Use direct copy to flush contents to the display */ 989 /* Use direct copy to flush contents to the display */
950 CGrafPtr savePort; 990 CGrafPtr savePort;
951 CGrafPtr dstPort, srcPort; 991 CGrafPtr dstPort, srcPort;
990 } 1030 }
991 1031
992 SetPort (savePort); 1032 SetPort (savePort);
993 } 1033 }
994 else { 1034 else {
995
996 /* Use QDFlushPortBuffer() to flush content to display */ 1035 /* Use QDFlushPortBuffer() to flush content to display */
997 int i; 1036 int i;
998 RgnHandle dirty = NewRgn (); 1037 RgnHandle dirty = NewRgn ();
999 RgnHandle temp = NewRgn (); 1038 RgnHandle temp = NewRgn ();
1000 1039
1002 1041
1003 /* Build the region of dirty rectangles */ 1042 /* Build the region of dirty rectangles */
1004 for (i = 0; i < numRects; i++) { 1043 for (i = 0; i < numRects; i++) {
1005 1044
1006 MacSetRectRgn (temp, rects[i].x, rects[i].y, 1045 MacSetRectRgn (temp, rects[i].x, rects[i].y,
1007 rects[i].x + rects[i].w, rects[i].y + rects[i].h); 1046 rects[i].x + rects[i].w, rects[i].y + rects[i].h);
1008 MacUnionRgn (dirty, temp, dirty); 1047 MacUnionRgn (dirty, temp, dirty);
1009 } 1048 }
1010 1049
1050 QZ_DrawResizeIcon (this, dirty);
1051
1011 /* Flush the dirty region */ 1052 /* Flush the dirty region */
1012 QDFlushPortBuffer ( [ window_view qdPort ], dirty ); 1053 QDFlushPortBuffer ( [ window_view qdPort ], dirty );
1013 DisposeRgn (dirty); 1054 DisposeRgn (dirty);
1014 DisposeRgn (temp); 1055 DisposeRgn (temp);
1015 } 1056 }
1361 DisposeHandle ((Handle)yuv_idh); 1402 DisposeHandle ((Handle)yuv_idh);
1362 } 1403 }
1363 1404
1364 #include "SDL_yuvfuncs.h" 1405 #include "SDL_yuvfuncs.h"
1365 1406
1366 /** 1407 /* check for 16 byte alignment, bail otherwise */
1367 * check for 16 byte alignment, bail otherwise
1368 **/
1369 #define CHECK_ALIGN(x) do { if ((Uint32)x & 15) { SDL_SetError("Alignment error"); return NULL; } } while(0) 1408 #define CHECK_ALIGN(x) do { if ((Uint32)x & 15) { SDL_SetError("Alignment error"); return NULL; } } while(0)
1370 1409
1371 /** 1410 /* align a byte offset, return how much to add to make it a multiple of 16 */
1372 * align a byte offset, return how much to add to make it
1373 * a multiple of 16
1374 **/
1375 #define ALIGN(x) ((16 - (x & 15)) & 15) 1411 #define ALIGN(x) ((16 - (x & 15)) & 15)
1376 1412
1377 static SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height, 1413 static SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height,
1378 Uint32 format, SDL_Surface *display) { 1414 Uint32 format, SDL_Surface *display) {
1379 1415
1415 return NULL; 1451 return NULL;
1416 } 1452 }
1417 1453
1418 if (SDL_VideoSurface->flags & SDL_FULLSCREEN) { 1454 if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
1419 1455
1420 /** 1456 /*
1421 * Good acceleration requires a window to be present. 1457 Acceleration requires a window to be present.
1422 * A CGrafPtr that points to the screen isn't good enough 1458 A CGrafPtr that points to the screen isn't good enough
1423 **/ 1459 */
1424 NSRect content = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); 1460 NSRect content = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
1425 1461
1426 qz_window = [ [ SDL_QuartzWindow alloc ] 1462 qz_window = [ [ SDL_QuartzWindow alloc ]
1427 initWithContentRect:content 1463 initWithContentRect:content
1428 styleMask:NSBorderlessWindowMask 1464 styleMask:NSBorderlessWindowMask
1440 [ qz_window setLevel:CGShieldingWindowLevel() ]; 1476 [ qz_window setLevel:CGShieldingWindowLevel() ];
1441 [ qz_window makeKeyAndOrderFront:nil ]; 1477 [ qz_window makeKeyAndOrderFront:nil ];
1442 1478
1443 port = [ [ qz_window contentView ] qdPort ]; 1479 port = [ [ qz_window contentView ] qdPort ];
1444 SetPort (port); 1480 SetPort (port);
1445 // BUG: would like to remove white flash when window kicks in 1481
1446 //{ 1482 /*
1447 // Rect r; 1483 BUG: would like to remove white flash when window kicks in
1448 // SetRect (&r, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); 1484 {
1449 // PaintRect (&r); 1485 Rect r;
1450 // QDFlushPortBuffer (port, nil); 1486 SetRect (&r, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
1451 //} 1487 PaintRect (&r);
1488 QDFlushPortBuffer (port, nil);
1489 }
1490 */
1452 1491
1453 } 1492 }
1454 else { 1493 else {
1455 port = [ [ qz_window contentView ] qdPort ]; 1494 port = [ window_view qdPort ];
1456 SetPort (port); 1495 SetPort (port);
1457 } 1496 }
1458 1497
1459 SetIdentityMatrix (yuv_matrix); 1498 SetIdentityMatrix (yuv_matrix);
1460 1499
1542 if (yuv_pixmap == NULL) { 1581 if (yuv_pixmap == NULL) {
1543 SDL_OutOfMemory (); 1582 SDL_OutOfMemory ();
1544 return NULL; 1583 return NULL;
1545 } 1584 }
1546 1585
1547 //CHECK_ALIGN(yuv_pixmap); 1586 /* CHECK_ALIGN(yuv_pixmap); */
1548 offset = sizeof(PlanarPixmapInfoYUV420); 1587 offset = sizeof(PlanarPixmapInfoYUV420);
1549 //offset += ALIGN(offset); 1588 /* offset += ALIGN(offset); */
1550 //CHECK_ALIGN(offset); 1589 /* CHECK_ALIGN(offset); */
1551 1590
1552 pixels[0] = (Uint8*)yuv_pixmap + offset; 1591 pixels[0] = (Uint8*)yuv_pixmap + offset;
1553 //CHECK_ALIGN(pixels[0]); 1592 /* CHECK_ALIGN(pixels[0]); */
1554 1593
1555 pitches[0] = width; 1594 pitches[0] = width;
1556 yuv_pixmap->componentInfoY.offset = offset; 1595 yuv_pixmap->componentInfoY.offset = offset;
1557 yuv_pixmap->componentInfoY.rowBytes = width; 1596 yuv_pixmap->componentInfoY.rowBytes = width;
1558 1597
1586 yuv_width = overlay->w; 1625 yuv_width = overlay->w;
1587 yuv_height = overlay->h; 1626 yuv_height = overlay->h;
1588 1627
1589 return overlay; 1628 return overlay;
1590 } 1629 }
1591