Skip to content

Commit

Permalink
Date: Sat, 19 Jan 2002 17:24:32 -0500 (EST)
Browse files Browse the repository at this point in the history
From: Darrell Walisser <dwaliss1@purdue.edu>
Subject: SDL Quartz video update

-better mouse motion events
-fixed minification bugs (except OpenGL)
-fixed QZ_SetGamma for correct semantics
-fade/unfade display before/after rez switch
-experimental obscured-check/blind-copy code

The obscured code, while it speeds up window drawing substantially, isn't
ready yet. The reason is that there doesn't (yet) seem to be a way to know
when the window is dragged or when the window suddenly comes to the
foreground. Since Carbon windows seem to allow detection of such things, I
suspect it is possible through some window server API. Cocoa(NSWindow) has no
functions for such things, AFAIK.
  • Loading branch information
slouken committed Jan 22, 2002
1 parent 9267bd4 commit c944e03
Show file tree
Hide file tree
Showing 5 changed files with 855 additions and 180 deletions.
125 changes: 84 additions & 41 deletions src/video/quartz/SDL_QuartzEvents.m
Expand Up @@ -19,6 +19,7 @@
Sam Lantinga
slouken@libsdl.org
*/
#include <sys/time.h>

#include "SDL_QuartzKeys.h"

Expand Down Expand Up @@ -305,7 +306,13 @@ static void QZ_DoDeactivate (_THIS) {

static void QZ_PumpEvents (_THIS)
{
NSDate *distantPast;

static NSPoint lastMouse;
NSPoint mouse, saveMouse;
Point qdMouse;
CGMouseDelta dx, dy;

NSDate *distantPast;
NSEvent *event;
NSRect winRect;
NSRect titleBarRect;
Expand All @@ -314,10 +321,36 @@ static void QZ_PumpEvents (_THIS)
pool = [ [ NSAutoreleasePool alloc ] init ];
distantPast = [ NSDate distantPast ];

winRect = NSMakeRect (0, 0, SDL_VideoSurface->w + 1, SDL_VideoSurface->h + 1);
winRect = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
titleBarRect = NSMakeRect ( 0, SDL_VideoSurface->h, SDL_VideoSurface->w,
SDL_VideoSurface->h + 22 );


if (currentGrabMode != SDL_GRAB_ON) { /* if grabbed, the cursor can't move! (see fallback below) */

/* 1/2 second after a warp, the mouse cannot move (don't ask me why) */
/* So, approximate motion with CGGetLastMouseDelta, which still works, somehow */
if (! warp_flag) {

GetGlobalMouse (&qdMouse); /* use Carbon since [ NSEvent mouseLocation ] is broken */
mouse = NSMakePoint (qdMouse.h, qdMouse.v);
saveMouse = mouse;

if (mouse.x != lastMouse.x || mouse.y != lastMouse.y) {

QZ_PrivateCGToSDL (this, &mouse);
if (inForeground && NSPointInRect (mouse, winRect)) {
//printf ("Mouse Loc: (%f, %f)\n", mouse.x, mouse.y);
SDL_PrivateMouseMotion (0, 0, mouse.x, mouse.y);
}
}
lastMouse = saveMouse;
}
}

/* accumulate any mouse events into one SDL mouse event */
dx = 0;
dy = 0;

do {

/* Poll for an event. This will not block */
Expand All @@ -330,22 +363,22 @@ static void QZ_PumpEvents (_THIS)
BOOL isForGameWin;

#define DO_MOUSE_DOWN(button, sendToWindow) do { \
if ( inForeground ) { \
if ( inForeground ) { \
if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) || \
NSPointInRect([event locationInWindow], winRect) ) \
SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); \
} \
else { \
QZ_DoActivate (this); \
} \
[ NSApp sendEvent:event ]; \
} \
else { \
QZ_DoActivate (this); \
} \
[ NSApp sendEvent:event ]; \
} while(0)

#define DO_MOUSE_UP(button, sendToWindow) do { \
if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) || \
!NSPointInRect([event locationInWindow], titleBarRect) )\
SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); \
[ NSApp sendEvent:event ]; \
!NSPointInRect([event locationInWindow], titleBarRect) ) \
SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); \
[ NSApp sendEvent:event ]; \
} while(0)

type = [ event type ];
Expand All @@ -365,7 +398,7 @@ static void QZ_PumpEvents (_THIS)
DO_MOUSE_DOWN (1, 1);
}
break;
case 25: DO_MOUSE_DOWN (2, 0); break;
case NSOtherMouseDown: DO_MOUSE_DOWN (2, 0); break;
case NSRightMouseDown: DO_MOUSE_DOWN (3, 0); break;
case NSLeftMouseUp:

