mirror of
https://github.com/AxioDL/boo.git
synced 2025-05-15 11:51:27 +00:00
OS X fixes
This commit is contained in:
parent
de51c2dcc5
commit
13edb3eb01
@ -17,9 +17,12 @@ elseif(APPLE)
|
|||||||
lib/mac/ApplicationCocoa.mm
|
lib/mac/ApplicationCocoa.mm
|
||||||
lib/mac/WindowCocoa.mm
|
lib/mac/WindowCocoa.mm
|
||||||
lib/mac/GLViewCocoa.mm
|
lib/mac/GLViewCocoa.mm
|
||||||
lib/mac/GraphicsContextCocoa.cpp
|
|
||||||
lib/inputdev/HIDListenerIOKit.cpp
|
lib/inputdev/HIDListenerIOKit.cpp
|
||||||
lib/inputdev/HIDDeviceIOKit.cpp)
|
lib/inputdev/HIDDeviceIOKit.cpp)
|
||||||
|
find_library(APPKIT_LIBRARY AppKit)
|
||||||
|
find_library(IOKIT_LIBRARY IOKit)
|
||||||
|
find_library(OPENGL_LIBRARY OpenGL)
|
||||||
|
list(APPEND _BOO_SYS_LIBS ${APPKIT_LIBRARY} ${IOKIT_LIBRARY} ${OPENGL_LIBRARY})
|
||||||
else()
|
else()
|
||||||
list(APPEND PLAT_SRCS
|
list(APPEND PLAT_SRCS
|
||||||
lib/x11/ApplicationUnix.cpp
|
lib/x11/ApplicationUnix.cpp
|
||||||
|
@ -14,6 +14,7 @@ class IApplication;
|
|||||||
|
|
||||||
struct IApplicationCallback
|
struct IApplicationCallback
|
||||||
{
|
{
|
||||||
|
virtual void appMain(IApplication*) {}
|
||||||
virtual void appQuitting(IApplication*) {}
|
virtual void appQuitting(IApplication*) {}
|
||||||
virtual void appFilesOpen(IApplication*, const std::vector<SystemString>&) {}
|
virtual void appFilesOpen(IApplication*, const std::vector<SystemString>&) {}
|
||||||
};
|
};
|
||||||
|
@ -6,8 +6,8 @@ namespace boo
|
|||||||
|
|
||||||
class IGraphicsContext
|
class IGraphicsContext
|
||||||
{
|
{
|
||||||
friend class CWindowCocoa;
|
friend class WindowCocoa;
|
||||||
friend class CWindowXCB;
|
friend class WindowXCB;
|
||||||
virtual void _setCallback(class IWindowCallback* cb) {(void)cb;}
|
virtual void _setCallback(class IWindowCallback* cb) {(void)cb;}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "IHIDDevice.hpp"
|
#include "IHIDDevice.hpp"
|
||||||
#include "inputdev/CDeviceToken.hpp"
|
#include "boo/inputdev/DeviceToken.hpp"
|
||||||
#include "inputdev/CDeviceBase.hpp"
|
#include "boo/inputdev/DeviceBase.hpp"
|
||||||
#include <IOKit/hid/IOHIDLib.h>
|
#include <IOKit/hid/IOHIDLib.h>
|
||||||
#include <IOKit/usb/IOUSBLib.h>
|
#include <IOKit/usb/IOUSBLib.h>
|
||||||
#include <IOKit/IOCFPlugIn.h>
|
#include <IOKit/IOCFPlugIn.h>
|
||||||
@ -9,10 +9,10 @@
|
|||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
class CHIDDeviceIOKit final : public IHIDDevice
|
class HIDDeviceIOKit : public IHIDDevice
|
||||||
{
|
{
|
||||||
CDeviceToken& m_token;
|
DeviceToken& m_token;
|
||||||
CDeviceBase& m_devImp;
|
DeviceBase& m_devImp;
|
||||||
|
|
||||||
IOUSBInterfaceInterface** m_usbIntf = NULL;
|
IOUSBInterfaceInterface** m_usbIntf = NULL;
|
||||||
uint8_t m_usbIntfInPipe = 0;
|
uint8_t m_usbIntfInPipe = 0;
|
||||||
@ -47,7 +47,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _threadProcUSBLL(CHIDDeviceIOKit* device)
|
static void _threadProcUSBLL(HIDDeviceIOKit* device)
|
||||||
{
|
{
|
||||||
char thrName[128];
|
char thrName[128];
|
||||||
snprintf(thrName, 128, "%s Transfer Thread", device->m_token.getProductName().c_str());
|
snprintf(thrName, 128, "%s Transfer Thread", device->m_token.getProductName().c_str());
|
||||||
@ -174,7 +174,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _threadProcBTLL(CHIDDeviceIOKit* device)
|
static void _threadProcBTLL(HIDDeviceIOKit* device)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _threadProcHID(CHIDDeviceIOKit* device)
|
static void _threadProcHID(HIDDeviceIOKit* device)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
||||||
|
|
||||||
@ -219,26 +219,29 @@ class CHIDDeviceIOKit final : public IHIDDevice
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CHIDDeviceIOKit(CDeviceToken& token, CDeviceBase& devImp)
|
HIDDeviceIOKit(DeviceToken& token, DeviceBase& devImp)
|
||||||
: m_token(token),
|
: m_token(token),
|
||||||
m_devImp(devImp),
|
m_devImp(devImp),
|
||||||
m_devPath(token.getDevicePath())
|
m_devPath(token.getDevicePath())
|
||||||
{
|
{
|
||||||
devImp.m_hidDev = this;
|
devImp.m_hidDev = this;
|
||||||
std::unique_lock<std::mutex> lk(m_initMutex);
|
std::unique_lock<std::mutex> lk(m_initMutex);
|
||||||
CDeviceToken::TDeviceType dType = token.getDeviceType();
|
DeviceToken::TDeviceType dType = token.getDeviceType();
|
||||||
if (dType == CDeviceToken::DEVTYPE_USB)
|
if (dType == DeviceToken::DEVTYPE_USB)
|
||||||
m_thread = new std::thread(_threadProcUSBLL, this);
|
m_thread = new std::thread(_threadProcUSBLL, this);
|
||||||
else if (dType == CDeviceToken::DEVTYPE_BLUETOOTH)
|
else if (dType == DeviceToken::DEVTYPE_BLUETOOTH)
|
||||||
m_thread = new std::thread(_threadProcBTLL, this);
|
m_thread = new std::thread(_threadProcBTLL, this);
|
||||||
else if (dType == CDeviceToken::DEVTYPE_GENERICHID)
|
else if (dType == DeviceToken::DEVTYPE_GENERICHID)
|
||||||
m_thread = new std::thread(_threadProcHID, this);
|
m_thread = new std::thread(_threadProcHID, this);
|
||||||
else
|
else
|
||||||
throw std::runtime_error("invalid token supplied to device constructor");
|
{
|
||||||
|
fprintf(stderr, "invalid token supplied to device constructor\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_initCond.wait(lk);
|
m_initCond.wait(lk);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CHIDDeviceIOKit()
|
~HIDDeviceIOKit()
|
||||||
{
|
{
|
||||||
m_runningTransferLoop = false;
|
m_runningTransferLoop = false;
|
||||||
m_thread->join();
|
m_thread->join();
|
||||||
@ -248,9 +251,9 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp)
|
IHIDDevice* IHIDDeviceNew(DeviceToken& token, DeviceBase& devImp)
|
||||||
{
|
{
|
||||||
return new CHIDDeviceIOKit(token, devImp);
|
return new HIDDeviceIOKit(token, devImp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "IHIDListener.hpp"
|
#include "boo/inputdev/IHIDListener.hpp"
|
||||||
#include "inputdev/CDeviceFinder.hpp"
|
#include "boo/inputdev/DeviceFinder.hpp"
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <IOKit/hid/IOHIDLib.h>
|
#include <IOKit/hid/IOHIDLib.h>
|
||||||
#include <IOKit/IOKitLib.h>
|
#include <IOKit/IOKitLib.h>
|
||||||
@ -52,16 +52,16 @@ static bool getUSBStringDescriptor(IOUSBDeviceInterface182** usbDevice, UInt8 id
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CHIDListenerIOKit final : public IHIDListener
|
class HIDListenerIOKit : public IHIDListener
|
||||||
{
|
{
|
||||||
CDeviceFinder& m_finder;
|
DeviceFinder& m_finder;
|
||||||
|
|
||||||
CFRunLoopRef m_listenerRunLoop;
|
CFRunLoopRef m_listenerRunLoop;
|
||||||
IONotificationPortRef m_llPort;
|
IONotificationPortRef m_llPort;
|
||||||
io_iterator_t m_llAddNotif, m_llRemoveNotif;
|
io_iterator_t m_llAddNotif, m_llRemoveNotif;
|
||||||
bool m_scanningEnabled;
|
bool m_scanningEnabled;
|
||||||
|
|
||||||
static void devicesConnectedUSBLL(CHIDListenerIOKit* listener,
|
static void devicesConnectedUSBLL(HIDListenerIOKit* listener,
|
||||||
io_iterator_t iterator)
|
io_iterator_t iterator)
|
||||||
{
|
{
|
||||||
io_object_t obj;
|
io_object_t obj;
|
||||||
@ -83,14 +83,20 @@ class CHIDListenerIOKit final : public IHIDListener
|
|||||||
IOReturn err;
|
IOReturn err;
|
||||||
err = IOCreatePlugInInterfaceForService(obj, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &devServ, &score);
|
err = IOCreatePlugInInterfaceForService(obj, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &devServ, &score);
|
||||||
if (err != kIOReturnSuccess)
|
if (err != kIOReturnSuccess)
|
||||||
throw std::runtime_error("unable to open IOKit plugin interface");
|
{
|
||||||
|
fprintf(stderr, "unable to open IOKit plugin interface\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IOUSBDeviceInterface182 **dev;
|
IOUSBDeviceInterface182 **dev;
|
||||||
err = (*devServ)->QueryInterface(devServ,
|
err = (*devServ)->QueryInterface(devServ,
|
||||||
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID182),
|
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID182),
|
||||||
(LPVOID*)&dev);
|
(LPVOID*)&dev);
|
||||||
if (err != kIOReturnSuccess)
|
if (err != kIOReturnSuccess)
|
||||||
throw std::runtime_error("unable to open IOKit device interface");
|
{
|
||||||
|
fprintf(stderr, "unable to open IOKit device interface\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UInt16 vid, pid;
|
UInt16 vid, pid;
|
||||||
(*dev)->GetDeviceVendor(dev, &vid);
|
(*dev)->GetDeviceVendor(dev, &vid);
|
||||||
@ -105,8 +111,8 @@ class CHIDListenerIOKit final : public IHIDListener
|
|||||||
getUSBStringDescriptor(dev, vstridx, vstr);
|
getUSBStringDescriptor(dev, vstridx, vstr);
|
||||||
getUSBStringDescriptor(dev, pstridx, pstr);
|
getUSBStringDescriptor(dev, pstridx, pstr);
|
||||||
|
|
||||||
if (!listener->m_finder._insertToken(CDeviceToken(CDeviceToken::DEVTYPE_USB,
|
if (!listener->m_finder._insertToken(DeviceToken(DeviceToken::DEVTYPE_USB,
|
||||||
vid, pid, vstr, pstr, devPath)))
|
vid, pid, vstr, pstr, devPath)))
|
||||||
{
|
{
|
||||||
/* Matched-insertion failed; see if generic HID interface is available */
|
/* Matched-insertion failed; see if generic HID interface is available */
|
||||||
/* TODO: Do */
|
/* TODO: Do */
|
||||||
@ -120,7 +126,7 @@ class CHIDListenerIOKit final : public IHIDListener
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void devicesDisconnectedUSBLL(CHIDListenerIOKit* listener,
|
static void devicesDisconnectedUSBLL(HIDListenerIOKit* listener,
|
||||||
io_iterator_t iterator)
|
io_iterator_t iterator)
|
||||||
{
|
{
|
||||||
if (CFRunLoopGetCurrent() != listener->m_listenerRunLoop)
|
if (CFRunLoopGetCurrent() != listener->m_listenerRunLoop)
|
||||||
@ -144,7 +150,7 @@ class CHIDListenerIOKit final : public IHIDListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CHIDListenerIOKit(CDeviceFinder& finder)
|
HIDListenerIOKit(DeviceFinder& finder)
|
||||||
: m_finder(finder)
|
: m_finder(finder)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -174,7 +180,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~CHIDListenerIOKit()
|
~HIDListenerIOKit()
|
||||||
{
|
{
|
||||||
CFRunLoopRemoveSource(m_listenerRunLoop, IONotificationPortGetRunLoopSource(m_llPort), kCFRunLoopDefaultMode);
|
CFRunLoopRemoveSource(m_listenerRunLoop, IONotificationPortGetRunLoopSource(m_llPort), kCFRunLoopDefaultMode);
|
||||||
IOObjectRelease(m_llAddNotif);
|
IOObjectRelease(m_llAddNotif);
|
||||||
@ -209,9 +215,9 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IHIDListener* IHIDListenerNew(CDeviceFinder& finder)
|
IHIDListener* IHIDListenerNew(DeviceFinder& finder)
|
||||||
{
|
{
|
||||||
return new CHIDListenerIOKit(finder);
|
return new HIDListenerIOKit(finder);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include <AppKit/AppKit.h>
|
#include <AppKit/AppKit.h>
|
||||||
|
|
||||||
#include "IApplication.hpp"
|
#include "boo/IApplication.hpp"
|
||||||
|
|
||||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||||
{
|
{
|
||||||
@ -21,17 +21,27 @@
|
|||||||
- (void)applicationDidFinishLaunching:(NSNotification*)notification
|
- (void)applicationDidFinishLaunching:(NSNotification*)notification
|
||||||
{
|
{
|
||||||
(void)notification;
|
(void)notification;
|
||||||
callback->appLaunched(boo::IApplicationInstance());
|
callback->appMain(boo::APP);
|
||||||
}
|
}
|
||||||
- (void)applicationWillTerminate:(NSNotification*)notification
|
- (void)applicationWillTerminate:(NSNotification*)notification
|
||||||
{
|
{
|
||||||
(void)notification;
|
(void)notification;
|
||||||
callback->appQuitting(boo::IApplicationInstance());
|
callback->appQuitting(boo::APP);
|
||||||
}
|
}
|
||||||
- (BOOL)application:(NSApplication*)sender openFile:(NSString*)filename
|
- (BOOL)application:(NSApplication*)sender openFile:(NSString*)filename
|
||||||
{
|
{
|
||||||
(void)sender;
|
std::vector<boo::SystemString> strVec;
|
||||||
return callback->appFileOpen(boo::IApplicationInstance(), [filename UTF8String]);
|
strVec.push_back(boo::SystemString([filename UTF8String]));
|
||||||
|
callback->appFilesOpen(boo::APP, strVec);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
- (void)application:(NSApplication*)sender openFiles:(NSArray*)filenames
|
||||||
|
{
|
||||||
|
std::vector<boo::SystemString> strVec;
|
||||||
|
strVec.reserve([filenames count]);
|
||||||
|
for (NSString* str in filenames)
|
||||||
|
strVec.push_back(boo::SystemString([str UTF8String]));
|
||||||
|
callback->appFilesOpen(boo::APP, strVec);
|
||||||
}
|
}
|
||||||
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender {
|
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender {
|
||||||
(void)sender;
|
(void)sender;
|
||||||
@ -62,14 +72,15 @@
|
|||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
IWindow* _CWindowCocoaNew(const std::string& title);
|
IWindow* _WindowCocoaNew(const SystemString& title);
|
||||||
|
|
||||||
class CApplicationCocoa final : public IApplication
|
class ApplicationCocoa : public IApplication
|
||||||
{
|
{
|
||||||
IApplicationCallback& m_callback;
|
IApplicationCallback& m_callback;
|
||||||
const std::string m_friendlyName;
|
const SystemString m_uniqueName;
|
||||||
const std::string m_pname;
|
const SystemString m_friendlyName;
|
||||||
const std::vector<std::string> m_args;
|
const SystemString m_pname;
|
||||||
|
const std::vector<SystemString> m_args;
|
||||||
|
|
||||||
NSPanel* aboutPanel;
|
NSPanel* aboutPanel;
|
||||||
|
|
||||||
@ -79,22 +90,16 @@ class CApplicationCocoa final : public IApplication
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CApplicationCocoa(IApplicationCallback& callback,
|
ApplicationCocoa(IApplicationCallback& callback,
|
||||||
const std::string& friendlyName,
|
const SystemString& uniqueName,
|
||||||
const std::string& pname,
|
const SystemString& friendlyName,
|
||||||
const std::vector<std::string>& args)
|
const SystemString& pname,
|
||||||
|
const std::vector<SystemString>& args)
|
||||||
: m_callback(callback),
|
: m_callback(callback),
|
||||||
|
m_uniqueName(uniqueName),
|
||||||
m_friendlyName(friendlyName),
|
m_friendlyName(friendlyName),
|
||||||
m_pname(pname),
|
m_pname(pname),
|
||||||
m_args(args)
|
m_args(args)
|
||||||
{}
|
|
||||||
|
|
||||||
EPlatformType getPlatformType() const
|
|
||||||
{
|
|
||||||
return PLAT_COCOA;
|
|
||||||
}
|
|
||||||
|
|
||||||
void run()
|
|
||||||
{
|
{
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
@ -141,42 +146,64 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EPlatformType getPlatformType() const
|
||||||
|
{
|
||||||
|
return PLAT_COCOA;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pump()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void quit()
|
void quit()
|
||||||
{
|
{
|
||||||
[NSApp terminate:nil];
|
[NSApp terminate:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& getProcessName() const
|
const SystemString& getUniqueName() const
|
||||||
|
{
|
||||||
|
return m_uniqueName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SystemString& getFriendlyName() const
|
||||||
|
{
|
||||||
|
return m_friendlyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SystemString& getProcessName() const
|
||||||
{
|
{
|
||||||
return m_pname;
|
return m_pname;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string>& getArgs() const
|
const std::vector<SystemString>& getArgs() const
|
||||||
{
|
{
|
||||||
return m_args;
|
return m_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWindow* newWindow(const std::string& title)
|
IWindow* newWindow(const std::string& title)
|
||||||
{
|
{
|
||||||
return _CWindowCocoaNew(title);
|
return _WindowCocoaNew(title);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
IApplication* APP = NULL;
|
IApplication* APP = NULL;
|
||||||
IApplication* IApplicationBootstrap(IApplication::EPlatformType platform,
|
std::unique_ptr<IApplication> ApplicationBootstrap(IApplication::EPlatformType platform,
|
||||||
IApplicationCallback& cb,
|
IApplicationCallback& cb,
|
||||||
const std::string& friendlyName,
|
const SystemString& uniqueName,
|
||||||
const std::string& pname,
|
const SystemString& friendlyName,
|
||||||
const std::vector<std::string>& args)
|
const SystemString& pname,
|
||||||
|
const std::vector<SystemString>& args,
|
||||||
|
bool singleInstance)
|
||||||
{
|
{
|
||||||
if (!APP)
|
if (!APP)
|
||||||
{
|
{
|
||||||
if (platform != IApplication::PLAT_COCOA &&
|
if (platform != IApplication::PLAT_COCOA &&
|
||||||
platform != IApplication::PLAT_AUTO)
|
platform != IApplication::PLAT_AUTO)
|
||||||
return NULL;
|
return NULL;
|
||||||
APP = new CApplicationCocoa(cb, friendlyName, pname, args);
|
APP = new ApplicationCocoa(cb, uniqueName, friendlyName, pname, args);
|
||||||
}
|
}
|
||||||
return APP;
|
return std::unique_ptr<IApplication>(APP);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,639 +0,0 @@
|
|||||||
#import <AppKit/AppKit.h>
|
|
||||||
#include <OpenGL/OpenGL.h>
|
|
||||||
#include <OpenGL/gl3.h>
|
|
||||||
#include "windowsys/IGraphicsContext.hpp"
|
|
||||||
#include "windowsys/IWindow.hpp"
|
|
||||||
|
|
||||||
/* AppKit applies OpenGL much differently than other platforms
|
|
||||||
* the NSOpenGLView class composes together all necessary
|
|
||||||
* OGL context members and provides the necessary event hooks
|
|
||||||
* for KB/Mouse/Touch events
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const NSOpenGLPixelFormatAttribute PF_RGBA8_ATTRS[] =
|
|
||||||
{
|
|
||||||
NSOpenGLPFAAccelerated,
|
|
||||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
|
||||||
NSOpenGLPFADoubleBuffer,
|
|
||||||
NSOpenGLPFAColorSize, 24,
|
|
||||||
NSOpenGLPFAAlphaSize, 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const NSOpenGLPixelFormatAttribute PF_RGBA8_Z24_ATTRS[] =
|
|
||||||
{
|
|
||||||
NSOpenGLPFAAccelerated,
|
|
||||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
|
||||||
NSOpenGLPFADoubleBuffer,
|
|
||||||
NSOpenGLPFAColorSize, 24,
|
|
||||||
NSOpenGLPFAAlphaSize, 8,
|
|
||||||
NSOpenGLPFADepthSize, 24,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const NSOpenGLPixelFormatAttribute PF_RGBAF32_ATTRS[] =
|
|
||||||
{
|
|
||||||
NSOpenGLPFAAccelerated,
|
|
||||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
|
||||||
NSOpenGLPFADoubleBuffer,
|
|
||||||
NSOpenGLPFAColorFloat,
|
|
||||||
NSOpenGLPFAColorSize, 96,
|
|
||||||
NSOpenGLPFAAlphaSize, 32,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const NSOpenGLPixelFormatAttribute PF_RGBAF32_Z24_ATTRS[] =
|
|
||||||
{
|
|
||||||
NSOpenGLPFAAccelerated,
|
|
||||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
|
||||||
NSOpenGLPFADoubleBuffer,
|
|
||||||
NSOpenGLPFAColorFloat,
|
|
||||||
NSOpenGLPFAColorSize, 96,
|
|
||||||
NSOpenGLPFAAlphaSize, 32,
|
|
||||||
NSOpenGLPFADepthSize, 24,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const NSOpenGLPixelFormatAttribute* PF_TABLE[] =
|
|
||||||
{
|
|
||||||
NULL,
|
|
||||||
PF_RGBA8_ATTRS,
|
|
||||||
PF_RGBA8_Z24_ATTRS,
|
|
||||||
PF_RGBAF32_ATTRS,
|
|
||||||
PF_RGBAF32_Z24_ATTRS
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace boo {class CGraphicsContextCocoa;}
|
|
||||||
@interface CGraphicsContextCocoaInternal : NSOpenGLView
|
|
||||||
{
|
|
||||||
NSUInteger lastModifiers;
|
|
||||||
boo::CGraphicsContextCocoa* booContext;
|
|
||||||
}
|
|
||||||
- (id)initWithBooContext:(boo::CGraphicsContextCocoa*)bctx;
|
|
||||||
@end
|
|
||||||
|
|
||||||
namespace boo
|
|
||||||
{
|
|
||||||
|
|
||||||
class CGraphicsContextCocoa final : public IGraphicsContext
|
|
||||||
{
|
|
||||||
|
|
||||||
EGraphicsAPI m_api;
|
|
||||||
EPixelFormat m_pf;
|
|
||||||
IWindow* m_parentWindow;
|
|
||||||
CGraphicsContextCocoaInternal* m_nsContext;
|
|
||||||
NSOpenGLContext* m_nsShareContext;
|
|
||||||
|
|
||||||
public:
|
|
||||||
IWindowCallback* m_callback;
|
|
||||||
|
|
||||||
CGraphicsContextCocoa(EGraphicsAPI api, IWindow* parentWindow)
|
|
||||||
: m_api(api),
|
|
||||||
m_pf(PF_RGBA8),
|
|
||||||
m_parentWindow(parentWindow),
|
|
||||||
m_nsContext(NULL),
|
|
||||||
m_nsShareContext(NULL),
|
|
||||||
m_callback(NULL)
|
|
||||||
{}
|
|
||||||
|
|
||||||
~CGraphicsContextCocoa()
|
|
||||||
{
|
|
||||||
[m_nsContext release];
|
|
||||||
[m_nsShareContext release];
|
|
||||||
}
|
|
||||||
|
|
||||||
void _setCallback(IWindowCallback* cb)
|
|
||||||
{
|
|
||||||
m_callback = cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
EGraphicsAPI getAPI() const
|
|
||||||
{
|
|
||||||
return m_api;
|
|
||||||
}
|
|
||||||
|
|
||||||
EPixelFormat getPixelFormat() const
|
|
||||||
{
|
|
||||||
return m_pf;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPixelFormat(EPixelFormat pf)
|
|
||||||
{
|
|
||||||
if (pf > PF_RGBAF32_Z24)
|
|
||||||
return;
|
|
||||||
m_pf = pf;
|
|
||||||
}
|
|
||||||
|
|
||||||
void initializeContext()
|
|
||||||
{
|
|
||||||
if (m_nsShareContext)
|
|
||||||
return;
|
|
||||||
m_nsContext = [[CGraphicsContextCocoaInternal alloc] initWithBooContext:this];
|
|
||||||
[(NSWindow*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext];
|
|
||||||
}
|
|
||||||
|
|
||||||
IGraphicsContext* makeShareContext() const
|
|
||||||
{
|
|
||||||
NSOpenGLContext* nsctx;
|
|
||||||
if (m_nsContext)
|
|
||||||
{
|
|
||||||
nsctx = [[NSOpenGLContext alloc] initWithFormat:[m_nsContext pixelFormat]
|
|
||||||
shareContext:[m_nsContext openGLContext]];
|
|
||||||
}
|
|
||||||
else if (m_nsShareContext)
|
|
||||||
{
|
|
||||||
nsctx = [[NSOpenGLContext alloc] initWithFormat:[m_nsShareContext pixelFormat]
|
|
||||||
shareContext:m_nsShareContext];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
if (!nsctx)
|
|
||||||
return NULL;
|
|
||||||
CGraphicsContextCocoa* newCtx = new CGraphicsContextCocoa(m_api, NULL);
|
|
||||||
newCtx->m_nsShareContext = nsctx;
|
|
||||||
return newCtx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeCurrent()
|
|
||||||
{
|
|
||||||
if (m_nsContext)
|
|
||||||
[[m_nsContext openGLContext] makeCurrentContext];
|
|
||||||
else if (m_nsShareContext)
|
|
||||||
[m_nsShareContext makeCurrentContext];
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearCurrent()
|
|
||||||
{
|
|
||||||
[NSOpenGLContext clearCurrentContext];
|
|
||||||
}
|
|
||||||
|
|
||||||
void swapBuffer()
|
|
||||||
{
|
|
||||||
[[m_nsContext openGLContext] flushBuffer];
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
IGraphicsContext* _CGraphicsContextCocoaNew(IGraphicsContext::EGraphicsAPI api,
|
|
||||||
IWindow* parentWindow)
|
|
||||||
{
|
|
||||||
if (api != IGraphicsContext::API_OPENGL_3_3 && api != IGraphicsContext::API_OPENGL_4_2)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Create temporary context to query GL version */
|
|
||||||
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_RGBA8_ATTRS];
|
|
||||||
if (!nspf)
|
|
||||||
return NULL;
|
|
||||||
NSOpenGLContext* nsctx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:nil];
|
|
||||||
[nspf release];
|
|
||||||
if (!nsctx)
|
|
||||||
return NULL;
|
|
||||||
[nsctx makeCurrentContext];
|
|
||||||
const char* glVersion = (char*)glGetString(GL_VERSION);
|
|
||||||
unsigned major = 0;
|
|
||||||
unsigned minor = 0;
|
|
||||||
if (glVersion)
|
|
||||||
{
|
|
||||||
major = glVersion[0] - '0';
|
|
||||||
minor = glVersion[2] - '0';
|
|
||||||
}
|
|
||||||
[NSOpenGLContext clearCurrentContext];
|
|
||||||
[nsctx release];
|
|
||||||
if (!glVersion)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (major > 4 || (major == 4 && minor >= 2))
|
|
||||||
api = IGraphicsContext::API_OPENGL_4_2;
|
|
||||||
else if (major == 3 && minor >= 3)
|
|
||||||
if (api == IGraphicsContext::API_OPENGL_4_2)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return new CGraphicsContextCocoa(api, parentWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@implementation CGraphicsContextCocoaInternal
|
|
||||||
- (id)initWithBooContext:(boo::CGraphicsContextCocoa*)bctx
|
|
||||||
{
|
|
||||||
lastModifiers = 0;
|
|
||||||
booContext = bctx;
|
|
||||||
boo::IGraphicsContext::EPixelFormat pf = bctx->getPixelFormat();
|
|
||||||
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[pf]];
|
|
||||||
self = [self initWithFrame:NSMakeRect(0, 0, 100, 100) pixelFormat:nspf];
|
|
||||||
[nspf release];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)acceptsTouchEvents
|
|
||||||
{
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline boo::IWindowCallback::EModifierKey getMod(NSEventModifierFlags flags)
|
|
||||||
{
|
|
||||||
int ret = boo::IWindowCallback::MKEY_NONE;
|
|
||||||
if (flags & NSControlKeyMask)
|
|
||||||
ret |= boo::IWindowCallback::MKEY_CTRL;
|
|
||||||
if (flags & NSAlternateKeyMask)
|
|
||||||
ret |= boo::IWindowCallback::MKEY_ALT;
|
|
||||||
if (flags & NSShiftKeyMask)
|
|
||||||
ret |= boo::IWindowCallback::MKEY_SHIFT;
|
|
||||||
if (flags & NSCommandKeyMask)
|
|
||||||
ret |= boo::IWindowCallback::MKEY_COMMAND;
|
|
||||||
return static_cast<boo::IWindowCallback::EModifierKey>(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline boo::IWindowCallback::EMouseButton getButton(NSEvent* event)
|
|
||||||
{
|
|
||||||
NSInteger buttonNumber = event.buttonNumber;
|
|
||||||
if (buttonNumber == 3)
|
|
||||||
return boo::IWindowCallback::BUTTON_MIDDLE;
|
|
||||||
else if (buttonNumber == 4)
|
|
||||||
return boo::IWindowCallback::BUTTON_AUX1;
|
|
||||||
else if (buttonNumber == 5)
|
|
||||||
return boo::IWindowCallback::BUTTON_AUX2;
|
|
||||||
return boo::IWindowCallback::BUTTON_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)mouseDown:(NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
||||||
float pixelFactor = [[self window] backingScaleFactor];
|
|
||||||
NSRect frame = [self frame];
|
|
||||||
boo::IWindowCallback::SWindowCoord coord =
|
|
||||||
{
|
|
||||||
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
|
||||||
{(unsigned)liw.x, (unsigned)liw.y},
|
|
||||||
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
|
||||||
};
|
|
||||||
booContext->m_callback->mouseDown(coord, boo::IWindowCallback::BUTTON_PRIMARY,
|
|
||||||
getMod([theEvent modifierFlags]));
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)mouseUp:(NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
||||||
float pixelFactor = [[self window] backingScaleFactor];
|
|
||||||
NSRect frame = [self frame];
|
|
||||||
boo::IWindowCallback::SWindowCoord coord =
|
|
||||||
{
|
|
||||||
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
|
||||||
{(unsigned)liw.x, (unsigned)liw.y},
|
|
||||||
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
|
||||||
};
|
|
||||||
booContext->m_callback->mouseUp(coord, boo::IWindowCallback::BUTTON_PRIMARY,
|
|
||||||
getMod([theEvent modifierFlags]));
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)rightMouseDown:(NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
||||||
float pixelFactor = [[self window] backingScaleFactor];
|
|
||||||
NSRect frame = [self frame];
|
|
||||||
boo::IWindowCallback::SWindowCoord coord =
|
|
||||||
{
|
|
||||||
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
|
||||||
{(unsigned)liw.x, (unsigned)liw.y},
|
|
||||||
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
|
||||||
};
|
|
||||||
booContext->m_callback->mouseDown(coord, boo::IWindowCallback::BUTTON_SECONDARY,
|
|
||||||
getMod([theEvent modifierFlags]));
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)rightMouseUp:(NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
||||||
float pixelFactor = [[self window] backingScaleFactor];
|
|
||||||
NSRect frame = [self frame];
|
|
||||||
boo::IWindowCallback::SWindowCoord coord =
|
|
||||||
{
|
|
||||||
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
|
||||||
{(unsigned)liw.x, (unsigned)liw.y},
|
|
||||||
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
|
||||||
};
|
|
||||||
booContext->m_callback->mouseUp(coord, boo::IWindowCallback::BUTTON_SECONDARY,
|
|
||||||
getMod([theEvent modifierFlags]));
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)otherMouseDown:(NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
boo::IWindowCallback::EMouseButton button = getButton(theEvent);
|
|
||||||
if (!button)
|
|
||||||
return;
|
|
||||||
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
||||||
float pixelFactor = [[self window] backingScaleFactor];
|
|
||||||
NSRect frame = [self frame];
|
|
||||||
boo::IWindowCallback::SWindowCoord coord =
|
|
||||||
{
|
|
||||||
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
|
||||||
{(unsigned)liw.x, (unsigned)liw.y},
|
|
||||||
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
|
||||||
};
|
|
||||||
booContext->m_callback->mouseDown(coord, button, getMod([theEvent modifierFlags]));
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)otherMouseUp:(NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
boo::IWindowCallback::EMouseButton button = getButton(theEvent);
|
|
||||||
if (!button)
|
|
||||||
return;
|
|
||||||
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
||||||
float pixelFactor = [[self window] backingScaleFactor];
|
|
||||||
NSRect frame = [self frame];
|
|
||||||
boo::IWindowCallback::SWindowCoord coord =
|
|
||||||
{
|
|
||||||
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
|
||||||
{(unsigned)liw.x, (unsigned)liw.y},
|
|
||||||
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
|
||||||
};
|
|
||||||
booContext->m_callback->mouseUp(coord, button, getMod([theEvent modifierFlags]));
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)mouseMoved:(NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
||||||
float pixelFactor = [[self window] backingScaleFactor];
|
|
||||||
NSRect frame = [self frame];
|
|
||||||
boo::IWindowCallback::SWindowCoord coord =
|
|
||||||
{
|
|
||||||
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
|
||||||
{(unsigned)liw.x, (unsigned)liw.y},
|
|
||||||
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
|
||||||
};
|
|
||||||
booContext->m_callback->mouseMove(coord);
|
|
||||||
}
|
|
||||||
- (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
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
boo::IWindowCallback::SScrollDelta scroll =
|
|
||||||
{
|
|
||||||
{(float)[theEvent scrollingDeltaX], (float)[theEvent scrollingDeltaY]},
|
|
||||||
(bool)[theEvent hasPreciseScrollingDeltas]
|
|
||||||
};
|
|
||||||
booContext->m_callback->scroll(scroll);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)touchesBeganWithEvent:(NSEvent*)event
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseBegan inView:nil])
|
|
||||||
{
|
|
||||||
NSPoint pos = touch.normalizedPosition;
|
|
||||||
boo::IWindowCallback::SWindowCoord coord =
|
|
||||||
{
|
|
||||||
{0, 0},
|
|
||||||
{0, 0},
|
|
||||||
{(float)pos.x, (float)pos.y}
|
|
||||||
};
|
|
||||||
booContext->m_callback->touchDown(coord, (uintptr_t)touch.identity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)touchesEndedWithEvent:(NSEvent*)event
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseEnded inView:nil])
|
|
||||||
{
|
|
||||||
NSPoint pos = touch.normalizedPosition;
|
|
||||||
boo::IWindowCallback::SWindowCoord coord =
|
|
||||||
{
|
|
||||||
{0, 0},
|
|
||||||
{0, 0},
|
|
||||||
{(float)pos.x, (float)pos.y}
|
|
||||||
};
|
|
||||||
booContext->m_callback->touchUp(coord, (uintptr_t)touch.identity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)touchesMovedWithEvent:(NSEvent*)event
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseMoved inView:nil])
|
|
||||||
{
|
|
||||||
NSPoint pos = touch.normalizedPosition;
|
|
||||||
boo::IWindowCallback::SWindowCoord coord =
|
|
||||||
{
|
|
||||||
{0, 0},
|
|
||||||
{0, 0},
|
|
||||||
{(float)pos.x, (float)pos.y}
|
|
||||||
};
|
|
||||||
booContext->m_callback->touchMove(coord, (uintptr_t)touch.identity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)touchesCancelledWithEvent:(NSEvent*)event
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseCancelled inView:nil])
|
|
||||||
{
|
|
||||||
NSPoint pos = touch.normalizedPosition;
|
|
||||||
boo::IWindowCallback::SWindowCoord coord =
|
|
||||||
{
|
|
||||||
{0, 0},
|
|
||||||
{0, 0},
|
|
||||||
{(float)pos.x, (float)pos.y}
|
|
||||||
};
|
|
||||||
booContext->m_callback->touchUp(coord, (uintptr_t)touch.identity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* keycodes for keys that are independent of keyboard layout*/
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
kVK_Return = 0x24,
|
|
||||||
kVK_Tab = 0x30,
|
|
||||||
kVK_Space = 0x31,
|
|
||||||
kVK_Delete = 0x33,
|
|
||||||
kVK_Escape = 0x35,
|
|
||||||
kVK_Command = 0x37,
|
|
||||||
kVK_Shift = 0x38,
|
|
||||||
kVK_CapsLock = 0x39,
|
|
||||||
kVK_Option = 0x3A,
|
|
||||||
kVK_Control = 0x3B,
|
|
||||||
kVK_RightShift = 0x3C,
|
|
||||||
kVK_RightOption = 0x3D,
|
|
||||||
kVK_RightControl = 0x3E,
|
|
||||||
kVK_Function = 0x3F,
|
|
||||||
kVK_F17 = 0x40,
|
|
||||||
kVK_VolumeUp = 0x48,
|
|
||||||
kVK_VolumeDown = 0x49,
|
|
||||||
kVK_Mute = 0x4A,
|
|
||||||
kVK_F18 = 0x4F,
|
|
||||||
kVK_F19 = 0x50,
|
|
||||||
kVK_F20 = 0x5A,
|
|
||||||
kVK_F5 = 0x60,
|
|
||||||
kVK_F6 = 0x61,
|
|
||||||
kVK_F7 = 0x62,
|
|
||||||
kVK_F3 = 0x63,
|
|
||||||
kVK_F8 = 0x64,
|
|
||||||
kVK_F9 = 0x65,
|
|
||||||
kVK_F11 = 0x67,
|
|
||||||
kVK_F13 = 0x69,
|
|
||||||
kVK_F16 = 0x6A,
|
|
||||||
kVK_F14 = 0x6B,
|
|
||||||
kVK_F10 = 0x6D,
|
|
||||||
kVK_F12 = 0x6F,
|
|
||||||
kVK_F15 = 0x71,
|
|
||||||
kVK_Help = 0x72,
|
|
||||||
kVK_Home = 0x73,
|
|
||||||
kVK_PageUp = 0x74,
|
|
||||||
kVK_ForwardDelete = 0x75,
|
|
||||||
kVK_F4 = 0x76,
|
|
||||||
kVK_End = 0x77,
|
|
||||||
kVK_F2 = 0x78,
|
|
||||||
kVK_PageDown = 0x79,
|
|
||||||
kVK_F1 = 0x7A,
|
|
||||||
kVK_LeftArrow = 0x7B,
|
|
||||||
kVK_RightArrow = 0x7C,
|
|
||||||
kVK_DownArrow = 0x7D,
|
|
||||||
kVK_UpArrow = 0x7E
|
|
||||||
};
|
|
||||||
static boo::IWindowCallback::ESpecialKey translateKeycode(short code)
|
|
||||||
{
|
|
||||||
switch (code) {
|
|
||||||
case kVK_F1:
|
|
||||||
return boo::IWindowCallback::KEY_F1;
|
|
||||||
case kVK_F2:
|
|
||||||
return boo::IWindowCallback::KEY_F2;
|
|
||||||
case kVK_F3:
|
|
||||||
return boo::IWindowCallback::KEY_F3;
|
|
||||||
case kVK_F4:
|
|
||||||
return boo::IWindowCallback::KEY_F4;
|
|
||||||
case kVK_F5:
|
|
||||||
return boo::IWindowCallback::KEY_F5;
|
|
||||||
case kVK_F6:
|
|
||||||
return boo::IWindowCallback::KEY_F6;
|
|
||||||
case kVK_F7:
|
|
||||||
return boo::IWindowCallback::KEY_F7;
|
|
||||||
case kVK_F8:
|
|
||||||
return boo::IWindowCallback::KEY_F8;
|
|
||||||
case kVK_F9:
|
|
||||||
return boo::IWindowCallback::KEY_F9;
|
|
||||||
case kVK_F10:
|
|
||||||
return boo::IWindowCallback::KEY_F10;
|
|
||||||
case kVK_F11:
|
|
||||||
return boo::IWindowCallback::KEY_F11;
|
|
||||||
case kVK_F12:
|
|
||||||
return boo::IWindowCallback::KEY_F12;
|
|
||||||
case kVK_Escape:
|
|
||||||
return boo::IWindowCallback::KEY_ESC;
|
|
||||||
case kVK_Return:
|
|
||||||
return boo::IWindowCallback::KEY_ENTER;
|
|
||||||
case kVK_Delete:
|
|
||||||
return boo::IWindowCallback::KEY_BACKSPACE;
|
|
||||||
case kVK_ForwardDelete:
|
|
||||||
return boo::IWindowCallback::KEY_DELETE;
|
|
||||||
case kVK_Home:
|
|
||||||
return boo::IWindowCallback::KEY_HOME;
|
|
||||||
case kVK_End:
|
|
||||||
return boo::IWindowCallback::KEY_END;
|
|
||||||
case kVK_PageUp:
|
|
||||||
return boo::IWindowCallback::KEY_PGUP;
|
|
||||||
case kVK_PageDown:
|
|
||||||
return boo::IWindowCallback::KEY_PGDOWN;
|
|
||||||
case kVK_LeftArrow:
|
|
||||||
return boo::IWindowCallback::KEY_LEFT;
|
|
||||||
case kVK_RightArrow:
|
|
||||||
return boo::IWindowCallback::KEY_RIGHT;
|
|
||||||
case kVK_UpArrow:
|
|
||||||
return boo::IWindowCallback::KEY_UP;
|
|
||||||
case kVK_DownArrow:
|
|
||||||
return boo::IWindowCallback::KEY_DOWN;
|
|
||||||
default:
|
|
||||||
return boo::IWindowCallback::KEY_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)keyDown:(NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
NSString* chars = theEvent.characters;
|
|
||||||
if ([chars length] == 0)
|
|
||||||
booContext->m_callback->specialKeyDown(translateKeycode(theEvent.keyCode),
|
|
||||||
getMod(theEvent.modifierFlags),
|
|
||||||
theEvent.isARepeat);
|
|
||||||
else
|
|
||||||
booContext->m_callback->charKeyDown([chars characterAtIndex:0],
|
|
||||||
getMod(theEvent.modifierFlags),
|
|
||||||
theEvent.isARepeat);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)keyUp:(NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
NSString* chars = theEvent.characters;
|
|
||||||
if ([chars length] == 0)
|
|
||||||
booContext->m_callback->specialKeyUp(translateKeycode(theEvent.keyCode),
|
|
||||||
getMod(theEvent.modifierFlags));
|
|
||||||
else
|
|
||||||
booContext->m_callback->charKeyUp([chars characterAtIndex:0],
|
|
||||||
getMod(theEvent.modifierFlags));
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)flagsChanged:(NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
if (!booContext->m_callback)
|
|
||||||
return;
|
|
||||||
NSUInteger modFlags = theEvent.modifierFlags;
|
|
||||||
bool isRepeat = theEvent.isARepeat;
|
|
||||||
if (modFlags != lastModifiers)
|
|
||||||
{
|
|
||||||
NSUInteger changedFlags = modFlags ^ lastModifiers;
|
|
||||||
|
|
||||||
NSUInteger downFlags = changedFlags & modFlags;
|
|
||||||
if (downFlags & NSControlKeyMask)
|
|
||||||
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_CTRL, isRepeat);
|
|
||||||
if (downFlags & NSAlternateKeyMask)
|
|
||||||
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_ALT, isRepeat);
|
|
||||||
if (downFlags & NSShiftKeyMask)
|
|
||||||
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_SHIFT, isRepeat);
|
|
||||||
if (downFlags & NSCommandKeyMask)
|
|
||||||
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_COMMAND, isRepeat);
|
|
||||||
|
|
||||||
NSUInteger upFlags = changedFlags & ~modFlags;
|
|
||||||
if (upFlags & NSControlKeyMask)
|
|
||||||
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_CTRL);
|
|
||||||
if (upFlags & NSAlternateKeyMask)
|
|
||||||
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_ALT);
|
|
||||||
if (upFlags & NSShiftKeyMask)
|
|
||||||
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_SHIFT);
|
|
||||||
if (upFlags & NSCommandKeyMask)
|
|
||||||
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_COMMAND);
|
|
||||||
|
|
||||||
lastModifiers = modFlags;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
@ -1,35 +1,668 @@
|
|||||||
#import <AppKit/AppKit.h>
|
#import <AppKit/AppKit.h>
|
||||||
#include "IApplication.hpp"
|
#include <OpenGL/OpenGL.h>
|
||||||
#include "windowsys/IWindow.hpp"
|
#include <OpenGL/gl3.h>
|
||||||
#include "windowsys/IGraphicsContext.hpp"
|
#include "boo/IApplication.hpp"
|
||||||
|
#include "boo/IWindow.hpp"
|
||||||
|
#include "boo/IGraphicsContext.hpp"
|
||||||
|
|
||||||
namespace boo {class CWindowCocoa;}
|
namespace boo {class WindowCocoa;}
|
||||||
@interface CWindowCocoaInternal : NSWindow
|
@interface WindowCocoaInternal : NSWindow
|
||||||
{
|
{
|
||||||
boo::CWindowCocoa* booWindow;
|
boo::WindowCocoa* booWindow;
|
||||||
}
|
}
|
||||||
- (id)initWithBooWindow:(boo::CWindowCocoa*)bw title:(const std::string&)title;
|
- (id)initWithBooWindow:(boo::WindowCocoa*)bw title:(const std::string&)title;
|
||||||
- (void)setFrameDefault;
|
- (void)setFrameDefault;
|
||||||
- (NSRect)genFrameDefault;
|
- (NSRect)genFrameDefault;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
/* AppKit applies OpenGL much differently than other platforms
|
||||||
|
* the NSOpenGLView class composes together all necessary
|
||||||
|
* OGL context members and provides the necessary event hooks
|
||||||
|
* for KB/Mouse/Touch events
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const NSOpenGLPixelFormatAttribute PF_RGBA8_ATTRS[] =
|
||||||
|
{
|
||||||
|
NSOpenGLPFAAccelerated,
|
||||||
|
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||||
|
NSOpenGLPFADoubleBuffer,
|
||||||
|
NSOpenGLPFAColorSize, 24,
|
||||||
|
NSOpenGLPFAAlphaSize, 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NSOpenGLPixelFormatAttribute PF_RGBA8_Z24_ATTRS[] =
|
||||||
|
{
|
||||||
|
NSOpenGLPFAAccelerated,
|
||||||
|
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||||
|
NSOpenGLPFADoubleBuffer,
|
||||||
|
NSOpenGLPFAColorSize, 24,
|
||||||
|
NSOpenGLPFAAlphaSize, 8,
|
||||||
|
NSOpenGLPFADepthSize, 24,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NSOpenGLPixelFormatAttribute PF_RGBAF32_ATTRS[] =
|
||||||
|
{
|
||||||
|
NSOpenGLPFAAccelerated,
|
||||||
|
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||||
|
NSOpenGLPFADoubleBuffer,
|
||||||
|
NSOpenGLPFAColorFloat,
|
||||||
|
NSOpenGLPFAColorSize, 96,
|
||||||
|
NSOpenGLPFAAlphaSize, 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NSOpenGLPixelFormatAttribute PF_RGBAF32_Z24_ATTRS[] =
|
||||||
|
{
|
||||||
|
NSOpenGLPFAAccelerated,
|
||||||
|
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||||
|
NSOpenGLPFADoubleBuffer,
|
||||||
|
NSOpenGLPFAColorFloat,
|
||||||
|
NSOpenGLPFAColorSize, 96,
|
||||||
|
NSOpenGLPFAAlphaSize, 32,
|
||||||
|
NSOpenGLPFADepthSize, 24,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NSOpenGLPixelFormatAttribute* PF_TABLE[] =
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
PF_RGBA8_ATTRS,
|
||||||
|
PF_RGBA8_Z24_ATTRS,
|
||||||
|
PF_RGBAF32_ATTRS,
|
||||||
|
PF_RGBAF32_Z24_ATTRS
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace boo {class GraphicsContextCocoa;}
|
||||||
|
@interface GraphicsContextCocoaInternal : NSOpenGLView
|
||||||
|
{
|
||||||
|
NSUInteger lastModifiers;
|
||||||
|
boo::GraphicsContextCocoa* booContext;
|
||||||
|
}
|
||||||
|
- (id)initWithBooContext:(boo::GraphicsContextCocoa*)bctx;
|
||||||
|
@end
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
IGraphicsContext* _CGraphicsContextCocoaNew(IGraphicsContext::EGraphicsAPI api,
|
class GraphicsContextCocoa : public IGraphicsContext
|
||||||
IWindow* parentWindow);
|
|
||||||
|
|
||||||
class CWindowCocoa final : public IWindow
|
|
||||||
{
|
{
|
||||||
|
|
||||||
CWindowCocoaInternal* m_nsWindow;
|
EGraphicsAPI m_api;
|
||||||
|
EPixelFormat m_pf;
|
||||||
|
IWindow* m_parentWindow;
|
||||||
|
GraphicsContextCocoaInternal* m_nsContext;
|
||||||
|
NSOpenGLContext* m_nsShareContext;
|
||||||
|
|
||||||
|
public:
|
||||||
|
IWindowCallback* m_callback;
|
||||||
|
|
||||||
|
GraphicsContextCocoa(EGraphicsAPI api, IWindow* parentWindow)
|
||||||
|
: m_api(api),
|
||||||
|
m_pf(PF_RGBA8),
|
||||||
|
m_parentWindow(parentWindow),
|
||||||
|
m_nsContext(NULL),
|
||||||
|
m_nsShareContext(NULL),
|
||||||
|
m_callback(NULL)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~GraphicsContextCocoa()
|
||||||
|
{
|
||||||
|
[m_nsContext release];
|
||||||
|
[m_nsShareContext release];
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setCallback(IWindowCallback* cb)
|
||||||
|
{
|
||||||
|
m_callback = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
EGraphicsAPI getAPI() const
|
||||||
|
{
|
||||||
|
return m_api;
|
||||||
|
}
|
||||||
|
|
||||||
|
EPixelFormat getPixelFormat() const
|
||||||
|
{
|
||||||
|
return m_pf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPixelFormat(EPixelFormat pf)
|
||||||
|
{
|
||||||
|
if (pf > PF_RGBAF32_Z24)
|
||||||
|
return;
|
||||||
|
m_pf = pf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeContext()
|
||||||
|
{
|
||||||
|
if (m_nsShareContext)
|
||||||
|
return;
|
||||||
|
m_nsContext = [[GraphicsContextCocoaInternal alloc] initWithBooContext:this];
|
||||||
|
[(NSWindow*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
IGraphicsContext* makeShareContext() const
|
||||||
|
{
|
||||||
|
NSOpenGLContext* nsctx;
|
||||||
|
if (m_nsContext)
|
||||||
|
{
|
||||||
|
nsctx = [[NSOpenGLContext alloc] initWithFormat:[m_nsContext pixelFormat]
|
||||||
|
shareContext:[m_nsContext openGLContext]];
|
||||||
|
}
|
||||||
|
else if (m_nsShareContext)
|
||||||
|
{
|
||||||
|
nsctx = [[NSOpenGLContext alloc] initWithFormat:[m_nsShareContext pixelFormat]
|
||||||
|
shareContext:m_nsShareContext];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
if (!nsctx)
|
||||||
|
return NULL;
|
||||||
|
GraphicsContextCocoa* newCtx = new GraphicsContextCocoa(m_api, NULL);
|
||||||
|
newCtx->m_nsShareContext = nsctx;
|
||||||
|
return newCtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeCurrent()
|
||||||
|
{
|
||||||
|
if (m_nsContext)
|
||||||
|
[[m_nsContext openGLContext] makeCurrentContext];
|
||||||
|
else if (m_nsShareContext)
|
||||||
|
[m_nsShareContext makeCurrentContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearCurrent()
|
||||||
|
{
|
||||||
|
[NSOpenGLContext clearCurrentContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
void swapBuffer()
|
||||||
|
{
|
||||||
|
[[m_nsContext openGLContext] flushBuffer];
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IGraphicsContext* _CGraphicsContextCocoaNew(IGraphicsContext::EGraphicsAPI api,
|
||||||
|
IWindow* parentWindow)
|
||||||
|
{
|
||||||
|
if (api != IGraphicsContext::API_OPENGL_3_3 && api != IGraphicsContext::API_OPENGL_4_2)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Create temporary context to query GL version */
|
||||||
|
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_RGBA8_ATTRS];
|
||||||
|
if (!nspf)
|
||||||
|
return NULL;
|
||||||
|
NSOpenGLContext* nsctx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:nil];
|
||||||
|
[nspf release];
|
||||||
|
if (!nsctx)
|
||||||
|
return NULL;
|
||||||
|
[nsctx makeCurrentContext];
|
||||||
|
const char* glVersion = (char*)glGetString(GL_VERSION);
|
||||||
|
unsigned major = 0;
|
||||||
|
unsigned minor = 0;
|
||||||
|
if (glVersion)
|
||||||
|
{
|
||||||
|
major = glVersion[0] - '0';
|
||||||
|
minor = glVersion[2] - '0';
|
||||||
|
}
|
||||||
|
[NSOpenGLContext clearCurrentContext];
|
||||||
|
[nsctx release];
|
||||||
|
if (!glVersion)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (major > 4 || (major == 4 && minor >= 2))
|
||||||
|
api = IGraphicsContext::API_OPENGL_4_2;
|
||||||
|
else if (major == 3 && minor >= 3)
|
||||||
|
if (api == IGraphicsContext::API_OPENGL_4_2)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return new GraphicsContextCocoa(api, parentWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation GraphicsContextCocoaInternal
|
||||||
|
- (id)initWithBooContext:(boo::GraphicsContextCocoa*)bctx
|
||||||
|
{
|
||||||
|
lastModifiers = 0;
|
||||||
|
booContext = bctx;
|
||||||
|
boo::IGraphicsContext::EPixelFormat pf = bctx->getPixelFormat();
|
||||||
|
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[pf]];
|
||||||
|
self = [self initWithFrame:NSMakeRect(0, 0, 100, 100) pixelFormat:nspf];
|
||||||
|
[nspf release];
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)acceptsTouchEvents
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline boo::IWindowCallback::EModifierKey getMod(NSEventModifierFlags flags)
|
||||||
|
{
|
||||||
|
int ret = boo::IWindowCallback::MKEY_NONE;
|
||||||
|
if (flags & NSControlKeyMask)
|
||||||
|
ret |= boo::IWindowCallback::MKEY_CTRL;
|
||||||
|
if (flags & NSAlternateKeyMask)
|
||||||
|
ret |= boo::IWindowCallback::MKEY_ALT;
|
||||||
|
if (flags & NSShiftKeyMask)
|
||||||
|
ret |= boo::IWindowCallback::MKEY_SHIFT;
|
||||||
|
if (flags & NSCommandKeyMask)
|
||||||
|
ret |= boo::IWindowCallback::MKEY_COMMAND;
|
||||||
|
return static_cast<boo::IWindowCallback::EModifierKey>(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline boo::IWindowCallback::EMouseButton getButton(NSEvent* event)
|
||||||
|
{
|
||||||
|
NSInteger buttonNumber = event.buttonNumber;
|
||||||
|
if (buttonNumber == 3)
|
||||||
|
return boo::IWindowCallback::BUTTON_MIDDLE;
|
||||||
|
else if (buttonNumber == 4)
|
||||||
|
return boo::IWindowCallback::BUTTON_AUX1;
|
||||||
|
else if (buttonNumber == 5)
|
||||||
|
return boo::IWindowCallback::BUTTON_AUX2;
|
||||||
|
return boo::IWindowCallback::BUTTON_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseDown:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseDown(coord, boo::IWindowCallback::BUTTON_PRIMARY,
|
||||||
|
getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseUp:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseUp(coord, boo::IWindowCallback::BUTTON_PRIMARY,
|
||||||
|
getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)rightMouseDown:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseDown(coord, boo::IWindowCallback::BUTTON_SECONDARY,
|
||||||
|
getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)rightMouseUp:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseUp(coord, boo::IWindowCallback::BUTTON_SECONDARY,
|
||||||
|
getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)otherMouseDown:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
boo::IWindowCallback::EMouseButton button = getButton(theEvent);
|
||||||
|
if (!button)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseDown(coord, button, getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)otherMouseUp:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
boo::IWindowCallback::EMouseButton button = getButton(theEvent);
|
||||||
|
if (!button)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseUp(coord, button, getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseMoved:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseMove(coord);
|
||||||
|
}
|
||||||
|
- (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
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
boo::IWindowCallback::SScrollDelta scroll =
|
||||||
|
{
|
||||||
|
{(float)[theEvent scrollingDeltaX], (float)[theEvent scrollingDeltaY]},
|
||||||
|
(bool)[theEvent hasPreciseScrollingDeltas]
|
||||||
|
};
|
||||||
|
booContext->m_callback->scroll(coord, scroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesBeganWithEvent:(NSEvent*)event
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseBegan inView:nil])
|
||||||
|
{
|
||||||
|
NSPoint pos = touch.normalizedPosition;
|
||||||
|
boo::IWindowCallback::STouchCoord coord =
|
||||||
|
{
|
||||||
|
{(float)pos.x, (float)pos.y}
|
||||||
|
};
|
||||||
|
booContext->m_callback->touchDown(coord, (uintptr_t)touch.identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesEndedWithEvent:(NSEvent*)event
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseEnded inView:nil])
|
||||||
|
{
|
||||||
|
NSPoint pos = touch.normalizedPosition;
|
||||||
|
boo::IWindowCallback::STouchCoord coord =
|
||||||
|
{
|
||||||
|
{(float)pos.x, (float)pos.y}
|
||||||
|
};
|
||||||
|
booContext->m_callback->touchUp(coord, (uintptr_t)touch.identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesMovedWithEvent:(NSEvent*)event
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseMoved inView:nil])
|
||||||
|
{
|
||||||
|
NSPoint pos = touch.normalizedPosition;
|
||||||
|
boo::IWindowCallback::STouchCoord coord =
|
||||||
|
{
|
||||||
|
{(float)pos.x, (float)pos.y}
|
||||||
|
};
|
||||||
|
booContext->m_callback->touchMove(coord, (uintptr_t)touch.identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesCancelledWithEvent:(NSEvent*)event
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseCancelled inView:nil])
|
||||||
|
{
|
||||||
|
NSPoint pos = touch.normalizedPosition;
|
||||||
|
boo::IWindowCallback::STouchCoord coord =
|
||||||
|
{
|
||||||
|
{(float)pos.x, (float)pos.y}
|
||||||
|
};
|
||||||
|
booContext->m_callback->touchUp(coord, (uintptr_t)touch.identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* keycodes for keys that are independent of keyboard layout*/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kVK_Return = 0x24,
|
||||||
|
kVK_Tab = 0x30,
|
||||||
|
kVK_Space = 0x31,
|
||||||
|
kVK_Delete = 0x33,
|
||||||
|
kVK_Escape = 0x35,
|
||||||
|
kVK_Command = 0x37,
|
||||||
|
kVK_Shift = 0x38,
|
||||||
|
kVK_CapsLock = 0x39,
|
||||||
|
kVK_Option = 0x3A,
|
||||||
|
kVK_Control = 0x3B,
|
||||||
|
kVK_RightShift = 0x3C,
|
||||||
|
kVK_RightOption = 0x3D,
|
||||||
|
kVK_RightControl = 0x3E,
|
||||||
|
kVK_Function = 0x3F,
|
||||||
|
kVK_F17 = 0x40,
|
||||||
|
kVK_VolumeUp = 0x48,
|
||||||
|
kVK_VolumeDown = 0x49,
|
||||||
|
kVK_Mute = 0x4A,
|
||||||
|
kVK_F18 = 0x4F,
|
||||||
|
kVK_F19 = 0x50,
|
||||||
|
kVK_F20 = 0x5A,
|
||||||
|
kVK_F5 = 0x60,
|
||||||
|
kVK_F6 = 0x61,
|
||||||
|
kVK_F7 = 0x62,
|
||||||
|
kVK_F3 = 0x63,
|
||||||
|
kVK_F8 = 0x64,
|
||||||
|
kVK_F9 = 0x65,
|
||||||
|
kVK_F11 = 0x67,
|
||||||
|
kVK_F13 = 0x69,
|
||||||
|
kVK_F16 = 0x6A,
|
||||||
|
kVK_F14 = 0x6B,
|
||||||
|
kVK_F10 = 0x6D,
|
||||||
|
kVK_F12 = 0x6F,
|
||||||
|
kVK_F15 = 0x71,
|
||||||
|
kVK_Help = 0x72,
|
||||||
|
kVK_Home = 0x73,
|
||||||
|
kVK_PageUp = 0x74,
|
||||||
|
kVK_ForwardDelete = 0x75,
|
||||||
|
kVK_F4 = 0x76,
|
||||||
|
kVK_End = 0x77,
|
||||||
|
kVK_F2 = 0x78,
|
||||||
|
kVK_PageDown = 0x79,
|
||||||
|
kVK_F1 = 0x7A,
|
||||||
|
kVK_LeftArrow = 0x7B,
|
||||||
|
kVK_RightArrow = 0x7C,
|
||||||
|
kVK_DownArrow = 0x7D,
|
||||||
|
kVK_UpArrow = 0x7E
|
||||||
|
};
|
||||||
|
static boo::IWindowCallback::ESpecialKey translateKeycode(short code)
|
||||||
|
{
|
||||||
|
switch (code) {
|
||||||
|
case kVK_F1:
|
||||||
|
return boo::IWindowCallback::KEY_F1;
|
||||||
|
case kVK_F2:
|
||||||
|
return boo::IWindowCallback::KEY_F2;
|
||||||
|
case kVK_F3:
|
||||||
|
return boo::IWindowCallback::KEY_F3;
|
||||||
|
case kVK_F4:
|
||||||
|
return boo::IWindowCallback::KEY_F4;
|
||||||
|
case kVK_F5:
|
||||||
|
return boo::IWindowCallback::KEY_F5;
|
||||||
|
case kVK_F6:
|
||||||
|
return boo::IWindowCallback::KEY_F6;
|
||||||
|
case kVK_F7:
|
||||||
|
return boo::IWindowCallback::KEY_F7;
|
||||||
|
case kVK_F8:
|
||||||
|
return boo::IWindowCallback::KEY_F8;
|
||||||
|
case kVK_F9:
|
||||||
|
return boo::IWindowCallback::KEY_F9;
|
||||||
|
case kVK_F10:
|
||||||
|
return boo::IWindowCallback::KEY_F10;
|
||||||
|
case kVK_F11:
|
||||||
|
return boo::IWindowCallback::KEY_F11;
|
||||||
|
case kVK_F12:
|
||||||
|
return boo::IWindowCallback::KEY_F12;
|
||||||
|
case kVK_Escape:
|
||||||
|
return boo::IWindowCallback::KEY_ESC;
|
||||||
|
case kVK_Return:
|
||||||
|
return boo::IWindowCallback::KEY_ENTER;
|
||||||
|
case kVK_Delete:
|
||||||
|
return boo::IWindowCallback::KEY_BACKSPACE;
|
||||||
|
case kVK_ForwardDelete:
|
||||||
|
return boo::IWindowCallback::KEY_DELETE;
|
||||||
|
case kVK_Home:
|
||||||
|
return boo::IWindowCallback::KEY_HOME;
|
||||||
|
case kVK_End:
|
||||||
|
return boo::IWindowCallback::KEY_END;
|
||||||
|
case kVK_PageUp:
|
||||||
|
return boo::IWindowCallback::KEY_PGUP;
|
||||||
|
case kVK_PageDown:
|
||||||
|
return boo::IWindowCallback::KEY_PGDOWN;
|
||||||
|
case kVK_LeftArrow:
|
||||||
|
return boo::IWindowCallback::KEY_LEFT;
|
||||||
|
case kVK_RightArrow:
|
||||||
|
return boo::IWindowCallback::KEY_RIGHT;
|
||||||
|
case kVK_UpArrow:
|
||||||
|
return boo::IWindowCallback::KEY_UP;
|
||||||
|
case kVK_DownArrow:
|
||||||
|
return boo::IWindowCallback::KEY_DOWN;
|
||||||
|
default:
|
||||||
|
return boo::IWindowCallback::KEY_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)keyDown:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSString* chars = theEvent.characters;
|
||||||
|
if ([chars length] == 0)
|
||||||
|
booContext->m_callback->specialKeyDown(translateKeycode(theEvent.keyCode),
|
||||||
|
getMod(theEvent.modifierFlags),
|
||||||
|
theEvent.isARepeat);
|
||||||
|
else
|
||||||
|
booContext->m_callback->charKeyDown([chars characterAtIndex:0],
|
||||||
|
getMod(theEvent.modifierFlags),
|
||||||
|
theEvent.isARepeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)keyUp:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSString* chars = theEvent.characters;
|
||||||
|
if ([chars length] == 0)
|
||||||
|
booContext->m_callback->specialKeyUp(translateKeycode(theEvent.keyCode),
|
||||||
|
getMod(theEvent.modifierFlags));
|
||||||
|
else
|
||||||
|
booContext->m_callback->charKeyUp([chars characterAtIndex:0],
|
||||||
|
getMod(theEvent.modifierFlags));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)flagsChanged:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSUInteger modFlags = theEvent.modifierFlags;
|
||||||
|
bool isRepeat = theEvent.isARepeat;
|
||||||
|
if (modFlags != lastModifiers)
|
||||||
|
{
|
||||||
|
NSUInteger changedFlags = modFlags ^ lastModifiers;
|
||||||
|
|
||||||
|
NSUInteger downFlags = changedFlags & modFlags;
|
||||||
|
if (downFlags & NSControlKeyMask)
|
||||||
|
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_CTRL, isRepeat);
|
||||||
|
if (downFlags & NSAlternateKeyMask)
|
||||||
|
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_ALT, isRepeat);
|
||||||
|
if (downFlags & NSShiftKeyMask)
|
||||||
|
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_SHIFT, isRepeat);
|
||||||
|
if (downFlags & NSCommandKeyMask)
|
||||||
|
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_COMMAND, isRepeat);
|
||||||
|
|
||||||
|
NSUInteger upFlags = changedFlags & ~modFlags;
|
||||||
|
if (upFlags & NSControlKeyMask)
|
||||||
|
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_CTRL);
|
||||||
|
if (upFlags & NSAlternateKeyMask)
|
||||||
|
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_ALT);
|
||||||
|
if (upFlags & NSShiftKeyMask)
|
||||||
|
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_SHIFT);
|
||||||
|
if (upFlags & NSCommandKeyMask)
|
||||||
|
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_COMMAND);
|
||||||
|
|
||||||
|
lastModifiers = modFlags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
|
||||||
|
class WindowCocoa : public IWindow
|
||||||
|
{
|
||||||
|
|
||||||
|
WindowCocoaInternal* m_nsWindow;
|
||||||
IGraphicsContext* m_gfxCtx;
|
IGraphicsContext* m_gfxCtx;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CWindowCocoa(const std::string& title)
|
WindowCocoa(const std::string& title)
|
||||||
{
|
{
|
||||||
m_nsWindow = [[CWindowCocoaInternal alloc] initWithBooWindow:this title:title];
|
m_nsWindow = [[WindowCocoaInternal alloc] initWithBooWindow:this title:title];
|
||||||
m_gfxCtx = _CGraphicsContextCocoaNew(IGraphicsContext::API_OPENGL_3_3, this);
|
m_gfxCtx = _CGraphicsContextCocoaNew(IGraphicsContext::API_OPENGL_3_3, this);
|
||||||
m_gfxCtx->initializeContext();
|
m_gfxCtx->initializeContext();
|
||||||
}
|
}
|
||||||
@ -39,12 +672,12 @@ public:
|
|||||||
m_nsWindow = NULL;
|
m_nsWindow = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
~CWindowCocoa()
|
~WindowCocoa()
|
||||||
{
|
{
|
||||||
[m_nsWindow orderOut:nil];
|
[m_nsWindow orderOut:nil];
|
||||||
[m_nsWindow release];
|
[m_nsWindow release];
|
||||||
delete m_gfxCtx;
|
delete m_gfxCtx;
|
||||||
IApplicationInstance()->_deletedWindow(this);
|
APP->_deletedWindow(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCallback(IWindowCallback* cb)
|
void setCallback(IWindowCallback* cb)
|
||||||
@ -117,6 +750,11 @@ public:
|
|||||||
return TOUCH_TRACKPAD;
|
return TOUCH_TRACKPAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waitForRetrace()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t getPlatformHandle() const
|
uintptr_t getPlatformHandle() const
|
||||||
{
|
{
|
||||||
return (uintptr_t)m_nsWindow;
|
return (uintptr_t)m_nsWindow;
|
||||||
@ -124,15 +762,15 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IWindow* _CWindowCocoaNew(const std::string& title)
|
IWindow* _WindowCocoaNew(const SystemString& title)
|
||||||
{
|
{
|
||||||
return new CWindowCocoa(title);
|
return new WindowCocoa(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@implementation CWindowCocoaInternal
|
@implementation WindowCocoaInternal
|
||||||
- (id)initWithBooWindow:(boo::CWindowCocoa *)bw title:(const std::string&)title
|
- (id)initWithBooWindow:(boo::WindowCocoa *)bw title:(const boo::SystemString&)title
|
||||||
{
|
{
|
||||||
self = [self initWithContentRect:[self genFrameDefault]
|
self = [self initWithContentRect:[self genFrameDefault]
|
||||||
styleMask:NSTitledWindowMask|
|
styleMask:NSTitledWindowMask|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user