From afe93bee381313c6d0c2611ce40e53c0065c2bb6 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 4 May 2015 13:37:28 -1000 Subject: [PATCH 01/10] initial appkit window/glcontext implementation --- include/boo.hpp | 16 +- include/mac/CCGLContext.hpp | 34 ---- include/windowsys/IGraphicsContext.hpp | 52 +++++++ include/windowsys/IWindow.hpp | 34 ++++ libBoo.pri | 20 +-- src/mac/CCGLCocoaView.mm | 0 src/mac/CCGLContext.cpp | 67 -------- src/windowsys/CGraphicsContextCocoa.mm | 207 +++++++++++++++++++++++++ src/windowsys/CWindowCocoa.mm | 102 ++++++++++++ 9 files changed, 401 insertions(+), 131 deletions(-) delete mode 100644 include/mac/CCGLContext.hpp create mode 100644 include/windowsys/IGraphicsContext.hpp create mode 100644 include/windowsys/IWindow.hpp delete mode 100644 src/mac/CCGLCocoaView.mm delete mode 100644 src/mac/CCGLContext.cpp create mode 100644 src/windowsys/CGraphicsContextCocoa.mm create mode 100644 src/windowsys/CWindowCocoa.mm diff --git a/include/boo.hpp b/include/boo.hpp index c407f9e..f4f01c9 100644 --- a/include/boo.hpp +++ b/include/boo.hpp @@ -1,21 +1,7 @@ #ifndef BOO_HPP #define BOO_HPP -#if defined(_WIN32) -#include "win/CWGLContext.hpp" -namespace boo {typedef CWGLContext CGraphicsContext;} - -#elif defined(__APPLE__) -#include "mac/CCGLContext.hpp" -namespace boo {typedef CCGLContext CGraphicsContext;} - -#elif defined(__GNUC__) || defined(__clang__) -#include "x11/CGLXContext.hpp" -namespace boo {typedef CGLXContext CGraphicsContext;} - -#endif - -#include "IGraphicsContext.hpp" +#include "windowsys/IWindow.hpp" #include "inputdev/CDeviceFinder.hpp" #include "inputdev/CDolphinSmashAdapter.hpp" diff --git a/include/mac/CCGLContext.hpp b/include/mac/CCGLContext.hpp deleted file mode 100644 index 5a66f40..0000000 --- a/include/mac/CCGLContext.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef CCGLCONTEXT_HPP -#define CCGLCONTEXT_HPP - -#ifdef __APPLE__ -#include "IGraphicsContext.hpp" -#include - -namespace boo -{ - -class CCGLContext final : public IGraphicsContext -{ -public: - CCGLContext(); - virtual ~CCGLContext(); - - bool create(); - void setMinVersion (const int& min) override; - void setMajorVersion(const int& maj) override; - const std::string version() const override; - const std::string name() const override; - int depthSize() const override; - int redDepth() const override; - int greenDepth() const override; - int blueDepth() const override; -private: - int m_minVersion; - int m_majVersion; -}; - -} - -#endif // __APPLE__ -#endif // CCGLCONTEXT_HPP diff --git a/include/windowsys/IGraphicsContext.hpp b/include/windowsys/IGraphicsContext.hpp new file mode 100644 index 0000000..ebcd5c6 --- /dev/null +++ b/include/windowsys/IGraphicsContext.hpp @@ -0,0 +1,52 @@ +#ifndef IGRAPHICSCONTEXT_HPP +#define IGRAPHICSCONTEXT_HPP + +namespace boo +{ + +class IGraphicsContext +{ +public: + + enum EGraphicsAPI + { + API_NONE = 0, + API_OPENGL_3_3 = 1, + API_OPENGL_4_2 = 2, + API_OPENGLES_3 = 3, + API_VULKAN = 4, + API_D3D11 = 5, + API_METAL = 6 + }; + + enum EPixelFormat + { + PF_NONE = 0, + PF_RGBA8 = 1, /* Default */ + PF_RGBA8_Z24 = 2, + PF_RGBAF32 = 3, + PF_RGBAF32_Z24 = 4 + }; + + virtual ~IGraphicsContext() {} + + virtual EGraphicsAPI getAPI() const=0; + virtual EPixelFormat getPixelFormat() const=0; + virtual void setPixelFormat(EPixelFormat pf)=0; + virtual void setPlatformWindowHandle(void* handle)=0; + virtual void initializeContext()=0; + virtual IGraphicsContext* makeShareContext() const=0; + virtual void makeCurrent()=0; + virtual void clearCurrent()=0; + + /* Note: *all* contexts are double-buffered with + * v-sync interval; please call this */ + virtual void swapBuffer()=0; + +}; + +IGraphicsContext* IGraphicsContextNew(IGraphicsContext::EGraphicsAPI api); + +} + +#endif // IGRAPHICSCONTEXT_HPP diff --git a/include/windowsys/IWindow.hpp b/include/windowsys/IWindow.hpp new file mode 100644 index 0000000..212b44c --- /dev/null +++ b/include/windowsys/IWindow.hpp @@ -0,0 +1,34 @@ +#ifndef IWINDOW_HPP +#define IWINDOW_HPP + +#include + +namespace boo +{ + +class IWindow +{ +public: + + virtual ~IWindow() {} + + virtual void showWindow()=0; + virtual void hideWindow()=0; + + virtual std::string getTitle()=0; + virtual void setTitle(const std::string& title)=0; + + virtual void setWindowFrameDefault()=0; + virtual void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const=0; + virtual void setWindowFrame(float x, float y, float w, float h)=0; + + virtual bool isFullscreen() const=0; + virtual void setFullscreen(bool fs)=0; + +}; + +IWindow* IWindowNew(); + +} + +#endif // IWINDOW_HPP diff --git a/libBoo.pri b/libBoo.pri index f589cd3..f15161c 100644 --- a/libBoo.pri +++ b/libBoo.pri @@ -1,12 +1,7 @@ HEADERS += \ $$PWD/include/boo.hpp \ - $$PWD/include/IGraphicsContext.hpp \ - $$PWD/include/ISurface.hpp \ - $$PWD/include/CSurface.hpp \ - $$PWD/include/IRetraceWaiter.hpp \ - $$PWD/include/IInputWaiter.hpp \ - $$PWD/include/CInputRelay.hpp \ - $$PWD/include/CInputDeferredRelay.hpp \ + $$PWD/include/windowsys/IWindow.hpp \ + $$PWD/include/windowsys/IGraphicsContext.hpp \ $$PWD/include/inputdev/CDolphinSmashAdapter.hpp \ $$PWD/include/inputdev/CRevolutionPad.hpp \ $$PWD/include/inputdev/CCafeProPad.hpp \ @@ -36,7 +31,6 @@ SOURCES += \ unix:!macx { HEADERS += \ $$PWD/include/x11/CGLXContext.hpp - SOURCES += \ $$PWD/src/x11/CGLXContext.cpp } @@ -45,21 +39,17 @@ linux { SOURCES += \ $$PWD/src/inputdev/CHIDListenerUdev.cpp \ $$PWD/src/inputdev/CHIDDeviceUdev.cpp - LIBS += -ludev } macx { - HEADERS += \ - $$PWD/include/mac/CCGLContext.hpp - SOURCES += \ - $$PWD/src/mac/CCGLContext.cpp \ $$PWD/src/inputdev/CHIDDeviceIOKit.cpp \ $$PWD/src/inputdev/CHIDListenerIOKit.cpp - OBJECTIVE_SOURCES += \ - $$PWD/src/mac/CCGLCocoaView.mm + $$PWD/src/windowsys/CWindowCocoa.mm \ + $$PWD/src/windowsys/CGraphicsContextCocoa.mm + LIBS += -framework AppKit } win32 { diff --git a/src/mac/CCGLCocoaView.mm b/src/mac/CCGLCocoaView.mm deleted file mode 100644 index e69de29..0000000 diff --git a/src/mac/CCGLContext.cpp b/src/mac/CCGLContext.cpp deleted file mode 100644 index 7e3217c..0000000 --- a/src/mac/CCGLContext.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#ifdef __APPLE__ -#include "CCGLContext.hpp" -#include - -namespace boo -{ - -CCGLContext::CCGLContext() - : m_minVersion(3), - m_majVersion(3) -{ - std::cout << "Hello from CGL" << std::endl; -} - -CCGLContext::~CCGLContext() -{ - -} - -bool CCGLContext::create() -{ - return true; -} - -void CCGLContext::setMinVersion(const int& min) -{ - m_minVersion = min; -} - -void CCGLContext::setMajorVersion(const int& maj) -{ - m_majVersion = maj; -} - -const std::string CCGLContext::version() const -{ - return "Invalid version"; -} - -const std::string CCGLContext::name() const -{ - return "GLX Context"; -} - -int CCGLContext::depthSize() const -{ - return -1; -} - -int CCGLContext::redDepth() const -{ - return -1; -} - -int CCGLContext::greenDepth() const -{ - return -1; -} - -int CCGLContext::blueDepth() const -{ - return -1; -} - -} - -#endif \ No newline at end of file diff --git a/src/windowsys/CGraphicsContextCocoa.mm b/src/windowsys/CGraphicsContextCocoa.mm new file mode 100644 index 0000000..e217697 --- /dev/null +++ b/src/windowsys/CGraphicsContextCocoa.mm @@ -0,0 +1,207 @@ +#import +#include +#include +#include "windowsys/IGraphicsContext.hpp" + +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 +- (id)initWithBooContext:(boo::CGraphicsContextCocoa*)bctx; +@end + +namespace boo +{ + +class CGraphicsContextCocoa final : public IGraphicsContext +{ + + EGraphicsAPI m_api; + EPixelFormat m_pf; + NSWindow* m_parentWindow; + CGraphicsContextCocoaInternal* m_nsContext; + NSOpenGLContext* m_nsShareContext; + +public: + CGraphicsContextCocoa(EGraphicsAPI api) + : m_api(api), + m_pf(PF_RGBA8), + m_parentWindow(NULL), + m_nsContext(NULL), + m_nsShareContext(NULL) + {} + + ~CGraphicsContextCocoa() + { + [m_nsContext release]; + [m_nsShareContext release]; + } + + 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 setPlatformWindowHandle(void* handle) + { + m_parentWindow = (NSWindow*)handle; + } + + void initializeContext() + { + if (m_nsShareContext) + return; + m_nsContext = [[CGraphicsContextCocoaInternal alloc] initWithBooContext:this]; + [m_parentWindow 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); + 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* IGraphicsContextNew(IGraphicsContext::EGraphicsAPI api) +{ + 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); +} + +} + +@implementation CGraphicsContextCocoaInternal +- (id)initWithBooContext:(boo::CGraphicsContextCocoa*)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; +} +@end + diff --git a/src/windowsys/CWindowCocoa.mm b/src/windowsys/CWindowCocoa.mm new file mode 100644 index 0000000..9d41c3a --- /dev/null +++ b/src/windowsys/CWindowCocoa.mm @@ -0,0 +1,102 @@ +#import +#include "windowsys/IWindow.hpp" +#include "windowsys/IGraphicsContext.hpp" + +@interface CWindowCocoaInternal : NSWindow +@end + +namespace boo +{ + +class CWindowCocoa final : public IWindow +{ + + CWindowCocoaInternal* m_nsWindow; + IGraphicsContext* m_gfxCtx; + +public: + CWindowCocoa() + { + m_nsWindow = [CWindowCocoaInternal new]; + m_gfxCtx = IGraphicsContextNew(IGraphicsContext::API_OPENGL_3_3); + m_gfxCtx->setPlatformWindowHandle(m_nsWindow); + m_gfxCtx->initializeContext(); + } + + ~CWindowCocoa() + { + [m_nsWindow orderOut:nil]; + [m_nsWindow release]; + delete m_gfxCtx; + } + + void showWindow() + { + [m_nsWindow makeKeyAndOrderFront:nil]; + } + + void hideWindow() + { + [m_nsWindow orderOut:nil]; + } + + std::string getTitle() + { + return [[m_nsWindow title] UTF8String]; + } + + void setTitle(const std::string& title) + { + [m_nsWindow setTitle:[NSString stringWithUTF8String:title.c_str()]]; + } + + void setWindowFrameDefault() + { + NSScreen* mainScreen = [NSScreen mainScreen]; + NSRect scrFrame = mainScreen.frame; + float x_off = scrFrame.size.width / 3.0; + float y_off = scrFrame.size.height / 3.0; + [m_nsWindow setFrame:NSMakeRect(x_off, y_off, x_off * 2.0, y_off * 2.0) display:NO]; + } + + void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const + { + NSRect wFrame = m_nsWindow.frame; + xOut = wFrame.origin.x; + yOut = wFrame.origin.y; + wOut = wFrame.size.width; + hOut = wFrame.size.height; + } + + void setWindowFrame(float x, float y, float w, float h) + { + NSRect wFrame = NSMakeRect(x, y, w, h); + [m_nsWindow setFrame:wFrame display:NO]; + } + + bool isFullscreen() const + { + return ([m_nsWindow styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask; + } + + void setFullscreen(bool fs) + { + if ((fs && !isFullscreen()) || (!fs && isFullscreen())) + [m_nsWindow toggleFullScreen:nil]; + } + +}; + +IWindow* IWindowNew() +{ + return new CWindowCocoa; +} + +} + +@implementation CWindowCocoaInternal +{ + +} +@end + From df4c484489667caa4ae57f80f5452a82d7689c03 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 4 May 2015 21:16:06 -1000 Subject: [PATCH 02/10] added keyboard/mouse events to AppKit implementation --- include/inputdev/CDeviceBase.hpp | 2 +- include/inputdev/CDeviceFinder.hpp | 9 +- include/inputdev/CDolphinSmashAdapter.hpp | 6 +- include/inputdev/SDeviceSignature.hpp | 10 +- include/windowsys/IGraphicsContext.hpp | 9 +- include/windowsys/IWindow.hpp | 106 ++++++ src/windowsys/CGraphicsContextCocoa.mm | 432 +++++++++++++++++++++- src/windowsys/CWindowCocoa.mm | 38 +- test/main.cpp | 19 +- 9 files changed, 600 insertions(+), 31 deletions(-) diff --git a/include/inputdev/CDeviceBase.hpp b/include/inputdev/CDeviceBase.hpp index 392802f..6319dc1 100644 --- a/include/inputdev/CDeviceBase.hpp +++ b/include/inputdev/CDeviceBase.hpp @@ -35,7 +35,7 @@ public: /* High-Level API */ bool sendHIDReport(const uint8_t* data, size_t length); - virtual size_t receiveReport(uint8_t* data, size_t length) {return 0;} + virtual size_t receiveReport(uint8_t* data, size_t length) {(void)data;(void)length;return 0;} }; diff --git a/include/inputdev/CDeviceFinder.hpp b/include/inputdev/CDeviceFinder.hpp index ec68a78..00f09b3 100644 --- a/include/inputdev/CDeviceFinder.hpp +++ b/include/inputdev/CDeviceFinder.hpp @@ -1,7 +1,8 @@ #ifndef CDEVICEFINDER_HPP #define CDEVICEFINDER_HPP -#include +#include +#include #include #include #include "CDeviceToken.hpp" @@ -91,18 +92,18 @@ public: }; /* Application must specify its interested device-types */ - CDeviceFinder(std::vector types) + CDeviceFinder(std::unordered_set types) : m_listener(NULL) { if (skDevFinder) throw std::runtime_error("only one instance of CDeviceFinder may be constructed"); skDevFinder = this; - for (const char* typeName : types) + for (const std::type_index& typeIdx : types) { const SDeviceSignature* sigIter = BOO_DEVICE_SIGS; while (sigIter->m_name) { - if (!strcmp(sigIter->m_name, typeName)) + if (sigIter->m_typeIdx == typeIdx) m_types.push_back(sigIter); ++sigIter; } diff --git a/include/inputdev/CDolphinSmashAdapter.hpp b/include/inputdev/CDolphinSmashAdapter.hpp index ceb0795..ae21b15 100644 --- a/include/inputdev/CDolphinSmashAdapter.hpp +++ b/include/inputdev/CDolphinSmashAdapter.hpp @@ -40,10 +40,10 @@ struct SDolphinControllerState struct IDolphinSmashAdapterCallback { - virtual void controllerConnected(unsigned idx, EDolphinControllerType type) {} - virtual void controllerDisconnected(unsigned idx, EDolphinControllerType type) {} + virtual void controllerConnected(unsigned idx, EDolphinControllerType type) {(void)idx;(void)type;} + virtual void controllerDisconnected(unsigned idx, EDolphinControllerType type) {(void)idx;(void)type;} virtual void controllerUpdate(unsigned idx, EDolphinControllerType type, - const SDolphinControllerState& state) {} + const SDolphinControllerState& state) {(void)idx;(void)type;(void)state;} }; class CDolphinSmashAdapter final : public CDeviceBase diff --git a/include/inputdev/SDeviceSignature.hpp b/include/inputdev/SDeviceSignature.hpp index 80708b9..7c89d62 100644 --- a/include/inputdev/SDeviceSignature.hpp +++ b/include/inputdev/SDeviceSignature.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace boo { @@ -15,17 +16,18 @@ struct SDeviceSignature typedef std::vector TDeviceSignatureSet; typedef std::function TFactoryLambda; const char* m_name; + std::type_index m_typeIdx; unsigned m_vid, m_pid; TFactoryLambda m_factory; - SDeviceSignature() : m_name(NULL) {} /* Sentinel constructor */ - SDeviceSignature(const char* name, unsigned vid, unsigned pid, TFactoryLambda&& factory) - : m_name(name), m_vid(vid), m_pid(pid), m_factory(factory) {} + SDeviceSignature() : m_name(NULL), m_typeIdx(typeid(SDeviceSignature)) {} /* Sentinel constructor */ + SDeviceSignature(const char* name, std::type_index&& typeIdx, unsigned vid, unsigned pid, TFactoryLambda&& factory) + : m_name(name), m_typeIdx(typeIdx), m_vid(vid), m_pid(pid), m_factory(factory) {} static bool DeviceMatchToken(const CDeviceToken& token, const TDeviceSignatureSet& sigSet); static CDeviceBase* DeviceNew(CDeviceToken& token); }; #define DEVICE_SIG(name, vid, pid) \ - SDeviceSignature(#name, vid, pid, [](CDeviceToken* tok) -> CDeviceBase* {return new name(tok);}) + SDeviceSignature(#name, typeid(name), vid, pid, [](CDeviceToken* tok) -> CDeviceBase* {return new name(tok);}) #define DEVICE_SIG_SENTINEL() SDeviceSignature() extern const SDeviceSignature BOO_DEVICE_SIGS[]; diff --git a/include/windowsys/IGraphicsContext.hpp b/include/windowsys/IGraphicsContext.hpp index ebcd5c6..e1ba30e 100644 --- a/include/windowsys/IGraphicsContext.hpp +++ b/include/windowsys/IGraphicsContext.hpp @@ -6,6 +6,10 @@ namespace boo class IGraphicsContext { + friend class CWindowCocoa; + virtual void _setPlatformWindowHandle(void* handle) {(void)handle;}; + virtual void _setCallback(class IWindowCallback* cb) {(void)cb;}; + public: enum EGraphicsAPI @@ -16,7 +20,9 @@ public: API_OPENGLES_3 = 3, API_VULKAN = 4, API_D3D11 = 5, - API_METAL = 6 + API_METAL = 6, + API_GX = 7, + API_GX2 = 8 }; enum EPixelFormat @@ -33,7 +39,6 @@ public: virtual EGraphicsAPI getAPI() const=0; virtual EPixelFormat getPixelFormat() const=0; virtual void setPixelFormat(EPixelFormat pf)=0; - virtual void setPlatformWindowHandle(void* handle)=0; virtual void initializeContext()=0; virtual IGraphicsContext* makeShareContext() const=0; virtual void makeCurrent()=0; diff --git a/include/windowsys/IWindow.hpp b/include/windowsys/IWindow.hpp index 212b44c..f5a7d46 100644 --- a/include/windowsys/IWindow.hpp +++ b/include/windowsys/IWindow.hpp @@ -5,6 +5,101 @@ namespace boo { + +class IWindowCallback +{ +public: + enum EMouseButton + { + BUTTON_NONE = 0, + BUTTON_PRIMARY = 1, + BUTTON_SECONDARY = 2, + BUTTON_MIDDLE = 3, + BUTTON_AUX1 = 4, + BUTTON_AUX2 = 5 + }; + + struct SWindowCoord + { + unsigned pixel[2]; + unsigned virtualPixel[2]; + float norm[2]; + }; + + struct SScrollDelta + { + float delta[2]; + bool isFine; /* Use system-scale fine-scroll (for scrollable-trackpads) */ + }; + + enum ESpecialKey + { + KEY_NONE = 0, + KEY_F1 = 1, + KEY_F2 = 2, + KEY_F3 = 3, + KEY_F4 = 4, + KEY_F5 = 5, + KEY_F6 = 6, + KEY_F7 = 7, + KEY_F8 = 8, + KEY_F9 = 9, + KEY_F10 = 10, + KEY_F11 = 11, + KEY_F12 = 12, + KEY_ESC = 13, + KEY_ENTER = 14, + KEY_BACKSPACE = 15, + KEY_INSERT = 16, + KEY_DELETE = 17, + KEY_HOME = 18, + KEY_END = 19, + KEY_PGUP = 20, + KEY_PGDOWN = 21, + KEY_LEFT = 22, + KEY_RIGHT = 23, + KEY_UP = 24, + KEY_DOWN = 25 + }; + + enum EModifierKey + { + MKEY_NONE = 0, + MKEY_CTRL = 1<<0, + MKEY_ALT = 1<<2, + MKEY_SHIFT = 1<<3, + MKEY_COMMAND = 1<<4 + }; + + virtual void mouseDown(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) + {(void)coord;(void)button;(void)mods;} + virtual void mouseUp(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) + {(void)coord;(void)button;(void)mods;} + virtual void mouseMove(const SWindowCoord& coord) + {(void)coord;} + virtual void scroll(const SScrollDelta& scroll) + {(void)scroll;}; + + virtual void touchDown(const SWindowCoord& coord, uintptr_t tid) + {(void)coord;(void)tid;} + virtual void touchUp(const SWindowCoord& coord, uintptr_t tid) + {(void)coord;(void)tid;} + virtual void touchMove(const SWindowCoord& coord, uintptr_t tid) + {(void)coord;(void)tid;} + + virtual void charKeyDown(unsigned long charCode, EModifierKey mods, bool isRepeat) + {(void)charCode;(void)mods;(void)isRepeat;} + virtual void charKeyUp(unsigned long charCode, EModifierKey mods) + {(void)charCode;(void)mods;} + virtual void specialKeyDown(ESpecialKey key, EModifierKey mods, bool isRepeat) + {(void)key;(void)mods;(void)isRepeat;} + virtual void specialKeyUp(ESpecialKey key, EModifierKey mods) + {(void)key;(void)mods;} + virtual void modKeyDown(EModifierKey mod, bool isRepeat) + {(void)mod;(void)isRepeat;} + virtual void modKeyUp(EModifierKey mod) {(void)mod;} + +}; class IWindow { @@ -12,6 +107,8 @@ public: virtual ~IWindow() {} + virtual void setCallback(IWindowCallback* cb)=0; + virtual void showWindow()=0; virtual void hideWindow()=0; @@ -21,10 +118,19 @@ public: virtual void setWindowFrameDefault()=0; virtual void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const=0; virtual void setWindowFrame(float x, float y, float w, float h)=0; + virtual float getVirtualPixelFactor() const=0; virtual bool isFullscreen() const=0; virtual void setFullscreen(bool fs)=0; + enum ETouchType + { + TOUCH_NONE = 0, + TOUCH_DISPLAY = 1, + TOUCH_TRACKPAD = 2 + }; + virtual ETouchType getTouchType() const=0; + }; IWindow* IWindowNew(); diff --git a/src/windowsys/CGraphicsContextCocoa.mm b/src/windowsys/CGraphicsContextCocoa.mm index e217697..2a0ed3f 100644 --- a/src/windowsys/CGraphicsContextCocoa.mm +++ b/src/windowsys/CGraphicsContextCocoa.mm @@ -2,6 +2,7 @@ #include #include #include "windowsys/IGraphicsContext.hpp" +#include "windowsys/IWindow.hpp" static const NSOpenGLPixelFormatAttribute PF_RGBA8_ATTRS[] = { @@ -54,6 +55,10 @@ static const NSOpenGLPixelFormatAttribute* PF_TABLE[] = namespace boo {class CGraphicsContextCocoa;} @interface CGraphicsContextCocoaInternal : NSOpenGLView +{ + NSUInteger lastModifiers; + boo::CGraphicsContextCocoa* booContext; +} - (id)initWithBooContext:(boo::CGraphicsContextCocoa*)bctx; @end @@ -70,12 +75,15 @@ class CGraphicsContextCocoa final : public IGraphicsContext NSOpenGLContext* m_nsShareContext; public: + IWindowCallback* m_callback; + CGraphicsContextCocoa(EGraphicsAPI api) : m_api(api), m_pf(PF_RGBA8), m_parentWindow(NULL), m_nsContext(NULL), - m_nsShareContext(NULL) + m_nsShareContext(NULL), + m_callback(NULL) {} ~CGraphicsContextCocoa() @@ -84,6 +92,11 @@ public: [m_nsShareContext release]; } + void _setCallback(IWindowCallback* cb) + { + m_callback = cb; + } + EGraphicsAPI getAPI() const { return m_api; @@ -197,11 +210,428 @@ IGraphicsContext* IGraphicsContextNew(IGraphicsContext::EGraphicsAPI api) @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(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 diff --git a/src/windowsys/CWindowCocoa.mm b/src/windowsys/CWindowCocoa.mm index 9d41c3a..0fde361 100644 --- a/src/windowsys/CWindowCocoa.mm +++ b/src/windowsys/CWindowCocoa.mm @@ -2,7 +2,12 @@ #include "windowsys/IWindow.hpp" #include "windowsys/IGraphicsContext.hpp" +namespace boo {class CWindowCocoa;} @interface CWindowCocoaInternal : NSWindow +{ + boo::CWindowCocoa* booWindow; +} +- (id)initWithBooWindow:(boo::CWindowCocoa*)bw; @end namespace boo @@ -13,13 +18,14 @@ class CWindowCocoa final : public IWindow CWindowCocoaInternal* m_nsWindow; IGraphicsContext* m_gfxCtx; - + public: + CWindowCocoa() { - m_nsWindow = [CWindowCocoaInternal new]; + m_nsWindow = [[CWindowCocoaInternal alloc] initWithBooWindow:this]; m_gfxCtx = IGraphicsContextNew(IGraphicsContext::API_OPENGL_3_3); - m_gfxCtx->setPlatformWindowHandle(m_nsWindow); + m_gfxCtx->_setPlatformWindowHandle(m_nsWindow); m_gfxCtx->initializeContext(); } @@ -30,6 +36,11 @@ public: delete m_gfxCtx; } + void setCallback(IWindowCallback* cb) + { + m_gfxCtx->_setCallback(cb); + } + void showWindow() { [m_nsWindow makeKeyAndOrderFront:nil]; @@ -74,6 +85,11 @@ public: [m_nsWindow setFrame:wFrame display:NO]; } + float getVirtualPixelFactor() const + { + return [m_nsWindow backingScaleFactor]; + } + bool isFullscreen() const { return ([m_nsWindow styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask; @@ -85,6 +101,11 @@ public: [m_nsWindow toggleFullScreen:nil]; } + ETouchType getTouchType() const + { + return TOUCH_TRACKPAD; + } + }; IWindow* IWindowNew() @@ -95,8 +116,17 @@ IWindow* IWindowNew() } @implementation CWindowCocoaInternal +- (id)initWithBooWindow:(boo::CWindowCocoa *)bw { - + self = [self initWithContentRect:NSMakeRect(0, 0, 100, 100) + styleMask:NSTitledWindowMask| + NSClosableWindowMask| + NSMiniaturizableWindowMask| + NSResizableWindowMask + backing:NSBackingStoreBuffered + defer:YES]; + booWindow = bw; + return self; } @end diff --git a/test/main.cpp b/test/main.cpp index 79e4b27..d287d65 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -20,15 +20,15 @@ namespace boo class CDolphinSmashAdapterCallback : public IDolphinSmashAdapterCallback { - void controllerConnected(unsigned idx, EDolphinControllerType type) + void controllerConnected(unsigned idx, EDolphinControllerType) { printf("CONTROLLER %u CONNECTED\n", idx); } - void controllerDisconnected(unsigned idx, EDolphinControllerType type) + void controllerDisconnected(unsigned idx, EDolphinControllerType) { printf("CONTROLLER %u DISCONNECTED\n", idx); } - void controllerUpdate(unsigned idx, EDolphinControllerType type, + void controllerUpdate(unsigned idx, EDolphinControllerType, const SDolphinControllerState& state) { printf("CONTROLLER %u UPDATE %d %d\n", idx, state.m_leftStick[0], state.m_leftStick[1]); @@ -41,7 +41,7 @@ class CTestDeviceFinder : public CDeviceFinder CDolphinSmashAdapterCallback m_cb; public: CTestDeviceFinder() - : CDeviceFinder({"CDolphinSmashAdapter"}) + : CDeviceFinder({typeid(CDolphinSmashAdapter)}) {} void deviceConnected(CDeviceToken& tok) { @@ -141,19 +141,14 @@ int APIENTRY wWinMain( #else -int main(int argc, char** argv) +int main(int, char**) { boo::CTestDeviceFinder finder; finder.startScanning(); -#if 0 - boo::IGraphicsContext* ctx = new boo::CGraphicsContext; - - if (ctx->create()) - { - } -#endif + boo::IWindow* window = boo::IWindowNew(); + (void)window; #if __APPLE__ CFRunLoopRun(); From de7f062944c529fde39a0c60ac73cfb4cb807baf Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 5 May 2015 14:50:57 -1000 Subject: [PATCH 03/10] major application architecture work --- include/CInputDeferredRelay.hpp | 11 -- include/CInputRelay.hpp | 16 -- include/CQtOpenGLWindow.hpp | 36 ----- include/CSurface.hpp | 14 -- include/IApplication.hpp | 79 ++++++++++ include/IGraphicsContext.hpp | 27 ---- include/IInputWaiter.hpp | 14 -- include/IRetraceWaiter.hpp | 14 -- include/ISurface.hpp | 15 -- include/boo.hpp | 1 + include/win/CWGLContext.hpp | 19 --- include/windowsys/IGraphicsContext.hpp | 2 - include/windowsys/IWindow.hpp | 4 +- include/x11/CGLXContext.hpp | 36 ----- libBoo.pri | 23 +-- src/CApplicationCocoa.mm | 180 ++++++++++++++++++++++ src/CApplicationUnix.cpp | 32 ++++ src/CApplicationWayland.hpp | 61 ++++++++ src/CApplicationWin32.cpp | 162 +++++++++++++++++++ src/CApplicationXCB.hpp | 61 ++++++++ src/CInputDeferredRelay.cpp | 1 - src/CInputRelay.cpp | 1 - src/CQtOpenGLWindow.cpp | 3 - src/CRetraceWaiter.cpp | 1 - src/CSurface.cpp | 16 -- src/win/CWGLContext.cpp | 4 - src/windowsys/CGraphicsContextCocoa.mm | 26 ++-- src/windowsys/CGraphicsContextWayland.cpp | 87 +++++++++++ src/windowsys/CGraphicsContextWin32.cpp | 87 +++++++++++ src/windowsys/CGraphicsContextXCB.cpp | 87 +++++++++++ src/windowsys/CWindowCocoa.mm | 67 ++++++-- src/windowsys/CWindowWayland.cpp | 93 +++++++++++ src/windowsys/CWindowWin32.cpp | 96 ++++++++++++ src/windowsys/CWindowXCB.cpp | 93 +++++++++++ src/x11/CGLXContext.cpp | 63 -------- test/main.cpp | 123 ++++----------- 36 files changed, 1231 insertions(+), 424 deletions(-) delete mode 100644 include/CInputDeferredRelay.hpp delete mode 100644 include/CInputRelay.hpp delete mode 100644 include/CQtOpenGLWindow.hpp delete mode 100644 include/CSurface.hpp create mode 100644 include/IApplication.hpp delete mode 100644 include/IGraphicsContext.hpp delete mode 100644 include/IInputWaiter.hpp delete mode 100644 include/IRetraceWaiter.hpp delete mode 100644 include/ISurface.hpp delete mode 100644 include/win/CWGLContext.hpp delete mode 100644 include/x11/CGLXContext.hpp create mode 100644 src/CApplicationCocoa.mm create mode 100644 src/CApplicationUnix.cpp create mode 100644 src/CApplicationWayland.hpp create mode 100644 src/CApplicationWin32.cpp create mode 100644 src/CApplicationXCB.hpp delete mode 100644 src/CInputDeferredRelay.cpp delete mode 100644 src/CInputRelay.cpp delete mode 100644 src/CQtOpenGLWindow.cpp delete mode 100644 src/CRetraceWaiter.cpp delete mode 100644 src/CSurface.cpp delete mode 100644 src/win/CWGLContext.cpp create mode 100644 src/windowsys/CGraphicsContextWayland.cpp create mode 100644 src/windowsys/CGraphicsContextWin32.cpp create mode 100644 src/windowsys/CGraphicsContextXCB.cpp create mode 100644 src/windowsys/CWindowWayland.cpp create mode 100644 src/windowsys/CWindowWin32.cpp create mode 100644 src/windowsys/CWindowXCB.cpp delete mode 100644 src/x11/CGLXContext.cpp diff --git a/include/CInputDeferredRelay.hpp b/include/CInputDeferredRelay.hpp deleted file mode 100644 index 524261c..0000000 --- a/include/CInputDeferredRelay.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef CINPUTDEFERREDRELAY_HPP -#define CINPUTDEFERREDRELAY_HPP - -#include "IInputWaiter.hpp" - -namespace boo -{ - -} - -#endif // CINPUTDEFERREDRELAY_HPP diff --git a/include/CInputRelay.hpp b/include/CInputRelay.hpp deleted file mode 100644 index 03eacbe..0000000 --- a/include/CInputRelay.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef CINPUTRELAY_HPP -#define CINPUTRELAY_HPP - -#include "IInputWaiter.hpp" - -namespace boo -{ - -class CInputRelay : IInputWaiter -{ - -}; - -} - -#endif // CINPUTRELAY_HPP diff --git a/include/CQtOpenGLWindow.hpp b/include/CQtOpenGLWindow.hpp deleted file mode 100644 index 650513c..0000000 --- a/include/CQtOpenGLWindow.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef CQTOPENGLWINDOW_HPP -#define CQTOPENGLWINDOW_HPP - -#include -#include -#include - -class CQtOpenGLWindow : public QWindow, ISurface -{ - Q_OBJECT -public: - explicit CQtOpenGLWindow(QWindow *parent = 0); - CQtOpenGLWindow(); - - virtual void render(); - - virtual void initialize(); - - - public slots: - void renderLater(); - void renderNow(); - -protected: - bool event(QEvent *event) Q_DECL_OVERRIDE; - - void exposeEvent(QExposeEvent *event) Q_DECL_OVERRIDE; - -private: - bool m_update_pending; - bool m_animating; - - QOpenGLContext *m_context; -}; - -#endif // CQTOPENGLWINDOW_HPP diff --git a/include/CSurface.hpp b/include/CSurface.hpp deleted file mode 100644 index a1916a8..0000000 --- a/include/CSurface.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef CSURFACE_HPP -#define CSURFACE_HPP - -#include "ISurface.hpp" - -namespace boo -{ - -ISurface* CSurfaceNewWindow(); -ISurface* CSurfaceNewQWidget(); - -} - -#endif // CSURFACE_HPP diff --git a/include/IApplication.hpp b/include/IApplication.hpp new file mode 100644 index 0000000..5c1690b --- /dev/null +++ b/include/IApplication.hpp @@ -0,0 +1,79 @@ +#ifndef IRUNLOOP_HPP +#define IRUNLOOP_HPP + +#include +#include + +#include "windowsys/IWindow.hpp" +#include "inputdev/CDeviceFinder.hpp" + +namespace boo +{ +class IApplication; + +struct IApplicationCallback +{ + virtual void appLaunched(IApplication* app) {(void)app;} + virtual void appQuitting(IApplication* app) {(void)app;} + virtual bool appFileOpen(IApplication* app, const std::string& path) {(void)app;(void)path;return true;} +}; + +class IApplication +{ + friend class CWindowCocoa; + friend class CWindowWayland; + friend class CWindowXCB; + friend class CWindowWin32; + virtual void _deletedWindow(IWindow* window)=0; +public: + virtual ~IApplication() {} + + enum EPlatformType + { + PLAT_AUTO = 0, + PLAT_WAYLAND = 1, + PLAT_XCB = 2, + PLAT_ANDROID = 3, + PLAT_COCOA = 4, + PLAT_COCOA_TOUCH = 5, + PLAT_WIN32 = 6, + PLAT_WINRT = 7, + PLAT_REVOLUTION = 8, + PLAT_CAFE = 9 + }; + virtual EPlatformType getPlatformType() const=0; + + virtual void run()=0; + virtual void quit()=0; + virtual const std::string& getProcessName() const=0; + virtual const std::vector& getArgs() const=0; + + /* Constructors/initializers for sub-objects */ + virtual IWindow* newWindow(const std::string& title)=0; + +}; + +IApplication* IApplicationBootstrap(IApplication::EPlatformType platform, + IApplicationCallback& cb, + const std::string& friendlyName, + const std::string& pname, + const std::vector& args); +extern IApplication* APP; +#define IApplicationInstance() APP + +static inline IApplication* IApplicationBootstrap(IApplication::EPlatformType platform, + IApplicationCallback& cb, + const std::string& friendlyName, + int argc, char** argv) +{ + if (APP) + return APP; + std::vector args; + for (int i=1 ; i - -namespace boo -{ - -class IGraphicsContext -{ -public: - virtual ~IGraphicsContext() {} - - virtual void setMinVersion (const int& min)=0; - virtual void setMajorVersion(const int& maj)=0; - virtual bool create()=0; - virtual const std::string version() const=0; - virtual const std::string name() const=0; - virtual int depthSize() const=0; - virtual int redDepth() const=0; - virtual int greenDepth() const=0; - virtual int blueDepth() const=0; -}; - -} - -#endif // IGRAPHICSCONTEXT_HPP diff --git a/include/IInputWaiter.hpp b/include/IInputWaiter.hpp deleted file mode 100644 index 552a2d8..0000000 --- a/include/IInputWaiter.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef IINPUTWAITER_HPP -#define IINPUTWAITER_HPP - -namespace boo -{ - -class IInputWaiter -{ - -}; - -} - -#endif // IINPUTWAITER_HPP diff --git a/include/IRetraceWaiter.hpp b/include/IRetraceWaiter.hpp deleted file mode 100644 index aacd34f..0000000 --- a/include/IRetraceWaiter.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef IRETRACEWAITER_HPP -#define IRETRACEWAITER_HPP - -namespace boo -{ - -class IRetraceWaiter -{ - -}; - -} - -#endif // IRETRACEWAITER_HPP diff --git a/include/ISurface.hpp b/include/ISurface.hpp deleted file mode 100644 index 6f2f13d..0000000 --- a/include/ISurface.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef ISURFACE_HPP -#define ISURFACE_HPP - -namespace boo -{ - -class ISurface -{ -public: - -}; - -} - -#endif // CSURFACE_HPP diff --git a/include/boo.hpp b/include/boo.hpp index f4f01c9..c2a5e6f 100644 --- a/include/boo.hpp +++ b/include/boo.hpp @@ -1,6 +1,7 @@ #ifndef BOO_HPP #define BOO_HPP +#include "IApplication.hpp" #include "windowsys/IWindow.hpp" #include "inputdev/CDeviceFinder.hpp" #include "inputdev/CDolphinSmashAdapter.hpp" diff --git a/include/win/CWGLContext.hpp b/include/win/CWGLContext.hpp deleted file mode 100644 index ea40ff7..0000000 --- a/include/win/CWGLContext.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef CWGLCONTEXT_HPP -#define CWGLCONTEXT_HPP - -#ifdef _WIN32 - -#include "IGraphicsContext.hpp" - -namespace boo -{ - -class CWGLContext : public IGraphicsContext -{ - -}; - -} - -#endif // _WIN32 -#endif // CWGLCONTEXT_HPP diff --git a/include/windowsys/IGraphicsContext.hpp b/include/windowsys/IGraphicsContext.hpp index e1ba30e..3411570 100644 --- a/include/windowsys/IGraphicsContext.hpp +++ b/include/windowsys/IGraphicsContext.hpp @@ -50,8 +50,6 @@ public: }; -IGraphicsContext* IGraphicsContextNew(IGraphicsContext::EGraphicsAPI api); - } #endif // IGRAPHICSCONTEXT_HPP diff --git a/include/windowsys/IWindow.hpp b/include/windowsys/IWindow.hpp index f5a7d46..4cd70d8 100644 --- a/include/windowsys/IWindow.hpp +++ b/include/windowsys/IWindow.hpp @@ -123,6 +123,8 @@ public: virtual bool isFullscreen() const=0; virtual void setFullscreen(bool fs)=0; + virtual void* getPlatformHandle() const=0; + enum ETouchType { TOUCH_NONE = 0, @@ -133,8 +135,6 @@ public: }; -IWindow* IWindowNew(); - } #endif // IWINDOW_HPP diff --git a/include/x11/CGLXContext.hpp b/include/x11/CGLXContext.hpp deleted file mode 100644 index 809101a..0000000 --- a/include/x11/CGLXContext.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef CGLXCONTEXT_HPP -#define CGLXCONTEXT_HPP - -#if !defined(__APPLE__) && (defined(__linux__) || defined(BSD)) -#include -#include "IGraphicsContext.hpp" - -namespace boo -{ - -class CGLXContext final : public IGraphicsContext -{ -public: - CGLXContext(); - virtual ~CGLXContext() {} - - bool create(); - void setMajorVersion(const int& maj) override; - void setMinVersion(const int& min) override; - const std::string version() const override; - const std::string name() const override; - int depthSize() const override; - int redDepth() const override; - int greenDepth() const override; - int blueDepth() const override; -private: - int m_majVersion; - int m_minVersion; - - Display* m_display; -}; - -} - -#endif // !defined(__APPLE__) && (defined(__linux__) || defined(BSD)) -#endif // CGLXCONTEXT_HPP diff --git a/libBoo.pri b/libBoo.pri index f15161c..36a9714 100644 --- a/libBoo.pri +++ b/libBoo.pri @@ -1,5 +1,6 @@ HEADERS += \ $$PWD/include/boo.hpp \ + $$PWD/include/IApplication.hpp \ $$PWD/include/windowsys/IWindow.hpp \ $$PWD/include/windowsys/IGraphicsContext.hpp \ $$PWD/include/inputdev/CDolphinSmashAdapter.hpp \ @@ -16,10 +17,6 @@ HEADERS += \ SOURCES += \ $$PWD/InputDeviceClasses.cpp \ - $$PWD/src/CSurface.cpp \ - $$PWD/src/CRetraceWaiter.cpp \ - $$PWD/src/CInputRelay.cpp \ - $$PWD/src/CInputDeferredRelay.cpp \ $$PWD/src/inputdev/CDolphinSmashAdapter.cpp \ $$PWD/src/inputdev/CRevolutionPad.cpp \ $$PWD/src/inputdev/CCafeProPad.cpp \ @@ -29,10 +26,13 @@ SOURCES += \ $$PWD/src/inputdev/SDeviceSignature.cpp unix:!macx { - HEADERS += \ - $$PWD/include/x11/CGLXContext.hpp SOURCES += \ - $$PWD/src/x11/CGLXContext.cpp + $$PWD/src/CApplicationXCB.cpp \ + $$PWD/src/CApplicationWayland.cpp \ + $$PWD/src/windowsys/CWindowXCB.cpp \ + $$PWD/src/windowsys/CWindowWayland.cpp \ + $$PWD/src/windowsys/CGraphicsContextXCB.cpp \ + $$PWD/src/windowsys/CGraphicsContextWayland.cpp } linux { @@ -47,18 +47,19 @@ macx { $$PWD/src/inputdev/CHIDDeviceIOKit.cpp \ $$PWD/src/inputdev/CHIDListenerIOKit.cpp OBJECTIVE_SOURCES += \ + $$PWD/src/CApplicationCocoa.mm \ $$PWD/src/windowsys/CWindowCocoa.mm \ $$PWD/src/windowsys/CGraphicsContextCocoa.mm LIBS += -framework AppKit } win32 { - HEADERS += \ - $$PWD/include/win/CWGLContext.hpp SOURCES += \ - $$PWD/src/win/CWGLContext.cpp \ + $$PWD/src/CApplicationWin32.cpp \ $$PWD/src/inputdev/CHIDListenerWinUSB.cpp \ - $$PWD/src/inputdev/CHIDDeviceWinUSB.cpp + $$PWD/src/inputdev/CHIDDeviceWinUSB.cpp \ + $$PWD/src/windowsys/CWindowWin32.cpp \ + $$PWD/src/windowsys/CGraphicsContextWin32.cpp } INCLUDEPATH += $$PWD/include diff --git a/src/CApplicationCocoa.mm b/src/CApplicationCocoa.mm new file mode 100644 index 0000000..f972666 --- /dev/null +++ b/src/CApplicationCocoa.mm @@ -0,0 +1,180 @@ +#include + +#include "IApplication.hpp" + +@interface AppDelegate : NSObject +{ + boo::IApplicationCallback* callback; + NSPanel* aboutPanel; +} +- (id)initWithCallback:(boo::IApplicationCallback*)cb; +@end + +@implementation AppDelegate +- (id)initWithCallback:(boo::IApplicationCallback*)cb +{ + self = [super init]; + callback = cb; + return self; +} +- (void)applicationDidFinishLaunching:(NSNotification*)notification +{ + (void)notification; + callback->appLaunched(boo::IApplicationInstance()); +} +- (void)applicationWillTerminate:(NSNotification*)notification +{ + (void)notification; + callback->appQuitting(boo::IApplicationInstance()); +} +- (BOOL)application:(NSApplication*)sender openFile:(NSString*)filename +{ + (void)sender; + return callback->appFileOpen(boo::IApplicationInstance(), [filename UTF8String]); +} +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender { + (void)sender; + return YES; +} +- (IBAction)aboutApp:(id)sender +{ + (void)sender; + NSRect screenFrame = [[aboutPanel screen] frame]; + CGFloat xPos = NSWidth(screenFrame)/2 - 300/2; + CGFloat yPos = NSHeight(screenFrame)/2 - 220/2; + NSRect aboutCr = NSMakeRect(xPos, yPos, 300, 220); + [aboutPanel setFrame:aboutCr display:NO]; + [aboutPanel makeKeyAndOrderFront:self]; +} +- (IBAction)toggleFs:(id)sender +{ + (void)sender; + [[NSApp keyWindow] toggleFullScreen:nil]; +} +- (IBAction)quitApp:(id)sender +{ + (void)sender; + [NSApp terminate:nil]; +} +@end + +namespace boo +{ + +IWindow* _CWindowCocoaNew(const std::string& title); + +class CApplicationCocoa final : public IApplication +{ + IApplicationCallback& m_callback; + const std::string m_friendlyName; + const std::string m_pname; + const std::vector m_args; + + NSPanel* aboutPanel; + + void _deletedWindow(IWindow* window) + { + (void)window; + } + +public: + CApplicationCocoa(IApplicationCallback& callback, + const std::string& friendlyName, + const std::string& pname, + const std::vector& args) + : m_callback(callback), + m_friendlyName(friendlyName), + m_pname(pname), + m_args(args) + {} + + EPlatformType getPlatformType() const + { + return PLAT_COCOA; + } + + void run() + { + @autoreleasepool + { + NSApplication* app = [NSApplication sharedApplication]; + [app setActivationPolicy:NSApplicationActivationPolicyRegular]; + + /* Delegate (OS X callbacks) */ + AppDelegate* appDelegate = [[AppDelegate alloc] initWithCallback:&m_callback]; + [app setDelegate:appDelegate]; + + /* App menu */ + NSMenu* appMenu = [[NSMenu alloc] initWithTitle:@"main"]; + NSMenu* rwkMenu = [[NSMenu alloc] initWithTitle:[[NSString stringWithUTF8String:m_friendlyName.c_str()] autorelease]]; + [rwkMenu addItemWithTitle:[[NSString stringWithFormat:@"About %s", m_friendlyName.c_str()] autorelease] + action:@selector(aboutApp:) + keyEquivalent:@""]; + NSMenuItem* fsItem = [rwkMenu addItemWithTitle:@"Toggle Full Screen" + action:@selector(toggleFs:) + keyEquivalent:@"f"]; + [fsItem setKeyEquivalentModifierMask:NSCommandKeyMask]; + [rwkMenu addItem:[NSMenuItem separatorItem]]; + NSMenuItem* quit_item = [rwkMenu addItemWithTitle:[[NSString stringWithFormat:@"Quit %s", m_friendlyName.c_str()] autorelease] + action:@selector(quitApp:) + keyEquivalent:@"q"]; + [quit_item setKeyEquivalentModifierMask:NSCommandKeyMask]; + [[appMenu addItemWithTitle:[[NSString stringWithUTF8String:m_friendlyName.c_str()] autorelease] + action:nil keyEquivalent:@""] setSubmenu:rwkMenu]; + [[NSApplication sharedApplication] setMainMenu:appMenu]; + + /* About panel */ + NSRect aboutCr = NSMakeRect(0, 0, 300, 220); + aboutPanel = [[NSPanel alloc] initWithContentRect:aboutCr + styleMask:NSUtilityWindowMask|NSTitledWindowMask|NSClosableWindowMask + backing:NSBackingStoreBuffered defer:YES]; + [aboutPanel setTitle:[[NSString stringWithFormat:@"About %s", m_friendlyName.c_str()] autorelease]]; + NSText* aboutText = [[NSText alloc] initWithFrame:aboutCr]; + [aboutText setEditable:NO]; + [aboutText setAlignment:NSCenterTextAlignment]; + [aboutText setString:@"\nRWK Authors\n\nJackoalan\nAntidote\n"]; + [aboutPanel setContentView:aboutText]; + + [app run]; + } + } + + void quit() + { + [NSApp terminate:nil]; + } + + const std::string& getProcessName() const + { + return m_pname; + } + + const std::vector& getArgs() const + { + return m_args; + } + + IWindow* newWindow(const std::string& title) + { + return _CWindowCocoaNew(title); + } +}; + +IApplication* APP = NULL; +IApplication* IApplicationBootstrap(IApplication::EPlatformType platform, + IApplicationCallback& cb, + const std::string& friendlyName, + const std::string& pname, + const std::vector& args) +{ + if (!APP) + { + if (platform != IApplication::PLAT_COCOA && + platform != IApplication::PLAT_AUTO) + return NULL; + APP = new CApplicationCocoa(cb, friendlyName, pname, args); + } + return APP; +} + +} diff --git a/src/CApplicationUnix.cpp b/src/CApplicationUnix.cpp new file mode 100644 index 0000000..61c8318 --- /dev/null +++ b/src/CApplicationUnix.cpp @@ -0,0 +1,32 @@ +/* Meta-implementation for dynamically-constructing user's preferred + * platform interface + */ + +#define CAPPLICATION_UNIX_CPP +#include "CApplicationXCB.hpp" +#include "CApplicationWayland.hpp" + +namespace boo +{ + +IApplication* APP = NULL; +IApplication* IApplicationBootstrap(IApplication::EPlatformType platform, + IApplicationCallback& cb, + const std::string& friendlyName, + const std::string& pname, + const std::vector& args) +{ + if (!APP) + { + if (platform == IApplication::PLAT_WAYLAND) + APP = new CApplicationWayland(cb, friendlyName, pname, args); + else if (platform == IApplication::PLAT_XCB || + platform == IApplication::PLAT_AUTO) + APP = new CApplicationXCB(cb, friendlyName, pname, args); + else + return NULL; + } + return APP; +} + +} diff --git a/src/CApplicationWayland.hpp b/src/CApplicationWayland.hpp new file mode 100644 index 0000000..06556c6 --- /dev/null +++ b/src/CApplicationWayland.hpp @@ -0,0 +1,61 @@ +#ifndef CAPPLICATION_UNIX_CPP +#error This file may only be included from CApplicationUnix.cpp +#endif + +#include "IApplication.hpp" + +namespace boo +{ + +IWindow* _CWindowWaylandNew(const std::string& title); + +class CApplicationWayland final : public IApplication +{ + const IApplicationCallback& m_callback; + const std::string m_friendlyName; + const std::string m_pname; + const std::vector m_args; + + void _deletedWindow(IWindow* window) + { + (void)window; + } + +public: + CApplicationWayland(const IApplicationCallback& callback, + const std::string& friendlyName, + const std::string& pname, + const std::vector& args) + : m_callback(callback), + m_friendlyName(friendlyName), + m_pname(pname), + m_args(args) + {} + + EPlatformType getPlatformType() const + { + return PLAT_WAYLAND; + } + + void run() + { + + } + + const std::string& getProcessName() const + { + return m_pname; + } + + const std::vector& getArgs() const + { + return m_args; + } + + IWindow* newWindow(const std::string& title) + { + return _CWindowWaylandNew(title); + } +}; + +} diff --git a/src/CApplicationWin32.cpp b/src/CApplicationWin32.cpp new file mode 100644 index 0000000..67f1842 --- /dev/null +++ b/src/CApplicationWin32.cpp @@ -0,0 +1,162 @@ +#define _CRT_SECURE_NO_WARNINGS 1 /* STFU MSVC */ +#define _WIN32_LEAN_AND_MEAN 1 +#include +#include +#include + +#include + +#include "IRunLoop.hpp" +#include "inputdev/CDeviceFinder.hpp" + +namespace boo +{ + +IWindow* _CWindowWin32New(const std::string& title); + +class CApplicationWin32 final : public IApplication +{ + const IApplicationCallback& m_callback; + const std::string m_friendlyName; + const std::string m_pname; + const std::vector m_args; + std::unordered_map m_allWindows; + + void _deletedWindow(IWindow* window) + { + m_allWindows.erase(window); + } + +public: + + CApplicationWin32(const IApplicationCallback& callback, + const std::string& friendlyName, + const std::string& pname, + const std::vector& args) + : m_callback(callback), + m_friendlyName(friendlyName), + m_pname(pname), + m_args(args) + {} + + EPlatformType getPlatformType() const + { + return PLAT_WIN32; + } + + LRESULT winHwndHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + /* Lookup boo window instance */ + IWindow* window = m_allWindows[hwnd]; + switch (uMsg) + { + case WM_CREATE: + return 0; + + case WM_DEVICECHANGE: + return CDeviceFinder::winDevChangedHandler(wParam, lParam); + + default: + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } + } + + void run() + { + /* Pump messages */ + MSG msg = {0}; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + const std::string& getProcessName() const + { + return m_pname; + } + + const std::vector& getArgs() const + { + return m_args; + } + + IWindow* newWindow(const std::string& title) + { + IWindow* window = _CWindowWin32New(title); + HWND hwnd = window->getPlatformHandle(); + m_allWindows[hwnd] = window; + } +}; + +IApplication* APP = NULL; +IApplication* IApplicationBootstrap(IApplication::EPlatformType platform, + IApplicationCallback& cb, + const std::string& friendlyName, + const std::string& pname, + const std::vector& args) +{ + if (!APP) + { + if (platform != IApplication::PLAT_WIN32 && + platform != IApplication::PLAT_AUTO) + return NULL; + APP = new CApplicationWin32(cb, friendlyName, pname, args); + } + return APP; +} + +} + +static const DEV_BROADCAST_DEVICEINTERFACE_A HOTPLUG_CONF = +{ + sizeof(DEV_BROADCAST_DEVICEINTERFACE_A), + DBT_DEVTYP_DEVICEINTERFACE, + 0, + GUID_DEVINTERFACE_USB_DEVICE +}; +static bool HOTPLUG_REGISTERED = false; +static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (!HOTPLUG_REGISTERED && hwnd == WM_CREATE) + { + /* Register hotplug notification with windows */ + RegisterDeviceNotificationA(hwnd, (LPVOID)&HOTPLUG_CONF, DEVICE_NOTIFY_WINDOW_HANDLE); + HOTPLUG_REGISTERED = true; + } + return IRunLoopInstance()->winHwndHandler(hwnd, uMsg, wParam, lParam); +} + +int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPCWSTR lpCmdLine, int) +{ +#if DEBUG + /* Debug console */ + AllocConsole(); + freopen("CONOUT$", "w", stdout); +#endif + + /* One class for *all* boo windows */ + WNDCLASS wndClass = + { + 0, + WindowProc, + 0, + 0, + hInstance, + 0, + 0, + 0, + 0, + L"BooWindow" + }; + + RegisterClassW(&wndClass); + + int argc = 0; + LPWSTR* argv = CommandLineToArgvW(lpCmdLine, &argc); + + /* Call into the 'proper' entry point */ + return main(argc, argv); + +} diff --git a/src/CApplicationXCB.hpp b/src/CApplicationXCB.hpp new file mode 100644 index 0000000..1b0a7f5 --- /dev/null +++ b/src/CApplicationXCB.hpp @@ -0,0 +1,61 @@ +#ifndef CAPPLICATION_UNIX_CPP +#error This file may only be included from CApplicationUnix.cpp +#endif + +#include "IApplication.hpp" + +namespace boo +{ + +IWindow* _CWindowXCBNew(const std::string& title); + +class CApplicationXCB final : public IApplication +{ + const IApplicationCallback& m_callback; + const std::string m_friendlyName; + const std::string m_pname; + const std::vector m_args; + + void _deletedWindow(IWindow* window) + { + (void)window; + } + +public: + CApplicationXCB(const IApplicationCallback& callback, + const std::string& friendlyName, + const std::string& pname, + const std::vector& args) + : m_callback(callback), + m_friendlyName(friendlyName), + m_pname(pname), + m_args(args) + {} + + EPlatformType getPlatformType() const + { + return PLAT_XCB; + } + + void run() + { + + } + + const std::string& getProcessName() const + { + return m_pname; + } + + const std::vector& getArgs() const + { + return m_args; + } + + IWindow* newWindow(const std::string& title) + { + return _CWindowXCBNew(title); + } +}; + +} diff --git a/src/CInputDeferredRelay.cpp b/src/CInputDeferredRelay.cpp deleted file mode 100644 index 7fed569..0000000 --- a/src/CInputDeferredRelay.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "CInputDeferredRelay.hpp" \ No newline at end of file diff --git a/src/CInputRelay.cpp b/src/CInputRelay.cpp deleted file mode 100644 index 2d38700..0000000 --- a/src/CInputRelay.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "CInputRelay.hpp" \ No newline at end of file diff --git a/src/CQtOpenGLWindow.cpp b/src/CQtOpenGLWindow.cpp deleted file mode 100644 index 07d3ba2..0000000 --- a/src/CQtOpenGLWindow.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "CQtOpenGLWindow.hpp" - - diff --git a/src/CRetraceWaiter.cpp b/src/CRetraceWaiter.cpp deleted file mode 100644 index 6734c86..0000000 --- a/src/CRetraceWaiter.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "IRetraceWaiter.hpp" diff --git a/src/CSurface.cpp b/src/CSurface.cpp deleted file mode 100644 index e23af70..0000000 --- a/src/CSurface.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "CSurface.hpp" - -namespace boo -{ - -ISurface* CSurfaceNewWindow() -{ - return nullptr; -} - -ISurface* CSurfaceNewQWidget() -{ - return nullptr; -} - -} diff --git a/src/win/CWGLContext.cpp b/src/win/CWGLContext.cpp deleted file mode 100644 index dfdd625..0000000 --- a/src/win/CWGLContext.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef _WIN32 -#include "win/CWGLContext.hpp" - -#endif diff --git a/src/windowsys/CGraphicsContextCocoa.mm b/src/windowsys/CGraphicsContextCocoa.mm index 2a0ed3f..ef61ad1 100644 --- a/src/windowsys/CGraphicsContextCocoa.mm +++ b/src/windowsys/CGraphicsContextCocoa.mm @@ -4,6 +4,12 @@ #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, @@ -70,17 +76,17 @@ class CGraphicsContextCocoa final : public IGraphicsContext EGraphicsAPI m_api; EPixelFormat m_pf; - NSWindow* m_parentWindow; + IWindow* m_parentWindow; CGraphicsContextCocoaInternal* m_nsContext; NSOpenGLContext* m_nsShareContext; public: IWindowCallback* m_callback; - CGraphicsContextCocoa(EGraphicsAPI api) + CGraphicsContextCocoa(EGraphicsAPI api, IWindow* parentWindow) : m_api(api), m_pf(PF_RGBA8), - m_parentWindow(NULL), + m_parentWindow(parentWindow), m_nsContext(NULL), m_nsShareContext(NULL), m_callback(NULL) @@ -114,17 +120,12 @@ public: m_pf = pf; } - void setPlatformWindowHandle(void* handle) - { - m_parentWindow = (NSWindow*)handle; - } - void initializeContext() { if (m_nsShareContext) return; m_nsContext = [[CGraphicsContextCocoaInternal alloc] initWithBooContext:this]; - [m_parentWindow setContentView:m_nsContext]; + [(NSWindow*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext]; } IGraphicsContext* makeShareContext() const @@ -144,7 +145,7 @@ public: return NULL; if (!nsctx) return NULL; - CGraphicsContextCocoa* newCtx = new CGraphicsContextCocoa(m_api); + CGraphicsContextCocoa* newCtx = new CGraphicsContextCocoa(m_api, NULL); newCtx->m_nsShareContext = nsctx; return newCtx; } @@ -169,7 +170,8 @@ public: }; -IGraphicsContext* IGraphicsContextNew(IGraphicsContext::EGraphicsAPI api) +IGraphicsContext* _CGraphicsContextCocoaNew(IGraphicsContext::EGraphicsAPI api, + IWindow* parentWindow) { if (api != IGraphicsContext::API_OPENGL_3_3 && api != IGraphicsContext::API_OPENGL_4_2) return NULL; @@ -202,7 +204,7 @@ IGraphicsContext* IGraphicsContextNew(IGraphicsContext::EGraphicsAPI api) if (api == IGraphicsContext::API_OPENGL_4_2) return NULL; - return new CGraphicsContextCocoa(api); + return new CGraphicsContextCocoa(api, parentWindow); } } diff --git a/src/windowsys/CGraphicsContextWayland.cpp b/src/windowsys/CGraphicsContextWayland.cpp new file mode 100644 index 0000000..a669d77 --- /dev/null +++ b/src/windowsys/CGraphicsContextWayland.cpp @@ -0,0 +1,87 @@ +#include "windowsys/IGraphicsContext.hpp" +#include "windowsys/IWindow.hpp" + +namespace boo +{ + +class CGraphicsContextWayland final : public IGraphicsContext +{ + + EGraphicsAPI m_api; + EPixelFormat m_pf; + IWindow* m_parentWindow; + +public: + IWindowCallback* m_callback; + + CGraphicsContextWayland(EGraphicsAPI api, IWindow* parentWindow) + : m_api(api), + m_pf(PF_RGBA8), + m_parentWindow(parentWindow) + {} + + ~CGraphicsContextWayland() + { + + } + + 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 setPlatformWindowHandle(void* handle) + { + } + + void initializeContext() + { + + } + + IGraphicsContext* makeShareContext() const + { + + } + + void makeCurrent() + { + + } + + void clearCurrent() + { + + } + + void swapBuffer() + { + + } + +}; + +IGraphicsContext* _CGraphicsContextWaylandNew(IGraphicsContext::EGraphicsAPI api, + IWindow* parentWindow) +{ + +} + +} diff --git a/src/windowsys/CGraphicsContextWin32.cpp b/src/windowsys/CGraphicsContextWin32.cpp new file mode 100644 index 0000000..f8036c5 --- /dev/null +++ b/src/windowsys/CGraphicsContextWin32.cpp @@ -0,0 +1,87 @@ +#include "windowsys/IGraphicsContext.hpp" +#include "windowsys/IWindow.hpp" + +namespace boo +{ + +class CGraphicsContextWin32 final : public IGraphicsContext +{ + + EGraphicsAPI m_api; + EPixelFormat m_pf; + IWindow* m_parentWindow; + +public: + IWindowCallback* m_callback; + + CGraphicsContextWin32(EGraphicsAPI api, IWindow* parentWindow) + : m_api(api), + m_pf(PF_RGBA8), + m_parentWindow(parentWindow) + {} + + ~CGraphicsContextWin32() + { + + } + + 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 setPlatformWindowHandle(void* handle) + { + } + + void initializeContext() + { + + } + + IGraphicsContext* makeShareContext() const + { + + } + + void makeCurrent() + { + + } + + void clearCurrent() + { + + } + + void swapBuffer() + { + + } + +}; + +IGraphicsContext* _CGraphicsContextWin32New(IGraphicsContext::EGraphicsAPI api, + IWindow* parentWindow) +{ + +} + +} diff --git a/src/windowsys/CGraphicsContextXCB.cpp b/src/windowsys/CGraphicsContextXCB.cpp new file mode 100644 index 0000000..60799d5 --- /dev/null +++ b/src/windowsys/CGraphicsContextXCB.cpp @@ -0,0 +1,87 @@ +#include "windowsys/IGraphicsContext.hpp" +#include "windowsys/IWindow.hpp" + +namespace boo +{ + +class CGraphicsContextXCB final : public IGraphicsContext +{ + + EGraphicsAPI m_api; + EPixelFormat m_pf; + IWindow* m_parentWindow; + +public: + IWindowCallback* m_callback; + + CGraphicsContextXCB(EGraphicsAPI api, IWindow* parentWindow) + : m_api(api), + m_pf(PF_RGBA8), + m_parentWindow(parentWindow) + {} + + ~CGraphicsContextXCB() + { + + } + + 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 setPlatformWindowHandle(void* handle) + { + } + + void initializeContext() + { + + } + + IGraphicsContext* makeShareContext() const + { + + } + + void makeCurrent() + { + + } + + void clearCurrent() + { + + } + + void swapBuffer() + { + + } + +}; + +IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api, + IWindow* parentWindow) +{ + +} + +} diff --git a/src/windowsys/CWindowCocoa.mm b/src/windowsys/CWindowCocoa.mm index 0fde361..42b1819 100644 --- a/src/windowsys/CWindowCocoa.mm +++ b/src/windowsys/CWindowCocoa.mm @@ -1,4 +1,5 @@ #import +#include "IApplication.hpp" #include "windowsys/IWindow.hpp" #include "windowsys/IGraphicsContext.hpp" @@ -7,11 +8,16 @@ namespace boo {class CWindowCocoa;} { boo::CWindowCocoa* booWindow; } -- (id)initWithBooWindow:(boo::CWindowCocoa*)bw; +- (id)initWithBooWindow:(boo::CWindowCocoa*)bw title:(const std::string&)title; +- (void)setFrameDefault; +- (NSRect)genFrameDefault; @end namespace boo { + +IGraphicsContext* _CGraphicsContextCocoaNew(IGraphicsContext::EGraphicsAPI api, + IWindow* parentWindow); class CWindowCocoa final : public IWindow { @@ -21,19 +27,25 @@ class CWindowCocoa final : public IWindow public: - CWindowCocoa() + CWindowCocoa(const std::string& title) { - m_nsWindow = [[CWindowCocoaInternal alloc] initWithBooWindow:this]; - m_gfxCtx = IGraphicsContextNew(IGraphicsContext::API_OPENGL_3_3); + m_nsWindow = [[CWindowCocoaInternal alloc] initWithBooWindow:this title:title]; + m_gfxCtx = _CGraphicsContextCocoaNew(IGraphicsContext::API_OPENGL_3_3, this); m_gfxCtx->_setPlatformWindowHandle(m_nsWindow); m_gfxCtx->initializeContext(); } + void _clearWindow() + { + m_nsWindow = NULL; + } + ~CWindowCocoa() { [m_nsWindow orderOut:nil]; [m_nsWindow release]; delete m_gfxCtx; + IApplicationInstance()->_deletedWindow(this); } void setCallback(IWindowCallback* cb) @@ -58,7 +70,7 @@ public: void setTitle(const std::string& title) { - [m_nsWindow setTitle:[NSString stringWithUTF8String:title.c_str()]]; + [m_nsWindow setTitle:[[NSString stringWithUTF8String:title.c_str()] autorelease]]; } void setWindowFrameDefault() @@ -106,27 +118,64 @@ public: return TOUCH_TRACKPAD; } + void* getPlatformHandle() const + { + return m_nsWindow; + } + }; -IWindow* IWindowNew() +IWindow* _CWindowCocoaNew(const std::string& title) { - return new CWindowCocoa; + return new CWindowCocoa(title); } } @implementation CWindowCocoaInternal -- (id)initWithBooWindow:(boo::CWindowCocoa *)bw +- (id)initWithBooWindow:(boo::CWindowCocoa *)bw title:(const std::string&)title { - self = [self initWithContentRect:NSMakeRect(0, 0, 100, 100) + self = [self initWithContentRect:[self genFrameDefault] styleMask:NSTitledWindowMask| NSClosableWindowMask| NSMiniaturizableWindowMask| NSResizableWindowMask backing:NSBackingStoreBuffered defer:YES]; + self.title = [[NSString stringWithUTF8String:title.c_str()] autorelease]; booWindow = bw; return self; } +- (void)setFrameDefault +{ + [self setFrame:[self genFrameDefault] display:NO]; +} +- (NSRect)genFrameDefault +{ + NSScreen* mainScreen = [NSScreen mainScreen]; + NSRect scrFrame = mainScreen.frame; + float width = scrFrame.size.width * 2.0 / 3.0; + float height = scrFrame.size.height * 2.0 / 3.0; + return NSMakeRect((scrFrame.size.width - width) / 2.0, + (scrFrame.size.height - height) / 2.0, + width, height); +} +- (void)close +{ + booWindow->_clearWindow(); + [super close]; +} +- (BOOL)acceptsFirstResponder +{ + return YES; +} +- (BOOL)acceptsMouseMovedEvents +{ + return YES; +} +- (NSWindowCollectionBehavior)collectionBehavior +{ + return NSWindowCollectionBehaviorFullScreenPrimary; +} @end diff --git a/src/windowsys/CWindowWayland.cpp b/src/windowsys/CWindowWayland.cpp new file mode 100644 index 0000000..ffbd2d4 --- /dev/null +++ b/src/windowsys/CWindowWayland.cpp @@ -0,0 +1,93 @@ +#include "windowsys/IWindow.hpp" +#include "windowsys/IGraphicsContext.hpp" + +namespace boo +{ + +IGraphicsContext* _CGraphicsContextWaylandNew(IGraphicsContext::EGraphicsAPI api, + IWindow* parentWindow); + +class CWindowWayland final : public IWindow +{ + + +public: + + CWindowWayland(const std::string& title) + { + + } + + ~CWindowWayland() + { + + } + + void setCallback(IWindowCallback* cb) + { + + } + + void showWindow() + { + + } + + void hideWindow() + { + + } + + std::string getTitle() + { + + } + + void setTitle(const std::string& title) + { + + } + + void setWindowFrameDefault() + { + + } + + void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const + { + + } + + void setWindowFrame(float x, float y, float w, float h) + { + + } + + float getVirtualPixelFactor() const + { + + } + + bool isFullscreen() const + { + + } + + void setFullscreen(bool fs) + { + + } + + ETouchType getTouchType() const + { + + } + +}; + +IWindow* _CWindowWaylandNew(const std::string& title) +{ + return new CWindowWayland(title); +} + +} diff --git a/src/windowsys/CWindowWin32.cpp b/src/windowsys/CWindowWin32.cpp new file mode 100644 index 0000000..5617358 --- /dev/null +++ b/src/windowsys/CWindowWin32.cpp @@ -0,0 +1,96 @@ +#include "windowsys/IWindow.hpp" +#include "windowsys/IGraphicsContext.hpp" + +namespace boo +{ + +IGraphicsContext* _CGraphicsContextWin32New(IGraphicsContext::EGraphicsAPI api, + IWindow* parentWindow); + +class CWindowWin32 final : public IWindow +{ + + HWND m_hwnd; + +public: + + CWindowWin32(const std::string& title) + { + m_hwnd = CreateWindowW(L"BooWindow", L"BooTest", WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, hInstance, NULL); + } + + ~CWindowWin32() + { + + } + + void setCallback(IWindowCallback* cb) + { + + } + + void showWindow() + { + + } + + void hideWindow() + { + + } + + std::string getTitle() + { + + } + + void setTitle(const std::string& title) + { + + } + + void setWindowFrameDefault() + { + + } + + void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const + { + + } + + void setWindowFrame(float x, float y, float w, float h) + { + + } + + float getVirtualPixelFactor() const + { + + } + + bool isFullscreen() const + { + + } + + void setFullscreen(bool fs) + { + + } + + ETouchType getTouchType() const + { + + } + +}; + +IWindow* _CWindowWin32New(const std::string& title) +{ + return new CWindowWin32(title); +} + +} diff --git a/src/windowsys/CWindowXCB.cpp b/src/windowsys/CWindowXCB.cpp new file mode 100644 index 0000000..f30fc69 --- /dev/null +++ b/src/windowsys/CWindowXCB.cpp @@ -0,0 +1,93 @@ +#include "windowsys/IWindow.hpp" +#include "windowsys/IGraphicsContext.hpp" + +namespace boo +{ + +IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api, + IWindow* parentWindow); + +class CWindowXCB final : public IWindow +{ + + +public: + + CWindowXCB(const std::string& title) + { + + } + + ~CWindowXCB() + { + + } + + void setCallback(IWindowCallback* cb) + { + + } + + void showWindow() + { + + } + + void hideWindow() + { + + } + + std::string getTitle() + { + + } + + void setTitle(const std::string& title) + { + + } + + void setWindowFrameDefault() + { + + } + + void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const + { + + } + + void setWindowFrame(float x, float y, float w, float h) + { + + } + + float getVirtualPixelFactor() const + { + + } + + bool isFullscreen() const + { + + } + + void setFullscreen(bool fs) + { + + } + + ETouchType getTouchType() const + { + + } + +}; + +IWindow* _CWindowXCBNew(const std::string& title) +{ + return new CWindowXCB(title); +} + +} diff --git a/src/x11/CGLXContext.cpp b/src/x11/CGLXContext.cpp deleted file mode 100644 index f1e42e2..0000000 --- a/src/x11/CGLXContext.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#if !defined(__APPLE__) && (defined(__linux__) || defined(BSD)) -#include "x11/CGLXContext.hpp" -#include - -namespace boo -{ - -CGLXContext::CGLXContext() - : m_majVersion(3), - m_minVersion(3), - m_display(nullptr) -{ - std::cout << "Hello from GLX" << std::endl; -} - -bool CGLXContext::create() -{ - return true; -} - -void CGLXContext::setMinVersion(const int& min) -{ - m_minVersion = min; -} - -void CGLXContext::setMajorVersion(const int& maj) -{ - m_majVersion = maj; -} - -const std::string CGLXContext::version() const -{ - return "Invalid version"; -} - -const std::string CGLXContext::name() const -{ - return "GLX Context"; -} - -int CGLXContext::depthSize() const -{ - return -1; -} - -int CGLXContext::redDepth() const -{ - return -1; -} - -int CGLXContext::greenDepth() const -{ - return -1; -} - -int CGLXContext::blueDepth() const -{ - return -1; -} - -} - -#endif // !defined(__APPLE__) && (defined(__linux__) || defined(BSD)) diff --git a/test/main.cpp b/test/main.cpp index d287d65..b4a0a86 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,4 +1,3 @@ -#define _CRT_SECURE_NO_WARNINGS 1 #if __APPLE__ #include @@ -7,10 +6,7 @@ #include #include #if _WIN32 -#define _WIN32_LEAN_AND_MEAN 1 -#include -#include -#include + #else #include #endif @@ -58,104 +54,37 @@ public: } } }; - -} - -#if _WIN32 - -/* This simple 'test' console app needs a full windows - * message loop for receiving device connection events - */ -static const DEV_BROADCAST_DEVICEINTERFACE_A HOTPLUG_CONF = + + +struct CTestApplicationCallback : public IApplicationCallback { - sizeof(DEV_BROADCAST_DEVICEINTERFACE_A), - DBT_DEVTYP_DEVICEINTERFACE, - 0, - GUID_DEVINTERFACE_USB_DEVICE + IWindow* mainWindow = NULL; + boo::CTestDeviceFinder devFinder; + void appLaunched(IApplication* app) + { + mainWindow = app->newWindow("YAY!"); + mainWindow->showWindow(); + devFinder.startScanning(); + } + void appQuitting(IApplication*) + { + delete mainWindow; + } + bool appFileOpen(IApplication*, const std::string& path) + { + printf("OPENING: %s\n", path.c_str()); + return true; + } }; -LRESULT CALLBACK WindowProc( - _In_ HWND hwnd, - _In_ UINT uMsg, - _In_ WPARAM wParam, - _In_ LPARAM lParam -) -{ - switch (uMsg) - { - case WM_CREATE: - /* Register hotplug notification with windows */ - RegisterDeviceNotificationA(hwnd, (LPVOID)&HOTPLUG_CONF, DEVICE_NOTIFY_WINDOW_HANDLE); - return 0; - - case WM_DEVICECHANGE: - return boo::CDeviceFinder::winDevChangedHandler(wParam, lParam); - - default: - return DefWindowProc(hwnd, uMsg, wParam, lParam); - } } -int APIENTRY wWinMain( - _In_ HINSTANCE hInstance, - _In_ HINSTANCE, - _In_ LPTSTR, - _In_ int -) +int main(int argc, char** argv) { - AllocConsole(); - freopen("CONOUT$", "w", stdout); - - WNDCLASS wndClass = - { - 0, - WindowProc, - 0, - 0, - hInstance, - 0, - 0, - 0, - 0, - L"BooTestWindow" - }; - - RegisterClassW(&wndClass); - - boo::CTestDeviceFinder finder; - finder.startScanning(); - - HWND hwnd = CreateWindowW(L"BooTestWindow", L"BooTest", WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - NULL, NULL, hInstance, NULL); - - /* Pump messages */ - MSG msg = {0}; - while (GetMessage(&msg, hwnd, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - -} - -#else - -int main(int, char**) -{ - - boo::CTestDeviceFinder finder; - finder.startScanning(); - - boo::IWindow* window = boo::IWindowNew(); - (void)window; - -#if __APPLE__ - CFRunLoopRun(); -#endif - - //delete ctx; + boo::CTestApplicationCallback appCb; + boo::IApplication* app = IApplicationBootstrap(boo::IApplication::PLAT_AUTO, appCb, "RWK", argc, argv); + app->run(); + delete app; return 0; } -#endif From c357c9d91fc12bc771943c5581adb24d09e1e7bb Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 5 May 2015 15:03:49 -1000 Subject: [PATCH 04/10] minor cleanup work --- src/CApplicationCocoa.mm | 2 ++ test/main.cpp | 10 ---------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/CApplicationCocoa.mm b/src/CApplicationCocoa.mm index f972666..9ebaa86 100644 --- a/src/CApplicationCocoa.mm +++ b/src/CApplicationCocoa.mm @@ -5,6 +5,7 @@ @interface AppDelegate : NSObject { boo::IApplicationCallback* callback; + @public NSPanel* aboutPanel; } - (id)initWithCallback:(boo::IApplicationCallback*)cb; @@ -134,6 +135,7 @@ public: [aboutText setAlignment:NSCenterTextAlignment]; [aboutText setString:@"\nRWK Authors\n\nJackoalan\nAntidote\n"]; [aboutPanel setContentView:aboutText]; + appDelegate->aboutPanel = aboutPanel; [app run]; } diff --git a/test/main.cpp b/test/main.cpp index b4a0a86..badad65 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,15 +1,5 @@ - -#if __APPLE__ -#include -#else -#endif #include #include -#if _WIN32 - -#else -#include -#endif namespace boo { From a70cc2c9d1461991db6a5d29af7b91004c1184cb Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 8 May 2015 19:33:48 -1000 Subject: [PATCH 05/10] much work on XCB events --- include/windowsys/IWindow.hpp | 7 +- libBoo.pri | 6 +- libBoo.pro | 2 +- src/CApplicationWayland.hpp | 5 + src/CApplicationXCB.hpp | 110 ++++++++- src/windowsys/CWindowCocoa.mm | 4 +- src/windowsys/CWindowWayland.cpp | 5 + src/windowsys/CWindowXCB.cpp | 378 +++++++++++++++++++++++++++++-- 8 files changed, 487 insertions(+), 30 deletions(-) diff --git a/include/windowsys/IWindow.hpp b/include/windowsys/IWindow.hpp index 4cd70d8..d100bec 100644 --- a/include/windowsys/IWindow.hpp +++ b/include/windowsys/IWindow.hpp @@ -78,7 +78,7 @@ public: virtual void mouseMove(const SWindowCoord& coord) {(void)coord;} virtual void scroll(const SScrollDelta& scroll) - {(void)scroll;}; + {(void)scroll;} virtual void touchDown(const SWindowCoord& coord, uintptr_t tid) {(void)coord;(void)tid;} @@ -123,8 +123,9 @@ public: virtual bool isFullscreen() const=0; virtual void setFullscreen(bool fs)=0; - virtual void* getPlatformHandle() const=0; - + virtual uintptr_t getPlatformHandle() const=0; + virtual void _incomingEvent(void* event) {(void)event;} + enum ETouchType { TOUCH_NONE = 0, diff --git a/libBoo.pri b/libBoo.pri index 36a9714..102e20f 100644 --- a/libBoo.pri +++ b/libBoo.pri @@ -26,9 +26,11 @@ SOURCES += \ $$PWD/src/inputdev/SDeviceSignature.cpp unix:!macx { + HEADERS += \ + $$PWD/src/CApplicationXCB.hpp \ + $$PWD/src/CApplicationWayland.hpp SOURCES += \ - $$PWD/src/CApplicationXCB.cpp \ - $$PWD/src/CApplicationWayland.cpp \ + $$PWD/src/CApplicationUnix.cpp \ $$PWD/src/windowsys/CWindowXCB.cpp \ $$PWD/src/windowsys/CWindowWayland.cpp \ $$PWD/src/windowsys/CGraphicsContextXCB.cpp \ diff --git a/libBoo.pro b/libBoo.pro index f26f9eb..4611b89 100644 --- a/libBoo.pro +++ b/libBoo.pro @@ -3,7 +3,7 @@ CONFIG += console #QMAKE_CXXFLAGS -= -std=c++0x #CONFIG += c++11 unix:QMAKE_CXXFLAGS += -std=c++11 -stdlib=libc++ -unix:LIBS += -std=c++11 -stdlib=libc++ -lc++abi +unix:LIBS += -std=c++11 -stdlib=libc++ -lc++abi -lxcb -lxcb-xkb -lxcb-keysyms -lxkbcommon -lxkbcommon-x11 win32:LIBS += Setupapi.lib winusb.lib User32.lib /SUBSYSTEM:Windows diff --git a/src/CApplicationWayland.hpp b/src/CApplicationWayland.hpp index 06556c6..4b821e9 100644 --- a/src/CApplicationWayland.hpp +++ b/src/CApplicationWayland.hpp @@ -40,6 +40,11 @@ public: void run() { + } + + void quit() + { + } const std::string& getProcessName() const diff --git a/src/CApplicationXCB.hpp b/src/CApplicationXCB.hpp index 1b0a7f5..21a5e1a 100644 --- a/src/CApplicationXCB.hpp +++ b/src/CApplicationXCB.hpp @@ -4,10 +4,68 @@ #include "IApplication.hpp" +#define explicit explicit_c +#include +#include +#include +#undef explicit + namespace boo { + +static xcb_window_t getWindowOfEvent(xcb_generic_event_t* event, bool& windowEvent) +{ + switch (event->response_type & ~0x80) + { + case XCB_EXPOSE: + { + xcb_expose_event_t* ev = (xcb_expose_event_t*)event; + windowEvent = true; + return ev->window; + } + case XCB_CONFIGURE_NOTIFY: + { + xcb_configure_notify_event_t* ev = (xcb_configure_notify_event_t*)event; + windowEvent = true; + return ev->window; + } + case XCB_KEY_PRESS: + { + xcb_key_press_event_t* ev = (xcb_key_press_event_t*)event; + windowEvent = true; + return ev->root; + } + case XCB_KEY_RELEASE: + { + xcb_key_release_event_t* ev = (xcb_key_release_event_t*)event; + windowEvent = true; + return ev->root; + } + case XCB_BUTTON_PRESS: + { + xcb_button_press_event_t* ev = (xcb_button_press_event_t*)event; + windowEvent = true; + return ev->root; + } + case XCB_BUTTON_RELEASE: + { + xcb_button_release_event_t* ev = (xcb_button_release_event_t*)event; + windowEvent = true; + return ev->root; + } + case XCB_MOTION_NOTIFY: + { + xcb_motion_notify_event_t* ev = (xcb_motion_notify_event_t*)event; + windowEvent = true; + return ev->root; + } + default: + windowEvent = false; + return 0; + } +} -IWindow* _CWindowXCBNew(const std::string& title); +IWindow* _CWindowXCBNew(const std::string& title, xcb_connection_t* conn); class CApplicationXCB final : public IApplication { @@ -15,10 +73,16 @@ class CApplicationXCB final : public IApplication const std::string m_friendlyName; const std::string m_pname; const std::vector m_args; + + /* All windows */ + std::unordered_map m_windows; + + xcb_connection_t* m_xcbConn; + bool m_running; void _deletedWindow(IWindow* window) { - (void)window; + m_windows.erase((xcb_window_t)window->getPlatformHandle()); } public: @@ -30,7 +94,25 @@ public: m_friendlyName(friendlyName), m_pname(pname), m_args(args) - {} + { + m_xcbConn = xcb_connect(NULL, NULL); + + /* The convoluted xkb extension requests that the X server does not + * send repeated keydown events when a key is held */ + xkb_x11_setup_xkb_extension(m_xcbConn, + XKB_X11_MIN_MAJOR_XKB_VERSION, + XKB_X11_MIN_MINOR_XKB_VERSION, + XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, + NULL, NULL, NULL, NULL); + xcb_xkb_per_client_flags(m_xcbConn, XCB_XKB_ID_USE_CORE_KBD, + XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT, + XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT, 0, 0, 0); + } + + ~CApplicationXCB() + { + xcb_disconnect(m_xcbConn); + } EPlatformType getPlatformType() const { @@ -39,7 +121,23 @@ public: void run() { - + xcb_generic_event_t* event; + while (m_running && (event = xcb_wait_for_event(m_xcbConn))) + { + bool windowEvent; + xcb_window_t evWindow = getWindowOfEvent(event, windowEvent); + if (windowEvent) + { + IWindow* window = m_windows[evWindow]; + + } + free(event); + } + } + + void quit() + { + m_running = false; } const std::string& getProcessName() const @@ -54,7 +152,9 @@ public: IWindow* newWindow(const std::string& title) { - return _CWindowXCBNew(title); + IWindow* newWindow = _CWindowXCBNew(title, m_xcbConn); + m_windows[(xcb_window_t)newWindow->getPlatformHandle()] = newWindow; + return newWindow; } }; diff --git a/src/windowsys/CWindowCocoa.mm b/src/windowsys/CWindowCocoa.mm index 42b1819..0d092ec 100644 --- a/src/windowsys/CWindowCocoa.mm +++ b/src/windowsys/CWindowCocoa.mm @@ -118,9 +118,9 @@ public: return TOUCH_TRACKPAD; } - void* getPlatformHandle() const + uintptr_t getPlatformHandle() const { - return m_nsWindow; + return (uintptr_t)m_nsWindow; } }; diff --git a/src/windowsys/CWindowWayland.cpp b/src/windowsys/CWindowWayland.cpp index ffbd2d4..c335d36 100644 --- a/src/windowsys/CWindowWayland.cpp +++ b/src/windowsys/CWindowWayland.cpp @@ -76,6 +76,11 @@ public: void setFullscreen(bool fs) { + } + + uintptr_t getPlatformHandle() const + { + } ETouchType getTouchType() const diff --git a/src/windowsys/CWindowXCB.cpp b/src/windowsys/CWindowXCB.cpp index f30fc69..1a07b47 100644 --- a/src/windowsys/CWindowXCB.cpp +++ b/src/windowsys/CWindowXCB.cpp @@ -1,8 +1,133 @@ #include "windowsys/IWindow.hpp" #include "windowsys/IGraphicsContext.hpp" +#include "IApplication.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#define XK_MISCELLANY +#define XK_XKB_KEYS +#define XK_LATIN1 +#include + +#define REF_DPMM 3.7824 /* 96 DPI */ +#define FS_ATOM "_NET_WM_STATE_FULLSCREEN" namespace boo { + +static uint32_t translateKeysym(xcb_keysym_t sym, int& specialSym, int& modifierSym) +{ + specialSym = IWindowCallback::KEY_NONE; + modifierSym = IWindowCallback::MKEY_NONE; + if (sym >= XK_F1 && sym <= XK_F12) + specialSym = IWindowCallback::KEY_F1 + sym - XK_F1; + else if (sym == XK_Escape) + specialSym = IWindowCallback::KEY_ESC; + else if (sym == XK_Return) + specialSym = IWindowCallback::KEY_ENTER; + else if (sym == XK_BackSpace) + specialSym = IWindowCallback::KEY_BACKSPACE; + else if (sym == XK_Insert) + specialSym = IWindowCallback::KEY_INSERT; + else if (sym == XK_Delete) + specialSym = IWindowCallback::KEY_DELETE; + else if (sym == XK_Home) + specialSym = IWindowCallback::KEY_HOME; + else if (sym == XK_End) + specialSym = IWindowCallback::KEY_END; + else if (sym == XK_Page_Up) + specialSym = IWindowCallback::KEY_PGUP; + else if (sym == XK_Page_Down) + specialSym = IWindowCallback::KEY_PGDOWN; + else if (sym == XK_Left) + specialSym = IWindowCallback::KEY_LEFT; + else if (sym == XK_Right) + specialSym = IWindowCallback::KEY_RIGHT; + else if (sym == XK_Up) + specialSym = IWindowCallback::KEY_UP; + else if (sym == XK_Down) + specialSym = IWindowCallback::KEY_DOWN; + else if (sym == XK_Shift_L || sym == XK_Shift_R) + modifierSym = IWindowCallback::MKEY_SHIFT; + else if (sym == XK_Control_L || sym == XK_Control_R) + modifierSym = IWindowCallback::MKEY_CTRL; + else if (sym == XK_Alt_L || sym == XK_Alt_R) + modifierSym = IWindowCallback::MKEY_ALT; + else + return xkb_keysym_to_utf32(sym); + return 0; +} + +static int translateModifiers(unsigned state) +{ + int retval = 0; + if (state & XCB_MOD_MASK_SHIFT) + retval |= IWindowCallback::MKEY_SHIFT; + if (state & XCB_MOD_MASK_CONTROL) + retval |= IWindowCallback::MKEY_CTRL; + if (state & XCB_MOD_MASK_1) + retval |= IWindowCallback::MKEY_ALT; + return retval; +} + +static int translateButton(unsigned state) +{ + int retval = 0; + if (state & XCB_BUTTON_MASK_1) + retval = IWindowCallback::BUTTON_PRIMARY; + else if (state & XCB_BUTTON_MASK_2) + retval = IWindowCallback::BUTTON_SECONDARY; + else if (state & XCB_BUTTON_MASK_3) + retval = IWindowCallback::BUTTON_MIDDLE; + else if (state & XCB_BUTTON_MASK_4) + retval = IWindowCallback::BUTTON_AUX1; + else if (state & XCB_BUTTON_MASK_5) + retval = IWindowCallback::BUTTON_AUX2; + return retval; +} + +#define INTERN_ATOM(var, conn, name) \ +do {\ + xcb_intern_atom_cookie_t cookie = \ + xcb_intern_atom(conn, 0, sizeof(#name), #name); \ + xcb_intern_atom_reply_t* reply = \ + xcb_intern_atom_reply(conn, cookie, NULL); \ + var = reply->atom; \ +} while(0) + +struct SXCBAtoms +{ + xcb_atom_t m_netwmState = 0; + xcb_atom_t m_netwmStateFullscreen = 0; + xcb_atom_t m_netwmStateAdd = 0; + xcb_atom_t m_netwmStateRemove = 0; + xcb_key_symbols_t* m_keySyms = NULL; + SXCBAtoms(xcb_connection_t* conn) + { + INTERN_ATOM(m_netwmState, conn, _NET_WM_STATE); + INTERN_ATOM(m_netwmStateFullscreen, conn, _NET_WM_STATE_FULLSCREEN); + INTERN_ATOM(m_netwmStateAdd, conn, _NET_WM_STATE_ADD); + INTERN_ATOM(m_netwmStateRemove, conn, _NET_WM_STATE_REMOVE); + m_keySyms = xcb_key_symbols_alloc(conn); + } +}; +static SXCBAtoms* S_ATOMS = NULL; + +static void genFrameDefault(xcb_screen_t* screen, int* xOut, int* yOut, int* wOut, int* hOut) +{ + float width = screen->width_in_pixels * 2.0 / 3.0; + float height = screen->height_in_pixels * 2.0 / 3.0; + *xOut = (screen->width_in_pixels - width) / 2.0; + *yOut = (screen->height_in_pixels - height) / 2.0; + *wOut = width; + *hOut = height; +} IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api, IWindow* parentWindow); @@ -10,84 +135,303 @@ IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api, class CWindowXCB final : public IWindow { + xcb_connection_t* m_xcbConn; + xcb_window_t m_windowId; + IGraphicsContext* m_gfxCtx; + IWindowCallback* m_callback; + + /* Cached window rectangle (to avoid repeated X queries) */ + int m_wx, m_wy, m_ww, m_wh; + float m_pixelFactor; public: - CWindowXCB(const std::string& title) + CWindowXCB(const std::string& title, xcb_connection_t* conn) + : m_xcbConn(conn), m_callback(NULL) { - + if (!S_ATOMS) + S_ATOMS = new SXCBAtoms(conn); + m_windowId = xcb_generate_id(conn); + + /* Default screen */ + xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(m_xcbConn)).data; + m_pixelFactor = screen->width_in_pixels / (float)screen->width_in_millimeters / REF_DPMM; + + /* Create window */ + int x, y, w, h; + genFrameDefault(screen, &x, &y, &w, &h); + uint32_t valueMasks[] = + { + XCB_NONE, + XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY + }; + xcb_create_window(m_xcbConn, 0, m_windowId, 0, x, y, w, h, 10, 0, screen->root_visual, + XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK, valueMasks); + + /* Set the title of the window */ + const char* c_title = title.c_str(); + xcb_change_property(m_xcbConn, XCB_PROP_MODE_REPLACE, m_windowId, + XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, + strlen(c_title), c_title); + + /* Set the title of the window icon */ + xcb_change_property(m_xcbConn, XCB_PROP_MODE_REPLACE, m_windowId, + XCB_ATOM_WM_ICON_NAME, XCB_ATOM_STRING, 8, + strlen(c_title), c_title); + + /* Construct graphics context */ + m_gfxCtx = _CGraphicsContextXCBNew(IGraphicsContext::API_OPENGL_3_3, this); + } ~CWindowXCB() { - + IApplicationInstance()->_deletedWindow(this); } void setCallback(IWindowCallback* cb) { - + m_callback = cb; } void showWindow() { - + xcb_map_window(m_xcbConn, m_windowId); + xcb_flush(m_xcbConn); } void hideWindow() { - + xcb_unmap_window(m_xcbConn, m_windowId); + xcb_flush(m_xcbConn); } std::string getTitle() { - + xcb_get_property_cookie_t cookie = + xcb_get_property(m_xcbConn, 0, m_windowId, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 64); + xcb_get_property_reply_t* reply = + xcb_get_property_reply(m_xcbConn, cookie, NULL); + std::string retval((const char*)xcb_get_property_value(reply)); + free(reply); + return retval; } void setTitle(const std::string& title) { - + const char* c_title = title.c_str(); + xcb_change_property(m_xcbConn, XCB_PROP_MODE_REPLACE, m_windowId, + XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, + strlen(c_title), c_title); } void setWindowFrameDefault() { - + int x, y, w, h; + xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(m_xcbConn)).data; + genFrameDefault(screen, &x, &y, &w, &h); + uint32_t values[] = {(uint32_t)x, (uint32_t)y, (uint32_t)w, (uint32_t)h}; + xcb_configure_window(m_xcbConn, m_windowId, + XCB_CONFIG_WINDOW_X | + XCB_CONFIG_WINDOW_Y | + XCB_CONFIG_WINDOW_WIDTH | + XCB_CONFIG_WINDOW_HEIGHT, + values); } void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const { - + xOut = m_wx; + yOut = m_wy; + wOut = m_ww; + hOut = m_wh; } void setWindowFrame(float x, float y, float w, float h) { - + uint32_t values[] = {(uint32_t)x, (uint32_t)y, (uint32_t)w, (uint32_t)h}; + xcb_configure_window(m_xcbConn, m_windowId, + XCB_CONFIG_WINDOW_X | + XCB_CONFIG_WINDOW_Y | + XCB_CONFIG_WINDOW_WIDTH | + XCB_CONFIG_WINDOW_HEIGHT, + values); } float getVirtualPixelFactor() const { - + return m_pixelFactor; } bool isFullscreen() const { - + xcb_get_property_cookie_t cookie = + xcb_get_property(m_xcbConn, 0, m_windowId, S_ATOMS->m_netwmState, XCB_ATOM_ATOM, 0, 32); + xcb_get_property_reply_t* reply = + xcb_get_property_reply(m_xcbConn, cookie, NULL); + char* props = (char*)xcb_get_property_value(reply); + char fullscreen = false; + for (int i ; ilength/4 ; ++i) + { + if (props[i] == S_ATOMS->m_netwmStateFullscreen) + { + fullscreen = true; + break; + } + } + free(reply); + return fullscreen; } void setFullscreen(bool fs) { - + xcb_client_message_event_t fsEvent = + { + XCB_CLIENT_MESSAGE, + 32, + 0, + m_windowId, + S_ATOMS->m_netwmState + }; + fsEvent.data.data32[0] = fs ? S_ATOMS->m_netwmStateAdd : S_ATOMS->m_netwmStateRemove; + fsEvent.data.data32[1] = S_ATOMS->m_netwmStateFullscreen; + xcb_send_event(m_xcbConn, 0, m_windowId, + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char*)&fsEvent); + + } + + uintptr_t getPlatformHandle() const + { + return (uintptr_t)m_windowId; + } + + void _incomingEvent(void* e) + { + xcb_generic_event_t* event = (xcb_generic_event_t*)e; + switch (event->response_type & ~0x80) + { + case XCB_EXPOSE: + { + xcb_expose_event_t* ev = (xcb_expose_event_t*)event; + m_wx = ev->x; + m_wy = ev->y; + m_ww = ev->width; + m_wh = ev->height; + } + case XCB_CONFIGURE_NOTIFY: + { + xcb_configure_notify_event_t* ev = (xcb_configure_notify_event_t*)event; + m_wx = ev->x; + m_wy = ev->y; + m_ww = ev->width; + m_wh = ev->height; + } + case XCB_KEY_PRESS: + { + xcb_key_press_event_t* ev = (xcb_key_press_event_t*)event; + if (m_callback) + { + int specialKey; + int modifierKey; + wchar_t charCode = translateKeysym(xcb_key_press_lookup_keysym(S_ATOMS->m_keySyms, ev, 0), + specialKey, modifierKey); + int modifierMask = translateModifiers(ev->state); + if (charCode) + m_callback->charKeyDown(charCode, + (IWindowCallback::EModifierKey)modifierMask, false); + else if (specialKey) + m_callback->specialKeyDown((IWindowCallback::ESpecialKey)specialKey, + (IWindowCallback::EModifierKey)modifierMask, false); + else if (modifierKey) + m_callback->modKeyDown((IWindowCallback::EModifierKey)modifierKey, false); + } + } + case XCB_KEY_RELEASE: + { + xcb_key_release_event_t* ev = (xcb_key_release_event_t*)event; + if (m_callback) + { + int specialKey; + int modifierKey; + wchar_t charCode = translateKeysym(xcb_key_release_lookup_keysym(S_ATOMS->m_keySyms, ev, 0), + specialKey, modifierKey); + int modifierMask = translateModifiers(ev->state); + if (charCode) + m_callback->charKeyUp(charCode, + (IWindowCallback::EModifierKey)modifierMask); + else if (specialKey) + m_callback->specialKeyUp((IWindowCallback::ESpecialKey)specialKey, + (IWindowCallback::EModifierKey)modifierMask); + else if (modifierKey) + m_callback->modKeyUp((IWindowCallback::EModifierKey)modifierKey); + } + } + case XCB_BUTTON_PRESS: + { + xcb_button_press_event_t* ev = (xcb_button_press_event_t*)event; + int button = translateButton(ev->state); + if (m_callback && button) + { + int modifierMask = translateModifiers(ev->state); + IWindowCallback::SWindowCoord coord = + { + {(unsigned)ev->root_x, (unsigned)ev->root_y}, + {(unsigned)(ev->root_x / m_pixelFactor), (unsigned)(ev->root_y / m_pixelFactor)}, + {ev->root_x / (float)m_ww, ev->root_y / (float)m_wh} + }; + m_callback->mouseDown(coord, (IWindowCallback::EMouseButton)button, + (IWindowCallback::EModifierKey)modifierMask); + } + } + case XCB_BUTTON_RELEASE: + { + xcb_button_release_event_t* ev = (xcb_button_release_event_t*)event; + int button = translateButton(ev->state); + if (m_callback && button) + { + int modifierMask = translateModifiers(ev->state); + IWindowCallback::SWindowCoord coord = + { + {(unsigned)ev->root_x, (unsigned)ev->root_y}, + {(unsigned)(ev->root_x / m_pixelFactor), (unsigned)(ev->root_y / m_pixelFactor)}, + {ev->root_x / (float)m_ww, ev->root_y / (float)m_wh} + }; + m_callback->mouseUp(coord, (IWindowCallback::EMouseButton)button, + (IWindowCallback::EModifierKey)modifierMask); + } + } + case XCB_MOTION_NOTIFY: + { + xcb_motion_notify_event_t* ev = (xcb_motion_notify_event_t*)event; + if (m_callback) + { + IWindowCallback::SWindowCoord coord = + { + {(unsigned)ev->root_x, (unsigned)ev->root_y}, + {(unsigned)(ev->root_x / m_pixelFactor), (unsigned)(ev->root_y / m_pixelFactor)}, + {ev->root_x / (float)m_ww, ev->root_y / (float)m_wh} + }; + m_callback->mouseMove(coord); + } + } + } } ETouchType getTouchType() const { - + return TOUCH_NONE; } }; -IWindow* _CWindowXCBNew(const std::string& title) +IWindow* _CWindowXCBNew(const std::string& title, xcb_connection_t* conn) { - return new CWindowXCB(title); + return new CWindowXCB(title, conn); } } From a66469b9911e79d964c326ba87c830767de71fed Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sat, 9 May 2015 21:02:18 -1000 Subject: [PATCH 06/10] much xcb-glx work --- include/inputdev/CDeviceBase.hpp | 4 +- include/windowsys/IGraphicsContext.hpp | 1 - libBoo.pro | 2 +- src/CApplicationWayland.hpp | 4 +- src/CApplicationXCB.hpp | 16 ++- src/inputdev/CDeviceBase.cpp | 8 +- src/inputdev/CDolphinSmashAdapter.cpp | 8 +- src/inputdev/CHIDDeviceIOKit.cpp | 4 +- src/inputdev/CHIDDeviceUdev.cpp | 14 +-- src/inputdev/CHIDDeviceWinUSB.cpp | 4 +- src/inputdev/IHIDDevice.hpp | 4 +- src/windowsys/CGraphicsContextWayland.cpp | 8 +- src/windowsys/CGraphicsContextWin32.cpp | 4 - src/windowsys/CGraphicsContextXCB.cpp | 115 +++++++++++++++++++--- src/windowsys/CWindowCocoa.mm | 1 - src/windowsys/CWindowXCB.cpp | 43 +++++--- 16 files changed, 173 insertions(+), 67 deletions(-) diff --git a/include/inputdev/CDeviceBase.hpp b/include/inputdev/CDeviceBase.hpp index 6319dc1..053258e 100644 --- a/include/inputdev/CDeviceBase.hpp +++ b/include/inputdev/CDeviceBase.hpp @@ -27,8 +27,8 @@ public: virtual void deviceError(const char* error) {fprintf(stderr, "%s\n", error);} /* Low-Level API */ - bool sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length); - size_t receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length); + bool sendUSBInterruptTransfer(const uint8_t* data, size_t length); + size_t receiveUSBInterruptTransfer(uint8_t* data, size_t length); virtual void initialCycle() {} virtual void transferCycle() {} virtual void finalCycle() {} diff --git a/include/windowsys/IGraphicsContext.hpp b/include/windowsys/IGraphicsContext.hpp index 3411570..d2732fa 100644 --- a/include/windowsys/IGraphicsContext.hpp +++ b/include/windowsys/IGraphicsContext.hpp @@ -7,7 +7,6 @@ namespace boo class IGraphicsContext { friend class CWindowCocoa; - virtual void _setPlatformWindowHandle(void* handle) {(void)handle;}; virtual void _setCallback(class IWindowCallback* cb) {(void)cb;}; public: diff --git a/libBoo.pro b/libBoo.pro index 4611b89..eaa9eb4 100644 --- a/libBoo.pro +++ b/libBoo.pro @@ -3,7 +3,7 @@ CONFIG += console #QMAKE_CXXFLAGS -= -std=c++0x #CONFIG += c++11 unix:QMAKE_CXXFLAGS += -std=c++11 -stdlib=libc++ -unix:LIBS += -std=c++11 -stdlib=libc++ -lc++abi -lxcb -lxcb-xkb -lxcb-keysyms -lxkbcommon -lxkbcommon-x11 +unix:LIBS += -std=c++11 -stdlib=libc++ -lc++abi -lxcb -lxcb-glx -lxcb-xkb -lxcb-keysyms -lxkbcommon -lxkbcommon-x11 win32:LIBS += Setupapi.lib winusb.lib User32.lib /SUBSYSTEM:Windows diff --git a/src/CApplicationWayland.hpp b/src/CApplicationWayland.hpp index 4b821e9..f174349 100644 --- a/src/CApplicationWayland.hpp +++ b/src/CApplicationWayland.hpp @@ -11,7 +11,7 @@ IWindow* _CWindowWaylandNew(const std::string& title); class CApplicationWayland final : public IApplication { - const IApplicationCallback& m_callback; + IApplicationCallback& m_callback; const std::string m_friendlyName; const std::string m_pname; const std::vector m_args; @@ -22,7 +22,7 @@ class CApplicationWayland final : public IApplication } public: - CApplicationWayland(const IApplicationCallback& callback, + CApplicationWayland(IApplicationCallback& callback, const std::string& friendlyName, const std::string& pname, const std::vector& args) diff --git a/src/CApplicationXCB.hpp b/src/CApplicationXCB.hpp index 21a5e1a..8c1f907 100644 --- a/src/CApplicationXCB.hpp +++ b/src/CApplicationXCB.hpp @@ -6,6 +6,7 @@ #define explicit explicit_c #include +#include #include #include #undef explicit @@ -15,7 +16,7 @@ namespace boo static xcb_window_t getWindowOfEvent(xcb_generic_event_t* event, bool& windowEvent) { - switch (event->response_type & ~0x80) + switch (XCB_EVENT_RESPONSE_TYPE(event)) { case XCB_EXPOSE: { @@ -69,7 +70,7 @@ IWindow* _CWindowXCBNew(const std::string& title, xcb_connection_t* conn); class CApplicationXCB final : public IApplication { - const IApplicationCallback& m_callback; + IApplicationCallback& m_callback; const std::string m_friendlyName; const std::string m_pname; const std::vector m_args; @@ -86,7 +87,7 @@ class CApplicationXCB final : public IApplication } public: - CApplicationXCB(const IApplicationCallback& callback, + CApplicationXCB(IApplicationCallback& callback, const std::string& friendlyName, const std::string& pname, const std::vector& args) @@ -97,7 +98,7 @@ public: { m_xcbConn = xcb_connect(NULL, NULL); - /* The convoluted xkb extension requests that the X server does not + /* This convoluted xkb extension requests that the X server does not * send repeated keydown events when a key is held */ xkb_x11_setup_xkb_extension(m_xcbConn, XKB_X11_MIN_MAJOR_XKB_VERSION, @@ -122,17 +123,22 @@ public: void run() { xcb_generic_event_t* event; + m_running = true; + m_callback.appLaunched(this); while (m_running && (event = xcb_wait_for_event(m_xcbConn))) { bool windowEvent; xcb_window_t evWindow = getWindowOfEvent(event, windowEvent); + fprintf(stderr, "EVENT %d\n", XCB_EVENT_RESPONSE_TYPE(event)); if (windowEvent) { IWindow* window = m_windows[evWindow]; - + if (window) + window->_incomingEvent(event); } free(event); } + m_callback.appQuitting(this); } void quit() diff --git a/src/inputdev/CDeviceBase.cpp b/src/inputdev/CDeviceBase.cpp index c48c719..ff18922 100644 --- a/src/inputdev/CDeviceBase.cpp +++ b/src/inputdev/CDeviceBase.cpp @@ -33,17 +33,17 @@ void CDeviceBase::closeDevice() m_token->_deviceClose(); } -bool CDeviceBase::sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length) +bool CDeviceBase::sendUSBInterruptTransfer(const uint8_t* data, size_t length) { if (m_hidDev) - return m_hidDev->_sendUSBInterruptTransfer(pipe, data, length); + return m_hidDev->_sendUSBInterruptTransfer(data, length); return false; } -size_t CDeviceBase::receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length) +size_t CDeviceBase::receiveUSBInterruptTransfer(uint8_t* data, size_t length) { if (m_hidDev) - return m_hidDev->_receiveUSBInterruptTransfer(pipe, data, length); + return m_hidDev->_receiveUSBInterruptTransfer(data, length); return false; } diff --git a/src/inputdev/CDolphinSmashAdapter.cpp b/src/inputdev/CDolphinSmashAdapter.cpp index ab5106e..2a01fdd 100644 --- a/src/inputdev/CDolphinSmashAdapter.cpp +++ b/src/inputdev/CDolphinSmashAdapter.cpp @@ -59,13 +59,13 @@ parseState(SDolphinControllerState* stateOut, uint8_t* payload, bool& rumble) void CDolphinSmashAdapter::initialCycle() { uint8_t handshakePayload[] = {0x13}; - sendUSBInterruptTransfer(0, handshakePayload, sizeof(handshakePayload)); + sendUSBInterruptTransfer(handshakePayload, sizeof(handshakePayload)); } void CDolphinSmashAdapter::transferCycle() { uint8_t payload[37]; - size_t recvSz = receiveUSBInterruptTransfer(0, payload, sizeof(payload)); + size_t recvSz = receiveUSBInterruptTransfer(payload, sizeof(payload)); if (recvSz != 37 || payload[0] != 0x21) return; //printf("RECEIVED DATA %zu %02X\n", recvSz, payload[0]); @@ -108,7 +108,7 @@ void CDolphinSmashAdapter::transferCycle() else rumbleMessage[i+1] = 0; } - sendUSBInterruptTransfer(0, rumbleMessage, sizeof(rumbleMessage)); + sendUSBInterruptTransfer(rumbleMessage, sizeof(rumbleMessage)); m_rumbleState = rumbleReq; } } @@ -116,7 +116,7 @@ void CDolphinSmashAdapter::transferCycle() void CDolphinSmashAdapter::finalCycle() { uint8_t rumbleMessage[5] = {0x11, 0, 0, 0, 0}; - sendUSBInterruptTransfer(0, rumbleMessage, sizeof(rumbleMessage)); + sendUSBInterruptTransfer(rumbleMessage, sizeof(rumbleMessage)); } void CDolphinSmashAdapter::deviceDisconnected() diff --git a/src/inputdev/CHIDDeviceIOKit.cpp b/src/inputdev/CHIDDeviceIOKit.cpp index 95b115a..2b7798c 100644 --- a/src/inputdev/CHIDDeviceIOKit.cpp +++ b/src/inputdev/CHIDDeviceIOKit.cpp @@ -24,7 +24,7 @@ class CHIDDeviceIOKit final : public IHIDDevice std::condition_variable m_initCond; std::thread* m_thread; - bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length) + bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) { if (m_usbIntf) { @@ -34,7 +34,7 @@ class CHIDDeviceIOKit final : public IHIDDevice return false; } - size_t _receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length) + size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) { if (m_usbIntf) { diff --git a/src/inputdev/CHIDDeviceUdev.cpp b/src/inputdev/CHIDDeviceUdev.cpp index 48aaa11..5c387bf 100644 --- a/src/inputdev/CHIDDeviceUdev.cpp +++ b/src/inputdev/CHIDDeviceUdev.cpp @@ -38,7 +38,7 @@ class CHIDDeviceUdev final : public IHIDDevice std::condition_variable m_initCond; std::thread* m_thread; - bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length) + bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) { if (m_devFd) { @@ -57,7 +57,7 @@ class CHIDDeviceUdev final : public IHIDDevice return false; } - size_t _receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length) + size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) { if (m_devFd) { @@ -93,22 +93,22 @@ class CHIDDeviceUdev final : public IHIDDevice udev_device_unref(udevDev); return; } - usb_device_descriptor devDesc = {0}; + usb_device_descriptor devDesc = {}; read(device->m_devFd, &devDesc, 1); read(device->m_devFd, &devDesc.bDescriptorType, devDesc.bLength-1); if (devDesc.bNumConfigurations) { - usb_config_descriptor confDesc = {0}; + usb_config_descriptor confDesc = {}; read(device->m_devFd, &confDesc, 1); read(device->m_devFd, &confDesc.bDescriptorType, confDesc.bLength-1); if (confDesc.bNumInterfaces) { - usb_interface_descriptor intfDesc = {0}; + usb_interface_descriptor intfDesc = {}; read(device->m_devFd, &intfDesc, 1); read(device->m_devFd, &intfDesc.bDescriptorType, intfDesc.bLength-1); for (i=0 ; im_devFd, &endpDesc, 1); read(device->m_devFd, &endpDesc.bDescriptorType, endpDesc.bLength-1); if ((endpDesc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) @@ -193,6 +193,8 @@ class CHIDDeviceUdev final : public IHIDDevice bool _sendHIDReport(const uint8_t* data, size_t length) { + (void)data; + (void)length; return false; } diff --git a/src/inputdev/CHIDDeviceWinUSB.cpp b/src/inputdev/CHIDDeviceWinUSB.cpp index d419140..b17c36a 100644 --- a/src/inputdev/CHIDDeviceWinUSB.cpp +++ b/src/inputdev/CHIDDeviceWinUSB.cpp @@ -33,7 +33,7 @@ class CHIDDeviceWinUSB final : public IHIDDevice std::condition_variable m_initCond; std::thread* m_thread; - bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length) + bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) { if (m_usbHandle) { @@ -47,7 +47,7 @@ class CHIDDeviceWinUSB final : public IHIDDevice return false; } - size_t _receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length) + size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) { if (m_usbHandle) { diff --git a/src/inputdev/IHIDDevice.hpp b/src/inputdev/IHIDDevice.hpp index 99ca399..55c0a88 100644 --- a/src/inputdev/IHIDDevice.hpp +++ b/src/inputdev/IHIDDevice.hpp @@ -10,8 +10,8 @@ class IHIDDevice { friend class CDeviceBase; virtual void _deviceDisconnected()=0; - virtual bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)=0; - virtual size_t _receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)=0; + virtual bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length)=0; + virtual size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length)=0; virtual bool _sendHIDReport(const uint8_t* data, size_t length)=0; public: inline virtual ~IHIDDevice() {} diff --git a/src/windowsys/CGraphicsContextWayland.cpp b/src/windowsys/CGraphicsContextWayland.cpp index a669d77..65b9b60 100644 --- a/src/windowsys/CGraphicsContextWayland.cpp +++ b/src/windowsys/CGraphicsContextWayland.cpp @@ -47,10 +47,6 @@ public: m_pf = pf; } - void setPlatformWindowHandle(void* handle) - { - } - void initializeContext() { @@ -58,7 +54,7 @@ public: IGraphicsContext* makeShareContext() const { - + return NULL; } void makeCurrent() @@ -81,7 +77,7 @@ public: IGraphicsContext* _CGraphicsContextWaylandNew(IGraphicsContext::EGraphicsAPI api, IWindow* parentWindow) { - + return new CGraphicsContextWayland(api, parentWindow); } } diff --git a/src/windowsys/CGraphicsContextWin32.cpp b/src/windowsys/CGraphicsContextWin32.cpp index f8036c5..26436e9 100644 --- a/src/windowsys/CGraphicsContextWin32.cpp +++ b/src/windowsys/CGraphicsContextWin32.cpp @@ -47,10 +47,6 @@ public: m_pf = pf; } - void setPlatformWindowHandle(void* handle) - { - } - void initializeContext() { diff --git a/src/windowsys/CGraphicsContextXCB.cpp b/src/windowsys/CGraphicsContextXCB.cpp index 60799d5..d110991 100644 --- a/src/windowsys/CGraphicsContextXCB.cpp +++ b/src/windowsys/CGraphicsContextXCB.cpp @@ -1,6 +1,13 @@ #include "windowsys/IGraphicsContext.hpp" #include "windowsys/IWindow.hpp" +#include +#include +#include +#include +#include +#include + namespace boo { @@ -10,15 +17,90 @@ class CGraphicsContextXCB final : public IGraphicsContext EGraphicsAPI m_api; EPixelFormat m_pf; IWindow* m_parentWindow; + xcb_connection_t* m_xcbConn; + + xcb_glx_fbconfig_t m_fbconfig = 0; + xcb_visualid_t m_visualid = 0; + xcb_glx_window_t m_glxWindow = 0; + xcb_glx_context_t m_glxCtx = 0; + xcb_glx_context_tag_t m_glxCtxTag = 0; public: IWindowCallback* m_callback; - CGraphicsContextXCB(EGraphicsAPI api, IWindow* parentWindow) + CGraphicsContextXCB(EGraphicsAPI api, IWindow* parentWindow, xcb_connection_t* conn, uint32_t& visualIdOut) : m_api(api), m_pf(PF_RGBA8), - m_parentWindow(parentWindow) - {} + m_parentWindow(parentWindow), + m_xcbConn(conn) + { + /* WTF freedesktop?? Fix this awful API and your nonexistant docs */ + xcb_glx_get_fb_configs_reply_t* fbconfigs = + xcb_glx_get_fb_configs_reply(m_xcbConn, xcb_glx_get_fb_configs(m_xcbConn, 0), NULL); + struct conf_prop + { + uint32_t key; + uint32_t val; + }* props = (struct conf_prop*)xcb_glx_get_fb_configs_property_list(fbconfigs); + + for (uint32_t i=0 ; inum_FB_configs ; ++i) + { + struct conf_prop* configProps = &props[fbconfigs->num_properties * i]; + uint32_t fbconfId, visualId, depthSize, colorSize, doubleBuffer; + for (uint32_t j=0 ; jnum_properties ; ++j) + { + struct conf_prop* prop = &configProps[j]; + if (prop->key == GLX_FBCONFIG_ID) + fbconfId = prop->val; + if (prop->key == GLX_VISUAL_ID) + visualId = prop->val; + else if (prop->key == GLX_DEPTH_SIZE) + depthSize = prop->val; + else if (prop->key == GLX_BUFFER_SIZE) + colorSize = prop->val; + else if (prop->key == GLX_DOUBLEBUFFER) + doubleBuffer = prop->val; + } + + /* Double-buffer only */ + if (!doubleBuffer) + continue; + + if (m_pf == PF_RGBA8 && colorSize >= 32) + { + m_fbconfig = fbconfId; + m_visualid = visualId; + break; + } + else if (m_pf == PF_RGBA8_Z24 && colorSize >= 32 && depthSize >= 24) + { + m_fbconfig = fbconfId; + m_visualid = visualId; + break; + } + else if (m_pf == PF_RGBAF32 && colorSize >= 128) + { + m_fbconfig = fbconfId; + m_visualid = visualId; + break; + } + else if (m_pf == PF_RGBAF32_Z24 && colorSize >= 128 && depthSize >= 24) + { + m_fbconfig = fbconfId; + m_visualid = visualId; + break; + } + } + free(fbconfigs); + + if (!m_fbconfig) + { + throw std::runtime_error("unable to find suitable pixel format"); + return; + } + + visualIdOut = m_visualid; + } ~CGraphicsContextXCB() { @@ -47,41 +129,46 @@ public: m_pf = pf; } - void setPlatformWindowHandle(void* handle) - { - } - void initializeContext() { - + m_glxWindow = xcb_generate_id(m_xcbConn); + xcb_glx_create_window(m_xcbConn, 0, m_fbconfig, + m_parentWindow->getPlatformHandle(), + m_glxWindow, 0, NULL); } IGraphicsContext* makeShareContext() const { - + return NULL; } void makeCurrent() { - + xcb_glx_make_context_current_reply_t* reply = + xcb_glx_make_context_current_reply(m_xcbConn, + xcb_glx_make_context_current(m_xcbConn, 0, m_glxWindow, m_glxWindow, m_glxCtx), NULL); + m_glxCtxTag = reply->context_tag; + free(reply); } void clearCurrent() { - + xcb_glx_make_context_current(m_xcbConn, m_glxCtxTag, m_glxWindow, m_glxWindow, 0); + m_glxCtxTag = 0; } void swapBuffer() { - + xcb_glx_swap_buffers(m_xcbConn, m_glxCtxTag, m_glxWindow); } }; IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api, - IWindow* parentWindow) + IWindow* parentWindow, xcb_connection_t* conn, + uint32_t& visualIdOut) { - + return new CGraphicsContextXCB(api, parentWindow, conn, visualIdOut); } } diff --git a/src/windowsys/CWindowCocoa.mm b/src/windowsys/CWindowCocoa.mm index 0d092ec..942d9d2 100644 --- a/src/windowsys/CWindowCocoa.mm +++ b/src/windowsys/CWindowCocoa.mm @@ -31,7 +31,6 @@ public: { m_nsWindow = [[CWindowCocoaInternal alloc] initWithBooWindow:this title:title]; m_gfxCtx = _CGraphicsContextCocoaNew(IGraphicsContext::API_OPENGL_3_3, this); - m_gfxCtx->_setPlatformWindowHandle(m_nsWindow); m_gfxCtx->initializeContext(); } diff --git a/src/windowsys/CWindowXCB.cpp b/src/windowsys/CWindowXCB.cpp index 1a07b47..6bccc60 100644 --- a/src/windowsys/CWindowXCB.cpp +++ b/src/windowsys/CWindowXCB.cpp @@ -3,6 +3,7 @@ #include "IApplication.hpp" #include +#include #include #include #include @@ -99,6 +100,7 @@ do {\ xcb_intern_atom_reply_t* reply = \ xcb_intern_atom_reply(conn, cookie, NULL); \ var = reply->atom; \ + free(reply); \ } while(0) struct SXCBAtoms @@ -107,6 +109,7 @@ struct SXCBAtoms xcb_atom_t m_netwmStateFullscreen = 0; xcb_atom_t m_netwmStateAdd = 0; xcb_atom_t m_netwmStateRemove = 0; + xcb_atom_t m_ xcb_key_symbols_t* m_keySyms = NULL; SXCBAtoms(xcb_connection_t* conn) { @@ -130,7 +133,8 @@ static void genFrameDefault(xcb_screen_t* screen, int* xOut, int* yOut, int* wOu } IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api, - IWindow* parentWindow); + IWindow* parentWindow, xcb_connection_t* conn, + uint32_t& visualIdOut); class CWindowXCB final : public IWindow { @@ -151,12 +155,21 @@ public: { if (!S_ATOMS) S_ATOMS = new SXCBAtoms(conn); - m_windowId = xcb_generate_id(conn); /* Default screen */ xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(m_xcbConn)).data; m_pixelFactor = screen->width_in_pixels / (float)screen->width_in_millimeters / REF_DPMM; + /* Construct graphics context */ + uint32_t visualId; + m_gfxCtx = _CGraphicsContextXCBNew(IGraphicsContext::API_OPENGL_3_3, this, m_xcbConn, visualId); + + + /* Create colormap */ + xcb_colormap_t colormap = xcb_generate_id(m_xcbConn); + xcb_create_colormap(m_xcbConn, XCB_COLORMAP_ALLOC_NONE, + colormap, screen->root, visualId); + /* Create window */ int x, y, w, h; genFrameDefault(screen, &x, &y, &w, &h); @@ -166,10 +179,16 @@ public: XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | - XCB_EVENT_MASK_STRUCTURE_NOTIFY + XCB_EVENT_MASK_STRUCTURE_NOTIFY | 0xFFFFFF, + colormap, + XCB_NONE }; - xcb_create_window(m_xcbConn, 0, m_windowId, 0, x, y, w, h, 10, 0, screen->root_visual, - XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK, valueMasks); + m_windowId = xcb_generate_id(conn); + xcb_create_window(m_xcbConn, XCB_COPY_FROM_PARENT, m_windowId, screen->root, + x, y, w, h, 10, + XCB_WINDOW_CLASS_INPUT_OUTPUT, visualId, + XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP, + valueMasks); /* Set the title of the window */ const char* c_title = title.c_str(); @@ -182,8 +201,9 @@ public: XCB_ATOM_WM_ICON_NAME, XCB_ATOM_STRING, 8, strlen(c_title), c_title); - /* Construct graphics context */ - m_gfxCtx = _CGraphicsContextXCBNew(IGraphicsContext::API_OPENGL_3_3, this); + /* Initialize context */ + xcb_map_window(m_xcbConn, m_windowId); + m_gfxCtx->initializeContext(); } @@ -274,9 +294,9 @@ public: xcb_get_property_reply(m_xcbConn, cookie, NULL); char* props = (char*)xcb_get_property_value(reply); char fullscreen = false; - for (int i ; ilength/4 ; ++i) + for (unsigned i=0 ; ilength/4 ; ++i) { - if (props[i] == S_ATOMS->m_netwmStateFullscreen) + if ((xcb_atom_t)props[i] == S_ATOMS->m_netwmStateFullscreen) { fullscreen = true; break; @@ -294,7 +314,8 @@ public: 32, 0, m_windowId, - S_ATOMS->m_netwmState + S_ATOMS->m_netwmState, + {} }; fsEvent.data.data32[0] = fs ? S_ATOMS->m_netwmStateAdd : S_ATOMS->m_netwmStateRemove; fsEvent.data.data32[1] = S_ATOMS->m_netwmStateFullscreen; @@ -313,7 +334,7 @@ public: void _incomingEvent(void* e) { xcb_generic_event_t* event = (xcb_generic_event_t*)e; - switch (event->response_type & ~0x80) + switch (XCB_EVENT_RESPONSE_TYPE(event)) { case XCB_EXPOSE: { From d0db7b080fe84963eb8e073030a8a411b7e2e92e Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 11 May 2015 23:38:37 -1000 Subject: [PATCH 07/10] Added XInput event registration to XCB --- include/windowsys/IWindow.hpp | 2 +- libBoo.pro | 8 ++- src/CApplicationXCB.hpp | 56 +++++++++++++--- src/inputdev/CHIDListenerUdev.cpp | 3 + src/windowsys/CWindowXCB.cpp | 106 ++++++++++++++++++++---------- test/main.cpp | 66 ++++++++++++++++++- 6 files changed, 194 insertions(+), 47 deletions(-) diff --git a/include/windowsys/IWindow.hpp b/include/windowsys/IWindow.hpp index d100bec..0179f0d 100644 --- a/include/windowsys/IWindow.hpp +++ b/include/windowsys/IWindow.hpp @@ -77,7 +77,7 @@ public: {(void)coord;(void)button;(void)mods;} virtual void mouseMove(const SWindowCoord& coord) {(void)coord;} - virtual void scroll(const SScrollDelta& scroll) + virtual void scroll(const SWindowCoord& coord, const SScrollDelta& scroll) {(void)scroll;} virtual void touchDown(const SWindowCoord& coord, uintptr_t tid) diff --git a/libBoo.pro b/libBoo.pro index eaa9eb4..3107cc3 100644 --- a/libBoo.pro +++ b/libBoo.pro @@ -1,9 +1,13 @@ CONFIG -= Qt -CONFIG += console +QT = +LIBS -= -lQtGui -lQtCore +#CONFIG += console #QMAKE_CXXFLAGS -= -std=c++0x #CONFIG += c++11 unix:QMAKE_CXXFLAGS += -std=c++11 -stdlib=libc++ -unix:LIBS += -std=c++11 -stdlib=libc++ -lc++abi -lxcb -lxcb-glx -lxcb-xkb -lxcb-keysyms -lxkbcommon -lxkbcommon-x11 +unix:LIBS += -std=c++11 -stdlib=libc++ -lc++abi -lxcb \ + -lxcb-glx -lxcb-xkb -lxcb-xinput -lxcb-keysyms \ + -lxkbcommon -lxkbcommon-x11 win32:LIBS += Setupapi.lib winusb.lib User32.lib /SUBSYSTEM:Windows diff --git a/src/CApplicationXCB.hpp b/src/CApplicationXCB.hpp index 8c1f907..91bb205 100644 --- a/src/CApplicationXCB.hpp +++ b/src/CApplicationXCB.hpp @@ -9,15 +9,25 @@ #include #include #include +#include #undef explicit namespace boo { + +int XINPUT_OPCODE = 0; + static xcb_window_t getWindowOfEvent(xcb_generic_event_t* event, bool& windowEvent) { switch (XCB_EVENT_RESPONSE_TYPE(event)) { + case XCB_CLIENT_MESSAGE: + { + xcb_client_message_event_t* ev = (xcb_client_message_event_t*)event; + windowEvent = true; + return ev->window; + } case XCB_EXPOSE: { xcb_expose_event_t* ev = (xcb_expose_event_t*)event; @@ -34,31 +44,56 @@ static xcb_window_t getWindowOfEvent(xcb_generic_event_t* event, bool& windowEve { xcb_key_press_event_t* ev = (xcb_key_press_event_t*)event; windowEvent = true; - return ev->root; + return ev->event; } case XCB_KEY_RELEASE: { xcb_key_release_event_t* ev = (xcb_key_release_event_t*)event; windowEvent = true; - return ev->root; + return ev->event; } case XCB_BUTTON_PRESS: { xcb_button_press_event_t* ev = (xcb_button_press_event_t*)event; windowEvent = true; - return ev->root; + return ev->event; } case XCB_BUTTON_RELEASE: { xcb_button_release_event_t* ev = (xcb_button_release_event_t*)event; windowEvent = true; - return ev->root; + return ev->event; } case XCB_MOTION_NOTIFY: { xcb_motion_notify_event_t* ev = (xcb_motion_notify_event_t*)event; windowEvent = true; - return ev->root; + return ev->event; + } + case XCB_GE_GENERIC: + { + xcb_ge_event_t* gev = (xcb_ge_event_t*)event; + if (gev->pad0 == XINPUT_OPCODE) + { + fprintf(stderr, "INPUTEVENT\n"); + return 0; + switch (XCB_EVENT_RESPONSE_TYPE(gev)) + { + case XCB_INPUT_DEVICE_CHANGED: + { + xcb_input_device_changed_event_t* ev = (xcb_input_device_changed_event_t*)event; + return 0; + } + case XCB_INPUT_DEVICE_MOTION_NOTIFY: + { + xcb_input_device_motion_notify_event_t* ev = (xcb_input_device_motion_notify_event_t*)event; + windowEvent = true; + return ev->event; + } + default: + return 0; + } + } } default: windowEvent = false; @@ -108,6 +143,10 @@ public: xcb_xkb_per_client_flags(m_xcbConn, XCB_XKB_ID_USE_CORE_KBD, XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT, XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT, 0, 0, 0); + + + + } ~CApplicationXCB() @@ -125,6 +164,7 @@ public: xcb_generic_event_t* event; m_running = true; m_callback.appLaunched(this); + xcb_flush(m_xcbConn); while (m_running && (event = xcb_wait_for_event(m_xcbConn))) { bool windowEvent; @@ -132,9 +172,9 @@ public: fprintf(stderr, "EVENT %d\n", XCB_EVENT_RESPONSE_TYPE(event)); if (windowEvent) { - IWindow* window = m_windows[evWindow]; - if (window) - window->_incomingEvent(event); + auto window = m_windows.find(evWindow); + if (window != m_windows.end()) + window->second->_incomingEvent(event); } free(event); } diff --git a/src/inputdev/CHIDListenerUdev.cpp b/src/inputdev/CHIDListenerUdev.cpp index eba7e61..5fbbffb 100644 --- a/src/inputdev/CHIDListenerUdev.cpp +++ b/src/inputdev/CHIDListenerUdev.cpp @@ -2,6 +2,7 @@ #include "inputdev/CDeviceFinder.hpp" #include #include +#include #include namespace boo @@ -165,6 +166,8 @@ public: ~CHIDListenerUdev() { m_udevRunning = false; + //raise(SIGINT); + pthread_kill(m_udevThread->native_handle(), SIGINT); m_udevThread->join(); delete m_udevThread; udev_monitor_unref(m_udevMon); diff --git a/src/windowsys/CWindowXCB.cpp b/src/windowsys/CWindowXCB.cpp index 6bccc60..64fce35 100644 --- a/src/windowsys/CWindowXCB.cpp +++ b/src/windowsys/CWindowXCB.cpp @@ -7,8 +7,10 @@ #include #include #include +#include #include #include +#include #include #define XK_MISCELLANY @@ -77,46 +79,50 @@ static int translateModifiers(unsigned state) return retval; } -static int translateButton(unsigned state) +static int translateButton(unsigned detail) { int retval = 0; - if (state & XCB_BUTTON_MASK_1) + if (detail == 1) retval = IWindowCallback::BUTTON_PRIMARY; - else if (state & XCB_BUTTON_MASK_2) + else if (detail == 3) retval = IWindowCallback::BUTTON_SECONDARY; - else if (state & XCB_BUTTON_MASK_3) + else if (detail == 2) retval = IWindowCallback::BUTTON_MIDDLE; - else if (state & XCB_BUTTON_MASK_4) + else if (detail == 8) retval = IWindowCallback::BUTTON_AUX1; - else if (state & XCB_BUTTON_MASK_5) - retval = IWindowCallback::BUTTON_AUX2; + else if (detail == 9) + retval = +IWindowCallback::BUTTON_AUX2; return retval; } -#define INTERN_ATOM(var, conn, name) \ +#define INTERN_ATOM(var, conn, name, if_exists) \ do {\ xcb_intern_atom_cookie_t cookie = \ - xcb_intern_atom(conn, 0, sizeof(#name), #name); \ + xcb_intern_atom(conn, if_exists, sizeof(#name), #name); \ xcb_intern_atom_reply_t* reply = \ xcb_intern_atom_reply(conn, cookie, NULL); \ var = reply->atom; \ - free(reply); \ + /*free(reply);*/ \ } while(0) struct SXCBAtoms { + xcb_atom_t m_wmProtocols = 0; + xcb_atom_t m_wmDeleteWindow = 0; xcb_atom_t m_netwmState = 0; xcb_atom_t m_netwmStateFullscreen = 0; xcb_atom_t m_netwmStateAdd = 0; xcb_atom_t m_netwmStateRemove = 0; - xcb_atom_t m_ xcb_key_symbols_t* m_keySyms = NULL; SXCBAtoms(xcb_connection_t* conn) { - INTERN_ATOM(m_netwmState, conn, _NET_WM_STATE); - INTERN_ATOM(m_netwmStateFullscreen, conn, _NET_WM_STATE_FULLSCREEN); - INTERN_ATOM(m_netwmStateAdd, conn, _NET_WM_STATE_ADD); - INTERN_ATOM(m_netwmStateRemove, conn, _NET_WM_STATE_REMOVE); + INTERN_ATOM(m_wmProtocols, conn, WM_PROTOCOLS, 1); + INTERN_ATOM(m_wmDeleteWindow, conn, WM_DELETE_WINDOW, 1); + INTERN_ATOM(m_netwmState, conn, _NET_WM_STATE, 0); + INTERN_ATOM(m_netwmStateFullscreen, conn, _NET_WM_STATE_FULLSCREEN, 0); + INTERN_ATOM(m_netwmStateAdd, conn, _NET_WM_STATE_ADD, 0); + INTERN_ATOM(m_netwmStateRemove, conn, _NET_WM_STATE_REMOVE, 0); m_keySyms = xcb_key_symbols_alloc(conn); } }; @@ -138,7 +144,6 @@ IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api, class CWindowXCB final : public IWindow { - xcb_connection_t* m_xcbConn; xcb_window_t m_windowId; IGraphicsContext* m_gfxCtx; @@ -164,7 +169,6 @@ public: uint32_t visualId; m_gfxCtx = _CGraphicsContextXCBNew(IGraphicsContext::API_OPENGL_3_3, this, m_xcbConn, visualId); - /* Create colormap */ xcb_colormap_t colormap = xcb_generate_id(m_xcbConn); xcb_create_colormap(m_xcbConn, XCB_COLORMAP_ALLOC_NONE, @@ -179,7 +183,7 @@ public: XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | - XCB_EVENT_MASK_STRUCTURE_NOTIFY | 0xFFFFFF, + XCB_EVENT_MASK_STRUCTURE_NOTIFY, colormap, XCB_NONE }; @@ -190,6 +194,27 @@ public: XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP, valueMasks); + /* The XInput extension enables per-pixel smooth scrolling trackpads */ + struct + { + xcb_input_event_mask_t mask; + uint32_t maskVal; + } masks = + { + {XCB_INPUT_DEVICE_ALL_MASTER, 1}, + XCB_INPUT_XI_EVENT_MASK_MOTION + }; + xcb_input_xi_select_events(m_xcbConn, m_windowId, 1, &masks.mask); + + xcb_change_property(m_xcbConn, XCB_PROP_MODE_REPLACE, m_windowId, S_ATOMS->m_wmProtocols, + XCB_ATOM_ATOM, 32, 1, &S_ATOMS->m_wmDeleteWindow); + const xcb_atom_t wm_protocols[1] = { + S_ATOMS->m_wmDeleteWindow, + }; + xcb_change_property(m_xcbConn, XCB_PROP_MODE_REPLACE, m_windowId, + S_ATOMS->m_wmProtocols, 4, + 32, 1, wm_protocols); + /* Set the title of the window */ const char* c_title = title.c_str(); xcb_change_property(m_xcbConn, XCB_PROP_MODE_REPLACE, m_windowId, @@ -203,8 +228,9 @@ public: /* Initialize context */ xcb_map_window(m_xcbConn, m_windowId); - m_gfxCtx->initializeContext(); + xcb_flush(m_xcbConn); + m_gfxCtx->initializeContext(); } ~CWindowXCB() @@ -323,7 +349,6 @@ public: XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char*)&fsEvent); - } uintptr_t getPlatformHandle() const @@ -336,6 +361,14 @@ public: xcb_generic_event_t* event = (xcb_generic_event_t*)e; switch (XCB_EVENT_RESPONSE_TYPE(event)) { + case XCB_CLIENT_MESSAGE: + { + xcb_client_message_event_t* ev = (xcb_client_message_event_t*)event; + if (ev->data.data32[0] == S_ATOMS->m_wmDeleteWindow) + { + fprintf(stderr, "CLOSED\n"); + } + } case XCB_EXPOSE: { xcb_expose_event_t* ev = (xcb_expose_event_t*)event; @@ -347,10 +380,13 @@ public: case XCB_CONFIGURE_NOTIFY: { xcb_configure_notify_event_t* ev = (xcb_configure_notify_event_t*)event; - m_wx = ev->x; - m_wy = ev->y; - m_ww = ev->width; - m_wh = ev->height; + if (ev->width && ev->height) + { + m_wx = ev->x; + m_wy = ev->y; + m_ww = ev->width; + m_wh = ev->height; + } } case XCB_KEY_PRESS: { @@ -395,15 +431,15 @@ public: case XCB_BUTTON_PRESS: { xcb_button_press_event_t* ev = (xcb_button_press_event_t*)event; - int button = translateButton(ev->state); + int button = translateButton(ev->detail); if (m_callback && button) { int modifierMask = translateModifiers(ev->state); IWindowCallback::SWindowCoord coord = { - {(unsigned)ev->root_x, (unsigned)ev->root_y}, - {(unsigned)(ev->root_x / m_pixelFactor), (unsigned)(ev->root_y / m_pixelFactor)}, - {ev->root_x / (float)m_ww, ev->root_y / (float)m_wh} + {(unsigned)ev->event_x, (unsigned)ev->event_y}, + {(unsigned)(ev->event_x / m_pixelFactor), (unsigned)(ev->event_y / m_pixelFactor)}, + {ev->event_x / (float)m_ww, ev->event_y / (float)m_wh} }; m_callback->mouseDown(coord, (IWindowCallback::EMouseButton)button, (IWindowCallback::EModifierKey)modifierMask); @@ -412,15 +448,15 @@ public: case XCB_BUTTON_RELEASE: { xcb_button_release_event_t* ev = (xcb_button_release_event_t*)event; - int button = translateButton(ev->state); + int button = translateButton(ev->detail); if (m_callback && button) { int modifierMask = translateModifiers(ev->state); IWindowCallback::SWindowCoord coord = { - {(unsigned)ev->root_x, (unsigned)ev->root_y}, - {(unsigned)(ev->root_x / m_pixelFactor), (unsigned)(ev->root_y / m_pixelFactor)}, - {ev->root_x / (float)m_ww, ev->root_y / (float)m_wh} + {(unsigned)ev->event_x, (unsigned)ev->event_y}, + {(unsigned)(ev->event_x / m_pixelFactor), (unsigned)(ev->event_y / m_pixelFactor)}, + {ev->event_x / (float)m_ww, ev->event_y / (float)m_wh} }; m_callback->mouseUp(coord, (IWindowCallback::EMouseButton)button, (IWindowCallback::EModifierKey)modifierMask); @@ -433,9 +469,9 @@ public: { IWindowCallback::SWindowCoord coord = { - {(unsigned)ev->root_x, (unsigned)ev->root_y}, - {(unsigned)(ev->root_x / m_pixelFactor), (unsigned)(ev->root_y / m_pixelFactor)}, - {ev->root_x / (float)m_ww, ev->root_y / (float)m_wh} + {(unsigned)ev->event_x, (unsigned)ev->event_y}, + {(unsigned)(ev->event_x / m_pixelFactor), (unsigned)(ev->event_y / m_pixelFactor)}, + {ev->event_x / (float)m_ww, ev->event_y / (float)m_wh} }; m_callback->mouseMove(coord); } diff --git a/test/main.cpp b/test/main.cpp index badad65..12ed06f 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -44,15 +44,78 @@ public: } } }; - + + +struct CTestWindowCallback : public IWindowCallback +{ + + void mouseDown(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) + { + fprintf(stderr, "Mouse Down %d (%f,%f)\n", button, coord.norm[0], coord.norm[1]); + } + void mouseUp(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) + { + fprintf(stderr, "Mouse Up %d (%f,%f)\n", button, coord.norm[0], coord.norm[1]); + } + void mouseMove(const SWindowCoord& coord) + { + //fprintf(stderr, "Mouse Move (%f,%f)\n", coord.norm[0], coord.norm[1]); + } + void scroll(const SWindowCoord& coord, const SScrollDelta& scroll) + { + fprintf(stderr, "Mouse Move (%f,%f)\n", coord.norm[0], coord.norm[1]); + } + + void touchDown(const SWindowCoord& coord, uintptr_t tid) + { + + } + void touchUp(const SWindowCoord& coord, uintptr_t tid) + { + + } + void touchMove(const SWindowCoord& coord, uintptr_t tid) + { + + } + + void charKeyDown(unsigned long charCode, EModifierKey mods, bool isRepeat) + { + + } + void charKeyUp(unsigned long charCode, EModifierKey mods) + { + + } + void specialKeyDown(ESpecialKey key, EModifierKey mods, bool isRepeat) + { + + } + void specialKeyUp(ESpecialKey key, EModifierKey mods) + { + + } + void modKeyDown(EModifierKey mod, bool isRepeat) + { + + } + void modKeyUp(EModifierKey mod) + { + + } + +}; + struct CTestApplicationCallback : public IApplicationCallback { IWindow* mainWindow = NULL; boo::CTestDeviceFinder devFinder; + CTestWindowCallback windowCallback; void appLaunched(IApplication* app) { mainWindow = app->newWindow("YAY!"); + mainWindow->setCallback(&windowCallback); mainWindow->showWindow(); devFinder.startScanning(); } @@ -75,6 +138,7 @@ int main(int argc, char** argv) boo::IApplication* app = IApplicationBootstrap(boo::IApplication::PLAT_AUTO, appCb, "RWK", argc, argv); app->run(); delete app; + printf("IM DYING!!\n"); return 0; } From 6d8eb3039ba621c37b257d5b7acd9d5840d10595 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 12 May 2015 22:51:18 -1000 Subject: [PATCH 08/10] added scroll and touch events --- include/windowsys/IWindow.hpp | 17 +- src/CApplicationXCB.hpp | 50 +++-- src/inputdev/CHIDListenerUdev.cpp | 1 - src/windowsys/CWindowXCB.cpp | 355 ++++++++++++++++++++++++++---- test/main.cpp | 14 +- 5 files changed, 365 insertions(+), 72 deletions(-) diff --git a/include/windowsys/IWindow.hpp b/include/windowsys/IWindow.hpp index 0179f0d..6418f87 100644 --- a/include/windowsys/IWindow.hpp +++ b/include/windowsys/IWindow.hpp @@ -25,10 +25,15 @@ public: unsigned virtualPixel[2]; float norm[2]; }; + + struct STouchCoord + { + double coord[2]; + }; struct SScrollDelta { - float delta[2]; + double delta[2]; bool isFine; /* Use system-scale fine-scroll (for scrollable-trackpads) */ }; @@ -78,13 +83,13 @@ public: virtual void mouseMove(const SWindowCoord& coord) {(void)coord;} virtual void scroll(const SWindowCoord& coord, const SScrollDelta& scroll) - {(void)scroll;} - - virtual void touchDown(const SWindowCoord& coord, uintptr_t tid) + {(void)coord;(void)scroll;} + + virtual void touchDown(const STouchCoord& coord, uintptr_t tid) {(void)coord;(void)tid;} - virtual void touchUp(const SWindowCoord& coord, uintptr_t tid) + virtual void touchUp(const STouchCoord& coord, uintptr_t tid) {(void)coord;(void)tid;} - virtual void touchMove(const SWindowCoord& coord, uintptr_t tid) + virtual void touchMove(const STouchCoord& coord, uintptr_t tid) {(void)coord;(void)tid;} virtual void charKeyDown(unsigned long charCode, EModifierKey mods, bool isRepeat) diff --git a/src/CApplicationXCB.hpp b/src/CApplicationXCB.hpp index 91bb205..26b1e6b 100644 --- a/src/CApplicationXCB.hpp +++ b/src/CApplicationXCB.hpp @@ -15,7 +15,6 @@ namespace boo { - int XINPUT_OPCODE = 0; static xcb_window_t getWindowOfEvent(xcb_generic_event_t* event, bool& windowEvent) @@ -75,30 +74,38 @@ static xcb_window_t getWindowOfEvent(xcb_generic_event_t* event, bool& windowEve xcb_ge_event_t* gev = (xcb_ge_event_t*)event; if (gev->pad0 == XINPUT_OPCODE) { - fprintf(stderr, "INPUTEVENT\n"); - return 0; - switch (XCB_EVENT_RESPONSE_TYPE(gev)) + switch (gev->event_type) { - case XCB_INPUT_DEVICE_CHANGED: + case XCB_INPUT_MOTION: { - xcb_input_device_changed_event_t* ev = (xcb_input_device_changed_event_t*)event; - return 0; - } - case XCB_INPUT_DEVICE_MOTION_NOTIFY: - { - xcb_input_device_motion_notify_event_t* ev = (xcb_input_device_motion_notify_event_t*)event; + xcb_input_motion_event_t* ev = (xcb_input_motion_event_t*)event; + windowEvent = true; + return ev->event; + } + case XCB_INPUT_TOUCH_BEGIN: + { + xcb_input_touch_begin_event_t* ev = (xcb_input_touch_begin_event_t*)event; + windowEvent = true; + return ev->event; + } + case XCB_INPUT_TOUCH_UPDATE: + { + xcb_input_touch_update_event_t* ev = (xcb_input_touch_update_event_t*)event; + windowEvent = true; + return ev->event; + } + case XCB_INPUT_TOUCH_END: + { + xcb_input_touch_end_event_t* ev = (xcb_input_touch_end_event_t*)event; windowEvent = true; return ev->event; } - default: - return 0; } } } - default: - windowEvent = false; - return 0; } + windowEvent = false; + return 0; } IWindow* _CWindowXCBNew(const std::string& title, xcb_connection_t* conn); @@ -133,7 +140,7 @@ public: { m_xcbConn = xcb_connect(NULL, NULL); - /* This convoluted xkb extension requests that the X server does not + /* The xkb extension requests that the X server does not * send repeated keydown events when a key is held */ xkb_x11_setup_xkb_extension(m_xcbConn, XKB_X11_MIN_MAJOR_XKB_VERSION, @@ -144,6 +151,12 @@ public: XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT, XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT, 0, 0, 0); + /* Xinput major opcode */ + const xcb_query_extension_reply_t* xiReply = + xcb_get_extension_data(m_xcbConn, &xcb_input_id); + if (xiReply) + XINPUT_OPCODE = xiReply->major_opcode; + @@ -165,11 +178,12 @@ public: m_running = true; m_callback.appLaunched(this); xcb_flush(m_xcbConn); + while (m_running && (event = xcb_wait_for_event(m_xcbConn))) { bool windowEvent; xcb_window_t evWindow = getWindowOfEvent(event, windowEvent); - fprintf(stderr, "EVENT %d\n", XCB_EVENT_RESPONSE_TYPE(event)); + //fprintf(stderr, "EVENT %d\n", XCB_EVENT_RESPONSE_TYPE(event)); if (windowEvent) { auto window = m_windows.find(evWindow); diff --git a/src/inputdev/CHIDListenerUdev.cpp b/src/inputdev/CHIDListenerUdev.cpp index 5fbbffb..b2de124 100644 --- a/src/inputdev/CHIDListenerUdev.cpp +++ b/src/inputdev/CHIDListenerUdev.cpp @@ -166,7 +166,6 @@ public: ~CHIDListenerUdev() { m_udevRunning = false; - //raise(SIGINT); pthread_kill(m_udevThread->native_handle(), SIGINT); m_udevThread->join(); delete m_udevThread; diff --git a/src/windowsys/CWindowXCB.cpp b/src/windowsys/CWindowXCB.cpp index 64fce35..2be7629 100644 --- a/src/windowsys/CWindowXCB.cpp +++ b/src/windowsys/CWindowXCB.cpp @@ -24,6 +24,13 @@ namespace boo { +extern int XINPUT_OPCODE; + +static inline double fp3232val(xcb_input_fp3232_t* val) +{ + return val->integral + val->frac / (double)UINT_MAX; +} + static uint32_t translateKeysym(xcb_keysym_t sym, int& specialSym, int& modifierSym) { specialSym = IWindowCallback::KEY_NONE; @@ -103,7 +110,7 @@ do {\ xcb_intern_atom_reply_t* reply = \ xcb_intern_atom_reply(conn, cookie, NULL); \ var = reply->atom; \ - /*free(reply);*/ \ + free(reply); \ } while(0) struct SXCBAtoms @@ -149,6 +156,16 @@ class CWindowXCB final : public IWindow IGraphicsContext* m_gfxCtx; IWindowCallback* m_callback; + /* Last known input device id (0xffff if not yet set) */ + xcb_input_device_id_t m_lastInputID = 0xffff; + ETouchType m_touchType = TOUCH_NONE; + + /* Scroll valuators */ + int m_hScrollValuator = -1; + int m_vScrollValuator = -1; + double m_hScrollLast = 0.0; + double m_vScrollLast = 0.0; + /* Cached window rectangle (to avoid repeated X queries) */ int m_wx, m_wy, m_ww, m_wh; float m_pixelFactor; @@ -194,18 +211,31 @@ public: XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP, valueMasks); - /* The XInput extension enables per-pixel smooth scrolling trackpads */ - struct + /* The XInput 2.1 extension enables per-pixel smooth scrolling trackpads */ + xcb_generic_error_t* xiErr = NULL; + xcb_input_xi_query_version_reply_t* xiReply = + xcb_input_xi_query_version_reply(m_xcbConn, + xcb_input_xi_query_version(m_xcbConn, 2, 1), &xiErr); + if (!xiErr) { - xcb_input_event_mask_t mask; - uint32_t maskVal; - } masks = - { - {XCB_INPUT_DEVICE_ALL_MASTER, 1}, - XCB_INPUT_XI_EVENT_MASK_MOTION - }; - xcb_input_xi_select_events(m_xcbConn, m_windowId, 1, &masks.mask); + struct + { + xcb_input_event_mask_t mask; + uint32_t maskVal; + } masks = + { + {XCB_INPUT_DEVICE_ALL_MASTER, 1}, + XCB_INPUT_XI_EVENT_MASK_MOTION | + XCB_INPUT_XI_EVENT_MASK_TOUCH_BEGIN | + XCB_INPUT_XI_EVENT_MASK_TOUCH_UPDATE | + XCB_INPUT_XI_EVENT_MASK_TOUCH_END + }; + xcb_input_xi_select_events(m_xcbConn, m_windowId, 1, &masks.mask); + } + free(xiReply); + /* Register netwm extension atom for window closing */ +#if 0 xcb_change_property(m_xcbConn, XCB_PROP_MODE_REPLACE, m_windowId, S_ATOMS->m_wmProtocols, XCB_ATOM_ATOM, 32, 1, &S_ATOMS->m_wmDeleteWindow); const xcb_atom_t wm_protocols[1] = { @@ -214,6 +244,7 @@ public: xcb_change_property(m_xcbConn, XCB_PROP_MODE_REPLACE, m_windowId, S_ATOMS->m_wmProtocols, 4, 32, 1, wm_protocols); +#endif /* Set the title of the window */ const char* c_title = title.c_str(); @@ -356,19 +387,78 @@ public: return (uintptr_t)m_windowId; } + void _pointingDeviceChanged(xcb_input_device_id_t deviceId) + { + xcb_input_xi_query_device_reply_t* reply = + xcb_input_xi_query_device_reply(m_xcbConn, xcb_input_xi_query_device(m_xcbConn, deviceId), NULL); + + xcb_input_xi_device_info_iterator_t infoIter = xcb_input_xi_query_device_infos_iterator(reply); + while (infoIter.rem) + { + /* First iterate classes for scrollables */ + xcb_input_device_class_iterator_t classIter = + xcb_input_xi_device_info_classes_iterator(infoIter.data); + int hScroll = -1; + int vScroll = -1; + m_hScrollLast = 0.0; + m_vScrollLast = 0.0; + m_hScrollValuator = -1; + m_vScrollValuator = -1; + while (classIter.rem) + { + if (classIter.data->type == XCB_INPUT_DEVICE_CLASS_TYPE_SCROLL) + { + xcb_input_scroll_class_t* scrollClass = (xcb_input_scroll_class_t*)classIter.data; + if (scrollClass->scroll_type == XCB_INPUT_SCROLL_TYPE_VERTICAL) + vScroll = scrollClass->number; + else if (scrollClass->scroll_type == XCB_INPUT_SCROLL_TYPE_HORIZONTAL) + hScroll = scrollClass->number; + } + xcb_input_device_class_next(&classIter); + } + + /* Next iterate for touch and scroll valuators */ + classIter = xcb_input_xi_device_info_classes_iterator(infoIter.data); + while (classIter.rem) + { + if (classIter.data->type == XCB_INPUT_DEVICE_CLASS_TYPE_VALUATOR) + { + xcb_input_valuator_class_t* valClass = (xcb_input_valuator_class_t*)classIter.data; + if (valClass->number == vScroll) + { + m_vScrollLast = fp3232val(&valClass->value); + m_vScrollValuator = vScroll; + } + else if (valClass->number == hScroll) + { + m_hScrollLast = fp3232val(&valClass->value); + m_hScrollValuator = hScroll; + } + } + else if (classIter.data->type == XCB_INPUT_DEVICE_CLASS_TYPE_TOUCH) + { + xcb_input_touch_class_t* touchClass = (xcb_input_touch_class_t*)classIter.data; + if (touchClass->mode == XCB_INPUT_TOUCH_MODE_DIRECT) + m_touchType = TOUCH_DISPLAY; + else if (touchClass->mode == XCB_INPUT_TOUCH_MODE_DEPENDENT) + m_touchType = TOUCH_TRACKPAD; + else + m_touchType = TOUCH_NONE; + } + xcb_input_device_class_next(&classIter); + } + xcb_input_xi_device_info_next(&infoIter); + } + + free(reply); + m_lastInputID = deviceId; + } + void _incomingEvent(void* e) { xcb_generic_event_t* event = (xcb_generic_event_t*)e; switch (XCB_EVENT_RESPONSE_TYPE(event)) { - case XCB_CLIENT_MESSAGE: - { - xcb_client_message_event_t* ev = (xcb_client_message_event_t*)event; - if (ev->data.data32[0] == S_ATOMS->m_wmDeleteWindow) - { - fprintf(stderr, "CLOSED\n"); - } - } case XCB_EXPOSE: { xcb_expose_event_t* ev = (xcb_expose_event_t*)event; @@ -376,6 +466,7 @@ public: m_wy = ev->y; m_ww = ev->width; m_wh = ev->height; + return; } case XCB_CONFIGURE_NOTIFY: { @@ -387,6 +478,7 @@ public: m_ww = ev->width; m_wh = ev->height; } + return; } case XCB_KEY_PRESS: { @@ -407,6 +499,7 @@ public: else if (modifierKey) m_callback->modKeyDown((IWindowCallback::EModifierKey)modifierKey, false); } + return; } case XCB_KEY_RELEASE: { @@ -427,40 +520,75 @@ public: else if (modifierKey) m_callback->modKeyUp((IWindowCallback::EModifierKey)modifierKey); } + return; } case XCB_BUTTON_PRESS: { xcb_button_press_event_t* ev = (xcb_button_press_event_t*)event; - int button = translateButton(ev->detail); - if (m_callback && button) + if (m_callback) { - int modifierMask = translateModifiers(ev->state); - IWindowCallback::SWindowCoord coord = + int button = translateButton(ev->detail); + if (button) { - {(unsigned)ev->event_x, (unsigned)ev->event_y}, - {(unsigned)(ev->event_x / m_pixelFactor), (unsigned)(ev->event_y / m_pixelFactor)}, - {ev->event_x / (float)m_ww, ev->event_y / (float)m_wh} - }; - m_callback->mouseDown(coord, (IWindowCallback::EMouseButton)button, - (IWindowCallback::EModifierKey)modifierMask); + int modifierMask = translateModifiers(ev->state); + IWindowCallback::SWindowCoord coord = + { + {(unsigned)ev->event_x, (unsigned)ev->event_y}, + {(unsigned)(ev->event_x / m_pixelFactor), (unsigned)(ev->event_y / m_pixelFactor)}, + {ev->event_x / (float)m_ww, ev->event_y / (float)m_wh} + }; + m_callback->mouseDown(coord, (IWindowCallback::EMouseButton)button, + (IWindowCallback::EModifierKey)modifierMask); + } + + /* Also handle legacy scroll events here */ + if (ev->detail >= 4 && ev->detail <= 7 && + m_hScrollValuator == -1 && m_vScrollValuator == -1) + { + IWindowCallback::SWindowCoord coord = + { + {(unsigned)ev->event_x, (unsigned)ev->event_y}, + {(unsigned)(ev->event_x / m_pixelFactor), (unsigned)(ev->event_y / m_pixelFactor)}, + {ev->event_x / (float)m_ww, ev->event_y / (float)m_wh} + }; + IWindowCallback::SScrollDelta scrollDelta = + { + {0.0, 0.0}, + false + }; + if (ev->detail == 4) + scrollDelta.delta[1] = 1.0; + else if (ev->detail == 5) + scrollDelta.delta[1] = -1.0; + else if (ev->detail == 6) + scrollDelta.delta[0] = 1.0; + else if (ev->detail == 7) + scrollDelta.delta[0] = -1.0; + m_callback->scroll(coord, scrollDelta); + } } + return; } case XCB_BUTTON_RELEASE: { xcb_button_release_event_t* ev = (xcb_button_release_event_t*)event; - int button = translateButton(ev->detail); - if (m_callback && button) + if (m_callback) { - int modifierMask = translateModifiers(ev->state); - IWindowCallback::SWindowCoord coord = + int button = translateButton(ev->detail); + if (button) { - {(unsigned)ev->event_x, (unsigned)ev->event_y}, - {(unsigned)(ev->event_x / m_pixelFactor), (unsigned)(ev->event_y / m_pixelFactor)}, - {ev->event_x / (float)m_ww, ev->event_y / (float)m_wh} - }; - m_callback->mouseUp(coord, (IWindowCallback::EMouseButton)button, - (IWindowCallback::EModifierKey)modifierMask); + int modifierMask = translateModifiers(ev->state); + IWindowCallback::SWindowCoord coord = + { + {(unsigned)ev->event_x, (unsigned)ev->event_y}, + {(unsigned)(ev->event_x / m_pixelFactor), (unsigned)(ev->event_y / m_pixelFactor)}, + {ev->event_x / (float)m_ww, ev->event_y / (float)m_wh} + }; + m_callback->mouseUp(coord, (IWindowCallback::EMouseButton)button, + (IWindowCallback::EModifierKey)modifierMask); + } } + return; } case XCB_MOTION_NOTIFY: { @@ -475,13 +603,160 @@ public: }; m_callback->mouseMove(coord); } + return; + } + case XCB_GE_GENERIC: + { + xcb_ge_event_t* gev = (xcb_ge_event_t*)event; + if (gev->pad0 == XINPUT_OPCODE) + { + switch (gev->event_type) + { + case XCB_INPUT_MOTION: + { + xcb_input_motion_event_t* ev = (xcb_input_motion_event_t*)event; + if (m_lastInputID != ev->deviceid) + _pointingDeviceChanged(ev->deviceid); + + uint32_t* valuators = (uint32_t*)(((char*)ev) + sizeof(xcb_input_motion_event_t) + sizeof(uint32_t) * ev->buttons_len); + xcb_input_fp3232_t* valuatorVals = (xcb_input_fp3232_t*)(((char*)valuators) + sizeof(uint32_t) * ev->valuators_len); + int cv = 0; + double newScroll[2] = {m_hScrollLast, m_vScrollLast}; + bool didScroll = false; + for (int i=0 ; i<32 ; ++i) + { + if (valuators[0] & (1<event_x >> 16; + unsigned event_y = ev->event_y >> 16; + IWindowCallback::SWindowCoord coord = + { + {event_x, event_y}, + {(unsigned)(event_x / m_pixelFactor), (unsigned)(event_y / m_pixelFactor)}, + {event_x / (float)m_ww, event_y / (float)m_wh} + }; + m_callback->scroll(coord, scrollDelta); + } + return; + } + case XCB_INPUT_TOUCH_BEGIN: + { + xcb_input_touch_begin_event_t* ev = (xcb_input_touch_begin_event_t*)event; + if (m_lastInputID != ev->deviceid) + _pointingDeviceChanged(ev->deviceid); + + uint32_t* valuators = (uint32_t*)(((char*)ev) + sizeof(xcb_input_motion_event_t) + sizeof(uint32_t) * ev->buttons_len); + xcb_input_fp3232_t* valuatorVals = (xcb_input_fp3232_t*)(((char*)valuators) + sizeof(uint32_t) * ev->valuators_len); + int cv = 0; + double vals[32] = {}; + for (int i=0 ; i<32 ; ++i) + { + if (valuators[0] & (1<touchDown(coord, ev->detail); + return; + } + case XCB_INPUT_TOUCH_UPDATE: + { + xcb_input_touch_update_event_t* ev = (xcb_input_touch_update_event_t*)event; + if (m_lastInputID != ev->deviceid) + _pointingDeviceChanged(ev->deviceid); + + uint32_t* valuators = (uint32_t*)(((char*)ev) + sizeof(xcb_input_motion_event_t) + sizeof(uint32_t) * ev->buttons_len); + xcb_input_fp3232_t* valuatorVals = (xcb_input_fp3232_t*)(((char*)valuators) + sizeof(uint32_t) * ev->valuators_len); + int cv = 0; + double vals[32] = {}; + for (int i=0 ; i<32 ; ++i) + { + if (valuators[0] & (1<touchMove(coord, ev->detail); + return; + } + case XCB_INPUT_TOUCH_END: + { + xcb_input_touch_end_event_t* ev = (xcb_input_touch_end_event_t*)event; + if (m_lastInputID != ev->deviceid) + _pointingDeviceChanged(ev->deviceid); + + uint32_t* valuators = (uint32_t*)(((char*)ev) + sizeof(xcb_input_motion_event_t) + sizeof(uint32_t) * ev->buttons_len); + xcb_input_fp3232_t* valuatorVals = (xcb_input_fp3232_t*)(((char*)valuators) + sizeof(uint32_t) * ev->valuators_len); + int cv = 0; + double vals[32] = {}; + for (int i=0 ; i<32 ; ++i) + { + if (valuators[0] & (1<touchUp(coord, ev->detail); + return; + } + } + } } } } ETouchType getTouchType() const { - return TOUCH_NONE; + return m_touchType; } }; diff --git a/test/main.cpp b/test/main.cpp index 12ed06f..f81e620 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -63,20 +63,20 @@ struct CTestWindowCallback : public IWindowCallback } void scroll(const SWindowCoord& coord, const SScrollDelta& scroll) { - fprintf(stderr, "Mouse Move (%f,%f)\n", coord.norm[0], coord.norm[1]); + fprintf(stderr, "Mouse Scroll (%f,%f) (%f,%f)\n", coord.norm[0], coord.norm[1], scroll.delta[0], scroll.delta[1]); } - void touchDown(const SWindowCoord& coord, uintptr_t tid) + void touchDown(const STouchCoord& coord, uintptr_t tid) { - + //fprintf(stderr, "Touch Down %16lX (%f,%f)\n", tid, coord.coord[0], coord.coord[1]); } - void touchUp(const SWindowCoord& coord, uintptr_t tid) + void touchUp(const STouchCoord& coord, uintptr_t tid) { - + //fprintf(stderr, "Touch Up %16lX (%f,%f)\n", tid, coord.coord[0], coord.coord[1]); } - void touchMove(const SWindowCoord& coord, uintptr_t tid) + void touchMove(const STouchCoord& coord, uintptr_t tid) { - + //fprintf(stderr, "Touch Move %16lX (%f,%f)\n", tid, coord.coord[0], coord.coord[1]); } void charKeyDown(unsigned long charCode, EModifierKey mods, bool isRepeat) From 35f2156de15288dd87041821e0ff624f7ab99190 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Wed, 13 May 2015 12:21:13 -1000 Subject: [PATCH 09/10] working dbus instancing --- include/IApplication.hpp | 14 +++- libBoo.pro | 13 +--- src/CApplicationUnix.cpp | 45 ++++++++++- src/CApplicationWayland.hpp | 25 ++++++- src/CApplicationWin32.cpp | 12 ++- src/CApplicationXCB.hpp | 144 ++++++++++++++++++++++++++++++++---- test/main.cpp | 11 ++- 7 files changed, 222 insertions(+), 42 deletions(-) diff --git a/include/IApplication.hpp b/include/IApplication.hpp index 5c1690b..882afe5 100644 --- a/include/IApplication.hpp +++ b/include/IApplication.hpp @@ -15,7 +15,7 @@ struct IApplicationCallback { virtual void appLaunched(IApplication* app) {(void)app;} virtual void appQuitting(IApplication* app) {(void)app;} - virtual bool appFileOpen(IApplication* app, const std::string& path) {(void)app;(void)path;return true;} + virtual void appFilesOpen(IApplication* app, const std::vector& paths) {(void)app;(void)paths;} }; class IApplication @@ -45,6 +45,8 @@ public: virtual void run()=0; virtual void quit()=0; + virtual const std::string& getUniqueName() const=0; + virtual const std::string& getFriendlyName() const=0; virtual const std::string& getProcessName() const=0; virtual const std::vector& getArgs() const=0; @@ -55,23 +57,27 @@ public: IApplication* IApplicationBootstrap(IApplication::EPlatformType platform, IApplicationCallback& cb, + const std::string& uniqueName, const std::string& friendlyName, const std::string& pname, - const std::vector& args); + const std::vector& args, + bool singleInstance=true); extern IApplication* APP; #define IApplicationInstance() APP static inline IApplication* IApplicationBootstrap(IApplication::EPlatformType platform, IApplicationCallback& cb, + const std::string& uniqueName, const std::string& friendlyName, - int argc, char** argv) + int argc, char** argv, + bool singleInstance=true) { if (APP) return APP; std::vector args; for (int i=1 ; i +#include + +DBusConnection* registerDBus(const char* appName, bool& isFirst) +{ + isFirst = true; + DBusError err = {}; + dbus_error_init(&err); + + /* connect to the bus and check for errors */ + DBusConnection* conn = dbus_bus_get(DBUS_BUS_SESSION, &err); + if (dbus_error_is_set(&err)) + { + fprintf(stderr, "DBus Connection Error (%s)\n", err.message); + dbus_error_free(&err); + } + if (NULL == conn) + return NULL; + + /* request our name on the bus and check for errors */ + char busName[256]; + snprintf(busName, 256, "boo.%s.unique", appName); + int ret = dbus_bus_request_name(conn, busName, DBUS_NAME_FLAG_DO_NOT_QUEUE , &err); + if (dbus_error_is_set(&err)) + { + fprintf(stderr, "DBus Name Error (%s)\n", err.message); + dbus_error_free(&err); + dbus_connection_close(conn); + return NULL; + } + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) + isFirst = false; + + return conn; + +} + namespace boo { IApplication* APP = NULL; IApplication* IApplicationBootstrap(IApplication::EPlatformType platform, IApplicationCallback& cb, + const std::string& uniqueName, const std::string& friendlyName, const std::string& pname, - const std::vector& args) + const std::vector& args, + bool singleInstance) { if (!APP) { if (platform == IApplication::PLAT_WAYLAND) - APP = new CApplicationWayland(cb, friendlyName, pname, args); + APP = new CApplicationWayland(cb, uniqueName, friendlyName, pname, args, singleInstance); else if (platform == IApplication::PLAT_XCB || platform == IApplication::PLAT_AUTO) - APP = new CApplicationXCB(cb, friendlyName, pname, args); + APP = new CApplicationXCB(cb, uniqueName, friendlyName, pname, args, singleInstance); else return NULL; } diff --git a/src/CApplicationWayland.hpp b/src/CApplicationWayland.hpp index f174349..54dd06a 100644 --- a/src/CApplicationWayland.hpp +++ b/src/CApplicationWayland.hpp @@ -4,6 +4,9 @@ #include "IApplication.hpp" +#include +DBusConnection* registerDBus(const char* appName, bool& isFirst); + namespace boo { @@ -12,10 +15,12 @@ IWindow* _CWindowWaylandNew(const std::string& title); class CApplicationWayland final : public IApplication { IApplicationCallback& m_callback; + const std::string m_uniqueName; const std::string m_friendlyName; const std::string m_pname; const std::vector m_args; - + bool m_singleInstance; + void _deletedWindow(IWindow* window) { (void)window; @@ -23,13 +28,17 @@ class CApplicationWayland final : public IApplication public: CApplicationWayland(IApplicationCallback& callback, + const std::string& uniqueName, const std::string& friendlyName, const std::string& pname, - const std::vector& args) + const std::vector& args, + bool singleInstance) : m_callback(callback), + m_uniqueName(uniqueName), m_friendlyName(friendlyName), m_pname(pname), - m_args(args) + m_args(args), + m_singleInstance(singleInstance) {} EPlatformType getPlatformType() const @@ -46,6 +55,16 @@ public: { } + + const std::string& getUniqueName() const + { + return m_uniqueName; + } + + const std::string& getFriendlyName() const + { + return m_friendlyName; + } const std::string& getProcessName() const { diff --git a/src/CApplicationWin32.cpp b/src/CApplicationWin32.cpp index 67f1842..ba53335 100644 --- a/src/CApplicationWin32.cpp +++ b/src/CApplicationWin32.cpp @@ -21,6 +21,7 @@ class CApplicationWin32 final : public IApplication const std::string m_pname; const std::vector m_args; std::unordered_map m_allWindows; + bool m_singleInstance; void _deletedWindow(IWindow* window) { @@ -32,11 +33,13 @@ public: CApplicationWin32(const IApplicationCallback& callback, const std::string& friendlyName, const std::string& pname, - const std::vector& args) + const std::vector& args, + bool singleInstance) : m_callback(callback), m_friendlyName(friendlyName), m_pname(pname), - m_args(args) + m_args(args), + m_singleInstance(singleInstance) {} EPlatformType getPlatformType() const @@ -95,14 +98,15 @@ IApplication* IApplicationBootstrap(IApplication::EPlatformType platform, IApplicationCallback& cb, const std::string& friendlyName, const std::string& pname, - const std::vector& args) + const std::vector& args, + bool singleInstance) { if (!APP) { if (platform != IApplication::PLAT_WIN32 && platform != IApplication::PLAT_AUTO) return NULL; - APP = new CApplicationWin32(cb, friendlyName, pname, args); + APP = new CApplicationWin32(cb, friendlyName, pname, args, singleInstance); } return APP; } diff --git a/src/CApplicationXCB.hpp b/src/CApplicationXCB.hpp index 26b1e6b..72c4534 100644 --- a/src/CApplicationXCB.hpp +++ b/src/CApplicationXCB.hpp @@ -12,6 +12,11 @@ #include #undef explicit +#include +DBusConnection* registerDBus(const char* appName, bool& isFirst); + +#include + namespace boo { @@ -113,14 +118,19 @@ IWindow* _CWindowXCBNew(const std::string& title, xcb_connection_t* conn); class CApplicationXCB final : public IApplication { IApplicationCallback& m_callback; + const std::string m_uniqueName; const std::string m_friendlyName; const std::string m_pname; const std::vector m_args; + /* DBus single-instance */ + bool m_singleInstance; + DBusConnection* m_dbus = NULL; + /* All windows */ std::unordered_map m_windows; - xcb_connection_t* m_xcbConn; + xcb_connection_t* m_xcbConn = NULL; bool m_running; void _deletedWindow(IWindow* window) @@ -130,14 +140,62 @@ class CApplicationXCB final : public IApplication public: CApplicationXCB(IApplicationCallback& callback, + const std::string& uniqueName, const std::string& friendlyName, const std::string& pname, - const std::vector& args) + const std::vector& args, + bool singleInstance) : m_callback(callback), + m_uniqueName(uniqueName), m_friendlyName(friendlyName), m_pname(pname), - m_args(args) + m_args(args), + m_singleInstance(singleInstance) { + /* DBus single instance registration */ + bool isFirst; + m_dbus = registerDBus(uniqueName.c_str(), isFirst); + if (m_singleInstance) + { + if (!isFirst) + { + /* This is a duplicate instance, send signal and return */ + if (args.size()) + { + /* create a signal & check for errors */ + DBusMessage* + msg = dbus_message_new_signal("/boo/signal/FileHandler", + "boo.signal.FileHandling", + "Open"); + + /* append arguments onto signal */ + DBusMessageIter argsIter; + dbus_message_iter_init_append(msg, &argsIter); + for (const std::string& arg : args) + { + const char* sigvalue = arg.c_str(); + dbus_message_iter_append_basic(&argsIter, DBUS_TYPE_STRING, &sigvalue); + } + + /* send the message and flush the connection */ + dbus_uint32_t serial; + dbus_connection_send(m_dbus, msg, &serial); + dbus_connection_flush(m_dbus); + dbus_message_unref(msg); + } + return; + } + else + { + /* This is the first instance, register for signal */ + // add a rule for which messages we want to see + DBusError err = {}; + dbus_bus_add_match(m_dbus, "type='signal',interface='boo.signal.FileHandling'", &err); + dbus_connection_flush(m_dbus); + } + } + + /* Open X connection */ m_xcbConn = xcb_connect(NULL, NULL); /* The xkb extension requests that the X server does not @@ -157,9 +215,6 @@ public: if (xiReply) XINPUT_OPCODE = xiReply->major_opcode; - - - } ~CApplicationXCB() @@ -174,24 +229,73 @@ public: void run() { + if (!m_xcbConn) + return; + xcb_generic_event_t* event; m_running = true; m_callback.appLaunched(this); xcb_flush(m_xcbConn); - while (m_running && (event = xcb_wait_for_event(m_xcbConn))) + int xcbFd = xcb_get_file_descriptor(m_xcbConn); + int dbusFd; + dbus_connection_get_unix_fd(m_dbus, &dbusFd); + int maxFd = MAX(xcbFd, dbusFd); + + while (m_running) { - bool windowEvent; - xcb_window_t evWindow = getWindowOfEvent(event, windowEvent); - //fprintf(stderr, "EVENT %d\n", XCB_EVENT_RESPONSE_TYPE(event)); - if (windowEvent) + fd_set fds; + FD_ZERO(&fds); + FD_SET(xcbFd, &fds); + FD_SET(dbusFd, &fds); + select(maxFd+1, &fds, NULL, NULL, NULL); + + if (FD_ISSET(xcbFd, &fds)) { - auto window = m_windows.find(evWindow); - if (window != m_windows.end()) - window->second->_incomingEvent(event); + event = xcb_poll_for_event(m_xcbConn); + if (!event) + break; + + bool windowEvent; + xcb_window_t evWindow = getWindowOfEvent(event, windowEvent); + //fprintf(stderr, "EVENT %d\n", XCB_EVENT_RESPONSE_TYPE(event)); + if (windowEvent) + { + auto window = m_windows.find(evWindow); + if (window != m_windows.end()) + window->second->_incomingEvent(event); + } + free(event); + } + + if (FD_ISSET(dbusFd, &fds)) + { + DBusMessage* msg; + dbus_connection_read_write(m_dbus, 0); + while ((msg = dbus_connection_pop_message(m_dbus))) + { + + /* check if the message is a signal from the correct interface and with the correct name */ + if (dbus_message_is_signal(msg, "boo.signal.FileHandling", "Open")) + { + /* read the parameters */ + std::vector paths; + DBusMessageIter iter; + dbus_message_iter_init(msg, &iter); + while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) + { + const char* argVal; + dbus_message_iter_get_basic(&iter, &argVal); + paths.push_back(argVal); + dbus_message_iter_next(&iter); + } + m_callback.appFilesOpen(this, paths); + } + dbus_message_unref(msg); + } } - free(event); } + m_callback.appQuitting(this); } @@ -199,6 +303,16 @@ public: { m_running = false; } + + const std::string& getUniqueName() const + { + return m_uniqueName; + } + + const std::string& getFriendlyName() const + { + return m_friendlyName; + } const std::string& getProcessName() const { diff --git a/test/main.cpp b/test/main.cpp index f81e620..f00112c 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -123,10 +123,12 @@ struct CTestApplicationCallback : public IApplicationCallback { delete mainWindow; } - bool appFileOpen(IApplication*, const std::string& path) + void appFilesOpen(IApplication*, const std::vector& paths) { - printf("OPENING: %s\n", path.c_str()); - return true; + fprintf(stderr, "OPENING: "); + for (const std::string& path : paths) + fprintf(stderr, "%s ", path.c_str()); + fprintf(stderr, "\n"); } }; @@ -135,7 +137,8 @@ struct CTestApplicationCallback : public IApplicationCallback int main(int argc, char** argv) { boo::CTestApplicationCallback appCb; - boo::IApplication* app = IApplicationBootstrap(boo::IApplication::PLAT_AUTO, appCb, "RWK", argc, argv); + boo::IApplication* app = IApplicationBootstrap(boo::IApplication::PLAT_AUTO, + appCb, "rwk", "RWK", argc, argv); app->run(); delete app; printf("IM DYING!!\n"); From 6ce2472b27211a40e1d78f424f09cf26ba5e3281 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 14 May 2015 13:22:42 -1000 Subject: [PATCH 10/10] refactor of graphic system; initial HECL --- include/graphicsys/CGFXVertexLayoutBase.hpp | 20 +++++ include/graphicsys/IGFXCommandBuffer.hpp | 5 ++ .../IGFXContext.hpp} | 20 ++--- include/graphicsys/IGFXPipelineState.hpp | 5 ++ include/graphicsys/IGFXTransformSet.hpp | 5 ++ include/graphicsys/hecl/CHECLLexer.hpp | 20 +++++ include/graphicsys/hecl/HECLExpressions.hpp | 46 +++++++++++ include/graphicsys/hecl/IHECLBackend.hpp | 76 +++++++++++++++++++ libBoo.pri | 28 +++++-- src/CApplicationXCB.hpp | 1 - .../CGraphicsContextCocoa.mm | 0 .../CGraphicsContextWayland.cpp | 28 +------ .../CGraphicsContextWin32.cpp | 0 .../CGraphicsContextXCB.cpp | 39 +++------- src/graphicsys/hecl/CHECLBackendGLSL.cpp | 32 ++++++++ src/graphicsys/hecl/CHECLBackendHLSL.cpp | 15 ++++ src/graphicsys/hecl/CHECLBackendMetal.cpp | 15 ++++ src/graphicsys/hecl/CHECLBackendOutline.cpp | 16 ++++ src/graphicsys/hecl/CHECLBackendTEV.cpp | 15 ++++ src/graphicsys/hecl/CHECLLexer.cpp | 14 ++++ src/windowsys/CWindowXCB.cpp | 12 +-- 21 files changed, 332 insertions(+), 80 deletions(-) create mode 100644 include/graphicsys/CGFXVertexLayoutBase.hpp create mode 100644 include/graphicsys/IGFXCommandBuffer.hpp rename include/{windowsys/IGraphicsContext.hpp => graphicsys/IGFXContext.hpp} (66%) create mode 100644 include/graphicsys/IGFXPipelineState.hpp create mode 100644 include/graphicsys/IGFXTransformSet.hpp create mode 100644 include/graphicsys/hecl/CHECLLexer.hpp create mode 100644 include/graphicsys/hecl/HECLExpressions.hpp create mode 100644 include/graphicsys/hecl/IHECLBackend.hpp rename src/{windowsys => graphicsys}/CGraphicsContextCocoa.mm (100%) rename src/{windowsys => graphicsys}/CGraphicsContextWayland.cpp (64%) rename src/{windowsys => graphicsys}/CGraphicsContextWin32.cpp (100%) rename src/{windowsys => graphicsys}/CGraphicsContextXCB.cpp (79%) create mode 100644 src/graphicsys/hecl/CHECLBackendGLSL.cpp create mode 100644 src/graphicsys/hecl/CHECLBackendHLSL.cpp create mode 100644 src/graphicsys/hecl/CHECLBackendMetal.cpp create mode 100644 src/graphicsys/hecl/CHECLBackendOutline.cpp create mode 100644 src/graphicsys/hecl/CHECLBackendTEV.cpp create mode 100644 src/graphicsys/hecl/CHECLLexer.cpp diff --git a/include/graphicsys/CGFXVertexLayoutBase.hpp b/include/graphicsys/CGFXVertexLayoutBase.hpp new file mode 100644 index 0000000..a8ff1c4 --- /dev/null +++ b/include/graphicsys/CGFXVertexLayoutBase.hpp @@ -0,0 +1,20 @@ +#ifndef CGFXVERTEXLAYOUTBASE_HPP +#define CGFXVERTEXLAYOUTBASE_HPP + +class CGFXVertexLayoutBase +{ + unsigned m_uvCount; + unsigned m_weightCount; +public: + CGFXVertexLayoutBase(unsigned uvCount=0, unsigned weightCount=0) + : m_uvCount(uvCount), + m_weightCount(weightCount) {} + virtual ~CGFXVertexLayoutBase() {} + + inline unsigned uvCount() {return m_uvCount;} + inline unsigned weightCount() {return m_weightCount;} + inline bool isSkinned() {return m_weightCount > 0;} + +}; + +#endif // CGFXVERTEXLAYOUTBASE_HPP diff --git a/include/graphicsys/IGFXCommandBuffer.hpp b/include/graphicsys/IGFXCommandBuffer.hpp new file mode 100644 index 0000000..fc29bda --- /dev/null +++ b/include/graphicsys/IGFXCommandBuffer.hpp @@ -0,0 +1,5 @@ +#ifndef IGFXCOMMANDBUFFER_HPP +#define IGFXCOMMANDBUFFER_HPP + +#endif // IGFXCOMMANDBUFFER_HPP + diff --git a/include/windowsys/IGraphicsContext.hpp b/include/graphicsys/IGFXContext.hpp similarity index 66% rename from include/windowsys/IGraphicsContext.hpp rename to include/graphicsys/IGFXContext.hpp index d2732fa..94f3804 100644 --- a/include/windowsys/IGraphicsContext.hpp +++ b/include/graphicsys/IGFXContext.hpp @@ -1,13 +1,14 @@ -#ifndef IGRAPHICSCONTEXT_HPP -#define IGRAPHICSCONTEXT_HPP +#ifndef IGFXCONTEXT_HPP +#define IGFXCONTEXT_HPP namespace boo { -class IGraphicsContext +class IGFXContext { friend class CWindowCocoa; - virtual void _setCallback(class IWindowCallback* cb) {(void)cb;}; + friend class CWindowXCB; + virtual void _setCallback(class IWindowCallback* cb) {(void)cb;} public: @@ -33,22 +34,15 @@ public: PF_RGBAF32_Z24 = 4 }; - virtual ~IGraphicsContext() {} + virtual ~IGFXContext() {} virtual EGraphicsAPI getAPI() const=0; virtual EPixelFormat getPixelFormat() const=0; virtual void setPixelFormat(EPixelFormat pf)=0; virtual void initializeContext()=0; - virtual IGraphicsContext* makeShareContext() const=0; - virtual void makeCurrent()=0; - virtual void clearCurrent()=0; - - /* Note: *all* contexts are double-buffered with - * v-sync interval; please call this */ - virtual void swapBuffer()=0; }; } -#endif // IGRAPHICSCONTEXT_HPP +#endif // IGFXCONTEXT_HPP diff --git a/include/graphicsys/IGFXPipelineState.hpp b/include/graphicsys/IGFXPipelineState.hpp new file mode 100644 index 0000000..9792d97 --- /dev/null +++ b/include/graphicsys/IGFXPipelineState.hpp @@ -0,0 +1,5 @@ +#ifndef IGFXPIPELINESTATE_HPP +#define IGFXPIPELINESTATE_HPP + +#endif // IGFXPIPELINESTATE_HPP + diff --git a/include/graphicsys/IGFXTransformSet.hpp b/include/graphicsys/IGFXTransformSet.hpp new file mode 100644 index 0000000..ef66cb5 --- /dev/null +++ b/include/graphicsys/IGFXTransformSet.hpp @@ -0,0 +1,5 @@ +#ifndef IGFXTRANSFORMSET_HPP +#define IGFXTRANSFORMSET_HPP + +#endif // IGFXTRANSFORMSET_HPP + diff --git a/include/graphicsys/hecl/CHECLLexer.hpp b/include/graphicsys/hecl/CHECLLexer.hpp new file mode 100644 index 0000000..9c3b0e7 --- /dev/null +++ b/include/graphicsys/hecl/CHECLLexer.hpp @@ -0,0 +1,20 @@ +#ifndef CHECLLEXER_HPP +#define CHECLLEXER_HPP + +#include +#include "graphicsys/CGFXVertexLayoutBase.hpp" + +class CHECLLexer +{ + const CGFXVertexLayoutBase& m_vertLayout; +public: + CHECLLexer(const CGFXVertexLayoutBase& vertLayout, + const std::string& colorHECL); + CHECLLexer(const CGFXVertexLayoutBase& vertLayout, + const std::string& colorHECL, + const std::string& alphaHECL); + + inline const CGFXVertexLayoutBase& getVertLayout() const {return m_vertLayout;} +}; + +#endif // CHECLLEXER_HPP diff --git a/include/graphicsys/hecl/HECLExpressions.hpp b/include/graphicsys/hecl/HECLExpressions.hpp new file mode 100644 index 0000000..454d0d7 --- /dev/null +++ b/include/graphicsys/hecl/HECLExpressions.hpp @@ -0,0 +1,46 @@ +#ifndef HECLEXPRESSIONS_HPP +#define HECLEXPRESSIONS_HPP + +#include +#include "IHECLBackend.hpp" + +class IHECLExpression +{ + /* Traverse expression tree and assemble + * backend-specific stage objects */ + virtual IHECLBackendStage* recursiveStages(IHECLBackend& backend) const=0; +}; + +class CHECLNumberLiteral final : IHECLExpression +{ +}; + +class CHECLVector final : IHECLExpression +{ +}; + +class CHECLTextureSample final : IHECLExpression +{ +}; + +class CHECLTextureGatherSample final : IHECLExpression +{ +}; + +class CHECLMulOperation final : IHECLExpression +{ +}; + +class CHECLAddOperation final : IHECLExpression +{ +}; + +class CHECLSubOperation final : IHECLExpression +{ +}; + +class CHECLRoot final : IHECLExpression +{ +}; + +#endif // HECLEXPRESSIONS_HPP diff --git a/include/graphicsys/hecl/IHECLBackend.hpp b/include/graphicsys/hecl/IHECLBackend.hpp new file mode 100644 index 0000000..4585adc --- /dev/null +++ b/include/graphicsys/hecl/IHECLBackend.hpp @@ -0,0 +1,76 @@ +#ifndef IHECLBACKEND_HPP +#define IHECLBACKEND_HPP + +#include +#include "CHECLLexer.hpp" + +class IHECLBackend; + +IHECLBackend* NewHECLBackendOutline(const CHECLLexer& lexer); +IHECLBackend* NewHECLBackendGLSL(const CHECLLexer& lexer); +IHECLBackend* NewHECLBackendHLSL(const CHECLLexer& lexer); +IHECLBackend* NewHECLBackendMetal(const CHECLLexer& lexer); +IHECLBackend* NewHECLBackendTEV(const CHECLLexer& lexer); +IHECLBackend* NewHECLBackendGLSLCafe(const CHECLLexer& lexer); + +class IHECLBackend +{ +public: + enum Type + { + AUTO = 0, + OUTLINE = 1, + GLSL = 2, + HLSL = 3, + METAL = 4, + TEV = 5, + GLSL_CAFE = 6 + }; + virtual Type getType() const=0; + + virtual bool hasVertexSourceForm() const {return false;} + virtual bool hasFragmentSourceForm() const {return false;} + virtual bool hasVertexBinaryForm() const {return false;} + virtual bool hasFragmentBinaryForm() const {return false;} + virtual bool hasBinaryForm() const {return false;} + + virtual std::string* emitNewVertexSource() {return NULL;} + virtual std::string* emitNewFragmentSource() {return NULL;} + virtual void* emitNewVertexBinary(size_t& szOut) {szOut = 0;return NULL;} + virtual void* emitNewFragmentBinary(size_t& szOut) {szOut = 0;return NULL;} + virtual void* emitNewBinary(size_t& szOut) {szOut = 0;return NULL;} + + static inline IHECLBackend* NewHECLBackend(Type backendType, const CHECLLexer& lexer) + { + switch (backendType) + { + case AUTO: +#if HW_RVL + return NewHECLBackendTEV(lexer); +#elif HW_CAFE + return NewHECLBackendGLSLCafe(lexer); +#elif _WIN32 + return NewHECLBackendHLSL(lexer); +#else + return NewHECLBackendGLSL(lexer); +#endif + case OUTLINE: + return NewHECLBackendOutline(lexer); + case GLSL: + return NewHECLBackendGLSL(lexer); + case HLSL: + return NewHECLBackendHLSL(lexer); + case METAL: + return NewHECLBackendMetal(lexer); + case TEV: + return NewHECLBackendTEV(lexer); + case GLSL_CAFE: + return NewHECLBackendGLSLCafe(lexer); + } + return NULL; + } + +}; + + +#endif // IHECLBACKEND_HPP diff --git a/libBoo.pri b/libBoo.pri index 102e20f..caf013e 100644 --- a/libBoo.pri +++ b/libBoo.pri @@ -2,7 +2,6 @@ HEADERS += \ $$PWD/include/boo.hpp \ $$PWD/include/IApplication.hpp \ $$PWD/include/windowsys/IWindow.hpp \ - $$PWD/include/windowsys/IGraphicsContext.hpp \ $$PWD/include/inputdev/CDolphinSmashAdapter.hpp \ $$PWD/include/inputdev/CRevolutionPad.hpp \ $$PWD/include/inputdev/CCafeProPad.hpp \ @@ -13,7 +12,18 @@ HEADERS += \ $$PWD/include/inputdev/CDeviceBase.hpp \ $$PWD/include/inputdev/IHIDListener.hpp \ $$PWD/src/inputdev/IHIDDevice.hpp \ - $$PWD/include/inputdev/SDeviceSignature.hpp + $$PWD/include/inputdev/SDeviceSignature.hpp \ + $$PWD/include/windowsys/IGFXCommandBuffer.hpp \ + $$PWD/include/graphicsys/IGFXCommandBuffer.hpp \ + $$PWD/include/graphicsys/IGFXContext.hpp \ + $$PWD/include/graphicsys/IGFXPipelineState.hpp \ + $$PWD/include/graphicsys/IGFXTransformSet.hpp \ + $$PWD/include/graphicsys/hecl/CHECLLexer.hpp \ + $$PWD/src/graphicsys/hecl/IHECLBackend.hpp \ + $$PWD/src/graphicsys/hecl/HECLExpressions.hpp \ + $$PWD/include/graphicsys/CGFXVertexLayoutBase.hpp \ + $$PWD/include/graphicsys/hecl/HECLExpressions.hpp \ + $$PWD/include/graphicsys/hecl/IHECLBackend.hpp SOURCES += \ $$PWD/InputDeviceClasses.cpp \ @@ -23,7 +33,13 @@ SOURCES += \ $$PWD/src/inputdev/CDualshockPad.cpp \ $$PWD/src/inputdev/CGenericPad.cpp \ $$PWD/src/inputdev/CDeviceBase.cpp \ - $$PWD/src/inputdev/SDeviceSignature.cpp + $$PWD/src/inputdev/SDeviceSignature.cpp \ + $$PWD/src/graphicsys/hecl/CHECLBackendGLSL.cpp \ + $$PWD/src/graphicsys/hecl/CHECLBackendHLSL.cpp \ + $$PWD/src/graphicsys/hecl/CHECLBackendMetal.cpp \ + $$PWD/src/graphicsys/hecl/CHECLLexer.cpp \ + $$PWD/src/graphicsys/hecl/CHECLBackendOutline.cpp \ + $$PWD/src/graphicsys/hecl/CHECLBackendTEV.cpp unix:!macx { HEADERS += \ @@ -33,8 +49,8 @@ unix:!macx { $$PWD/src/CApplicationUnix.cpp \ $$PWD/src/windowsys/CWindowXCB.cpp \ $$PWD/src/windowsys/CWindowWayland.cpp \ - $$PWD/src/windowsys/CGraphicsContextXCB.cpp \ - $$PWD/src/windowsys/CGraphicsContextWayland.cpp + $$PWD/src/graphicsys/CGraphicsContextXCB.cpp \ + $$PWD/src/graphicsys/CGraphicsContextWayland.cpp } linux { @@ -61,7 +77,7 @@ win32 { $$PWD/src/inputdev/CHIDListenerWinUSB.cpp \ $$PWD/src/inputdev/CHIDDeviceWinUSB.cpp \ $$PWD/src/windowsys/CWindowWin32.cpp \ - $$PWD/src/windowsys/CGraphicsContextWin32.cpp + $$PWD/src/graphicsys/CGraphicsContextWin32.cpp } INCLUDEPATH += $$PWD/include diff --git a/src/CApplicationXCB.hpp b/src/CApplicationXCB.hpp index 72c4534..38a0363 100644 --- a/src/CApplicationXCB.hpp +++ b/src/CApplicationXCB.hpp @@ -274,7 +274,6 @@ public: dbus_connection_read_write(m_dbus, 0); while ((msg = dbus_connection_pop_message(m_dbus))) { - /* check if the message is a signal from the correct interface and with the correct name */ if (dbus_message_is_signal(msg, "boo.signal.FileHandling", "Open")) { diff --git a/src/windowsys/CGraphicsContextCocoa.mm b/src/graphicsys/CGraphicsContextCocoa.mm similarity index 100% rename from src/windowsys/CGraphicsContextCocoa.mm rename to src/graphicsys/CGraphicsContextCocoa.mm diff --git a/src/windowsys/CGraphicsContextWayland.cpp b/src/graphicsys/CGraphicsContextWayland.cpp similarity index 64% rename from src/windowsys/CGraphicsContextWayland.cpp rename to src/graphicsys/CGraphicsContextWayland.cpp index 65b9b60..056faea 100644 --- a/src/windowsys/CGraphicsContextWayland.cpp +++ b/src/graphicsys/CGraphicsContextWayland.cpp @@ -1,10 +1,10 @@ -#include "windowsys/IGraphicsContext.hpp" +#include "graphicsys/IGFXContext.hpp" #include "windowsys/IWindow.hpp" namespace boo { -class CGraphicsContextWayland final : public IGraphicsContext +class CGraphicsContextWayland final : public IGFXContext { EGraphicsAPI m_api; @@ -52,30 +52,10 @@ public: } - IGraphicsContext* makeShareContext() const - { - return NULL; - } - - void makeCurrent() - { - - } - - void clearCurrent() - { - - } - - void swapBuffer() - { - - } - }; -IGraphicsContext* _CGraphicsContextWaylandNew(IGraphicsContext::EGraphicsAPI api, - IWindow* parentWindow) +IGFXContext* _CGraphicsContextWaylandNew(IGFXContext::EGraphicsAPI api, + IWindow* parentWindow) { return new CGraphicsContextWayland(api, parentWindow); } diff --git a/src/windowsys/CGraphicsContextWin32.cpp b/src/graphicsys/CGraphicsContextWin32.cpp similarity index 100% rename from src/windowsys/CGraphicsContextWin32.cpp rename to src/graphicsys/CGraphicsContextWin32.cpp diff --git a/src/windowsys/CGraphicsContextXCB.cpp b/src/graphicsys/CGraphicsContextXCB.cpp similarity index 79% rename from src/windowsys/CGraphicsContextXCB.cpp rename to src/graphicsys/CGraphicsContextXCB.cpp index d110991..f18b75f 100644 --- a/src/windowsys/CGraphicsContextXCB.cpp +++ b/src/graphicsys/CGraphicsContextXCB.cpp @@ -1,4 +1,4 @@ -#include "windowsys/IGraphicsContext.hpp" +#include "graphicsys/IGFXContext.hpp" #include "windowsys/IWindow.hpp" #include @@ -7,11 +7,12 @@ #include #include #include +#include namespace boo { -class CGraphicsContextXCB final : public IGraphicsContext +class CGraphicsContextXCB final : public IGFXContext { EGraphicsAPI m_api; @@ -24,6 +25,8 @@ class CGraphicsContextXCB final : public IGraphicsContext xcb_glx_window_t m_glxWindow = 0; xcb_glx_context_t m_glxCtx = 0; xcb_glx_context_tag_t m_glxCtxTag = 0; + + std::thread* m_commandThread = NULL; public: IWindowCallback* m_callback; @@ -34,6 +37,7 @@ public: m_parentWindow(parentWindow), m_xcbConn(conn) { + /* WTF freedesktop?? Fix this awful API and your nonexistant docs */ xcb_glx_get_fb_configs_reply_t* fbconfigs = xcb_glx_get_fb_configs_reply(m_xcbConn, xcb_glx_get_fb_configs(m_xcbConn, 0), NULL); @@ -137,36 +141,11 @@ public: m_glxWindow, 0, NULL); } - IGraphicsContext* makeShareContext() const - { - return NULL; - } - - void makeCurrent() - { - xcb_glx_make_context_current_reply_t* reply = - xcb_glx_make_context_current_reply(m_xcbConn, - xcb_glx_make_context_current(m_xcbConn, 0, m_glxWindow, m_glxWindow, m_glxCtx), NULL); - m_glxCtxTag = reply->context_tag; - free(reply); - } - - void clearCurrent() - { - xcb_glx_make_context_current(m_xcbConn, m_glxCtxTag, m_glxWindow, m_glxWindow, 0); - m_glxCtxTag = 0; - } - - void swapBuffer() - { - xcb_glx_swap_buffers(m_xcbConn, m_glxCtxTag, m_glxWindow); - } - }; -IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api, - IWindow* parentWindow, xcb_connection_t* conn, - uint32_t& visualIdOut) +IGFXContext* _CGraphicsContextXCBNew(IGFXContext::EGraphicsAPI api, + IWindow* parentWindow, xcb_connection_t* conn, + uint32_t& visualIdOut) { return new CGraphicsContextXCB(api, parentWindow, conn, visualIdOut); } diff --git a/src/graphicsys/hecl/CHECLBackendGLSL.cpp b/src/graphicsys/hecl/CHECLBackendGLSL.cpp new file mode 100644 index 0000000..a3ce619 --- /dev/null +++ b/src/graphicsys/hecl/CHECLBackendGLSL.cpp @@ -0,0 +1,32 @@ +#include "graphicsys/hecl/IHECLBackend.hpp" + +class CHECLBackendGLSL : public IHECLBackend +{ +public: + CHECLBackendGLSL(const CHECLLexer& lexer) + { + } + Type getType() const {return GLSL;} +}; + +IHECLBackend* NewHECLBackendGLSL(const CHECLLexer& lexer) +{ + return new CHECLBackendGLSL(lexer); +} + + +class CHECLBackendGLSLCafe final : public CHECLBackendGLSL +{ +public: + CHECLBackendGLSLCafe(const CHECLLexer& lexer) + : CHECLBackendGLSL(lexer) + { + } + Type getType() const {return GLSL_CAFE;} +}; + +IHECLBackend* NewHECLBackendGLSLCafe(const CHECLLexer& lexer) +{ + return new CHECLBackendGLSLCafe(lexer); +} + diff --git a/src/graphicsys/hecl/CHECLBackendHLSL.cpp b/src/graphicsys/hecl/CHECLBackendHLSL.cpp new file mode 100644 index 0000000..14c9a4b --- /dev/null +++ b/src/graphicsys/hecl/CHECLBackendHLSL.cpp @@ -0,0 +1,15 @@ +#include "graphicsys/hecl/IHECLBackend.hpp" + +class CHECLBackendHLSL final : public IHECLBackend +{ +public: + CHECLBackendHLSL(const CHECLLexer& lexer) + { + } + Type getType() const {return HLSL;} +}; + +IHECLBackend* NewHECLBackendHLSL(const CHECLLexer& lexer) +{ + return new CHECLBackendHLSL(lexer); +} diff --git a/src/graphicsys/hecl/CHECLBackendMetal.cpp b/src/graphicsys/hecl/CHECLBackendMetal.cpp new file mode 100644 index 0000000..cf69b17 --- /dev/null +++ b/src/graphicsys/hecl/CHECLBackendMetal.cpp @@ -0,0 +1,15 @@ +#include "graphicsys/hecl/IHECLBackend.hpp" + +class CHECLBackendMetal final : public IHECLBackend +{ +public: + CHECLBackendMetal(const CHECLLexer& lexer) + { + } + Type getType() const {return METAL;} +}; + +IHECLBackend* NewHECLBackendMetal(const CHECLLexer& lexer) +{ + return new CHECLBackendMetal(lexer); +} diff --git a/src/graphicsys/hecl/CHECLBackendOutline.cpp b/src/graphicsys/hecl/CHECLBackendOutline.cpp new file mode 100644 index 0000000..ac6536b --- /dev/null +++ b/src/graphicsys/hecl/CHECLBackendOutline.cpp @@ -0,0 +1,16 @@ +#include "graphicsys/hecl/IHECLBackend.hpp" + +class CHECLBackendOutline final : public IHECLBackend +{ +public: + CHECLBackendOutline(const CHECLLexer& lexer) + { + } + Type getType() const {return OUTLINE;} +}; + +IHECLBackend* NewHECLBackendOutline(const CHECLLexer& lexer) +{ + return new CHECLBackendOutline(lexer); +} + diff --git a/src/graphicsys/hecl/CHECLBackendTEV.cpp b/src/graphicsys/hecl/CHECLBackendTEV.cpp new file mode 100644 index 0000000..f4565df --- /dev/null +++ b/src/graphicsys/hecl/CHECLBackendTEV.cpp @@ -0,0 +1,15 @@ +#include "graphicsys/hecl/IHECLBackend.hpp" + +class CHECLBackendTEV final : public IHECLBackend +{ +public: + CHECLBackendTEV(const CHECLLexer& lexer) + { + } + Type getType() const {return TEV;} +}; + +IHECLBackend* NewHECLBackendTEV(const CHECLLexer& lexer) +{ + return new CHECLBackendTEV(lexer); +} diff --git a/src/graphicsys/hecl/CHECLLexer.cpp b/src/graphicsys/hecl/CHECLLexer.cpp new file mode 100644 index 0000000..56ba45b --- /dev/null +++ b/src/graphicsys/hecl/CHECLLexer.cpp @@ -0,0 +1,14 @@ +#include "graphicsys/hecl/CHECLLexer.hpp" + +CHECLLexer::CHECLLexer(const CGFXVertexLayoutBase& vertLayout, + const std::string& colorHECL) +: m_vertLayout(vertLayout) +{ +} + +CHECLLexer::CHECLLexer(const CGFXVertexLayoutBase& vertLayout, + const std::string& colorHECL, + const std::string& alphaHECL) +: m_vertLayout(vertLayout) +{ +} diff --git a/src/windowsys/CWindowXCB.cpp b/src/windowsys/CWindowXCB.cpp index 2be7629..9507c9d 100644 --- a/src/windowsys/CWindowXCB.cpp +++ b/src/windowsys/CWindowXCB.cpp @@ -1,5 +1,5 @@ #include "windowsys/IWindow.hpp" -#include "windowsys/IGraphicsContext.hpp" +#include "graphicsys/IGFXContext.hpp" #include "IApplication.hpp" #include @@ -145,15 +145,15 @@ static void genFrameDefault(xcb_screen_t* screen, int* xOut, int* yOut, int* wOu *hOut = height; } -IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api, - IWindow* parentWindow, xcb_connection_t* conn, - uint32_t& visualIdOut); +IGFXContext* _CGraphicsContextXCBNew(IGFXContext::EGraphicsAPI api, + IWindow* parentWindow, xcb_connection_t* conn, + uint32_t& visualIdOut); class CWindowXCB final : public IWindow { xcb_connection_t* m_xcbConn; xcb_window_t m_windowId; - IGraphicsContext* m_gfxCtx; + IGFXContext* m_gfxCtx; IWindowCallback* m_callback; /* Last known input device id (0xffff if not yet set) */ @@ -184,7 +184,7 @@ public: /* Construct graphics context */ uint32_t visualId; - m_gfxCtx = _CGraphicsContextXCBNew(IGraphicsContext::API_OPENGL_3_3, this, m_xcbConn, visualId); + m_gfxCtx = _CGraphicsContextXCBNew(IGFXContext::API_OPENGL_3_3, this, m_xcbConn, visualId); /* Create colormap */ xcb_colormap_t colormap = xcb_generate_id(m_xcbConn);