- Added SDL, libjpeg and libpng
- Added Android project and Java files
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_cocoaclipboard_h
|
||||
#define _SDL_cocoaclipboard_h
|
||||
|
||||
/* Forward declaration */
|
||||
struct SDL_VideoData;
|
||||
|
||||
extern int Cocoa_SetClipboardText(_THIS, const char *text);
|
||||
extern char *Cocoa_GetClipboardText(_THIS);
|
||||
extern SDL_bool Cocoa_HasClipboardText(_THIS);
|
||||
extern void Cocoa_CheckClipboardUpdate(struct SDL_VideoData * data);
|
||||
|
||||
#endif /* _SDL_cocoaclipboard_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "../../events/SDL_clipboardevents_c.h"
|
||||
|
||||
static NSString *
|
||||
GetTextFormat(_THIS)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
|
||||
if (data->osversion >= 0x1060) {
|
||||
return NSPasteboardTypeString;
|
||||
} else {
|
||||
return NSStringPboardType;
|
||||
}
|
||||
#else
|
||||
return NSStringPboardType;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_SetClipboardText(_THIS, const char *text)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
NSAutoreleasePool *pool;
|
||||
NSPasteboard *pasteboard;
|
||||
NSString *format = GetTextFormat(_this);
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
pasteboard = [NSPasteboard generalPasteboard];
|
||||
data->clipboard_count = [pasteboard declareTypes:[NSArray arrayWithObject:format] owner:nil];
|
||||
[pasteboard setString:[NSString stringWithUTF8String:text] forType:format];
|
||||
|
||||
[pool release];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
Cocoa_GetClipboardText(_THIS)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NSPasteboard *pasteboard;
|
||||
NSString *format = GetTextFormat(_this);
|
||||
NSString *available;
|
||||
char *text;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
pasteboard = [NSPasteboard generalPasteboard];
|
||||
available = [pasteboard availableTypeFromArray: [NSArray arrayWithObject:format]];
|
||||
if ([available isEqualToString:format]) {
|
||||
NSString* string;
|
||||
const char *utf8;
|
||||
|
||||
string = [pasteboard stringForType:format];
|
||||
if (string == nil) {
|
||||
utf8 = "";
|
||||
} else {
|
||||
utf8 = [string UTF8String];
|
||||
}
|
||||
text = SDL_strdup(utf8);
|
||||
} else {
|
||||
text = SDL_strdup("");
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
Cocoa_HasClipboardText(_THIS)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NSPasteboard *pasteboard;
|
||||
NSString *format = GetTextFormat(_this);
|
||||
NSString *available;
|
||||
SDL_bool result;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
pasteboard = [NSPasteboard generalPasteboard];
|
||||
available = [pasteboard availableTypeFromArray: [NSArray arrayWithObject:format]];
|
||||
if ([available isEqualToString:format]) {
|
||||
result = SDL_TRUE;
|
||||
} else {
|
||||
result = SDL_FALSE;
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_CheckClipboardUpdate(struct SDL_VideoData * data)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NSPasteboard *pasteboard;
|
||||
NSInteger count;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
pasteboard = [NSPasteboard generalPasteboard];
|
||||
count = [pasteboard changeCount];
|
||||
if (count != data->clipboard_count) {
|
||||
if (data->clipboard_count) {
|
||||
SDL_SendClipboardUpdate();
|
||||
}
|
||||
data->clipboard_count = count;
|
||||
}
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_cocoaevents_h
|
||||
#define _SDL_cocoaevents_h
|
||||
|
||||
extern void Cocoa_RegisterApp(void);
|
||||
extern void Cocoa_PumpEvents(_THIS);
|
||||
|
||||
#endif /* _SDL_cocoaevents_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#if !defined(UsrActivity) && defined(__LP64__) && !defined(__POWER__)
|
||||
/*
|
||||
* Workaround for a bug in the 10.5 SDK: By accident, OSService.h does
|
||||
* not include Power.h at all when compiling in 64bit mode. This has
|
||||
* been fixed in 10.6, but for 10.5, we manually define UsrActivity
|
||||
* to ensure compilation works.
|
||||
*/
|
||||
#define UsrActivity 1
|
||||
#endif
|
||||
|
||||
/* setAppleMenu disappeared from the headers in 10.4 */
|
||||
@interface NSApplication(NSAppleMenu)
|
||||
- (void)setAppleMenu:(NSMenu *)menu;
|
||||
@end
|
||||
|
||||
@interface SDLAppDelegate : NSObject
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
|
||||
@end
|
||||
|
||||
@implementation SDLAppDelegate : NSObject
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
SDL_SendQuit();
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
@end
|
||||
|
||||
static NSString *
|
||||
GetApplicationName(void)
|
||||
{
|
||||
NSDictionary *dict;
|
||||
NSString *appName = 0;
|
||||
|
||||
/* Determine the application name */
|
||||
dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
|
||||
if (dict)
|
||||
appName = [dict objectForKey: @"CFBundleName"];
|
||||
|
||||
if (![appName length])
|
||||
appName = [[NSProcessInfo processInfo] processName];
|
||||
|
||||
return appName;
|
||||
}
|
||||
|
||||
static void
|
||||
CreateApplicationMenus(void)
|
||||
{
|
||||
NSString *appName;
|
||||
NSString *title;
|
||||
NSMenu *appleMenu;
|
||||
NSMenu *windowMenu;
|
||||
NSMenuItem *menuItem;
|
||||
|
||||
/* Create the main menu bar */
|
||||
[NSApp setMainMenu:[[NSMenu alloc] init]];
|
||||
|
||||
/* Create the application menu */
|
||||
appName = GetApplicationName();
|
||||
appleMenu = [[NSMenu alloc] initWithTitle:@""];
|
||||
|
||||
/* Add menu items */
|
||||
title = [@"About " stringByAppendingString:appName];
|
||||
[appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
|
||||
|
||||
[appleMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
[appleMenu addItemWithTitle:@"Preferences" action:nil keyEquivalent:@""];
|
||||
|
||||
[appleMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
title = [@"Hide " stringByAppendingString:appName];
|
||||
[appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@/*"h"*/""];
|
||||
|
||||
menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@/*"h"*/""];
|
||||
[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
|
||||
|
||||
[appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
|
||||
|
||||
[appleMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
title = [@"Quit " stringByAppendingString:appName];
|
||||
[appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@/*"q"*/""];
|
||||
|
||||
/* Put menu into the menubar */
|
||||
menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
|
||||
[menuItem setSubmenu:appleMenu];
|
||||
[[NSApp mainMenu] addItem:menuItem];
|
||||
[menuItem release];
|
||||
|
||||
/* Tell the application object that this is now the application menu */
|
||||
[NSApp setAppleMenu:appleMenu];
|
||||
[appleMenu release];
|
||||
|
||||
|
||||
/* Create the window menu */
|
||||
windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
|
||||
|
||||
/* "Minimize" item */
|
||||
menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@/*"m"*/""];
|
||||
[windowMenu addItem:menuItem];
|
||||
[menuItem release];
|
||||
|
||||
/* Put menu into the menubar */
|
||||
menuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
|
||||
[menuItem setSubmenu:windowMenu];
|
||||
[[NSApp mainMenu] addItem:menuItem];
|
||||
[menuItem release];
|
||||
|
||||
/* Tell the application object that this is now the window menu */
|
||||
[NSApp setWindowsMenu:windowMenu];
|
||||
[windowMenu release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_RegisterApp(void)
|
||||
{
|
||||
ProcessSerialNumber psn;
|
||||
NSAutoreleasePool *pool;
|
||||
|
||||
if (!GetCurrentProcess(&psn)) {
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
SetFrontProcess(&psn);
|
||||
}
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
if (NSApp == nil) {
|
||||
[NSApplication sharedApplication];
|
||||
|
||||
if ([NSApp mainMenu] == nil) {
|
||||
CreateApplicationMenus();
|
||||
}
|
||||
[NSApp finishLaunching];
|
||||
}
|
||||
if ([NSApp delegate] == nil) {
|
||||
[NSApp setDelegate:[[SDLAppDelegate alloc] init]];
|
||||
}
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_PumpEvents(_THIS)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
|
||||
/* Update activity every 30 seconds to prevent screensaver */
|
||||
if (_this->suspend_screensaver) {
|
||||
SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
|
||||
Uint32 now = SDL_GetTicks();
|
||||
if (!data->screensaver_activity ||
|
||||
(int)(now-data->screensaver_activity) >= 30000) {
|
||||
UpdateSystemActivity(UsrActivity);
|
||||
data->screensaver_activity = now;
|
||||
}
|
||||
}
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
for ( ; ; ) {
|
||||
NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES ];
|
||||
if ( event == nil ) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch ([event type]) {
|
||||
case NSLeftMouseDown:
|
||||
case NSOtherMouseDown:
|
||||
case NSRightMouseDown:
|
||||
case NSLeftMouseUp:
|
||||
case NSOtherMouseUp:
|
||||
case NSRightMouseUp:
|
||||
case NSLeftMouseDragged:
|
||||
case NSRightMouseDragged:
|
||||
case NSOtherMouseDragged: /* usually middle mouse dragged */
|
||||
case NSMouseMoved:
|
||||
case NSScrollWheel:
|
||||
Cocoa_HandleMouseEvent(_this, event);
|
||||
/* Pass through to NSApp to make sure everything stays in sync */
|
||||
[NSApp sendEvent:event];
|
||||
break;
|
||||
case NSKeyDown:
|
||||
case NSKeyUp:
|
||||
case NSFlagsChanged:
|
||||
Cocoa_HandleKeyEvent(_this, event);
|
||||
/* Fall through to pass event to NSApp; er, nevermind... */
|
||||
|
||||
/* Add to support system-wide keyboard shortcuts like CMD+Space */
|
||||
if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged)
|
||||
[NSApp sendEvent: event];
|
||||
break;
|
||||
default:
|
||||
[NSApp sendEvent:event];
|
||||
break;
|
||||
}
|
||||
}
|
||||
[pool release];
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_cocoakeyboard_h
|
||||
#define _SDL_cocoakeyboard_h
|
||||
|
||||
extern void Cocoa_InitKeyboard(_THIS);
|
||||
extern void Cocoa_HandleKeyEvent(_THIS, NSEvent * event);
|
||||
extern void Cocoa_QuitKeyboard(_THIS);
|
||||
|
||||
extern void Cocoa_StartTextInput(_THIS);
|
||||
extern void Cocoa_StopTextInput(_THIS);
|
||||
extern void Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect);
|
||||
|
||||
#endif /* _SDL_cocoakeyboard_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,736 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/scancodes_darwin.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
//#define DEBUG_IME NSLog
|
||||
#define DEBUG_IME
|
||||
|
||||
#ifndef NX_DEVICERCTLKEYMASK
|
||||
#define NX_DEVICELCTLKEYMASK 0x00000001
|
||||
#endif
|
||||
#ifndef NX_DEVICELSHIFTKEYMASK
|
||||
#define NX_DEVICELSHIFTKEYMASK 0x00000002
|
||||
#endif
|
||||
#ifndef NX_DEVICERSHIFTKEYMASK
|
||||
#define NX_DEVICERSHIFTKEYMASK 0x00000004
|
||||
#endif
|
||||
#ifndef NX_DEVICELCMDKEYMASK
|
||||
#define NX_DEVICELCMDKEYMASK 0x00000008
|
||||
#endif
|
||||
#ifndef NX_DEVICERCMDKEYMASK
|
||||
#define NX_DEVICERCMDKEYMASK 0x00000010
|
||||
#endif
|
||||
#ifndef NX_DEVICELALTKEYMASK
|
||||
#define NX_DEVICELALTKEYMASK 0x00000020
|
||||
#endif
|
||||
#ifndef NX_DEVICERALTKEYMASK
|
||||
#define NX_DEVICERALTKEYMASK 0x00000040
|
||||
#endif
|
||||
#ifndef NX_DEVICERCTLKEYMASK
|
||||
#define NX_DEVICERCTLKEYMASK 0x00002000
|
||||
#endif
|
||||
|
||||
@interface SDLTranslatorResponder : NSView <NSTextInput>
|
||||
{
|
||||
NSString *_markedText;
|
||||
NSRange _markedRange;
|
||||
NSRange _selectedRange;
|
||||
SDL_Rect _inputRect;
|
||||
}
|
||||
- (void) doCommandBySelector:(SEL)myselector;
|
||||
- (void) setInputRect:(SDL_Rect *) rect;
|
||||
@end
|
||||
|
||||
@implementation SDLTranslatorResponder
|
||||
|
||||
- (void) setInputRect:(SDL_Rect *) rect
|
||||
{
|
||||
_inputRect = *rect;
|
||||
}
|
||||
|
||||
- (void) insertText:(id) aString
|
||||
{
|
||||
const char *str;
|
||||
|
||||
DEBUG_IME(@"insertText: %@", aString);
|
||||
|
||||
/* Could be NSString or NSAttributedString, so we have
|
||||
* to test and convert it before return as SDL event */
|
||||
if ([aString isKindOfClass: [NSAttributedString class]])
|
||||
str = [[aString string] UTF8String];
|
||||
else
|
||||
str = [aString UTF8String];
|
||||
|
||||
SDL_SendKeyboardText(str);
|
||||
}
|
||||
|
||||
- (void) doCommandBySelector:(SEL) myselector
|
||||
{
|
||||
// No need to do anything since we are not using Cocoa
|
||||
// selectors to handle special keys, instead we use SDL
|
||||
// key events to do the same job.
|
||||
}
|
||||
|
||||
- (BOOL) hasMarkedText
|
||||
{
|
||||
return _markedText != nil;
|
||||
}
|
||||
|
||||
- (NSRange) markedRange
|
||||
{
|
||||
return _markedRange;
|
||||
}
|
||||
|
||||
- (NSRange) selectedRange
|
||||
{
|
||||
return _selectedRange;
|
||||
}
|
||||
|
||||
- (void) setMarkedText:(id) aString
|
||||
selectedRange:(NSRange) selRange
|
||||
{
|
||||
if ([aString isKindOfClass: [NSAttributedString class]])
|
||||
aString = [aString string];
|
||||
|
||||
if ([aString length] == 0)
|
||||
{
|
||||
[self unmarkText];
|
||||
return;
|
||||
}
|
||||
|
||||
if (_markedText != aString)
|
||||
{
|
||||
[_markedText release];
|
||||
_markedText = [aString retain];
|
||||
}
|
||||
|
||||
_selectedRange = selRange;
|
||||
_markedRange = NSMakeRange(0, [aString length]);
|
||||
|
||||
SDL_SendEditingText([aString UTF8String],
|
||||
selRange.location, selRange.length);
|
||||
|
||||
DEBUG_IME(@"setMarkedText: %@, (%d, %d)", _markedText,
|
||||
selRange.location, selRange.length);
|
||||
}
|
||||
|
||||
- (void) unmarkText
|
||||
{
|
||||
[_markedText release];
|
||||
_markedText = nil;
|
||||
|
||||
SDL_SendEditingText("", 0, 0);
|
||||
}
|
||||
|
||||
- (NSRect) firstRectForCharacterRange: (NSRange) theRange
|
||||
{
|
||||
NSWindow *window = [self window];
|
||||
NSRect contentRect = [window contentRectForFrameRect: [window frame]];
|
||||
float windowHeight = contentRect.size.height;
|
||||
NSRect rect = NSMakeRect(_inputRect.x, windowHeight - _inputRect.y - _inputRect.h,
|
||||
_inputRect.w, _inputRect.h);
|
||||
|
||||
DEBUG_IME(@"firstRectForCharacterRange: (%d, %d): windowHeight = %g, rect = %@",
|
||||
theRange.location, theRange.length, windowHeight,
|
||||
NSStringFromRect(rect));
|
||||
rect.origin = [[self window] convertBaseToScreen: rect.origin];
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
- (NSAttributedString *) attributedSubstringFromRange: (NSRange) theRange
|
||||
{
|
||||
DEBUG_IME(@"attributedSubstringFromRange: (%d, %d)", theRange.location, theRange.length);
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* Needs long instead of NSInteger for compilation on Mac OS X 10.4 */
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
|
||||
- (long) conversationIdentifier
|
||||
#else
|
||||
- (NSInteger) conversationIdentifier
|
||||
#endif
|
||||
{
|
||||
return (long) self;
|
||||
}
|
||||
|
||||
// This method returns the index for character that is
|
||||
// nearest to thePoint. thPoint is in screen coordinate system.
|
||||
- (NSUInteger) characterIndexForPoint:(NSPoint) thePoint
|
||||
{
|
||||
DEBUG_IME(@"characterIndexForPoint: (%g, %g)", thePoint.x, thePoint.y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This method is the key to attribute extension.
|
||||
// We could add new attributes through this method.
|
||||
// NSInputServer examines the return value of this
|
||||
// method & constructs appropriate attributed string.
|
||||
- (NSArray *) validAttributesForMarkedText
|
||||
{
|
||||
return [NSArray array];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* This is the original behavior, before support was added for
|
||||
* differentiating between left and right versions of the keys.
|
||||
*/
|
||||
static void
|
||||
DoUnsidedModifiers(unsigned short scancode,
|
||||
unsigned int oldMods, unsigned int newMods)
|
||||
{
|
||||
const int mapping[] = {
|
||||
SDL_SCANCODE_CAPSLOCK,
|
||||
SDL_SCANCODE_LSHIFT,
|
||||
SDL_SCANCODE_LCTRL,
|
||||
SDL_SCANCODE_LALT,
|
||||
SDL_SCANCODE_LGUI
|
||||
};
|
||||
unsigned int i, bit;
|
||||
|
||||
/* Iterate through the bits, testing each against the current modifiers */
|
||||
for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
|
||||
unsigned int oldMask, newMask;
|
||||
|
||||
oldMask = oldMods & bit;
|
||||
newMask = newMods & bit;
|
||||
|
||||
if (oldMask && oldMask != newMask) { /* modifier up event */
|
||||
/* If this was Caps Lock, we need some additional voodoo to make SDL happy */
|
||||
if (bit == NSAlphaShiftKeyMask) {
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, mapping[i]);
|
||||
}
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, mapping[i]);
|
||||
} else if (newMask && oldMask != newMask) { /* modifier down event */
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, mapping[i]);
|
||||
/* If this was Caps Lock, we need some additional voodoo to make SDL happy */
|
||||
if (bit == NSAlphaShiftKeyMask) {
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, mapping[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a helper function for HandleModifierSide. This
|
||||
* function reverts back to behavior before the distinction between
|
||||
* sides was made.
|
||||
*/
|
||||
static void
|
||||
HandleNonDeviceModifier(unsigned int device_independent_mask,
|
||||
unsigned int oldMods,
|
||||
unsigned int newMods,
|
||||
SDL_Scancode scancode)
|
||||
{
|
||||
unsigned int oldMask, newMask;
|
||||
|
||||
/* Isolate just the bits we care about in the depedent bits so we can
|
||||
* figure out what changed
|
||||
*/
|
||||
oldMask = oldMods & device_independent_mask;
|
||||
newMask = newMods & device_independent_mask;
|
||||
|
||||
if (oldMask && oldMask != newMask) {
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
|
||||
} else if (newMask && oldMask != newMask) {
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a helper function for HandleModifierSide.
|
||||
* This function sets the actual SDL_PrivateKeyboard event.
|
||||
*/
|
||||
static void
|
||||
HandleModifierOneSide(unsigned int oldMods, unsigned int newMods,
|
||||
SDL_Scancode scancode,
|
||||
unsigned int sided_device_dependent_mask)
|
||||
{
|
||||
unsigned int old_dep_mask, new_dep_mask;
|
||||
|
||||
/* Isolate just the bits we care about in the depedent bits so we can
|
||||
* figure out what changed
|
||||
*/
|
||||
old_dep_mask = oldMods & sided_device_dependent_mask;
|
||||
new_dep_mask = newMods & sided_device_dependent_mask;
|
||||
|
||||
/* We now know that this side bit flipped. But we don't know if
|
||||
* it went pressed to released or released to pressed, so we must
|
||||
* find out which it is.
|
||||
*/
|
||||
if (new_dep_mask && old_dep_mask != new_dep_mask) {
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
|
||||
} else {
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a helper function for DoSidedModifiers.
|
||||
* This function will figure out if the modifier key is the left or right side,
|
||||
* e.g. left-shift vs right-shift.
|
||||
*/
|
||||
static void
|
||||
HandleModifierSide(int device_independent_mask,
|
||||
unsigned int oldMods, unsigned int newMods,
|
||||
SDL_Scancode left_scancode,
|
||||
SDL_Scancode right_scancode,
|
||||
unsigned int left_device_dependent_mask,
|
||||
unsigned int right_device_dependent_mask)
|
||||
{
|
||||
unsigned int device_dependent_mask = (left_device_dependent_mask |
|
||||
right_device_dependent_mask);
|
||||
unsigned int diff_mod;
|
||||
|
||||
/* On the basis that the device independent mask is set, but there are
|
||||
* no device dependent flags set, we'll assume that we can't detect this
|
||||
* keyboard and revert to the unsided behavior.
|
||||
*/
|
||||
if ((device_dependent_mask & newMods) == 0) {
|
||||
/* Revert to the old behavior */
|
||||
HandleNonDeviceModifier(device_independent_mask, oldMods, newMods, left_scancode);
|
||||
return;
|
||||
}
|
||||
|
||||
/* XOR the previous state against the new state to see if there's a change */
|
||||
diff_mod = (device_dependent_mask & oldMods) ^
|
||||
(device_dependent_mask & newMods);
|
||||
if (diff_mod) {
|
||||
/* A change in state was found. Isolate the left and right bits
|
||||
* to handle them separately just in case the values can simulataneously
|
||||
* change or if the bits don't both exist.
|
||||
*/
|
||||
if (left_device_dependent_mask & diff_mod) {
|
||||
HandleModifierOneSide(oldMods, newMods, left_scancode, left_device_dependent_mask);
|
||||
}
|
||||
if (right_device_dependent_mask & diff_mod) {
|
||||
HandleModifierOneSide(oldMods, newMods, right_scancode, right_device_dependent_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a helper function for DoSidedModifiers.
|
||||
* This function will release a key press in the case that
|
||||
* it is clear that the modifier has been released (i.e. one side
|
||||
* can't still be down).
|
||||
*/
|
||||
static void
|
||||
ReleaseModifierSide(unsigned int device_independent_mask,
|
||||
unsigned int oldMods, unsigned int newMods,
|
||||
SDL_Scancode left_scancode,
|
||||
SDL_Scancode right_scancode,
|
||||
unsigned int left_device_dependent_mask,
|
||||
unsigned int right_device_dependent_mask)
|
||||
{
|
||||
unsigned int device_dependent_mask = (left_device_dependent_mask |
|
||||
right_device_dependent_mask);
|
||||
|
||||
/* On the basis that the device independent mask is set, but there are
|
||||
* no device dependent flags set, we'll assume that we can't detect this
|
||||
* keyboard and revert to the unsided behavior.
|
||||
*/
|
||||
if ((device_dependent_mask & oldMods) == 0) {
|
||||
/* In this case, we can't detect the keyboard, so use the left side
|
||||
* to represent both, and release it.
|
||||
*/
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This could have been done in an if-else case because at this point,
|
||||
* we know that all keys have been released when calling this function.
|
||||
* But I'm being paranoid so I want to handle each separately,
|
||||
* so I hope this doesn't cause other problems.
|
||||
*/
|
||||
if ( left_device_dependent_mask & oldMods ) {
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
|
||||
}
|
||||
if ( right_device_dependent_mask & oldMods ) {
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, right_scancode);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a helper function for DoSidedModifiers.
|
||||
* This function handles the CapsLock case.
|
||||
*/
|
||||
static void
|
||||
HandleCapsLock(unsigned short scancode,
|
||||
unsigned int oldMods, unsigned int newMods)
|
||||
{
|
||||
unsigned int oldMask, newMask;
|
||||
|
||||
oldMask = oldMods & NSAlphaShiftKeyMask;
|
||||
newMask = newMods & NSAlphaShiftKeyMask;
|
||||
|
||||
if (oldMask != newMask) {
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
|
||||
}
|
||||
|
||||
oldMask = oldMods & NSNumericPadKeyMask;
|
||||
newMask = newMods & NSNumericPadKeyMask;
|
||||
|
||||
if (oldMask != newMask) {
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_NUMLOCKCLEAR);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_NUMLOCKCLEAR);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function will handle the modifier keys and also determine the
|
||||
* correct side of the key.
|
||||
*/
|
||||
static void
|
||||
DoSidedModifiers(unsigned short scancode,
|
||||
unsigned int oldMods, unsigned int newMods)
|
||||
{
|
||||
/* Set up arrays for the key syms for the left and right side. */
|
||||
const SDL_Scancode left_mapping[] = {
|
||||
SDL_SCANCODE_LSHIFT,
|
||||
SDL_SCANCODE_LCTRL,
|
||||
SDL_SCANCODE_LALT,
|
||||
SDL_SCANCODE_LGUI
|
||||
};
|
||||
const SDL_Scancode right_mapping[] = {
|
||||
SDL_SCANCODE_RSHIFT,
|
||||
SDL_SCANCODE_RCTRL,
|
||||
SDL_SCANCODE_RALT,
|
||||
SDL_SCANCODE_RGUI
|
||||
};
|
||||
/* Set up arrays for the device dependent masks with indices that
|
||||
* correspond to the _mapping arrays
|
||||
*/
|
||||
const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
|
||||
const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
|
||||
|
||||
unsigned int i, bit;
|
||||
|
||||
/* Handle CAPSLOCK separately because it doesn't have a left/right side */
|
||||
HandleCapsLock(scancode, oldMods, newMods);
|
||||
|
||||
/* Iterate through the bits, testing each against the old modifiers */
|
||||
for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
|
||||
unsigned int oldMask, newMask;
|
||||
|
||||
oldMask = oldMods & bit;
|
||||
newMask = newMods & bit;
|
||||
|
||||
/* If the bit is set, we must always examine it because the left
|
||||
* and right side keys may alternate or both may be pressed.
|
||||
*/
|
||||
if (newMask) {
|
||||
HandleModifierSide(bit, oldMods, newMods,
|
||||
left_mapping[i], right_mapping[i],
|
||||
left_device_mapping[i], right_device_mapping[i]);
|
||||
}
|
||||
/* If the state changed from pressed to unpressed, we must examine
|
||||
* the device dependent bits to release the correct keys.
|
||||
*/
|
||||
else if (oldMask && oldMask != newMask) {
|
||||
ReleaseModifierSide(bit, oldMods, newMods,
|
||||
left_mapping[i], right_mapping[i],
|
||||
left_device_mapping[i], right_device_mapping[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
HandleModifiers(_THIS, unsigned short scancode, unsigned int modifierFlags)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
|
||||
if (modifierFlags == data->modifierFlags) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Starting with Panther (10.3.0), the ability to distinguish between
|
||||
* left side and right side modifiers is available.
|
||||
*/
|
||||
if (data->osversion >= 0x1030) {
|
||||
DoSidedModifiers(scancode, data->modifierFlags, modifierFlags);
|
||||
} else {
|
||||
DoUnsidedModifiers(scancode, data->modifierFlags, modifierFlags);
|
||||
}
|
||||
data->modifierFlags = modifierFlags;
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateKeymap(SDL_VideoData *data)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||
TISInputSourceRef key_layout;
|
||||
#else
|
||||
KeyboardLayoutRef key_layout;
|
||||
#endif
|
||||
const void *chr_data;
|
||||
int i;
|
||||
SDL_Scancode scancode;
|
||||
SDL_Keycode keymap[SDL_NUM_SCANCODES];
|
||||
|
||||
/* See if the keymap needs to be updated */
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||
key_layout = TISCopyCurrentKeyboardLayoutInputSource();
|
||||
#else
|
||||
KLGetCurrentKeyboardLayout(&key_layout);
|
||||
#endif
|
||||
if (key_layout == data->key_layout) {
|
||||
return;
|
||||
}
|
||||
data->key_layout = key_layout;
|
||||
|
||||
SDL_GetDefaultKeymap(keymap);
|
||||
|
||||
/* Try Unicode data first (preferred as of Mac OS X 10.5) */
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||
CFDataRef uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
|
||||
if (uchrDataRef)
|
||||
chr_data = CFDataGetBytePtr(uchrDataRef);
|
||||
else
|
||||
goto cleanup;
|
||||
#else
|
||||
KLGetKeyboardLayoutProperty(key_layout, kKLuchrData, &chr_data);
|
||||
#endif
|
||||
if (chr_data) {
|
||||
UInt32 keyboard_type = LMGetKbdType();
|
||||
OSStatus err;
|
||||
|
||||
for (i = 0; i < SDL_arraysize(darwin_scancode_table); i++) {
|
||||
UniChar s[8];
|
||||
UniCharCount len;
|
||||
UInt32 dead_key_state;
|
||||
|
||||
/* Make sure this scancode is a valid character scancode */
|
||||
scancode = darwin_scancode_table[i];
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN ||
|
||||
(keymap[scancode] & SDLK_SCANCODE_MASK)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dead_key_state = 0;
|
||||
err = UCKeyTranslate ((UCKeyboardLayout *) chr_data,
|
||||
i, kUCKeyActionDown,
|
||||
0, keyboard_type,
|
||||
kUCKeyTranslateNoDeadKeysMask,
|
||||
&dead_key_state, 8, &len, s);
|
||||
if (err != noErr)
|
||||
continue;
|
||||
|
||||
if (len > 0 && s[0] != 0x10) {
|
||||
keymap[scancode] = s[0];
|
||||
}
|
||||
}
|
||||
SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
|
||||
return;
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||
cleanup:
|
||||
CFRelease(key_layout);
|
||||
#else
|
||||
/* Fall back to older style key map data */
|
||||
KLGetKeyboardLayoutProperty(key_layout, kKLKCHRData, &chr_data);
|
||||
if (chr_data) {
|
||||
for (i = 0; i < 128; i++) {
|
||||
UInt32 c, state = 0;
|
||||
|
||||
/* Make sure this scancode is a valid character scancode */
|
||||
scancode = darwin_scancode_table[i];
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN ||
|
||||
(keymap[scancode] & SDLK_SCANCODE_MASK)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
c = KeyTranslate (chr_data, i, &state) & 255;
|
||||
if (state) {
|
||||
/* Dead key, process key up */
|
||||
c = KeyTranslate (chr_data, i | 128, &state) & 255;
|
||||
}
|
||||
|
||||
if (c != 0 && c != 0x10) {
|
||||
/* MacRoman to Unicode table, taken from X.org sources */
|
||||
static const unsigned short macroman_table[128] = {
|
||||
0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
|
||||
0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
|
||||
0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
|
||||
0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
|
||||
0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
|
||||
0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
|
||||
0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
|
||||
0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
|
||||
0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
|
||||
0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
|
||||
0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
|
||||
0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
|
||||
0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
|
||||
0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
|
||||
0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
|
||||
0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7,
|
||||
};
|
||||
|
||||
if (c >= 128) {
|
||||
c = macroman_table[c - 128];
|
||||
}
|
||||
keymap[scancode] = c;
|
||||
}
|
||||
}
|
||||
SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_InitKeyboard(_THIS)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
|
||||
UpdateKeymap(data);
|
||||
|
||||
/* Set our own names for the platform-dependent but layout-independent keys */
|
||||
/* This key is NumLock on the MacBook keyboard. :) */
|
||||
/*SDL_SetScancodeName(SDL_SCANCODE_NUMLOCKCLEAR, "Clear");*/
|
||||
SDL_SetScancodeName(SDL_SCANCODE_LALT, "Left Option");
|
||||
SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Command");
|
||||
SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option");
|
||||
SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command");
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_StartTextInput(_THIS)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSView *parentView = [[NSApp keyWindow] contentView];
|
||||
|
||||
/* We only keep one field editor per process, since only the front most
|
||||
* window can receive text input events, so it make no sense to keep more
|
||||
* than one copy. When we switched to another window and requesting for
|
||||
* text input, simply remove the field editor from its superview then add
|
||||
* it to the front most window's content view */
|
||||
if (!data->fieldEdit) {
|
||||
data->fieldEdit =
|
||||
[[SDLTranslatorResponder alloc] initWithFrame: NSMakeRect(0.0, 0.0, 0.0, 0.0)];
|
||||
}
|
||||
|
||||
if (![[data->fieldEdit superview] isEqual: parentView])
|
||||
{
|
||||
// DEBUG_IME(@"add fieldEdit to window contentView");
|
||||
[data->fieldEdit removeFromSuperview];
|
||||
[parentView addSubview: data->fieldEdit];
|
||||
[[NSApp keyWindow] makeFirstResponder: data->fieldEdit];
|
||||
}
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_StopTextInput(_THIS)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
|
||||
if (data && data->fieldEdit) {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[data->fieldEdit removeFromSuperview];
|
||||
[data->fieldEdit release];
|
||||
data->fieldEdit = nil;
|
||||
[pool release];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
|
||||
[data->fieldEdit setInputRect: rect];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
unsigned short scancode = [event keyCode];
|
||||
SDL_Scancode code;
|
||||
#if 0
|
||||
const char *text;
|
||||
#endif
|
||||
|
||||
if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) {
|
||||
/* see comments in SDL_cocoakeys.h */
|
||||
scancode = 60 - scancode;
|
||||
}
|
||||
if (scancode < SDL_arraysize(darwin_scancode_table)) {
|
||||
code = darwin_scancode_table[scancode];
|
||||
}
|
||||
else {
|
||||
/* Hmm, does this ever happen? If so, need to extend the keymap... */
|
||||
code = SDL_SCANCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
switch ([event type]) {
|
||||
case NSKeyDown:
|
||||
if (![event isARepeat]) {
|
||||
/* See if we need to rebuild the keyboard layout */
|
||||
UpdateKeymap(data);
|
||||
}
|
||||
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, code);
|
||||
#if 1
|
||||
if (code == SDL_SCANCODE_UNKNOWN) {
|
||||
fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL mailing list <sdl@libsdl.org> or to Christian Walther <cwalther@gmx.ch>. Mac virtual key code is %d.\n", scancode);
|
||||
}
|
||||
#endif
|
||||
if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
|
||||
/* FIXME CW 2007-08-16: only send those events to the field editor for which we actually want text events, not e.g. esc or function keys. Arrow keys in particular seem to produce crashes sometimes. */
|
||||
[data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
|
||||
#if 0
|
||||
text = [[event characters] UTF8String];
|
||||
if(text && *text) {
|
||||
SDL_SendKeyboardText(text);
|
||||
[data->fieldEdit setString:@""];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case NSKeyUp:
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, code);
|
||||
break;
|
||||
case NSFlagsChanged:
|
||||
/* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */
|
||||
HandleModifiers(_this, scancode, [event modifierFlags]);
|
||||
break;
|
||||
default: /* just to avoid compiler warnings */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_QuitKeyboard(_THIS)
|
||||
{
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_cocoamodes_h
|
||||
#define _SDL_cocoamodes_h
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CGDirectDisplayID display;
|
||||
} SDL_DisplayData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CFDictionaryRef moderef;
|
||||
} SDL_DisplayModeData;
|
||||
|
||||
extern void Cocoa_InitModes(_THIS);
|
||||
extern int Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
|
||||
extern void Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
|
||||
extern int Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
|
||||
extern void Cocoa_QuitModes(_THIS);
|
||||
|
||||
#endif /* _SDL_cocoamodes_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
|
||||
/*
|
||||
Add methods to get at private members of NSScreen.
|
||||
Since there is a bug in Apple's screen switching code
|
||||
that does not update this variable when switching
|
||||
to fullscreen, we'll set it manually (but only for the
|
||||
main screen).
|
||||
*/
|
||||
@interface NSScreen (NSScreenAccess)
|
||||
- (void) setFrame:(NSRect)frame;
|
||||
@end
|
||||
|
||||
@implementation NSScreen (NSScreenAccess)
|
||||
- (void) setFrame:(NSRect)frame;
|
||||
{
|
||||
_frame = frame;
|
||||
}
|
||||
@end
|
||||
#endif
|
||||
|
||||
static void
|
||||
CG_SetError(const char *prefix, CGDisplayErr result)
|
||||
{
|
||||
const char *error;
|
||||
|
||||
switch (result) {
|
||||
case kCGErrorFailure:
|
||||
error = "kCGErrorFailure";
|
||||
break;
|
||||
case kCGErrorIllegalArgument:
|
||||
error = "kCGErrorIllegalArgument";
|
||||
break;
|
||||
case kCGErrorInvalidConnection:
|
||||
error = "kCGErrorInvalidConnection";
|
||||
break;
|
||||
case kCGErrorInvalidContext:
|
||||
error = "kCGErrorInvalidContext";
|
||||
break;
|
||||
case kCGErrorCannotComplete:
|
||||
error = "kCGErrorCannotComplete";
|
||||
break;
|
||||
case kCGErrorNameTooLong:
|
||||
error = "kCGErrorNameTooLong";
|
||||
break;
|
||||
case kCGErrorNotImplemented:
|
||||
error = "kCGErrorNotImplemented";
|
||||
break;
|
||||
case kCGErrorRangeCheck:
|
||||
error = "kCGErrorRangeCheck";
|
||||
break;
|
||||
case kCGErrorTypeCheck:
|
||||
error = "kCGErrorTypeCheck";
|
||||
break;
|
||||
case kCGErrorNoCurrentPoint:
|
||||
error = "kCGErrorNoCurrentPoint";
|
||||
break;
|
||||
case kCGErrorInvalidOperation:
|
||||
error = "kCGErrorInvalidOperation";
|
||||
break;
|
||||
case kCGErrorNoneAvailable:
|
||||
error = "kCGErrorNoneAvailable";
|
||||
break;
|
||||
default:
|
||||
error = "Unknown Error";
|
||||
break;
|
||||
}
|
||||
SDL_SetError("%s: %s", prefix, error);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
GetDisplayMode(CFDictionaryRef moderef, SDL_DisplayMode *mode)
|
||||
{
|
||||
SDL_DisplayModeData *data;
|
||||
CFNumberRef number;
|
||||
long width, height, bpp, refreshRate;
|
||||
|
||||
data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
|
||||
if (!data) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
data->moderef = moderef;
|
||||
|
||||
number = CFDictionaryGetValue(moderef, kCGDisplayWidth);
|
||||
CFNumberGetValue(number, kCFNumberLongType, &width);
|
||||
number = CFDictionaryGetValue(moderef, kCGDisplayHeight);
|
||||
CFNumberGetValue(number, kCFNumberLongType, &height);
|
||||
number = CFDictionaryGetValue(moderef, kCGDisplayBitsPerPixel);
|
||||
CFNumberGetValue(number, kCFNumberLongType, &bpp);
|
||||
number = CFDictionaryGetValue(moderef, kCGDisplayRefreshRate);
|
||||
CFNumberGetValue(number, kCFNumberLongType, &refreshRate);
|
||||
|
||||
mode->format = SDL_PIXELFORMAT_UNKNOWN;
|
||||
switch (bpp) {
|
||||
case 8:
|
||||
/* We don't support palettized modes now */
|
||||
return SDL_FALSE;
|
||||
case 16:
|
||||
mode->format = SDL_PIXELFORMAT_ARGB1555;
|
||||
break;
|
||||
case 32:
|
||||
mode->format = SDL_PIXELFORMAT_ARGB8888;
|
||||
break;
|
||||
}
|
||||
mode->w = width;
|
||||
mode->h = height;
|
||||
mode->refresh_rate = refreshRate;
|
||||
mode->driverdata = data;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_InitModes(_THIS)
|
||||
{
|
||||
CGDisplayErr result;
|
||||
CGDirectDisplayID *displays;
|
||||
CGDisplayCount numDisplays;
|
||||
int pass, i;
|
||||
|
||||
result = CGGetOnlineDisplayList(0, NULL, &numDisplays);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGGetOnlineDisplayList()", result);
|
||||
return;
|
||||
}
|
||||
displays = SDL_stack_alloc(CGDirectDisplayID, numDisplays);
|
||||
result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGGetOnlineDisplayList()", result);
|
||||
SDL_stack_free(displays);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Pick up the primary display in the first pass, then get the rest */
|
||||
for (pass = 0; pass < 2; ++pass) {
|
||||
for (i = 0; i < numDisplays; ++i) {
|
||||
SDL_VideoDisplay display;
|
||||
SDL_DisplayData *displaydata;
|
||||
SDL_DisplayMode mode;
|
||||
CFDictionaryRef moderef;
|
||||
|
||||
if (pass == 0) {
|
||||
if (!CGDisplayIsMain(displays[i])) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (CGDisplayIsMain(displays[i])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay) {
|
||||
continue;
|
||||
}
|
||||
moderef = CGDisplayCurrentMode(displays[i]);
|
||||
if (!moderef) {
|
||||
continue;
|
||||
}
|
||||
|
||||
displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
|
||||
if (!displaydata) {
|
||||
continue;
|
||||
}
|
||||
displaydata->display = displays[i];
|
||||
|
||||
SDL_zero(display);
|
||||
if (!GetDisplayMode (moderef, &mode)) {
|
||||
SDL_free(displaydata);
|
||||
continue;
|
||||
}
|
||||
display.desktop_mode = mode;
|
||||
display.current_mode = mode;
|
||||
display.driverdata = displaydata;
|
||||
SDL_AddVideoDisplay(&display);
|
||||
}
|
||||
}
|
||||
SDL_stack_free(displays);
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
|
||||
{
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
|
||||
CGRect cgrect;
|
||||
|
||||
cgrect = CGDisplayBounds(displaydata->display);
|
||||
rect->x = (int)cgrect.origin.x;
|
||||
rect->y = (int)cgrect.origin.y;
|
||||
rect->w = (int)cgrect.size.width;
|
||||
rect->h = (int)cgrect.size.height;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
AddDisplayMode(const void *moderef, void *context)
|
||||
{
|
||||
SDL_VideoDisplay *display = (SDL_VideoDisplay *) context;
|
||||
SDL_DisplayMode mode;
|
||||
|
||||
if (GetDisplayMode(moderef, &mode)) {
|
||||
SDL_AddDisplayMode(display, &mode);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
|
||||
{
|
||||
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
|
||||
CFArrayRef modes;
|
||||
CFRange range;
|
||||
|
||||
modes = CGDisplayAvailableModes(data->display);
|
||||
if (!modes) {
|
||||
return;
|
||||
}
|
||||
range.location = 0;
|
||||
range.length = CFArrayGetCount(modes);
|
||||
CFArrayApplyFunction(modes, range, AddDisplayMode, display);
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
|
||||
{
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
|
||||
SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
|
||||
CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
|
||||
CGError result;
|
||||
|
||||
/* Fade to black to hide resolution-switching flicker */
|
||||
if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) {
|
||||
CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
|
||||
}
|
||||
|
||||
if (data == display->desktop_mode.driverdata) {
|
||||
/* Restoring desktop mode */
|
||||
CGDisplaySwitchToMode(displaydata->display, data->moderef);
|
||||
|
||||
if (CGDisplayIsMain(displaydata->display)) {
|
||||
CGReleaseAllDisplays();
|
||||
} else {
|
||||
CGDisplayRelease(displaydata->display);
|
||||
}
|
||||
|
||||
if (CGDisplayIsMain(displaydata->display)) {
|
||||
ShowMenuBar();
|
||||
}
|
||||
} else {
|
||||
/* Put up the blanking window (a window above all other windows) */
|
||||
if (CGDisplayIsMain(displaydata->display)) {
|
||||
/* If we don't capture all displays, Cocoa tries to rearrange windows... *sigh* */
|
||||
result = CGCaptureAllDisplays();
|
||||
} else {
|
||||
result = CGDisplayCapture(displaydata->display);
|
||||
}
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGDisplayCapture()", result);
|
||||
goto ERR_NO_CAPTURE;
|
||||
}
|
||||
|
||||
/* Do the physical switch */
|
||||
result = CGDisplaySwitchToMode(displaydata->display, data->moderef);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGDisplaySwitchToMode()", result);
|
||||
goto ERR_NO_SWITCH;
|
||||
}
|
||||
|
||||
/* Hide the menu bar so it doesn't intercept events */
|
||||
if (CGDisplayIsMain(displaydata->display)) {
|
||||
HideMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
/* Fade in again (asynchronously) */
|
||||
if (fade_token != kCGDisplayFadeReservationInvalidToken) {
|
||||
CGDisplayFade(fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
|
||||
CGReleaseDisplayFadeReservation(fade_token);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
/* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
|
||||
ERR_NO_SWITCH:
|
||||
CGDisplayRelease(displaydata->display);
|
||||
ERR_NO_CAPTURE:
|
||||
if (fade_token != kCGDisplayFadeReservationInvalidToken) {
|
||||
CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
|
||||
CGReleaseDisplayFadeReservation(fade_token);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_QuitModes(_THIS)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _this->num_displays; ++i) {
|
||||
SDL_VideoDisplay *display = &_this->displays[i];
|
||||
|
||||
if (display->current_mode.driverdata != display->desktop_mode.driverdata) {
|
||||
Cocoa_SetDisplayMode(_this, display, &display->desktop_mode);
|
||||
}
|
||||
}
|
||||
ShowMenuBar();
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_cocoamouse_h
|
||||
#define _SDL_cocoamouse_h
|
||||
|
||||
extern void Cocoa_InitMouse(_THIS);
|
||||
extern void Cocoa_HandleMouseEvent(_THIS, NSEvent * event);
|
||||
extern void Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent * event);
|
||||
extern void Cocoa_QuitMouse(_THIS);
|
||||
|
||||
#endif /* _SDL_cocoamouse_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_cocoavideo.h"
|
||||
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
|
||||
|
||||
static SDL_Cursor *
|
||||
Cocoa_CreateDefaultCursor()
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSCursor *nscursor;
|
||||
SDL_Cursor *cursor = NULL;
|
||||
|
||||
nscursor = [NSCursor arrowCursor];
|
||||
|
||||
if (nscursor) {
|
||||
cursor = SDL_calloc(1, sizeof(*cursor));
|
||||
if (cursor) {
|
||||
cursor->driverdata = nscursor;
|
||||
[nscursor retain];
|
||||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static SDL_Cursor *
|
||||
Cocoa_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSImage *nsimage;
|
||||
NSCursor *nscursor = NULL;
|
||||
SDL_Cursor *cursor = NULL;
|
||||
|
||||
nsimage = Cocoa_CreateImage(surface);
|
||||
if (nsimage) {
|
||||
nscursor = [[NSCursor alloc] initWithImage: nsimage hotSpot: NSMakePoint(hot_x, hot_y)];
|
||||
}
|
||||
|
||||
if (nscursor) {
|
||||
cursor = SDL_calloc(1, sizeof(*cursor));
|
||||
if (cursor) {
|
||||
cursor->driverdata = nscursor;
|
||||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
Cocoa_FreeCursor(SDL_Cursor * cursor)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSCursor *nscursor = (NSCursor *)cursor->driverdata;
|
||||
|
||||
[nscursor release];
|
||||
SDL_free(cursor);
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
static int
|
||||
Cocoa_ShowCursor(SDL_Cursor * cursor)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (SDL_GetMouseFocus()) {
|
||||
if (cursor) {
|
||||
NSCursor *nscursor = (NSCursor *)cursor->driverdata;
|
||||
|
||||
[nscursor set];
|
||||
[NSCursor unhide];
|
||||
} else {
|
||||
[NSCursor hide];
|
||||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
Cocoa_WarpMouse(SDL_Window * window, int x, int y)
|
||||
{
|
||||
CGPoint point;
|
||||
|
||||
point.x = (float)window->x + x;
|
||||
point.y = (float)window->y + y;
|
||||
CGWarpMouseCursorPosition(point);
|
||||
}
|
||||
|
||||
static int
|
||||
Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
CGError result;
|
||||
|
||||
if (enabled) {
|
||||
result = CGAssociateMouseAndMouseCursorPosition(NO);
|
||||
} else {
|
||||
result = CGAssociateMouseAndMouseCursorPosition(YES);
|
||||
}
|
||||
if (result != kCGErrorSuccess) {
|
||||
SDL_SetError("CGAssociateMouseAndMouseCursorPosition() failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_InitMouse(_THIS)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
mouse->CreateCursor = Cocoa_CreateCursor;
|
||||
mouse->ShowCursor = Cocoa_ShowCursor;
|
||||
mouse->FreeCursor = Cocoa_FreeCursor;
|
||||
mouse->WarpMouse = Cocoa_WarpMouse;
|
||||
mouse->SetRelativeMouseMode = Cocoa_SetRelativeMouseMode;
|
||||
|
||||
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
|
||||
}
|
||||
|
||||
static int
|
||||
ConvertMouseButtonToSDL(int button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case 0:
|
||||
return(SDL_BUTTON_LEFT); /* 1 */
|
||||
case 1:
|
||||
return(SDL_BUTTON_RIGHT); /* 3 */
|
||||
case 2:
|
||||
return(SDL_BUTTON_MIDDLE); /* 2 */
|
||||
}
|
||||
return button+1;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (mouse->relative_mode &&
|
||||
([event type] == NSMouseMoved ||
|
||||
[event type] == NSLeftMouseDragged ||
|
||||
[event type] == NSRightMouseDragged ||
|
||||
[event type] == NSOtherMouseDragged)) {
|
||||
float x = [event deltaX];
|
||||
float y = [event deltaY];
|
||||
SDL_SendMouseMotion(mouse->focus, 1, (int)x, (int)y);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
|
||||
{
|
||||
float x = [event deltaX];
|
||||
float y = [event deltaY];
|
||||
|
||||
if (x > 0) {
|
||||
x += 0.9f;
|
||||
} else if (x < 0) {
|
||||
x -= 0.9f;
|
||||
}
|
||||
if (y > 0) {
|
||||
y += 0.9f;
|
||||
} else if (y < 0) {
|
||||
y -= 0.9f;
|
||||
}
|
||||
SDL_SendMouseWheel(window, (int)x, (int)y);
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_QuitMouse(_THIS)
|
||||
{
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_cocoaopengl_h
|
||||
#define _SDL_cocoaopengl_h
|
||||
|
||||
#if SDL_VIDEO_OPENGL_CGL
|
||||
|
||||
/* Define this if you want to be able to toggle fullscreen mode seamlessly */
|
||||
#define FULLSCREEN_TOGGLEABLE
|
||||
|
||||
struct SDL_GLDriverData
|
||||
{
|
||||
int initialized;
|
||||
};
|
||||
|
||||
/* OpenGL functions */
|
||||
extern int Cocoa_GL_LoadLibrary(_THIS, const char *path);
|
||||
extern void *Cocoa_GL_GetProcAddress(_THIS, const char *proc);
|
||||
extern void Cocoa_GL_UnloadLibrary(_THIS);
|
||||
extern SDL_GLContext Cocoa_GL_CreateContext(_THIS, SDL_Window * window);
|
||||
extern int Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window,
|
||||
SDL_GLContext context);
|
||||
extern int Cocoa_GL_SetSwapInterval(_THIS, int interval);
|
||||
extern int Cocoa_GL_GetSwapInterval(_THIS);
|
||||
extern void Cocoa_GL_SwapWindow(_THIS, SDL_Window * window);
|
||||
extern void Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context);
|
||||
|
||||
#endif /* SDL_VIDEO_OPENGL_CGL */
|
||||
|
||||
#endif /* _SDL_cocoaopengl_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
|
||||
/* NSOpenGL implementation of SDL OpenGL support */
|
||||
|
||||
#if SDL_VIDEO_OPENGL_CGL
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenGL/CGLRenderers.h>
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_opengl.h"
|
||||
|
||||
|
||||
#define DEFAULT_OPENGL "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
|
||||
|
||||
int
|
||||
Cocoa_GL_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
/* Load the OpenGL library */
|
||||
if (path == NULL) {
|
||||
path = SDL_getenv("SDL_OPENGL_LIBRARY");
|
||||
}
|
||||
if (path == NULL) {
|
||||
path = DEFAULT_OPENGL;
|
||||
}
|
||||
_this->gl_config.dll_handle = SDL_LoadObject(path);
|
||||
if (!_this->gl_config.dll_handle) {
|
||||
return -1;
|
||||
}
|
||||
SDL_strlcpy(_this->gl_config.driver_path, path,
|
||||
SDL_arraysize(_this->gl_config.driver_path));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *
|
||||
Cocoa_GL_GetProcAddress(_THIS, const char *proc)
|
||||
{
|
||||
return SDL_LoadFunction(_this->gl_config.dll_handle, proc);
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_GL_UnloadLibrary(_THIS)
|
||||
{
|
||||
SDL_UnloadObject(_this->gl_config.dll_handle);
|
||||
_this->gl_config.dll_handle = NULL;
|
||||
}
|
||||
|
||||
SDL_GLContext
|
||||
Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
|
||||
NSOpenGLPixelFormatAttribute attr[32];
|
||||
NSOpenGLPixelFormat *fmt;
|
||||
NSOpenGLContext *context;
|
||||
int i = 0;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
#ifndef FULLSCREEN_TOGGLEABLE
|
||||
if (window->flags & SDL_WINDOW_FULLSCREEN) {
|
||||
attr[i++] = NSOpenGLPFAFullScreen;
|
||||
}
|
||||
#endif
|
||||
|
||||
attr[i++] = NSOpenGLPFAColorSize;
|
||||
attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
|
||||
|
||||
attr[i++] = NSOpenGLPFADepthSize;
|
||||
attr[i++] = _this->gl_config.depth_size;
|
||||
|
||||
if (_this->gl_config.double_buffer) {
|
||||
attr[i++] = NSOpenGLPFADoubleBuffer;
|
||||
}
|
||||
|
||||
if (_this->gl_config.stereo) {
|
||||
attr[i++] = NSOpenGLPFAStereo;
|
||||
}
|
||||
|
||||
if (_this->gl_config.stencil_size) {
|
||||
attr[i++] = NSOpenGLPFAStencilSize;
|
||||
attr[i++] = _this->gl_config.stencil_size;
|
||||
}
|
||||
|
||||
if ((_this->gl_config.accum_red_size +
|
||||
_this->gl_config.accum_green_size +
|
||||
_this->gl_config.accum_blue_size +
|
||||
_this->gl_config.accum_alpha_size) > 0) {
|
||||
attr[i++] = NSOpenGLPFAAccumSize;
|
||||
attr[i++] = _this->gl_config.accum_red_size + _this->gl_config.accum_green_size + _this->gl_config.accum_blue_size + _this->gl_config.accum_alpha_size;
|
||||
}
|
||||
|
||||
if (_this->gl_config.multisamplebuffers) {
|
||||
attr[i++] = NSOpenGLPFASampleBuffers;
|
||||
attr[i++] = _this->gl_config.multisamplebuffers;
|
||||
}
|
||||
|
||||
if (_this->gl_config.multisamplesamples) {
|
||||
attr[i++] = NSOpenGLPFASamples;
|
||||
attr[i++] = _this->gl_config.multisamplesamples;
|
||||
attr[i++] = NSOpenGLPFANoRecovery;
|
||||
}
|
||||
|
||||
if (_this->gl_config.accelerated >= 0) {
|
||||
if (_this->gl_config.accelerated) {
|
||||
attr[i++] = NSOpenGLPFAAccelerated;
|
||||
} else {
|
||||
attr[i++] = NSOpenGLPFARendererID;
|
||||
attr[i++] = kCGLRendererGenericFloatID;
|
||||
}
|
||||
}
|
||||
|
||||
attr[i++] = NSOpenGLPFAScreenMask;
|
||||
attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
|
||||
attr[i] = 0;
|
||||
|
||||
fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
|
||||
if (fmt == nil) {
|
||||
SDL_SetError ("Failed creating OpenGL pixel format");
|
||||
[pool release];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
|
||||
|
||||
[fmt release];
|
||||
|
||||
if (context == nil) {
|
||||
SDL_SetError ("Failed creating OpenGL context");
|
||||
[pool release];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
|
||||
* "You are blowing a couple of the internal OpenGL function caches. This
|
||||
* appears to be happening in the VAO case. You can tell OpenGL to up
|
||||
* the cache size by issuing the following calls right after you create
|
||||
* the OpenGL context. The default cache size is 16." --ryan.
|
||||
*/
|
||||
|
||||
#ifndef GLI_ARRAY_FUNC_CACHE_MAX
|
||||
#define GLI_ARRAY_FUNC_CACHE_MAX 284
|
||||
#endif
|
||||
|
||||
#ifndef GLI_SUBMIT_FUNC_CACHE_MAX
|
||||
#define GLI_SUBMIT_FUNC_CACHE_MAX 280
|
||||
#endif
|
||||
|
||||
{
|
||||
GLint cache_max = 64;
|
||||
CGLContextObj ctx = [context CGLContextObj];
|
||||
CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
|
||||
CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
|
||||
}
|
||||
|
||||
/* End Wisdom from Apple Engineer section. --ryan. */
|
||||
|
||||
[pool release];
|
||||
|
||||
if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
|
||||
Cocoa_GL_DeleteContext(_this, context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (context) {
|
||||
SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
|
||||
NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
|
||||
|
||||
#ifndef FULLSCREEN_TOGGLEABLE
|
||||
if (window->flags & SDL_WINDOW_FULLSCREEN) {
|
||||
[nscontext setFullScreen];
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
[nscontext setView:[windowdata->nswindow contentView]];
|
||||
[nscontext update];
|
||||
}
|
||||
[nscontext makeCurrentContext];
|
||||
} else {
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
|
||||
[pool release];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_GL_SetSwapInterval(_THIS, int interval)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NSOpenGLContext *nscontext;
|
||||
GLint value;
|
||||
int status;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
nscontext = [NSOpenGLContext currentContext];
|
||||
if (nscontext != nil) {
|
||||
value = interval;
|
||||
[nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
|
||||
status = 0;
|
||||
} else {
|
||||
SDL_SetError("No current OpenGL context");
|
||||
status = -1;
|
||||
}
|
||||
|
||||
[pool release];
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_GL_GetSwapInterval(_THIS)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NSOpenGLContext *nscontext;
|
||||
GLint value;
|
||||
int status;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
nscontext = [NSOpenGLContext currentContext];
|
||||
if (nscontext != nil) {
|
||||
[nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
|
||||
status = (int)value;
|
||||
} else {
|
||||
SDL_SetError("No current OpenGL context");
|
||||
status = -1;
|
||||
}
|
||||
|
||||
[pool release];
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NSOpenGLContext *nscontext;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
/* FIXME: Do we need to get the context for the window? */
|
||||
nscontext = [NSOpenGLContext currentContext];
|
||||
if (nscontext != nil) {
|
||||
[nscontext flushBuffer];
|
||||
}
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
[nscontext clearDrawable];
|
||||
[nscontext release];
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_OPENGL_CGL */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_cocoashape_h
|
||||
#define _SDL_cocoashape_h
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_shape.h"
|
||||
#include "../SDL_shape_internals.h"
|
||||
|
||||
typedef struct {
|
||||
NSGraphicsContext* context;
|
||||
SDL_bool saved;
|
||||
|
||||
SDL_ShapeTree* shape;
|
||||
} SDL_ShapeData;
|
||||
|
||||
extern SDL_WindowShaper* Cocoa_CreateShaper(SDL_Window* window);
|
||||
extern int Cocoa_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode);
|
||||
extern int Cocoa_ResizeWindowShape(SDL_Window *window);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "SDL_shape.h"
|
||||
#include "SDL_cocoashape.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
SDL_WindowShaper*
|
||||
Cocoa_CreateShaper(SDL_Window* window) {
|
||||
SDL_WindowData* windata = (SDL_WindowData*)window->driverdata;
|
||||
[windata->nswindow setOpaque:NO];
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
|
||||
[windata->nswindow setStyleMask:NSBorderlessWindowMask];
|
||||
#endif
|
||||
SDL_WindowShaper* result = result = malloc(sizeof(SDL_WindowShaper));
|
||||
result->window = window;
|
||||
result->mode.mode = ShapeModeDefault;
|
||||
result->mode.parameters.binarizationCutoff = 1;
|
||||
result->userx = result->usery = 0;
|
||||
window->shaper = result;
|
||||
|
||||
SDL_ShapeData* data = malloc(sizeof(SDL_ShapeData));
|
||||
result->driverdata = data;
|
||||
data->context = [windata->nswindow graphicsContext];
|
||||
data->saved = SDL_FALSE;
|
||||
data->shape = NULL;
|
||||
|
||||
int resized_properly = Cocoa_ResizeWindowShape(window);
|
||||
assert(resized_properly == 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
NSView* view;
|
||||
NSBezierPath* path;
|
||||
SDL_Window* window;
|
||||
} SDL_CocoaClosure;
|
||||
|
||||
void
|
||||
ConvertRects(SDL_ShapeTree* tree,void* closure) {
|
||||
SDL_CocoaClosure* data = (SDL_CocoaClosure*)closure;
|
||||
if(tree->kind == OpaqueShape) {
|
||||
NSRect rect = NSMakeRect(tree->data.shape.x,data->window->h - tree->data.shape.y,tree->data.shape.w,tree->data.shape.h);
|
||||
[data->path appendBezierPathWithRect:[data->view convertRect:rect toView:nil]];
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode) {
|
||||
SDL_ShapeData* data = (SDL_ShapeData*)shaper->driverdata;
|
||||
SDL_WindowData* windata = (SDL_WindowData*)shaper->window->driverdata;
|
||||
SDL_CocoaClosure closure;
|
||||
NSAutoreleasePool *pool = NULL;
|
||||
if(data->saved == SDL_TRUE) {
|
||||
[data->context restoreGraphicsState];
|
||||
data->saved = SDL_FALSE;
|
||||
}
|
||||
|
||||
//[data->context saveGraphicsState];
|
||||
//data->saved = SDL_TRUE;
|
||||
[NSGraphicsContext setCurrentContext:data->context];
|
||||
|
||||
[[NSColor clearColor] set];
|
||||
NSRectFill([[windata->nswindow contentView] frame]);
|
||||
data->shape = SDL_CalculateShapeTree(*shape_mode,shape);
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
closure.view = [windata->nswindow contentView];
|
||||
closure.path = [[NSBezierPath bezierPath] autorelease];
|
||||
closure.window = shaper->window;
|
||||
SDL_TraverseShapeTree(data->shape,&ConvertRects,&closure);
|
||||
[closure.path addClip];
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_ResizeWindowShape(SDL_Window *window) {
|
||||
SDL_ShapeData* data = window->shaper->driverdata;
|
||||
assert(data != NULL);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_cocoavideo_h
|
||||
#define _SDL_cocoavideo_h
|
||||
|
||||
#include "SDL_opengl.h"
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
#include "SDL_keycode.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#include "SDL_cocoaclipboard.h"
|
||||
#include "SDL_cocoaevents.h"
|
||||
#include "SDL_cocoakeyboard.h"
|
||||
#include "SDL_cocoamodes.h"
|
||||
#include "SDL_cocoamouse.h"
|
||||
#include "SDL_cocoaopengl.h"
|
||||
#include "SDL_cocoawindow.h"
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
|
||||
#if __LP64__
|
||||
typedef long NSInteger;
|
||||
typedef unsigned long NSUInteger;
|
||||
#else
|
||||
typedef int NSInteger;
|
||||
typedef unsigned int NSUInteger;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Private display data */
|
||||
|
||||
@class SDLTranslatorResponder;
|
||||
|
||||
typedef struct SDL_VideoData
|
||||
{
|
||||
SInt32 osversion;
|
||||
unsigned int modifierFlags;
|
||||
void *key_layout;
|
||||
SDLTranslatorResponder *fieldEdit;
|
||||
NSInteger clipboard_count;
|
||||
Uint32 screensaver_activity;
|
||||
} SDL_VideoData;
|
||||
|
||||
/* Utility functions */
|
||||
extern NSImage * Cocoa_CreateImage(SDL_Surface * surface);
|
||||
|
||||
#endif /* _SDL_cocoavideo_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "SDL_cocoashape.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int Cocoa_VideoInit(_THIS);
|
||||
static void Cocoa_VideoQuit(_THIS);
|
||||
|
||||
/* Cocoa driver bootstrap functions */
|
||||
|
||||
static int
|
||||
Cocoa_Available(void)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
Cocoa_DeleteDevice(SDL_VideoDevice * device)
|
||||
{
|
||||
SDL_free(device->driverdata);
|
||||
SDL_free(device);
|
||||
}
|
||||
|
||||
static SDL_VideoDevice *
|
||||
Cocoa_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_VideoDevice *device;
|
||||
SDL_VideoData *data;
|
||||
|
||||
Cocoa_RegisterApp();
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||
if (device) {
|
||||
data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
|
||||
} else {
|
||||
data = NULL;
|
||||
}
|
||||
if (!data) {
|
||||
SDL_OutOfMemory();
|
||||
if (device) {
|
||||
SDL_free(device);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
device->driverdata = data;
|
||||
|
||||
/* Find out what version of Mac OS X we're running */
|
||||
Gestalt(gestaltSystemVersion, &data->osversion);
|
||||
|
||||
/* Set the function pointers */
|
||||
device->VideoInit = Cocoa_VideoInit;
|
||||
device->VideoQuit = Cocoa_VideoQuit;
|
||||
device->GetDisplayBounds = Cocoa_GetDisplayBounds;
|
||||
device->GetDisplayModes = Cocoa_GetDisplayModes;
|
||||
device->SetDisplayMode = Cocoa_SetDisplayMode;
|
||||
device->PumpEvents = Cocoa_PumpEvents;
|
||||
|
||||
device->CreateWindow = Cocoa_CreateWindow;
|
||||
device->CreateWindowFrom = Cocoa_CreateWindowFrom;
|
||||
device->SetWindowTitle = Cocoa_SetWindowTitle;
|
||||
device->SetWindowIcon = Cocoa_SetWindowIcon;
|
||||
device->SetWindowPosition = Cocoa_SetWindowPosition;
|
||||
device->SetWindowSize = Cocoa_SetWindowSize;
|
||||
device->ShowWindow = Cocoa_ShowWindow;
|
||||
device->HideWindow = Cocoa_HideWindow;
|
||||
device->RaiseWindow = Cocoa_RaiseWindow;
|
||||
device->MaximizeWindow = Cocoa_MaximizeWindow;
|
||||
device->MinimizeWindow = Cocoa_MinimizeWindow;
|
||||
device->RestoreWindow = Cocoa_RestoreWindow;
|
||||
device->SetWindowFullscreen = Cocoa_SetWindowFullscreen;
|
||||
device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
|
||||
device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
|
||||
device->SetWindowGrab = Cocoa_SetWindowGrab;
|
||||
device->DestroyWindow = Cocoa_DestroyWindow;
|
||||
device->GetWindowWMInfo = Cocoa_GetWindowWMInfo;
|
||||
|
||||
device->shape_driver.CreateShaper = Cocoa_CreateShaper;
|
||||
device->shape_driver.SetWindowShape = Cocoa_SetWindowShape;
|
||||
device->shape_driver.ResizeWindowShape = Cocoa_ResizeWindowShape;
|
||||
|
||||
#if SDL_VIDEO_OPENGL_CGL
|
||||
device->GL_LoadLibrary = Cocoa_GL_LoadLibrary;
|
||||
device->GL_GetProcAddress = Cocoa_GL_GetProcAddress;
|
||||
device->GL_UnloadLibrary = Cocoa_GL_UnloadLibrary;
|
||||
device->GL_CreateContext = Cocoa_GL_CreateContext;
|
||||
device->GL_MakeCurrent = Cocoa_GL_MakeCurrent;
|
||||
device->GL_SetSwapInterval = Cocoa_GL_SetSwapInterval;
|
||||
device->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval;
|
||||
device->GL_SwapWindow = Cocoa_GL_SwapWindow;
|
||||
device->GL_DeleteContext = Cocoa_GL_DeleteContext;
|
||||
#endif
|
||||
|
||||
device->StartTextInput = Cocoa_StartTextInput;
|
||||
device->StopTextInput = Cocoa_StopTextInput;
|
||||
device->SetTextInputRect = Cocoa_SetTextInputRect;
|
||||
|
||||
device->SetClipboardText = Cocoa_SetClipboardText;
|
||||
device->GetClipboardText = Cocoa_GetClipboardText;
|
||||
device->HasClipboardText = Cocoa_HasClipboardText;
|
||||
|
||||
device->free = Cocoa_DeleteDevice;
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
VideoBootStrap COCOA_bootstrap = {
|
||||
"cocoa", "SDL Cocoa video driver",
|
||||
Cocoa_Available, Cocoa_CreateDevice
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
Cocoa_VideoInit(_THIS)
|
||||
{
|
||||
Cocoa_InitModes(_this);
|
||||
Cocoa_InitKeyboard(_this);
|
||||
Cocoa_InitMouse(_this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_VideoQuit(_THIS)
|
||||
{
|
||||
Cocoa_QuitModes(_this);
|
||||
Cocoa_QuitKeyboard(_this);
|
||||
Cocoa_QuitMouse(_this);
|
||||
}
|
||||
|
||||
/* This function assumes that it's called from within an autorelease pool */
|
||||
NSImage *
|
||||
Cocoa_CreateImage(SDL_Surface * surface)
|
||||
{
|
||||
SDL_Surface *converted;
|
||||
NSBitmapImageRep *imgrep;
|
||||
Uint8 *pixels;
|
||||
int i;
|
||||
NSImage *img;
|
||||
|
||||
converted = SDL_ConvertSurfaceFormat(surface,
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
SDL_PIXELFORMAT_RGBA8888,
|
||||
#else
|
||||
SDL_PIXELFORMAT_ABGR8888,
|
||||
#endif
|
||||
0);
|
||||
if (!converted) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
imgrep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
|
||||
pixelsWide: converted->w
|
||||
pixelsHigh: converted->h
|
||||
bitsPerSample: 8
|
||||
samplesPerPixel: 4
|
||||
hasAlpha: YES
|
||||
isPlanar: NO
|
||||
colorSpaceName: NSDeviceRGBColorSpace
|
||||
bytesPerRow: converted->pitch
|
||||
bitsPerPixel: converted->format->BitsPerPixel] autorelease];
|
||||
if (imgrep == nil) {
|
||||
SDL_FreeSurface(converted);
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* Copy the pixels */
|
||||
pixels = [imgrep bitmapData];
|
||||
SDL_memcpy(pixels, converted->pixels, converted->h * converted->pitch);
|
||||
SDL_FreeSurface(converted);
|
||||
|
||||
/* Premultiply the alpha channel */
|
||||
for (i = (converted->h * converted->w); i--; ) {
|
||||
Uint8 alpha = pixels[3];
|
||||
pixels[0] = (Uint8)(((Uint16)pixels[0] * alpha) / 255);
|
||||
pixels[1] = (Uint8)(((Uint16)pixels[1] * alpha) / 255);
|
||||
pixels[2] = (Uint8)(((Uint16)pixels[2] * alpha) / 255);
|
||||
pixels += 4;
|
||||
}
|
||||
|
||||
img = [[[NSImage alloc] initWithSize: NSMakeSize(surface->w, surface->h)] autorelease];
|
||||
if (img != nil) {
|
||||
[img addRepresentation: imgrep];
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mac OS X assertion support.
|
||||
*
|
||||
* This doesn't really have aything to do with the interfaces of the SDL video
|
||||
* subsystem, but we need to stuff this into an Objective-C source code file.
|
||||
*/
|
||||
|
||||
SDL_assert_state
|
||||
SDL_PromptAssertion_cocoa(const SDL_assert_data *data)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSString *msg = [NSString stringWithFormat:
|
||||
@"Assertion failure at %s (%s:%d), triggered %u time%s:\n '%s'",
|
||||
data->function, data->filename, data->linenum,
|
||||
data->trigger_count, (data->trigger_count == 1) ? "" : "s",
|
||||
data->condition];
|
||||
|
||||
NSLog(@"%s", msg);
|
||||
|
||||
/*
|
||||
* !!! FIXME: this code needs to deal with fullscreen modes:
|
||||
* !!! FIXME: reset to default desktop, runModal, reset to current?
|
||||
*/
|
||||
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
[alert setAlertStyle:NSCriticalAlertStyle];
|
||||
[alert setMessageText:msg];
|
||||
[alert addButtonWithTitle:@"Retry"];
|
||||
[alert addButtonWithTitle:@"Break"];
|
||||
[alert addButtonWithTitle:@"Abort"];
|
||||
[alert addButtonWithTitle:@"Ignore"];
|
||||
[alert addButtonWithTitle:@"Always Ignore"];
|
||||
const NSInteger clicked = [alert runModal];
|
||||
[pool release];
|
||||
return (SDL_assert_state) (clicked - NSAlertFirstButtonReturn);
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_cocoawindow_h
|
||||
#define _SDL_cocoawindow_h
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
typedef struct SDL_WindowData SDL_WindowData;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
|
||||
@interface Cocoa_WindowListener : NSResponder <NSWindowDelegate> {
|
||||
#else
|
||||
@interface Cocoa_WindowListener : NSResponder {
|
||||
#endif
|
||||
SDL_WindowData *_data;
|
||||
}
|
||||
|
||||
-(void) listen:(SDL_WindowData *) data;
|
||||
-(void) close;
|
||||
|
||||
/* Window delegate functionality */
|
||||
-(BOOL) windowShouldClose:(id) sender;
|
||||
-(void) windowDidExpose:(NSNotification *) aNotification;
|
||||
-(void) windowDidMove:(NSNotification *) aNotification;
|
||||
-(void) windowDidResize:(NSNotification *) aNotification;
|
||||
-(void) windowDidMiniaturize:(NSNotification *) aNotification;
|
||||
-(void) windowDidDeminiaturize:(NSNotification *) aNotification;
|
||||
-(void) windowDidBecomeKey:(NSNotification *) aNotification;
|
||||
-(void) windowDidResignKey:(NSNotification *) aNotification;
|
||||
|
||||
/* Window event handling */
|
||||
-(void) mouseDown:(NSEvent *) theEvent;
|
||||
-(void) rightMouseDown:(NSEvent *) theEvent;
|
||||
-(void) otherMouseDown:(NSEvent *) theEvent;
|
||||
-(void) mouseUp:(NSEvent *) theEvent;
|
||||
-(void) rightMouseUp:(NSEvent *) theEvent;
|
||||
-(void) otherMouseUp:(NSEvent *) theEvent;
|
||||
-(void) mouseEntered:(NSEvent *)theEvent;
|
||||
-(void) mouseExited:(NSEvent *)theEvent;
|
||||
-(void) mouseMoved:(NSEvent *) theEvent;
|
||||
-(void) mouseDragged:(NSEvent *) theEvent;
|
||||
-(void) rightMouseDragged:(NSEvent *) theEvent;
|
||||
-(void) otherMouseDragged:(NSEvent *) theEvent;
|
||||
-(void) scrollWheel:(NSEvent *) theEvent;
|
||||
-(void) touchesBeganWithEvent:(NSEvent *) theEvent;
|
||||
-(void) touchesMovedWithEvent:(NSEvent *) theEvent;
|
||||
-(void) touchesEndedWithEvent:(NSEvent *) theEvent;
|
||||
-(void) touchesCancelledWithEvent:(NSEvent *) theEvent;
|
||||
|
||||
/* Touch event handling */
|
||||
typedef enum {
|
||||
COCOA_TOUCH_DOWN,
|
||||
COCOA_TOUCH_UP,
|
||||
COCOA_TOUCH_MOVE,
|
||||
COCOA_TOUCH_CANCELLED
|
||||
} cocoaTouchType;
|
||||
-(void) handleTouches:(cocoaTouchType)type withEvent:(NSEvent*) event;
|
||||
|
||||
@end
|
||||
/* *INDENT-ON* */
|
||||
|
||||
struct SDL_WindowData
|
||||
{
|
||||
SDL_Window *window;
|
||||
NSWindow *nswindow;
|
||||
SDL_bool created;
|
||||
Cocoa_WindowListener *listener;
|
||||
struct SDL_VideoData *videodata;
|
||||
};
|
||||
|
||||
extern int Cocoa_CreateWindow(_THIS, SDL_Window * window);
|
||||
extern int Cocoa_CreateWindowFrom(_THIS, SDL_Window * window,
|
||||
const void *data);
|
||||
extern void Cocoa_SetWindowTitle(_THIS, SDL_Window * window);
|
||||
extern void Cocoa_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
|
||||
extern void Cocoa_SetWindowPosition(_THIS, SDL_Window * window);
|
||||
extern void Cocoa_SetWindowSize(_THIS, SDL_Window * window);
|
||||
extern void Cocoa_ShowWindow(_THIS, SDL_Window * window);
|
||||
extern void Cocoa_HideWindow(_THIS, SDL_Window * window);
|
||||
extern void Cocoa_RaiseWindow(_THIS, SDL_Window * window);
|
||||
extern void Cocoa_MaximizeWindow(_THIS, SDL_Window * window);
|
||||
extern void Cocoa_MinimizeWindow(_THIS, SDL_Window * window);
|
||||
extern void Cocoa_RestoreWindow(_THIS, SDL_Window * window);
|
||||
extern void Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
|
||||
extern int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
|
||||
extern int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
|
||||
extern void Cocoa_SetWindowGrab(_THIS, SDL_Window * window);
|
||||
extern void Cocoa_DestroyWindow(_THIS, SDL_Window * window);
|
||||
extern SDL_bool Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window,
|
||||
struct SDL_SysWMinfo *info);
|
||||
|
||||
#endif /* _SDL_cocoawindow_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,963 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "SDL_syswm.h"
|
||||
#include "SDL_timer.h" /* For SDL_GetTicks() */
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
#include "../../events/SDL_windowevents_c.h"
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "SDL_cocoashape.h"
|
||||
#include "SDL_cocoamouse.h"
|
||||
|
||||
|
||||
static Uint32 s_moveHack;
|
||||
|
||||
static __inline__ void ConvertNSRect(NSRect *r)
|
||||
{
|
||||
r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
|
||||
}
|
||||
|
||||
@implementation Cocoa_WindowListener
|
||||
|
||||
- (void)listen:(SDL_WindowData *)data
|
||||
{
|
||||
NSNotificationCenter *center;
|
||||
NSWindow *window = data->nswindow;
|
||||
NSView *view = [window contentView];
|
||||
|
||||
_data = data;
|
||||
|
||||
center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
if ([window delegate] != nil) {
|
||||
[center addObserver:self selector:@selector(windowDidExpose:) name:NSWindowDidExposeNotification object:window];
|
||||
[center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:window];
|
||||
[center addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:window];
|
||||
[center addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:window];
|
||||
[center addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:window];
|
||||
[center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:window];
|
||||
[center addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:window];
|
||||
} else {
|
||||
[window setDelegate:self];
|
||||
}
|
||||
|
||||
[window setNextResponder:self];
|
||||
[window setAcceptsMouseMovedEvents:YES];
|
||||
|
||||
[view setNextResponder:self];
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
|
||||
[view setAcceptsTouchEvents:YES];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
NSNotificationCenter *center;
|
||||
NSWindow *window = _data->nswindow;
|
||||
NSView *view = [window contentView];
|
||||
|
||||
center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
if ([window delegate] != self) {
|
||||
[center removeObserver:self name:NSWindowDidExposeNotification object:window];
|
||||
[center removeObserver:self name:NSWindowDidMoveNotification object:window];
|
||||
[center removeObserver:self name:NSWindowDidResizeNotification object:window];
|
||||
[center removeObserver:self name:NSWindowDidMiniaturizeNotification object:window];
|
||||
[center removeObserver:self name:NSWindowDidDeminiaturizeNotification object:window];
|
||||
[center removeObserver:self name:NSWindowDidBecomeKeyNotification object:window];
|
||||
[center removeObserver:self name:NSWindowDidResignKeyNotification object:window];
|
||||
} else {
|
||||
[window setDelegate:nil];
|
||||
}
|
||||
|
||||
if ([window nextResponder] == self) {
|
||||
[window setNextResponder:nil];
|
||||
}
|
||||
if ([view nextResponder] == self) {
|
||||
[view setNextResponder:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)windowShouldClose:(id)sender
|
||||
{
|
||||
SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)windowDidExpose:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
|
||||
}
|
||||
|
||||
- (void)windowDidMove:(NSNotification *)aNotification
|
||||
{
|
||||
int x, y;
|
||||
SDL_Window *window = _data->window;
|
||||
NSWindow *nswindow = _data->nswindow;
|
||||
NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
|
||||
ConvertNSRect(&rect);
|
||||
|
||||
if (s_moveHack) {
|
||||
SDL_bool blockMove = ((SDL_GetTicks() - s_moveHack) < 500);
|
||||
|
||||
s_moveHack = 0;
|
||||
|
||||
if (blockMove) {
|
||||
/* Cocoa is adjusting the window in response to a mode change */
|
||||
rect.origin.x = window->x;
|
||||
rect.origin.y = window->y;
|
||||
ConvertNSRect(&rect);
|
||||
[nswindow setFrameOrigin:rect.origin];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
x = (int)rect.origin.x;
|
||||
y = (int)rect.origin.y;
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
|
||||
}
|
||||
|
||||
- (void)windowDidResize:(NSNotification *)aNotification
|
||||
{
|
||||
int w, h;
|
||||
NSRect rect = [_data->nswindow contentRectForFrameRect:[_data->nswindow frame]];
|
||||
w = (int)rect.size.width;
|
||||
h = (int)rect.size.height;
|
||||
if (SDL_IsShapedWindow(_data->window))
|
||||
Cocoa_ResizeWindowShape(_data->window);
|
||||
SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_RESIZED, w, h);
|
||||
}
|
||||
|
||||
- (void)windowDidMiniaturize:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
|
||||
}
|
||||
|
||||
- (void)windowDidDeminiaturize:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeKey:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_Window *window = _data->window;
|
||||
|
||||
/* We're going to get keyboard events, since we're key. */
|
||||
SDL_SetKeyboardFocus(window);
|
||||
|
||||
/* If we just gained focus we need the updated mouse position */
|
||||
{
|
||||
NSPoint point;
|
||||
int x, y;
|
||||
|
||||
point = [_data->nswindow mouseLocationOutsideOfEventStream];
|
||||
x = (int)point.x;
|
||||
y = (int)(window->h - point.y);
|
||||
|
||||
if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
|
||||
if (SDL_GetMouseFocus() != window) {
|
||||
[self mouseEntered:nil];
|
||||
}
|
||||
SDL_SendMouseMotion(window, 0, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if someone updated the clipboard */
|
||||
Cocoa_CheckClipboardUpdate(_data->videodata);
|
||||
}
|
||||
|
||||
- (void)windowDidResignKey:(NSNotification *)aNotification
|
||||
{
|
||||
/* Some other window will get mouse events, since we're not key. */
|
||||
if (SDL_GetMouseFocus() == _data->window) {
|
||||
SDL_SetMouseFocus(NULL);
|
||||
}
|
||||
|
||||
/* Some other window will get keyboard events, since we're not key. */
|
||||
if (SDL_GetKeyboardFocus() == _data->window) {
|
||||
SDL_SetKeyboardFocus(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
int button;
|
||||
|
||||
switch ([theEvent buttonNumber]) {
|
||||
case 0:
|
||||
button = SDL_BUTTON_LEFT;
|
||||
break;
|
||||
case 1:
|
||||
button = SDL_BUTTON_RIGHT;
|
||||
break;
|
||||
case 2:
|
||||
button = SDL_BUTTON_MIDDLE;
|
||||
break;
|
||||
default:
|
||||
button = [theEvent buttonNumber] + 1;
|
||||
break;
|
||||
}
|
||||
SDL_SendMouseButton(_data->window, SDL_PRESSED, button);
|
||||
}
|
||||
|
||||
- (void)rightMouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseDown:theEvent];
|
||||
}
|
||||
|
||||
- (void)otherMouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseDown:theEvent];
|
||||
}
|
||||
|
||||
- (void)mouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
int button;
|
||||
|
||||
switch ([theEvent buttonNumber]) {
|
||||
case 0:
|
||||
button = SDL_BUTTON_LEFT;
|
||||
break;
|
||||
case 1:
|
||||
button = SDL_BUTTON_RIGHT;
|
||||
break;
|
||||
case 2:
|
||||
button = SDL_BUTTON_MIDDLE;
|
||||
break;
|
||||
default:
|
||||
button = [theEvent buttonNumber] + 1;
|
||||
break;
|
||||
}
|
||||
SDL_SendMouseButton(_data->window, SDL_RELEASED, button);
|
||||
}
|
||||
|
||||
- (void)rightMouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseUp:theEvent];
|
||||
}
|
||||
|
||||
- (void)otherMouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseUp:theEvent];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent *)theEvent
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
SDL_SetMouseFocus(_data->window);
|
||||
|
||||
SDL_SetCursor(NULL);
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent *)theEvent
|
||||
{
|
||||
SDL_Window *window = _data->window;
|
||||
|
||||
if (SDL_GetMouseFocus() == window) {
|
||||
if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
|
||||
int x, y;
|
||||
NSPoint point;
|
||||
CGPoint cgpoint;
|
||||
|
||||
point = [theEvent locationInWindow];
|
||||
point.y = window->h - point.y;
|
||||
|
||||
SDL_SendMouseMotion(window, 0, (int)point.x, (int)point.y);
|
||||
SDL_GetMouseState(&x, &y);
|
||||
cgpoint.x = window->x + x;
|
||||
cgpoint.y = window->y + y;
|
||||
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
|
||||
} else {
|
||||
SDL_SetMouseFocus(NULL);
|
||||
|
||||
[[NSCursor arrowCursor] set];
|
||||
[NSCursor unhide];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(NSEvent *)theEvent
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_Window *window = _data->window;
|
||||
NSPoint point;
|
||||
int x, y;
|
||||
|
||||
if (mouse->relative_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
point = [theEvent locationInWindow];
|
||||
x = (int)point.x;
|
||||
y = (int)(window->h - point.y);
|
||||
|
||||
if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
|
||||
if (SDL_GetMouseFocus() == window) {
|
||||
[self mouseExited:theEvent];
|
||||
}
|
||||
} else {
|
||||
if (SDL_GetMouseFocus() != window) {
|
||||
[self mouseEntered:theEvent];
|
||||
}
|
||||
SDL_SendMouseMotion(window, 0, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseMoved:theEvent];
|
||||
}
|
||||
|
||||
- (void)rightMouseDragged:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseMoved:theEvent];
|
||||
}
|
||||
|
||||
- (void)otherMouseDragged:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseMoved:theEvent];
|
||||
}
|
||||
|
||||
- (void)scrollWheel:(NSEvent *)theEvent
|
||||
{
|
||||
Cocoa_HandleMouseWheel(_data->window, theEvent);
|
||||
}
|
||||
|
||||
- (void)touchesBeganWithEvent:(NSEvent *) theEvent
|
||||
{
|
||||
[self handleTouches:COCOA_TOUCH_DOWN withEvent:theEvent];
|
||||
}
|
||||
|
||||
- (void)touchesMovedWithEvent:(NSEvent *) theEvent
|
||||
{
|
||||
[self handleTouches:COCOA_TOUCH_MOVE withEvent:theEvent];
|
||||
}
|
||||
|
||||
- (void)touchesEndedWithEvent:(NSEvent *) theEvent
|
||||
{
|
||||
[self handleTouches:COCOA_TOUCH_UP withEvent:theEvent];
|
||||
}
|
||||
|
||||
- (void)touchesCancelledWithEvent:(NSEvent *) theEvent
|
||||
{
|
||||
[self handleTouches:COCOA_TOUCH_CANCELLED withEvent:theEvent];
|
||||
}
|
||||
|
||||
- (void)handleTouches:(cocoaTouchType)type withEvent:(NSEvent *)event
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
|
||||
NSSet *touches = 0;
|
||||
NSEnumerator *enumerator;
|
||||
NSTouch *touch;
|
||||
|
||||
switch (type) {
|
||||
case COCOA_TOUCH_DOWN:
|
||||
touches = [event touchesMatchingPhase:NSTouchPhaseBegan inView:nil];
|
||||
break;
|
||||
case COCOA_TOUCH_UP:
|
||||
case COCOA_TOUCH_CANCELLED:
|
||||
touches = [event touchesMatchingPhase:NSTouchPhaseEnded inView:nil];
|
||||
break;
|
||||
case COCOA_TOUCH_MOVE:
|
||||
touches = [event touchesMatchingPhase:NSTouchPhaseMoved inView:nil];
|
||||
break;
|
||||
}
|
||||
|
||||
enumerator = [touches objectEnumerator];
|
||||
touch = (NSTouch*)[enumerator nextObject];
|
||||
while (touch) {
|
||||
SDL_TouchID touchId = (SDL_TouchID)[touch device];
|
||||
if (!SDL_GetTouch(touchId)) {
|
||||
SDL_Touch touch;
|
||||
|
||||
touch.id = touchId;
|
||||
touch.x_min = 0;
|
||||
touch.x_max = 1;
|
||||
touch.native_xres = touch.x_max - touch.x_min;
|
||||
touch.y_min = 0;
|
||||
touch.y_max = 1;
|
||||
touch.native_yres = touch.y_max - touch.y_min;
|
||||
touch.pressure_min = 0;
|
||||
touch.pressure_max = 1;
|
||||
touch.native_pressureres = touch.pressure_max - touch.pressure_min;
|
||||
|
||||
if (SDL_AddTouch(&touch, "") < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_FingerID fingerId = (SDL_FingerID)[touch identity];
|
||||
float x = [touch normalizedPosition].x;
|
||||
float y = [touch normalizedPosition].y;
|
||||
/* Make the origin the upper left instead of the lower left */
|
||||
y = 1.0f - y;
|
||||
|
||||
switch (type) {
|
||||
case COCOA_TOUCH_DOWN:
|
||||
SDL_SendFingerDown(touchId, fingerId, SDL_TRUE, x, y, 1);
|
||||
break;
|
||||
case COCOA_TOUCH_UP:
|
||||
case COCOA_TOUCH_CANCELLED:
|
||||
SDL_SendFingerDown(touchId, fingerId, SDL_FALSE, x, y, 1);
|
||||
break;
|
||||
case COCOA_TOUCH_MOVE:
|
||||
SDL_SendTouchMotion(touchId, fingerId, SDL_FALSE, x, y, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
touch = (NSTouch*)[enumerator nextObject];
|
||||
}
|
||||
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 */
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface SDLWindow : NSWindow
|
||||
/* These are needed for borderless/fullscreen windows */
|
||||
- (BOOL)canBecomeKeyWindow;
|
||||
- (BOOL)canBecomeMainWindow;
|
||||
@end
|
||||
|
||||
@implementation SDLWindow
|
||||
- (BOOL)canBecomeKeyWindow
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeMainWindow
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface SDLView : NSView
|
||||
/* The default implementation doesn't pass rightMouseDown to responder chain */
|
||||
- (void)rightMouseDown:(NSEvent *)theEvent;
|
||||
@end
|
||||
|
||||
@implementation SDLView
|
||||
- (void)rightMouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
[[self nextResponder] rightMouseDown:theEvent];
|
||||
}
|
||||
@end
|
||||
|
||||
static unsigned int
|
||||
GetWindowStyle(SDL_Window * window)
|
||||
{
|
||||
unsigned int style;
|
||||
|
||||
if (window->flags & SDL_WINDOW_FULLSCREEN) {
|
||||
style = NSBorderlessWindowMask;
|
||||
} else {
|
||||
if (window->flags & SDL_WINDOW_BORDERLESS) {
|
||||
style = NSBorderlessWindowMask;
|
||||
} else {
|
||||
style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask);
|
||||
}
|
||||
if (window->flags & SDL_WINDOW_RESIZABLE) {
|
||||
style |= NSResizableWindowMask;
|
||||
}
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
static int
|
||||
SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
|
||||
SDL_WindowData *data;
|
||||
|
||||
/* Allocate the window data */
|
||||
data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
data->window = window;
|
||||
data->nswindow = nswindow;
|
||||
data->created = created;
|
||||
data->videodata = videodata;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
/* Create an event listener for the window */
|
||||
data->listener = [[Cocoa_WindowListener alloc] init];
|
||||
|
||||
/* Fill in the SDL window with the window data */
|
||||
{
|
||||
NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
|
||||
NSView *contentView = [[SDLView alloc] initWithFrame:rect];
|
||||
[nswindow setContentView: contentView];
|
||||
[contentView release];
|
||||
|
||||
ConvertNSRect(&rect);
|
||||
window->x = (int)rect.origin.x;
|
||||
window->y = (int)rect.origin.y;
|
||||
window->w = (int)rect.size.width;
|
||||
window->h = (int)rect.size.height;
|
||||
}
|
||||
|
||||
/* Set up the listener after we create the view */
|
||||
[data->listener listen:data];
|
||||
|
||||
if ([nswindow isVisible]) {
|
||||
window->flags |= SDL_WINDOW_SHOWN;
|
||||
} else {
|
||||
window->flags &= ~SDL_WINDOW_SHOWN;
|
||||
}
|
||||
{
|
||||
unsigned int style = [nswindow styleMask];
|
||||
|
||||
if (style == NSBorderlessWindowMask) {
|
||||
window->flags |= SDL_WINDOW_BORDERLESS;
|
||||
} else {
|
||||
window->flags &= ~SDL_WINDOW_BORDERLESS;
|
||||
}
|
||||
if (style & NSResizableWindowMask) {
|
||||
window->flags |= SDL_WINDOW_RESIZABLE;
|
||||
} else {
|
||||
window->flags &= ~SDL_WINDOW_RESIZABLE;
|
||||
}
|
||||
}
|
||||
/* isZoomed always returns true if the window is not resizable */
|
||||
if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
|
||||
window->flags |= SDL_WINDOW_MAXIMIZED;
|
||||
} else {
|
||||
window->flags &= ~SDL_WINDOW_MAXIMIZED;
|
||||
}
|
||||
if ([nswindow isMiniaturized]) {
|
||||
window->flags |= SDL_WINDOW_MINIMIZED;
|
||||
} else {
|
||||
window->flags &= ~SDL_WINDOW_MINIMIZED;
|
||||
}
|
||||
if ([nswindow isKeyWindow]) {
|
||||
window->flags |= SDL_WINDOW_INPUT_FOCUS;
|
||||
SDL_SetKeyboardFocus(data->window);
|
||||
}
|
||||
|
||||
/* All done! */
|
||||
[pool release];
|
||||
window->driverdata = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_CreateWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSWindow *nswindow;
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
NSRect rect;
|
||||
SDL_Rect bounds;
|
||||
unsigned int style;
|
||||
|
||||
Cocoa_GetDisplayBounds(_this, display, &bounds);
|
||||
rect.origin.x = window->x;
|
||||
rect.origin.y = window->y;
|
||||
rect.size.width = window->w;
|
||||
rect.size.height = window->h;
|
||||
ConvertNSRect(&rect);
|
||||
|
||||
style = GetWindowStyle(window);
|
||||
|
||||
/* Figure out which screen to place this window */
|
||||
NSArray *screens = [NSScreen screens];
|
||||
NSScreen *screen = nil;
|
||||
NSScreen *candidate;
|
||||
int i, count = [screens count];
|
||||
for (i = 0; i < count; ++i) {
|
||||
candidate = [screens objectAtIndex:i];
|
||||
NSRect screenRect = [candidate frame];
|
||||
if (rect.origin.x >= screenRect.origin.x &&
|
||||
rect.origin.x < screenRect.origin.x + screenRect.size.width &&
|
||||
rect.origin.y >= screenRect.origin.y &&
|
||||
rect.origin.y < screenRect.origin.y + screenRect.size.height) {
|
||||
screen = candidate;
|
||||
rect.origin.x -= screenRect.origin.x;
|
||||
rect.origin.y -= screenRect.origin.y;
|
||||
}
|
||||
}
|
||||
nswindow = [[SDLWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:YES screen:screen];
|
||||
|
||||
[pool release];
|
||||
|
||||
if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) {
|
||||
[nswindow release];
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NSWindow *nswindow = (NSWindow *) data;
|
||||
NSString *title;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
/* Query the title from the existing window */
|
||||
title = [nswindow title];
|
||||
if (title) {
|
||||
window->title = SDL_strdup([title UTF8String]);
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return SetupWindowData(_this, window, nswindow, SDL_FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_SetWindowTitle(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
|
||||
NSString *string;
|
||||
|
||||
if(window->title) {
|
||||
string = [[NSString alloc] initWithUTF8String:window->title];
|
||||
} else {
|
||||
string = [[NSString alloc] init];
|
||||
}
|
||||
[nswindow setTitle:string];
|
||||
[string release];
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSImage *nsimage = Cocoa_CreateImage(icon);
|
||||
|
||||
if (nsimage) {
|
||||
[NSApp setApplicationIconImage:nsimage];
|
||||
}
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_SetWindowPosition(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
|
||||
NSRect rect;
|
||||
Uint32 moveHack;
|
||||
|
||||
rect.origin.x = window->x;
|
||||
rect.origin.y = window->y;
|
||||
rect.size.width = window->w;
|
||||
rect.size.height = window->h;
|
||||
ConvertNSRect(&rect);
|
||||
|
||||
moveHack = s_moveHack;
|
||||
s_moveHack = 0;
|
||||
[nswindow setFrameOrigin:rect.origin];
|
||||
s_moveHack = moveHack;
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_SetWindowSize(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
|
||||
NSSize size;
|
||||
|
||||
size.width = window->w;
|
||||
size.height = window->h;
|
||||
[nswindow setContentSize:size];
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_ShowWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
|
||||
|
||||
if (![nswindow isMiniaturized]) {
|
||||
[nswindow makeKeyAndOrderFront:nil];
|
||||
}
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_HideWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
|
||||
|
||||
[nswindow orderOut:nil];
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_RaiseWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
|
||||
|
||||
[nswindow makeKeyAndOrderFront:nil];
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_MaximizeWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
|
||||
|
||||
[nswindow zoom:nil];
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_MinimizeWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
|
||||
|
||||
[nswindow miniaturize:nil];
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_RestoreWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
|
||||
|
||||
if ([nswindow isMiniaturized]) {
|
||||
[nswindow deminiaturize:nil];
|
||||
} else if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
|
||||
[nswindow zoom:nil];
|
||||
}
|
||||
[pool release];
|
||||
}
|
||||
|
||||
static NSWindow *
|
||||
Cocoa_RebuildWindow(SDL_WindowData * data, NSWindow * nswindow, unsigned style)
|
||||
{
|
||||
if (!data->created) {
|
||||
/* Don't mess with other people's windows... */
|
||||
return nswindow;
|
||||
}
|
||||
|
||||
[data->listener close];
|
||||
data->nswindow = [[SDLWindow alloc] initWithContentRect:[[nswindow contentView] frame] styleMask:style backing:NSBackingStoreBuffered defer:YES screen:[nswindow screen]];
|
||||
[data->nswindow setContentView:[nswindow contentView]];
|
||||
[data->listener listen:data];
|
||||
|
||||
[nswindow close];
|
||||
|
||||
return data->nswindow;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
NSWindow *nswindow = data->nswindow;
|
||||
NSRect rect;
|
||||
|
||||
/* The view responder chain gets messed with during setStyleMask */
|
||||
if ([[nswindow contentView] nextResponder] == data->listener) {
|
||||
[[nswindow contentView] setNextResponder:nil];
|
||||
}
|
||||
|
||||
if (fullscreen) {
|
||||
SDL_Rect bounds;
|
||||
|
||||
Cocoa_GetDisplayBounds(_this, display, &bounds);
|
||||
rect.origin.x = bounds.x;
|
||||
rect.origin.y = bounds.y;
|
||||
rect.size.width = bounds.w;
|
||||
rect.size.height = bounds.h;
|
||||
ConvertNSRect(&rect);
|
||||
|
||||
/* Hack to fix origin on Mac OS X 10.4 */
|
||||
NSRect screenRect = [[nswindow screen] frame];
|
||||
if (screenRect.size.height >= 1.0f) {
|
||||
rect.origin.y += (screenRect.size.height - rect.size.height);
|
||||
}
|
||||
|
||||
if ([nswindow respondsToSelector: @selector(setStyleMask:)]) {
|
||||
[nswindow performSelector: @selector(setStyleMask:) withObject: (id)NSBorderlessWindowMask];
|
||||
} else {
|
||||
nswindow = Cocoa_RebuildWindow(data, nswindow, NSBorderlessWindowMask);
|
||||
}
|
||||
} else {
|
||||
rect.origin.x = window->windowed.x;
|
||||
rect.origin.y = window->windowed.y;
|
||||
rect.size.width = window->windowed.w;
|
||||
rect.size.height = window->windowed.h;
|
||||
ConvertNSRect(&rect);
|
||||
|
||||
if ([nswindow respondsToSelector: @selector(setStyleMask:)]) {
|
||||
[nswindow performSelector: @selector(setStyleMask:) withObject: (id)(uintptr_t)GetWindowStyle(window)];
|
||||
} else {
|
||||
nswindow = Cocoa_RebuildWindow(data, nswindow, GetWindowStyle(window));
|
||||
}
|
||||
}
|
||||
|
||||
/* The view responder chain gets messed with during setStyleMask */
|
||||
if ([[nswindow contentView] nextResponder] != data->listener) {
|
||||
[[nswindow contentView] setNextResponder:data->listener];
|
||||
}
|
||||
|
||||
s_moveHack = 0;
|
||||
[nswindow setFrameOrigin:rect.origin];
|
||||
[nswindow setContentSize:rect.size];
|
||||
s_moveHack = SDL_GetTicks();
|
||||
|
||||
/* When the window style changes the title is cleared */
|
||||
if (!fullscreen) {
|
||||
Cocoa_SetWindowTitle(_this, window);
|
||||
}
|
||||
|
||||
#ifdef FULLSCREEN_TOGGLEABLE
|
||||
if (fullscreen) {
|
||||
/* OpenGL is rendering to the window, so make it visible! */
|
||||
[nswindow setLevel:CGShieldingWindowLevel()];
|
||||
} else {
|
||||
[nswindow setLevel:kCGNormalWindowLevel];
|
||||
}
|
||||
#endif
|
||||
[nswindow makeKeyAndOrderFront:nil];
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
|
||||
{
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
|
||||
const uint32_t tableSize = 256;
|
||||
CGGammaValue redTable[tableSize];
|
||||
CGGammaValue greenTable[tableSize];
|
||||
CGGammaValue blueTable[tableSize];
|
||||
uint32_t i;
|
||||
float inv65535 = 1.0f / 65535.0f;
|
||||
|
||||
/* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
|
||||
for (i = 0; i < 256; i++) {
|
||||
redTable[i] = ramp[0*256+i] * inv65535;
|
||||
greenTable[i] = ramp[1*256+i] * inv65535;
|
||||
blueTable[i] = ramp[2*256+i] * inv65535;
|
||||
}
|
||||
|
||||
if (CGSetDisplayTransferByTable(display_id, tableSize,
|
||||
redTable, greenTable, blueTable) != CGDisplayNoErr) {
|
||||
SDL_SetError("CGSetDisplayTransferByTable()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
|
||||
{
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
|
||||
const uint32_t tableSize = 256;
|
||||
CGGammaValue redTable[tableSize];
|
||||
CGGammaValue greenTable[tableSize];
|
||||
CGGammaValue blueTable[tableSize];
|
||||
uint32_t i, tableCopied;
|
||||
|
||||
if (CGGetDisplayTransferByTable(display_id, tableSize,
|
||||
redTable, greenTable, blueTable, &tableCopied) != CGDisplayNoErr) {
|
||||
SDL_SetError("CGGetDisplayTransferByTable()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < tableCopied; i++) {
|
||||
ramp[0*256+i] = (Uint16)(redTable[i] * 65535.0f);
|
||||
ramp[1*256+i] = (Uint16)(greenTable[i] * 65535.0f);
|
||||
ramp[2*256+i] = (Uint16)(blueTable[i] * 65535.0f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_SetWindowGrab(_THIS, SDL_Window * window)
|
||||
{
|
||||
/* Move the cursor to the nearest point in the window */
|
||||
if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
|
||||
(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
|
||||
int x, y;
|
||||
CGPoint cgpoint;
|
||||
|
||||
SDL_GetMouseState(&x, &y);
|
||||
cgpoint.x = window->x + x;
|
||||
cgpoint.y = window->y + y;
|
||||
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_DestroyWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
if (data) {
|
||||
[data->listener close];
|
||||
[data->listener release];
|
||||
if (data->created) {
|
||||
[data->nswindow close];
|
||||
}
|
||||
SDL_free(data);
|
||||
}
|
||||
[pool release];
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
||||
{
|
||||
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
|
||||
|
||||
if (info->version.major <= SDL_MAJOR_VERSION) {
|
||||
info->subsystem = SDL_SYSWM_COCOA;
|
||||
info->info.cocoa.window = nswindow;
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
SDL_SetError("Application not compiled with SDL %d.%d\n",
|
||||
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
Reference in New Issue
Block a user