Expand All @@ -377,7 +410,7 @@ static void QZ_PumpEvents (_THIS)
DO_MOUSE_UP (1, 1);
}
break;
case 26: DO_MOUSE_UP (2, 0); break;
case NSOtherMouseUp: DO_MOUSE_UP (2, 0); break;
case NSRightMouseUp: DO_MOUSE_UP (3, 0); break;
case NSSystemDefined:
//if ([event subtype] == 7) {
Expand All @@ -389,30 +422,37 @@ static void QZ_PumpEvents (_THIS)
case NSRightMouseDragged:
case 27:
case NSMouseMoved:
if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN)
|| NSPointInRect([event locationInWindow], winRect) )
{
static int moves = 0;
NSPoint p;

if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) {
p = [ NSEvent mouseLocation ];
p.y = [[NSScreen mainScreen] frame].size.height - p.y;
} else {
p = [ event locationInWindow ];
p.y = SDL_VideoSurface->h - p.y;
}

if ( (moves % 10) == 0 ) {
SDL_PrivateMouseMotion (0, 0, p.x, p.y);
}
else {
CGMouseDelta dx, dy;
CGGetLastMouseDelta (&dx, &dy);
SDL_PrivateMouseMotion (0, 1, dx, dy);
}
moves++;
}

if (currentGrabMode == SDL_GRAB_ON) {

/**
* If input is grabbed, we'll wing it and try to send some mouse
* moved events with CGGetLastMouseDelta(). Not optimal, but better
* than nothing.
**/
CGMouseDelta dx1, dy1;
CGGetLastMouseDelta (&dx1, &dy1);
dx += dx1;
dy += dy1;
}
else if (warp_flag) {

Uint32 ticks;

ticks = SDL_GetTicks();
if (ticks - warp_ticks < 150) {

CGMouseDelta dx1, dy1;
CGGetLastMouseDelta (&dx1, &dy1);
dx += dx1;
dy += dy1;
}
else {

warp_flag = 0;
}
}

break;
case NSScrollWheel:
{
Expand All @@ -435,8 +475,6 @@ static void QZ_PumpEvents (_THIS)
case NSFlagsChanged:
QZ_DoModifiers( [ event modifierFlags ] );
break;
/* case NSMouseEntered: break; */
/* case NSMouseExited: break; */
case NSAppKitDefined:
switch ( [ event subtype ] ) {
case NSApplicationActivatedEventType:
Expand All @@ -451,12 +489,17 @@ static void QZ_PumpEvents (_THIS)
/* case NSApplicationDefined: break; */
/* case NSPeriodic: break; */
/* case NSCursorUpdate: break; */
default:

default:
[ NSApp sendEvent:event ];
}
}
} while (event != nil);

/* check for accumulated mouse events */
if (dx != 0 || dy != 0)
SDL_PrivateMouseMotion (0, 1, dx, dy);

[ pool release ];
}

122 changes: 93 additions & 29 deletions src/video/quartz/SDL_QuartzVideo.h
Expand Up @@ -34,25 +34,28 @@
- Multiple monitor support (currently only main display)
- Accelerated blitting support
- Set the window icon (dock icon when API is available)
- Avoid erasing window on minimize, or disable minimize
- Fix white OpenGL window on minimize
- Find out what events should be sent/ignored if window is mimimized
- Find a better way to deal with resolution/depth switch while app is running
- Resizeable windows
- Check accuracy of QZ_SetGamma()
Problems:
- OGL not working in full screen with software renderer
- SetColors sets palette correctly but clears framebuffer
- Crash in CG after several mode switches
- Retained windows don't draw their title bar quite right (OS Bug)
- Should I do depth switching for windowed modes? - No, not usually.
- Launch times are slow, maybe prebinding will help
- Direct framebuffer access has some artifacts, maybe a driver issue
- Cursor in 8 bit modes is screwy
- Retained windows don't draw their title bar quite right (OS Bug) (not using retained windows)
- Cursor in 8 bit modes is screwy (might just be Radeon PCI bug)
- Warping cursor delays mouse events for a fraction of a second,
there is a hack around this that helps a bit
*/

#include <ApplicationServices/ApplicationServices.h>
#include <OpenGL/OpenGL.h>
#include <Cocoa/Cocoa.h>
#include <OpenGL/OpenGL.h>
#include <Carbon/Carbon.h>

#include "SDL_video.h"
#include "SDL_error.h"
#include "SDL_timer.h"
#include "SDL_syswm.h"
#include "SDL_sysvideo.h"
#include "SDL_pixels_c.h"
Expand All @@ -71,21 +74,34 @@
}
@end

/* Structure for rez switch gamma fades */
/* We can hide the monitor flicker by setting the gamma tables to 0 */
#define QZ_GAMMA_TABLE_SIZE 256

typedef struct {

CGGammaValue red[QZ_GAMMA_TABLE_SIZE];
CGGammaValue green[QZ_GAMMA_TABLE_SIZE];
CGGammaValue blue[QZ_GAMMA_TABLE_SIZE];

} SDL_QuartzGammaTable;

/* Main driver structure to store required state information */
typedef struct SDL_PrivateVideoData {

CGDirectDisplayID display; /* 0 == main display */
CFDictionaryRef mode;
CFDictionaryRef save_mode;
CFArrayRef mode_list;
CGDirectPaletteRef palette;
NSOpenGLContext *gl_context;
Uint32 width, height, bpp;
Uint32 flags;
SDL_bool video_is_set; /* tell if the video mode was set */

/* Window-only fields */
NSWindow *window;
NSQuickDrawView *view;
CGDirectDisplayID display; /* 0 == main display (only support single display) */
CFDictionaryRef mode; /* current mode of the display */
CFDictionaryRef save_mode; /* original mode of the display */
CFArrayRef mode_list; /* list of available fullscreen modes */
CGDirectPaletteRef palette; /* palette of an 8-bit display */
NSOpenGLContext *gl_context; /* object that represents an OpenGL rendering context */
Uint32 width, height, bpp; /* frequently used data about the display */
Uint32 flags; /* flags for mode, for teardown purposes */
Uint32 video_set; /* boolean; indicates if video was set correctly */
Uint32 warp_flag; /* boolean; notify to event loop that a warp just occured */
Uint32 warp_ticks; /* timestamp when the warp occured */
NSWindow *window; /* Cocoa window to implement the SDL window */
NSQuickDrawView *view; /* the window's view; draw 2D into this view */

} SDL_PrivateVideoData ;

Expand All @@ -95,21 +111,68 @@ typedef struct SDL_PrivateVideoData {
#define save_mode (this->hidden->save_mode)
#define mode_list (this->hidden->mode_list)
#define palette (this->hidden->palette)
#define glcontext (this->hidden->glcontext)
#define objc_video (this->hidden->objc_video)
#define gl_context (this->hidden->gl_context)
#define device_width (this->hidden->width)
#define device_height (this->hidden->height)
#define device_bpp (this->hidden->bpp)
#define mode_flags (this->hidden->flags)
#define video_set (this->hidden->video_is_set)
#define qz_window (this->hidden->window)
#define windowView (this->hidden->view)
#define window_view (this->hidden->view)
#define video_set (this->hidden->video_set)
#define warp_ticks (this->hidden->warp_ticks)
#define warp_flag (this->hidden->warp_flag)

/* Obscuring code: maximum number of windows above ours (inclusive) */
#define kMaxWindows 256

/* Some of the Core Graphics Server API for obscuring code */
#define kCGSWindowLevelTop 2147483632
#define kCGSWindowLevelDockIconDrag 500
#define kCGSWindowLevelDockMenu 101
#define kCGSWindowLevelMenuIgnore 21
#define kCGSWindowLevelMenu 20
#define kCGSWindowLevelDockLabel 12
#define kCGSWindowLevelDockIcon 11
#define kCGSWindowLevelDock 10
#define kCGSWindowLevelUtility 3
#define kCGSWindowLevelNormal 0

/* For completeness; We never use these window levels, they are always below us
#define kCGSWindowLevelMBarShadow -20
#define kCGSWindowLevelDesktopPicture -2147483647
#define kCGSWindowLevelDesktop -2147483648
*/

/* Interface for hardware fill not (yet) in the public API */
int CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y,
typedef CGError CGSError;
typedef long CGSWindowCount;
typedef void * CGSConnectionID;
typedef int CGSWindowID;
typedef CGSWindowID* CGSWindowIDList;
typedef CGWindowLevel CGSWindowLevel;
typedef NSRect CGSRect;

extern CGSConnectionID _CGSDefaultConnection ();

extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid,
CGSConnectionID owner,
CGSWindowCount listCapacity,
CGSWindowIDList list,
CGSWindowCount *listCount);

extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid,
CGSWindowID wid,
CGSRect *rect);

extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid,
CGSWindowID wid,
CGSWindowLevel *level);

extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y,
unsigned int w, unsigned int h, unsigned int color);
int CGSDisplayCanHWFill (CGDirectDisplayID id);

extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id);

extern CGSError CGSGetMouseEnabledFlags (CGSConnectionID cid, CGSWindowID wid, int *flags);

/* Bootstrap functions */
static int QZ_Available ();
Expand Down Expand Up @@ -156,7 +219,7 @@ static void QZ_GL_SwapBuffers (_THIS);
static int QZ_GL_LoadLibrary (_THIS, const char *location);

/* Private function to warp the cursor (used internally) */
static void QZ_PrivateWarpCursor (_THIS, int fullscreen, int h, int x, int y);
static void QZ_PrivateWarpCursor (_THIS, int x, int y);

/* Cursor and Mouse functions */
static void QZ_FreeWMCursor (_THIS, WMcursor *cursor);
Expand All @@ -177,3 +240,4 @@ static void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask);
static int QZ_IconifyWindow (_THIS);
static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode);
/*static int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/

0 comments on commit c944e03

Please sign in to comment.