mirror of https://github.com/AxioDL/boo.git
Merge branch 'master' of https://github.com/RetroView/libBoo into ds3
This commit is contained in:
commit
10c14a0c39
|
@ -0,0 +1,101 @@
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(libBoo)
|
||||||
|
|
||||||
|
if (NOT MSVC)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
list(APPEND PLAT_SRCS
|
||||||
|
lib/win/ApplicationWin32.cpp
|
||||||
|
lib/win/WindowWin32.cpp
|
||||||
|
lib/win/GraphicsContextWin32.cpp
|
||||||
|
lib/inputdev/HIDListenerWinUSB.cpp
|
||||||
|
lib/inputdev/HIDDeviceWinUSB.cpp)
|
||||||
|
elseif(APPLE)
|
||||||
|
list(APPEND PLAT_SRCS
|
||||||
|
lib/mac/ApplicationCocoa.mm
|
||||||
|
lib/mac/WindowCocoa.mm
|
||||||
|
lib/mac/GLViewCocoa.mm
|
||||||
|
lib/mac/GraphicsContextCocoa.cpp
|
||||||
|
lib/inputdev/HIDListenerIOKit.cpp
|
||||||
|
lib/inputdev/HIDDeviceIOKit.cpp)
|
||||||
|
else()
|
||||||
|
list(APPEND PLAT_SRCS
|
||||||
|
lib/x11/ApplicationUnix.cpp
|
||||||
|
lib/x11/ApplicationXCB.hpp
|
||||||
|
lib/x11/ApplicationWayland.hpp
|
||||||
|
lib/x11/WindowXCB.cpp
|
||||||
|
lib/x11/WindowWayland.cpp
|
||||||
|
lib/x11/GraphicsContextXCB.cpp
|
||||||
|
lib/x11/GraphicsContextWayland.cpp
|
||||||
|
lib/inputdev/HIDListenerUdev.cpp
|
||||||
|
lib/inputdev/HIDDeviceUdev.cpp)
|
||||||
|
|
||||||
|
find_package(PkgConfig)
|
||||||
|
if(PKG_CONFIG_FOUND)
|
||||||
|
pkg_check_modules(dbus_pkg QUIET libdbus dbus-1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_path(DBUS_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
dbus/dbus.h
|
||||||
|
HINTS
|
||||||
|
${dbus_pkg_INCLUDE_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
include/
|
||||||
|
include/dbus-1.0/
|
||||||
|
dbus-1.0/)
|
||||||
|
|
||||||
|
find_path(DBUS_ARCH_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
dbus/dbus-arch-deps.h
|
||||||
|
HINTS
|
||||||
|
${dbus_pkg_INCLUDE_DIRS}
|
||||||
|
PATHS
|
||||||
|
# TODO use CMAKE_SYSTEM_PROCESSOR or similar?
|
||||||
|
/usr/lib/dbus-1.0/include
|
||||||
|
PATH_SUFFIXES
|
||||||
|
dbus-1.0/include/)
|
||||||
|
|
||||||
|
find_library(DBUS_LIBRARY
|
||||||
|
NAMES
|
||||||
|
dbus dbus-1
|
||||||
|
HINTS
|
||||||
|
${dbus_pkg_LIBRARY_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
lib
|
||||||
|
lib32
|
||||||
|
lib64)
|
||||||
|
|
||||||
|
if(DBUS_INCLUDE_DIR-NOTFOUND)
|
||||||
|
message(FATAL_ERROR "Unix build of libBoo requires dbus")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(${DBUS_INCLUDE_DIR} ${DBUS_ARCH_INCLUDE_DIR})
|
||||||
|
list(APPEND BOO_SYS_LIBS xcb xcb-glx xcb-xinput xcb-xkb xcb-keysyms xkbcommon xkbcommon-x11 ${DBUS_LIBRARY} udev pthread)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(BOO_SYS_LIBS ${BOO_SYS_LIBS} CACHE PATH "Boo System Libraries" FORCE)
|
||||||
|
|
||||||
|
include_directories(include)
|
||||||
|
|
||||||
|
add_library(Boo
|
||||||
|
lib/inputdev/CafeProPad.cpp include/boo/inputdev/CafeProPad.hpp
|
||||||
|
lib/inputdev/RevolutionPad.cpp include/boo/inputdev/RevolutionPad.hpp
|
||||||
|
lib/inputdev/DolphinSmashAdapter.cpp include/boo/inputdev/DolphinSmashAdapter.hpp
|
||||||
|
lib/inputdev/DualshockPad.cpp include/boo/inputdev/DualshockPad.hpp
|
||||||
|
lib/inputdev/GenericPad.cpp include/boo/inputdev/GenericPad.hpp
|
||||||
|
lib/inputdev/DeviceBase.cpp include/boo/inputdev/DeviceBase.hpp
|
||||||
|
lib/inputdev/DeviceSignature.cpp include/boo/inputdev/DeviceSignature.hpp
|
||||||
|
include/boo/inputdev/IHIDListener.hpp
|
||||||
|
lib/inputdev/IHIDDevice.hpp
|
||||||
|
include/boo/IGraphicsContext.hpp
|
||||||
|
include/boo/IWindow.hpp
|
||||||
|
include/boo/IApplication.hpp
|
||||||
|
include/boo/boo.hpp
|
||||||
|
InputDeviceClasses.cpp
|
||||||
|
${PLAT_SRCS})
|
||||||
|
|
||||||
|
add_subdirectory(test)
|
|
@ -1,14 +1,14 @@
|
||||||
#include "inputdev/SDeviceSignature.hpp"
|
#include "boo/inputdev/DeviceSignature.hpp"
|
||||||
#include "inputdev/CDolphinSmashAdapter.hpp"
|
#include "boo/inputdev/DolphinSmashAdapter.hpp"
|
||||||
#include "inputdev/CDualshockPad.hpp"
|
#include "boo/inputdev/DualshockPad.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
const SDeviceSignature BOO_DEVICE_SIGS[] =
|
const DeviceSignature BOO_DEVICE_SIGS[] =
|
||||||
{
|
{
|
||||||
DEVICE_SIG(CDolphinSmashAdapter, 0x57e, 0x337),
|
DEVICE_SIG(DolphinSmashAdapter, 0x57e, 0x337),
|
||||||
DEVICE_SIG(CDualshockController, 0x54c, 0x268),
|
DEVICE_SIG(DualshockPad, 0x54c, 0x268),
|
||||||
DEVICE_SIG_SENTINEL()
|
DEVICE_SIG_SENTINEL()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
#ifndef CINPUTDEFERREDRELAY_HPP
|
|
||||||
#define CINPUTDEFERREDRELAY_HPP
|
|
||||||
|
|
||||||
#include "IInputWaiter.hpp"
|
|
||||||
|
|
||||||
namespace boo
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CINPUTDEFERREDRELAY_HPP
|
|
|
@ -1,16 +0,0 @@
|
||||||
#ifndef CINPUTRELAY_HPP
|
|
||||||
#define CINPUTRELAY_HPP
|
|
||||||
|
|
||||||
#include "IInputWaiter.hpp"
|
|
||||||
|
|
||||||
namespace boo
|
|
||||||
{
|
|
||||||
|
|
||||||
class CInputRelay : IInputWaiter
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CINPUTRELAY_HPP
|
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef CQTOPENGLWINDOW_HPP
|
|
||||||
#define CQTOPENGLWINDOW_HPP
|
|
||||||
|
|
||||||
#include <QWindow>
|
|
||||||
#include <QOpenGLFunctions>
|
|
||||||
#include <ISurface.hpp>
|
|
||||||
|
|
||||||
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
|
|
|
@ -1,14 +0,0 @@
|
||||||
#ifndef CSURFACE_HPP
|
|
||||||
#define CSURFACE_HPP
|
|
||||||
|
|
||||||
#include "ISurface.hpp"
|
|
||||||
|
|
||||||
namespace boo
|
|
||||||
{
|
|
||||||
|
|
||||||
ISurface* CSurfaceNewWindow();
|
|
||||||
ISurface* CSurfaceNewQWidget();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CSURFACE_HPP
|
|
|
@ -1,27 +0,0 @@
|
||||||
#ifndef IGRAPHICSCONTEXT_HPP
|
|
||||||
#define IGRAPHICSCONTEXT_HPP
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
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
|
|
|
@ -1,14 +0,0 @@
|
||||||
#ifndef IINPUTWAITER_HPP
|
|
||||||
#define IINPUTWAITER_HPP
|
|
||||||
|
|
||||||
namespace boo
|
|
||||||
{
|
|
||||||
|
|
||||||
class IInputWaiter
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // IINPUTWAITER_HPP
|
|
|
@ -1,14 +0,0 @@
|
||||||
#ifndef IRETRACEWAITER_HPP
|
|
||||||
#define IRETRACEWAITER_HPP
|
|
||||||
|
|
||||||
namespace boo
|
|
||||||
{
|
|
||||||
|
|
||||||
class IRetraceWaiter
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // IRETRACEWAITER_HPP
|
|
|
@ -1,15 +0,0 @@
|
||||||
#ifndef ISURFACE_HPP
|
|
||||||
#define ISURFACE_HPP
|
|
||||||
|
|
||||||
namespace boo
|
|
||||||
{
|
|
||||||
|
|
||||||
class ISurface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CSURFACE_HPP
|
|
|
@ -1,23 +0,0 @@
|
||||||
#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 "inputdev/CDeviceFinder.hpp"
|
|
||||||
#include "inputdev/CDolphinSmashAdapter.hpp"
|
|
||||||
#include "inputdev/CDualshockPad.hpp"
|
|
||||||
|
|
||||||
#endif // BOO_HPP
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
#ifndef IRUNLOOP_HPP
|
||||||
|
#define IRUNLOOP_HPP
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "IWindow.hpp"
|
||||||
|
#include "inputdev/DeviceFinder.hpp"
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
class IApplication;
|
||||||
|
|
||||||
|
struct IApplicationCallback
|
||||||
|
{
|
||||||
|
virtual void appLaunched(IApplication* app) {(void)app;}
|
||||||
|
virtual void appQuitting(IApplication* app) {(void)app;}
|
||||||
|
virtual void appFilesOpen(IApplication* app, const std::vector<std::string>& paths) {(void)app;(void)paths;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class IApplication
|
||||||
|
{
|
||||||
|
friend class WindowCocoa;
|
||||||
|
friend class WindowWayland;
|
||||||
|
friend class WindowXCB;
|
||||||
|
friend class WindowWin32;
|
||||||
|
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& getUniqueName() const=0;
|
||||||
|
virtual const std::string& getFriendlyName() const=0;
|
||||||
|
virtual const std::string& getProcessName() const=0;
|
||||||
|
virtual const std::vector<std::string>& getArgs() const=0;
|
||||||
|
|
||||||
|
/* Constructors/initializers for sub-objects */
|
||||||
|
virtual IWindow* newWindow(const std::string& title)=0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<IApplication>
|
||||||
|
ApplicationBootstrap(IApplication::EPlatformType platform,
|
||||||
|
IApplicationCallback& cb,
|
||||||
|
const std::string& uniqueName,
|
||||||
|
const std::string& friendlyName,
|
||||||
|
const std::string& pname,
|
||||||
|
const std::vector<std::string>& args,
|
||||||
|
bool singleInstance=true);
|
||||||
|
extern IApplication* APP;
|
||||||
|
|
||||||
|
static inline std::unique_ptr<IApplication>
|
||||||
|
ApplicationBootstrap(IApplication::EPlatformType platform,
|
||||||
|
IApplicationCallback& cb,
|
||||||
|
const std::string& uniqueName,
|
||||||
|
const std::string& friendlyName,
|
||||||
|
int argc, const char** argv,
|
||||||
|
bool singleInstance=true)
|
||||||
|
{
|
||||||
|
if (APP)
|
||||||
|
return std::unique_ptr<IApplication>();
|
||||||
|
std::vector<std::string> args;
|
||||||
|
for (int i=1 ; i<argc ; ++i)
|
||||||
|
args.push_back(argv[i]);
|
||||||
|
return ApplicationBootstrap(platform, cb, uniqueName, friendlyName, argv[0], args, singleInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IRUNLOOP_HPP
|
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef IGFXCONTEXT_HPP
|
||||||
|
#define IGFXCONTEXT_HPP
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
|
||||||
|
class IGraphicsContext
|
||||||
|
{
|
||||||
|
friend class CWindowCocoa;
|
||||||
|
friend class CWindowXCB;
|
||||||
|
virtual void _setCallback(class IWindowCallback* cb) {(void)cb;}
|
||||||
|
|
||||||
|
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,
|
||||||
|
API_GX = 7,
|
||||||
|
API_GX2 = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
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 initializeContext()=0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IGFXCONTEXT_HPP
|
|
@ -0,0 +1,146 @@
|
||||||
|
#ifndef IWINDOW_HPP
|
||||||
|
#define IWINDOW_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
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 STouchCoord
|
||||||
|
{
|
||||||
|
double coord[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SScrollDelta
|
||||||
|
{
|
||||||
|
double 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 SWindowCoord& coord, const SScrollDelta& scroll)
|
||||||
|
{(void)coord;(void)scroll;}
|
||||||
|
|
||||||
|
virtual void touchDown(const STouchCoord& coord, uintptr_t tid)
|
||||||
|
{(void)coord;(void)tid;}
|
||||||
|
virtual void touchUp(const STouchCoord& coord, uintptr_t tid)
|
||||||
|
{(void)coord;(void)tid;}
|
||||||
|
virtual void touchMove(const STouchCoord& 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
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~IWindow() {}
|
||||||
|
|
||||||
|
virtual void setCallback(IWindowCallback* cb)=0;
|
||||||
|
|
||||||
|
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 float getVirtualPixelFactor() const=0;
|
||||||
|
|
||||||
|
virtual bool isFullscreen() const=0;
|
||||||
|
virtual void setFullscreen(bool fs)=0;
|
||||||
|
|
||||||
|
virtual uintptr_t getPlatformHandle() const=0;
|
||||||
|
virtual void _incomingEvent(void* event) {(void)event;}
|
||||||
|
|
||||||
|
enum ETouchType
|
||||||
|
{
|
||||||
|
TOUCH_NONE = 0,
|
||||||
|
TOUCH_DISPLAY = 1,
|
||||||
|
TOUCH_TRACKPAD = 2
|
||||||
|
};
|
||||||
|
virtual ETouchType getTouchType() const=0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IWINDOW_HPP
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef BOO_HPP
|
||||||
|
#define BOO_HPP
|
||||||
|
|
||||||
|
#include "IApplication.hpp"
|
||||||
|
#include "IWindow.hpp"
|
||||||
|
#include "inputdev/DeviceFinder.hpp"
|
||||||
|
#include "inputdev/DolphinSmashAdapter.hpp"
|
||||||
|
#include "inputdev/DualshockPad.hpp"
|
||||||
|
|
||||||
|
#endif // BOO_HPP
|
|
@ -8,27 +8,27 @@
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
class CDeviceBase
|
class DeviceBase
|
||||||
{
|
{
|
||||||
friend class CDeviceToken;
|
friend class DeviceToken;
|
||||||
friend class CHIDDeviceIOKit;
|
friend class HIDDeviceIOKit;
|
||||||
friend class CHIDDeviceUdev;
|
friend class HIDDeviceUdev;
|
||||||
friend class CHIDDeviceWinUSB;
|
friend class HIDDeviceWinUSB;
|
||||||
|
|
||||||
class CDeviceToken* m_token;
|
class DeviceToken* m_token;
|
||||||
class IHIDDevice* m_hidDev;
|
class IHIDDevice* m_hidDev;
|
||||||
void _deviceDisconnected();
|
void _deviceDisconnected();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDeviceBase(CDeviceToken* token);
|
DeviceBase(DeviceToken* token);
|
||||||
virtual ~CDeviceBase();
|
virtual ~DeviceBase();
|
||||||
void closeDevice();
|
void closeDevice();
|
||||||
virtual void deviceDisconnected()=0;
|
virtual void deviceDisconnected()=0;
|
||||||
virtual void deviceError(const char* error, ...);
|
virtual void deviceError(const char* error, ...);
|
||||||
|
|
||||||
/* Low-Level API */
|
/* Low-Level API */
|
||||||
bool sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length);
|
bool sendUSBInterruptTransfer(const uint8_t* data, size_t length);
|
||||||
size_t receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length);
|
size_t receiveUSBInterruptTransfer(uint8_t* data, size_t length);
|
||||||
virtual void initialCycle() {}
|
virtual void initialCycle() {}
|
||||||
virtual void transferCycle() {}
|
virtual void transferCycle() {}
|
||||||
virtual void finalCycle() {}
|
virtual void finalCycle() {}
|
|
@ -1,13 +1,14 @@
|
||||||
#ifndef CDEVICEFINDER_HPP
|
#ifndef CDEVICEFINDER_HPP
|
||||||
#define CDEVICEFINDER_HPP
|
#define CDEVICEFINDER_HPP
|
||||||
|
|
||||||
#include <set>
|
#include <unordered_set>
|
||||||
|
#include <typeindex>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <stdexcept>
|
#include "DeviceToken.hpp"
|
||||||
#include "CDeviceToken.hpp"
|
|
||||||
#include "IHIDListener.hpp"
|
#include "IHIDListener.hpp"
|
||||||
#include "SDeviceSignature.hpp"
|
#include "DeviceSignature.hpp"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define _WIN32_LEAN_AND_MEAN 1
|
#define _WIN32_LEAN_AND_MEAN 1
|
||||||
|
@ -18,20 +19,20 @@
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
static class CDeviceFinder* skDevFinder = NULL;
|
static class DeviceFinder* skDevFinder = NULL;
|
||||||
|
|
||||||
class CDeviceFinder
|
class DeviceFinder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
friend class CHIDListenerIOKit;
|
friend class HIDListenerIOKit;
|
||||||
friend class CHIDListenerUdev;
|
friend class HIDListenerUdev;
|
||||||
friend class CHIDListenerWinUSB;
|
friend class HIDListenerWinUSB;
|
||||||
static inline CDeviceFinder* instance() {return skDevFinder;}
|
static inline DeviceFinder* instance() {return skDevFinder;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/* Types this finder is interested in (immutable) */
|
/* Types this finder is interested in (immutable) */
|
||||||
SDeviceSignature::TDeviceSignatureSet m_types;
|
DeviceSignature::TDeviceSignatureSet m_types;
|
||||||
|
|
||||||
/* Platform-specific USB event registration
|
/* Platform-specific USB event registration
|
||||||
* (for auto-scanning, NULL if not registered) */
|
* (for auto-scanning, NULL if not registered) */
|
||||||
|
@ -50,9 +51,9 @@ private:
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inline bool _insertToken(CDeviceToken&& token)
|
inline bool _insertToken(DeviceToken&& token)
|
||||||
{
|
{
|
||||||
if (SDeviceSignature::DeviceMatchToken(token, m_types)) {
|
if (DeviceSignature::DeviceMatchToken(token, m_types)) {
|
||||||
m_tokensLock.lock();
|
m_tokensLock.lock();
|
||||||
TInsertedDeviceToken inseredTok =
|
TInsertedDeviceToken inseredTok =
|
||||||
m_tokens.insert(std::make_pair(token.getDevicePath(), std::move(token)));
|
m_tokens.insert(std::make_pair(token.getDevicePath(), std::move(token)));
|
||||||
|
@ -67,8 +68,8 @@ private:
|
||||||
auto preCheck = m_tokens.find(path);
|
auto preCheck = m_tokens.find(path);
|
||||||
if (preCheck != m_tokens.end())
|
if (preCheck != m_tokens.end())
|
||||||
{
|
{
|
||||||
CDeviceToken& tok = preCheck->second;
|
DeviceToken& tok = preCheck->second;
|
||||||
CDeviceBase* dev = tok.m_connectedDev;
|
DeviceBase* dev = tok.m_connectedDev;
|
||||||
tok._deviceClose();
|
tok._deviceClose();
|
||||||
deviceDisconnected(tok, dev);
|
deviceDisconnected(tok, dev);
|
||||||
m_tokensLock.lock();
|
m_tokensLock.lock();
|
||||||
|
@ -81,9 +82,9 @@ public:
|
||||||
|
|
||||||
class CDeviceTokensHandle
|
class CDeviceTokensHandle
|
||||||
{
|
{
|
||||||
CDeviceFinder& m_finder;
|
DeviceFinder& m_finder;
|
||||||
public:
|
public:
|
||||||
inline CDeviceTokensHandle(CDeviceFinder& finder) : m_finder(finder)
|
inline CDeviceTokensHandle(DeviceFinder& finder) : m_finder(finder)
|
||||||
{m_finder.m_tokensLock.lock();}
|
{m_finder.m_tokensLock.lock();}
|
||||||
inline ~CDeviceTokensHandle() {m_finder.m_tokensLock.unlock();}
|
inline ~CDeviceTokensHandle() {m_finder.m_tokensLock.unlock();}
|
||||||
inline TDeviceTokens::iterator begin() {return m_finder.m_tokens.begin();}
|
inline TDeviceTokens::iterator begin() {return m_finder.m_tokens.begin();}
|
||||||
|
@ -91,24 +92,27 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Application must specify its interested device-types */
|
/* Application must specify its interested device-types */
|
||||||
CDeviceFinder(std::vector<const char*> types)
|
DeviceFinder(std::unordered_set<std::type_index> types)
|
||||||
: m_listener(NULL)
|
: m_listener(NULL)
|
||||||
{
|
{
|
||||||
if (skDevFinder)
|
if (skDevFinder)
|
||||||
throw std::runtime_error("only one instance of CDeviceFinder may be constructed");
|
|
||||||
skDevFinder = this;
|
|
||||||
for (const char* typeName : types)
|
|
||||||
{
|
{
|
||||||
const SDeviceSignature* sigIter = BOO_DEVICE_SIGS;
|
fprintf(stderr, "only one instance of CDeviceFinder may be constructed");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
skDevFinder = this;
|
||||||
|
for (const std::type_index& typeIdx : types)
|
||||||
|
{
|
||||||
|
const DeviceSignature* sigIter = BOO_DEVICE_SIGS;
|
||||||
while (sigIter->m_name)
|
while (sigIter->m_name)
|
||||||
{
|
{
|
||||||
if (!strcmp(sigIter->m_name, typeName))
|
if (sigIter->m_typeIdx == typeIdx)
|
||||||
m_types.push_back(sigIter);
|
m_types.push_back(sigIter);
|
||||||
++sigIter;
|
++sigIter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~CDeviceFinder()
|
~DeviceFinder()
|
||||||
{
|
{
|
||||||
if (m_listener)
|
if (m_listener)
|
||||||
m_listener->stopScanning();
|
m_listener->stopScanning();
|
||||||
|
@ -117,7 +121,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get interested device-type mask */
|
/* Get interested device-type mask */
|
||||||
inline const SDeviceSignature::TDeviceSignatureSet& getTypes() const {return m_types;}
|
inline const DeviceSignature::TDeviceSignatureSet& getTypes() const {return m_types;}
|
||||||
|
|
||||||
/* Iterable set of tokens */
|
/* Iterable set of tokens */
|
||||||
inline CDeviceTokensHandle getTokens() {return CDeviceTokensHandle(*this);}
|
inline CDeviceTokensHandle getTokens() {return CDeviceTokensHandle(*this);}
|
||||||
|
@ -150,8 +154,8 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void deviceConnected(CDeviceToken&) {}
|
virtual void deviceConnected(DeviceToken&) {}
|
||||||
virtual void deviceDisconnected(CDeviceToken&, CDeviceBase*) {}
|
virtual void deviceDisconnected(DeviceToken&, DeviceBase*) {}
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
/* Windows-specific WM_DEVICECHANGED handler */
|
/* Windows-specific WM_DEVICECHANGED handler */
|
|
@ -0,0 +1,38 @@
|
||||||
|
#ifndef SDeviceSignature_HPP
|
||||||
|
#define SDeviceSignature_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
#include <typeindex>
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
|
||||||
|
class DeviceToken;
|
||||||
|
class DeviceBase;
|
||||||
|
|
||||||
|
struct DeviceSignature
|
||||||
|
{
|
||||||
|
typedef std::vector<const DeviceSignature*> TDeviceSignatureSet;
|
||||||
|
typedef std::function<DeviceBase*(DeviceToken*)> TFactoryLambda;
|
||||||
|
const char* m_name;
|
||||||
|
std::type_index m_typeIdx;
|
||||||
|
unsigned m_vid, m_pid;
|
||||||
|
TFactoryLambda m_factory;
|
||||||
|
DeviceSignature() : m_name(NULL), m_typeIdx(typeid(DeviceSignature)) {} /* Sentinel constructor */
|
||||||
|
DeviceSignature(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 DeviceToken& token, const TDeviceSignatureSet& sigSet);
|
||||||
|
static DeviceBase* DeviceNew(DeviceToken& token);
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEVICE_SIG(name, vid, pid) \
|
||||||
|
DeviceSignature(#name, typeid(name), vid, pid, [](DeviceToken* tok) -> DeviceBase* {return new name(tok);})
|
||||||
|
#define DEVICE_SIG_SENTINEL() DeviceSignature()
|
||||||
|
|
||||||
|
extern const DeviceSignature BOO_DEVICE_SIGS[];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SDeviceSignature_HPP
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
#define CDEVICETOKEN
|
#define CDEVICETOKEN
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "CDeviceBase.hpp"
|
#include "DeviceBase.hpp"
|
||||||
#include "SDeviceSignature.hpp"
|
#include "DeviceSignature.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
class CDeviceToken
|
class DeviceToken
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum TDeviceType
|
enum TDeviceType
|
||||||
|
@ -27,10 +27,10 @@ private:
|
||||||
std::string m_productName;
|
std::string m_productName;
|
||||||
std::string m_devPath;
|
std::string m_devPath;
|
||||||
|
|
||||||
friend class CDeviceBase;
|
friend class DeviceBase;
|
||||||
CDeviceBase* m_connectedDev;
|
DeviceBase* m_connectedDev;
|
||||||
|
|
||||||
friend class CDeviceFinder;
|
friend class DeviceFinder;
|
||||||
inline void _deviceClose()
|
inline void _deviceClose()
|
||||||
{
|
{
|
||||||
if (m_connectedDev)
|
if (m_connectedDev)
|
||||||
|
@ -40,8 +40,8 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CDeviceToken(const CDeviceToken&) = delete;
|
DeviceToken(const DeviceToken&) = delete;
|
||||||
CDeviceToken(const CDeviceToken&& other)
|
DeviceToken(const DeviceToken&& other)
|
||||||
: m_devType(other.m_devType),
|
: m_devType(other.m_devType),
|
||||||
m_vendorId(other.m_vendorId),
|
m_vendorId(other.m_vendorId),
|
||||||
m_productId(other.m_productId),
|
m_productId(other.m_productId),
|
||||||
|
@ -50,7 +50,7 @@ public:
|
||||||
m_devPath(other.m_devPath),
|
m_devPath(other.m_devPath),
|
||||||
m_connectedDev(other.m_connectedDev)
|
m_connectedDev(other.m_connectedDev)
|
||||||
{}
|
{}
|
||||||
inline CDeviceToken(enum TDeviceType devType, unsigned vid, unsigned pid, const char* vname, const char* pname, const char* path)
|
inline DeviceToken(enum TDeviceType devType, unsigned vid, unsigned pid, const char* vname, const char* pname, const char* path)
|
||||||
: m_devType(devType),
|
: m_devType(devType),
|
||||||
m_vendorId(vid),
|
m_vendorId(vid),
|
||||||
m_productId(pid),
|
m_productId(pid),
|
||||||
|
@ -70,16 +70,16 @@ public:
|
||||||
inline const std::string& getProductName() const {return m_productName;}
|
inline const std::string& getProductName() const {return m_productName;}
|
||||||
inline const std::string& getDevicePath() const {return m_devPath;}
|
inline const std::string& getDevicePath() const {return m_devPath;}
|
||||||
inline bool isDeviceOpen() const {return (m_connectedDev != NULL);}
|
inline bool isDeviceOpen() const {return (m_connectedDev != NULL);}
|
||||||
inline CDeviceBase* openAndGetDevice()
|
inline DeviceBase* openAndGetDevice()
|
||||||
{
|
{
|
||||||
if (!m_connectedDev)
|
if (!m_connectedDev)
|
||||||
m_connectedDev = SDeviceSignature::DeviceNew(*this);
|
m_connectedDev = DeviceSignature::DeviceNew(*this);
|
||||||
return m_connectedDev;
|
return m_connectedDev;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator ==(const CDeviceToken& rhs) const
|
inline bool operator ==(const DeviceToken& rhs) const
|
||||||
{return m_devPath == rhs.m_devPath;}
|
{return m_devPath == rhs.m_devPath;}
|
||||||
inline bool operator <(const CDeviceToken& rhs) const
|
inline bool operator <(const DeviceToken& rhs) const
|
||||||
{return m_devPath < rhs.m_devPath;}
|
{return m_devPath < rhs.m_devPath;}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define CDOLPHINSMASHADAPTER_HPP
|
#define CDOLPHINSMASHADAPTER_HPP
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "CDeviceBase.hpp"
|
#include "DeviceBase.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,8 @@ enum EDolphinControllerButtons
|
||||||
DOL_DOWN = 1<<14,
|
DOL_DOWN = 1<<14,
|
||||||
DOL_UP = 1<<15
|
DOL_UP = 1<<15
|
||||||
};
|
};
|
||||||
struct SDolphinControllerState
|
|
||||||
|
struct DolphinControllerState
|
||||||
{
|
{
|
||||||
uint8_t m_leftStick[2];
|
uint8_t m_leftStick[2];
|
||||||
uint8_t m_rightStick[2];
|
uint8_t m_rightStick[2];
|
||||||
|
@ -39,13 +40,13 @@ struct SDolphinControllerState
|
||||||
|
|
||||||
struct IDolphinSmashAdapterCallback
|
struct IDolphinSmashAdapterCallback
|
||||||
{
|
{
|
||||||
virtual void controllerConnected(unsigned idx, EDolphinControllerType type) {}
|
virtual void controllerConnected(unsigned idx, EDolphinControllerType type) {(void)idx;(void)type;}
|
||||||
virtual void controllerDisconnected(unsigned idx, EDolphinControllerType type) {}
|
virtual void controllerDisconnected(unsigned idx, EDolphinControllerType type) {(void)idx;(void)type;}
|
||||||
virtual void controllerUpdate(unsigned idx, EDolphinControllerType type,
|
virtual void controllerUpdate(unsigned idx, EDolphinControllerType type,
|
||||||
const SDolphinControllerState& state) {}
|
const DolphinControllerState& state) {(void)idx;(void)type;(void)state;}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDolphinSmashAdapter final : public CDeviceBase
|
class DolphinSmashAdapter final : public DeviceBase
|
||||||
{
|
{
|
||||||
IDolphinSmashAdapterCallback* m_callback;
|
IDolphinSmashAdapterCallback* m_callback;
|
||||||
uint8_t m_knownControllers;
|
uint8_t m_knownControllers;
|
||||||
|
@ -56,8 +57,8 @@ class CDolphinSmashAdapter final : public CDeviceBase
|
||||||
void transferCycle();
|
void transferCycle();
|
||||||
void finalCycle();
|
void finalCycle();
|
||||||
public:
|
public:
|
||||||
CDolphinSmashAdapter(CDeviceToken* token);
|
DolphinSmashAdapter(DeviceToken* token);
|
||||||
~CDolphinSmashAdapter();
|
~DolphinSmashAdapter();
|
||||||
|
|
||||||
inline void setCallback(IDolphinSmashAdapterCallback* cb)
|
inline void setCallback(IDolphinSmashAdapterCallback* cb)
|
||||||
{m_callback = cb; m_knownControllers = 0;}
|
{m_callback = cb; m_knownControllers = 0;}
|
|
@ -1,13 +1,12 @@
|
||||||
#ifndef CDUALSHOCKPAD_HPP
|
#ifndef CDUALSHOCKPAD_HPP
|
||||||
#define CDUALSHOCKPAD_HPP
|
#define CDUALSHOCKPAD_HPP
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "CDeviceBase.hpp"
|
#include "DeviceBase.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct DualshockLED
|
||||||
struct SDualshockLED
|
|
||||||
{
|
{
|
||||||
uint8_t timeEnabled;
|
uint8_t timeEnabled;
|
||||||
uint8_t dutyLength;
|
uint8_t dutyLength;
|
||||||
|
@ -16,7 +15,7 @@ struct SDualshockLED
|
||||||
uint8_t dutyOn;
|
uint8_t dutyOn;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDualshockRumble
|
struct DualshockRumble
|
||||||
{
|
{
|
||||||
uint8_t rightDuration;
|
uint8_t rightDuration;
|
||||||
bool rightOn;
|
bool rightOn;
|
||||||
|
@ -24,23 +23,23 @@ struct SDualshockRumble
|
||||||
uint8_t leftForce;
|
uint8_t leftForce;
|
||||||
};
|
};
|
||||||
|
|
||||||
union SDualshockOutReport
|
union DualshockOutReport
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint8_t reportId;
|
uint8_t reportId;
|
||||||
SDualshockRumble rumble;
|
DualshockRumble rumble;
|
||||||
uint8_t gyro1;
|
uint8_t gyro1;
|
||||||
uint8_t gyro2;
|
uint8_t gyro2;
|
||||||
uint8_t padding[2];
|
uint8_t padding[2];
|
||||||
uint8_t leds;
|
uint8_t leds;
|
||||||
SDualshockLED led[4];
|
DualshockLED led[4];
|
||||||
SDualshockLED reserved;
|
DualshockLED reserved;
|
||||||
};
|
};
|
||||||
uint8_t buf[36];
|
uint8_t buf[36];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EDualshockControllerButtons
|
enum EDualshockPadButtons
|
||||||
{
|
{
|
||||||
DS3_SELECT = 1<< 0,
|
DS3_SELECT = 1<< 0,
|
||||||
DS3_L3 = 1<< 1,
|
DS3_L3 = 1<< 1,
|
||||||
|
@ -75,7 +74,7 @@ enum EDualshockLED
|
||||||
DS3_LED_4 = 1<<4
|
DS3_LED_4 = 1<<4
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDualshockControllerState
|
struct DualshockPadState
|
||||||
{
|
{
|
||||||
uint8_t m_reportType;
|
uint8_t m_reportType;
|
||||||
uint8_t m_reserved1;
|
uint8_t m_reserved1;
|
||||||
|
@ -110,33 +109,33 @@ struct SDualshockControllerState
|
||||||
float gyroZ;
|
float gyroZ;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDualshockController;
|
class DualshockPad;
|
||||||
struct IDualshockControllerCallback
|
struct IDualshockPadCallback
|
||||||
{
|
{
|
||||||
CDualshockController* ctrl = nullptr;
|
DualshockPad* ctrl = nullptr;
|
||||||
virtual void controllerDisconnected() {}
|
virtual void controllerDisconnected() {}
|
||||||
virtual void controllerUpdate(const SDualshockControllerState&) {}
|
virtual void controllerUpdate(const DualshockPadState&) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDualshockController final : public CDeviceBase
|
class DualshockPad final : public DeviceBase
|
||||||
{
|
{
|
||||||
IDualshockControllerCallback* m_callback;
|
IDualshockPadCallback* m_callback;
|
||||||
uint8_t m_rumbleRequest;
|
uint8_t m_rumbleRequest;
|
||||||
uint8_t m_rumbleState;
|
uint8_t m_rumbleState;
|
||||||
uint8_t m_rumbleDuration[2];
|
uint8_t m_rumbleDuration[2];
|
||||||
uint8_t m_rumbleIntensity[2];
|
uint8_t m_rumbleIntensity[2];
|
||||||
uint8_t m_led;
|
uint8_t m_led;
|
||||||
SDualshockOutReport m_report;
|
DualshockOutReport m_report;
|
||||||
uint8_t m_btAddress[6];
|
uint8_t m_btAddress[6];
|
||||||
void deviceDisconnected();
|
void deviceDisconnected();
|
||||||
void initialCycle();
|
void initialCycle();
|
||||||
void transferCycle();
|
void transferCycle();
|
||||||
void finalCycle();
|
void finalCycle();
|
||||||
public:
|
public:
|
||||||
CDualshockController(CDeviceToken* token);
|
DualshockPad(DeviceToken* token);
|
||||||
~CDualshockController();
|
~DualshockPad();
|
||||||
|
|
||||||
inline void setCallback(IDualshockControllerCallback* cb)
|
inline void setCallback(IDualshockPadCallback* cb)
|
||||||
{ m_callback = cb; if (m_callback) m_callback->ctrl = this; }
|
{ m_callback = cb; if (m_callback) m_callback->ctrl = this; }
|
||||||
|
|
||||||
inline void startRumble(int motor, uint8_t duration = 254, uint8_t intensity=255)
|
inline void startRumble(int motor, uint8_t duration = 254, uint8_t intensity=255)
|
|
@ -1,16 +1,16 @@
|
||||||
#ifndef CGENERICPAD_HPP
|
#ifndef CGENERICPAD_HPP
|
||||||
#define CGENERICPAD_HPP
|
#define CGENERICPAD_HPP
|
||||||
|
|
||||||
#include "CDeviceBase.hpp"
|
#include "DeviceBase.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
class CGenericPad final : public CDeviceBase
|
class GenericPad final : public DeviceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CGenericPad(CDeviceToken* token);
|
GenericPad(DeviceToken* token);
|
||||||
~CGenericPad();
|
~GenericPad();
|
||||||
|
|
||||||
void deviceDisconnected();
|
void deviceDisconnected();
|
||||||
};
|
};
|
|
@ -3,14 +3,14 @@
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "CDeviceToken.hpp"
|
#include "DeviceToken.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef std::unordered_map<std::string, CDeviceToken> TDeviceTokens;
|
typedef std::unordered_map<std::string, DeviceToken> TDeviceTokens;
|
||||||
typedef std::pair<TDeviceTokens::iterator, bool> TInsertedDeviceToken;
|
typedef std::pair<TDeviceTokens::iterator, bool> TInsertedDeviceToken;
|
||||||
class CDeviceFinder;
|
class DeviceFinder;
|
||||||
|
|
||||||
class IHIDListener
|
class IHIDListener
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Platform-specific constructor */
|
/* Platform-specific constructor */
|
||||||
IHIDListener* IHIDListenerNew(CDeviceFinder& finder);
|
IHIDListener* IHIDListenerNew(DeviceFinder& finder);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef SDeviceSignature_HPP
|
|
||||||
#define SDeviceSignature_HPP
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
namespace boo
|
|
||||||
{
|
|
||||||
|
|
||||||
class CDeviceToken;
|
|
||||||
class CDeviceBase;
|
|
||||||
|
|
||||||
struct SDeviceSignature
|
|
||||||
{
|
|
||||||
typedef std::vector<const SDeviceSignature*> TDeviceSignatureSet;
|
|
||||||
typedef std::function<CDeviceBase*(CDeviceToken*)> TFactoryLambda;
|
|
||||||
const char* m_name;
|
|
||||||
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) {}
|
|
||||||
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);})
|
|
||||||
#define DEVICE_SIG_SENTINEL() SDeviceSignature()
|
|
||||||
|
|
||||||
extern const SDeviceSignature BOO_DEVICE_SIGS[];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SDeviceSignature_HPP
|
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
#ifndef CCGLCONTEXT_HPP
|
|
||||||
#define CCGLCONTEXT_HPP
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include "IGraphicsContext.hpp"
|
|
||||||
#include <OpenGL/OpenGL.h>
|
|
||||||
|
|
||||||
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
|
|
|
@ -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
|
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef CGLXCONTEXT_HPP
|
|
||||||
#define CGLXCONTEXT_HPP
|
|
||||||
|
|
||||||
#if !defined(__APPLE__) && (defined(__linux__) || defined(BSD))
|
|
||||||
#include <GL/glx.h>
|
|
||||||
#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
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include "boo/inputdev/CafeProPad.hpp"
|
|
@ -0,0 +1,73 @@
|
||||||
|
#include "boo/inputdev/DeviceBase.hpp"
|
||||||
|
#include "boo/inputdev/DeviceToken.hpp"
|
||||||
|
#include "IHIDDevice.hpp"
|
||||||
|
#include <cstdarg>
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
|
||||||
|
DeviceBase::DeviceBase(DeviceToken* token)
|
||||||
|
: m_token(token), m_hidDev(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceBase::~DeviceBase()
|
||||||
|
{
|
||||||
|
delete m_hidDev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceBase::_deviceDisconnected()
|
||||||
|
{
|
||||||
|
deviceDisconnected();
|
||||||
|
m_token = NULL;
|
||||||
|
if (m_hidDev)
|
||||||
|
{
|
||||||
|
m_hidDev->_deviceDisconnected();
|
||||||
|
delete m_hidDev;
|
||||||
|
m_hidDev = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceBase::closeDevice()
|
||||||
|
{
|
||||||
|
if (m_token)
|
||||||
|
m_token->_deviceClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceBase::deviceError(const char* error, ...)
|
||||||
|
{
|
||||||
|
va_list vl;
|
||||||
|
va_start(vl, error);
|
||||||
|
vfprintf(stderr, error, vl);
|
||||||
|
va_end(vl);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeviceBase::sendUSBInterruptTransfer(const uint8_t* data, size_t length)
|
||||||
|
{
|
||||||
|
if (m_hidDev)
|
||||||
|
return m_hidDev->_sendUSBInterruptTransfer(data, length);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DeviceBase::receiveUSBInterruptTransfer(uint8_t* data, size_t length)
|
||||||
|
{
|
||||||
|
if (m_hidDev)
|
||||||
|
return m_hidDev->_receiveUSBInterruptTransfer(data, length);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeviceBase::sendHIDReport(const uint8_t* data, size_t length, uint16_t message)
|
||||||
|
{
|
||||||
|
if (m_hidDev)
|
||||||
|
return m_hidDev->_sendHIDReport(data, length, message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DeviceBase::receiveReport(uint8_t* data, size_t length, uint16_t message)
|
||||||
|
{
|
||||||
|
if (m_hidDev)
|
||||||
|
return m_hidDev->_recieveReport(data, length, message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,19 +1,19 @@
|
||||||
#include "inputdev/SDeviceSignature.hpp"
|
#include "boo/inputdev/DeviceSignature.hpp"
|
||||||
#include "inputdev/CDeviceToken.hpp"
|
#include "boo/inputdev/DeviceToken.hpp"
|
||||||
#include "inputdev/CGenericPad.hpp"
|
#include "boo/inputdev/GenericPad.hpp"
|
||||||
#include "IHIDDevice.hpp"
|
#include "IHIDDevice.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
extern const SDeviceSignature BOO_DEVICE_SIGS[];
|
extern const DeviceSignature BOO_DEVICE_SIGS[];
|
||||||
|
|
||||||
|
|
||||||
bool SDeviceSignature::DeviceMatchToken(const CDeviceToken& token, const TDeviceSignatureSet& sigSet)
|
bool DeviceSignature::DeviceMatchToken(const DeviceToken& token, const TDeviceSignatureSet& sigSet)
|
||||||
{
|
{
|
||||||
if (token.getDeviceType() == CDeviceToken::DEVTYPE_GENERICHID)
|
if (token.getDeviceType() == DeviceToken::DEVTYPE_GENERICHID)
|
||||||
return true;
|
return true;
|
||||||
for (const SDeviceSignature* sig : sigSet)
|
for (const DeviceSignature* sig : sigSet)
|
||||||
{
|
{
|
||||||
if (sig->m_vid == token.getVendorId() && sig->m_pid == token.getProductId())
|
if (sig->m_vid == token.getVendorId() && sig->m_pid == token.getProductId())
|
||||||
return true;
|
return true;
|
||||||
|
@ -21,15 +21,15 @@ bool SDeviceSignature::DeviceMatchToken(const CDeviceToken& token, const TDevice
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp);
|
IHIDDevice* IHIDDeviceNew(DeviceToken& token, DeviceBase& devImp);
|
||||||
CDeviceBase* SDeviceSignature::DeviceNew(CDeviceToken& token)
|
DeviceBase* DeviceSignature::DeviceNew(DeviceToken& token)
|
||||||
{
|
{
|
||||||
CDeviceBase* retval = NULL;
|
DeviceBase* retval = NULL;
|
||||||
|
|
||||||
/* Early-return for generic HID devices */
|
/* Early-return for generic HID devices */
|
||||||
if (token.getDeviceType() == CDeviceToken::DEVTYPE_GENERICHID)
|
if (token.getDeviceType() == DeviceToken::DEVTYPE_GENERICHID)
|
||||||
{
|
{
|
||||||
retval = new CGenericPad(&token);
|
retval = new GenericPad(&token);
|
||||||
if (!retval)
|
if (!retval)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ CDeviceBase* SDeviceSignature::DeviceNew(CDeviceToken& token)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise perform signature-matching to find the appropriate device-factory */
|
/* Otherwise perform signature-matching to find the appropriate device-factory */
|
||||||
const SDeviceSignature* foundSig = NULL;
|
const DeviceSignature* foundSig = NULL;
|
||||||
const SDeviceSignature* sigIter = BOO_DEVICE_SIGS;
|
const DeviceSignature* sigIter = BOO_DEVICE_SIGS;
|
||||||
unsigned targetVid = token.getVendorId();
|
unsigned targetVid = token.getVendorId();
|
||||||
unsigned targetPid = token.getProductId();
|
unsigned targetPid = token.getProductId();
|
||||||
while (sigIter->m_name)
|
while (sigIter->m_name)
|
|
@ -1,4 +1,4 @@
|
||||||
#include "inputdev/CDolphinSmashAdapter.hpp"
|
#include "boo/inputdev/DolphinSmashAdapter.hpp"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ namespace boo
|
||||||
* Reference: https://github.com/ToadKing/wii-u-gc-adapter/blob/master/wii-u-gc-adapter.c
|
* Reference: https://github.com/ToadKing/wii-u-gc-adapter/blob/master/wii-u-gc-adapter.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CDolphinSmashAdapter::CDolphinSmashAdapter(CDeviceToken* token)
|
DolphinSmashAdapter::DolphinSmashAdapter(DeviceToken* token)
|
||||||
: CDeviceBase(token),
|
: DeviceBase(token),
|
||||||
m_callback(NULL),
|
m_callback(NULL),
|
||||||
m_knownControllers(0),
|
m_knownControllers(0),
|
||||||
m_rumbleRequest(0),
|
m_rumbleRequest(0),
|
||||||
|
@ -18,7 +18,7 @@ CDolphinSmashAdapter::CDolphinSmashAdapter(CDeviceToken* token)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CDolphinSmashAdapter::~CDolphinSmashAdapter()
|
DolphinSmashAdapter::~DolphinSmashAdapter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,9 +36,9 @@ static inline EDolphinControllerType parseType(unsigned char status)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline EDolphinControllerType
|
static inline EDolphinControllerType
|
||||||
parseState(SDolphinControllerState* stateOut, uint8_t* payload, bool& rumble)
|
parseState(DolphinControllerState* stateOut, uint8_t* payload, bool& rumble)
|
||||||
{
|
{
|
||||||
memset(stateOut, 0, sizeof(SDolphinControllerState));
|
memset(stateOut, 0, sizeof(DolphinControllerState));
|
||||||
unsigned char status = payload[0];
|
unsigned char status = payload[0];
|
||||||
EDolphinControllerType type = parseType(status);
|
EDolphinControllerType type = parseType(status);
|
||||||
|
|
||||||
|
@ -56,16 +56,16 @@ parseState(SDolphinControllerState* stateOut, uint8_t* payload, bool& rumble)
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDolphinSmashAdapter::initialCycle()
|
void DolphinSmashAdapter::initialCycle()
|
||||||
{
|
{
|
||||||
uint8_t handshakePayload[] = {0x13};
|
uint8_t handshakePayload[] = {0x13};
|
||||||
sendUSBInterruptTransfer(0, handshakePayload, sizeof(handshakePayload));
|
sendUSBInterruptTransfer(handshakePayload, sizeof(handshakePayload));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDolphinSmashAdapter::transferCycle()
|
void DolphinSmashAdapter::transferCycle()
|
||||||
{
|
{
|
||||||
uint8_t payload[37];
|
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)
|
if (recvSz != 37 || payload[0] != 0x21)
|
||||||
return;
|
return;
|
||||||
//printf("RECEIVED DATA %zu %02X\n", recvSz, payload[0]);
|
//printf("RECEIVED DATA %zu %02X\n", recvSz, payload[0]);
|
||||||
|
@ -78,7 +78,7 @@ void CDolphinSmashAdapter::transferCycle()
|
||||||
uint8_t rumbleMask = 0;
|
uint8_t rumbleMask = 0;
|
||||||
for (int i=0 ; i<4 ; i++, controller += 9)
|
for (int i=0 ; i<4 ; i++, controller += 9)
|
||||||
{
|
{
|
||||||
SDolphinControllerState state;
|
DolphinControllerState state;
|
||||||
bool rumble = false;
|
bool rumble = false;
|
||||||
EDolphinControllerType type = parseState(&state, controller, rumble);
|
EDolphinControllerType type = parseState(&state, controller, rumble);
|
||||||
if (type && !(m_knownControllers & 1<<i))
|
if (type && !(m_knownControllers & 1<<i))
|
||||||
|
@ -104,18 +104,18 @@ void CDolphinSmashAdapter::transferCycle()
|
||||||
for (int i=0 ; i<4 ; ++i)
|
for (int i=0 ; i<4 ; ++i)
|
||||||
rumbleMessage[i+1] = (rumbleReq & 1<<i);
|
rumbleMessage[i+1] = (rumbleReq & 1<<i);
|
||||||
|
|
||||||
sendUSBInterruptTransfer(0, rumbleMessage, sizeof(rumbleMessage));
|
sendUSBInterruptTransfer(rumbleMessage, sizeof(rumbleMessage));
|
||||||
m_rumbleState = rumbleReq;
|
m_rumbleState = rumbleReq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDolphinSmashAdapter::finalCycle()
|
void DolphinSmashAdapter::finalCycle()
|
||||||
{
|
{
|
||||||
uint8_t rumbleMessage[5] = {0x11, 0, 0, 0, 0};
|
uint8_t rumbleMessage[5] = {0x11, 0, 0, 0, 0};
|
||||||
sendUSBInterruptTransfer(0, rumbleMessage, sizeof(rumbleMessage));
|
sendUSBInterruptTransfer(rumbleMessage, sizeof(rumbleMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDolphinSmashAdapter::deviceDisconnected()
|
void DolphinSmashAdapter::deviceDisconnected()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
#include "inputdev/CDualshockPad.hpp"
|
#include "boo/inputdev/DualshockPad.hpp"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -38,8 +38,8 @@ static const uint8_t defaultReport[35] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
CDualshockController::CDualshockController(CDeviceToken* token)
|
DualshockPad::DualshockPad(DeviceToken* token)
|
||||||
: CDeviceBase(token),
|
: DeviceBase(token),
|
||||||
m_callback(nullptr),
|
m_callback(nullptr),
|
||||||
m_rumbleRequest(0),
|
m_rumbleRequest(0),
|
||||||
m_rumbleState(0)
|
m_rumbleState(0)
|
||||||
|
@ -47,18 +47,18 @@ CDualshockController::CDualshockController(CDeviceToken* token)
|
||||||
memcpy(m_report.buf, defaultReport, 35);
|
memcpy(m_report.buf, defaultReport, 35);
|
||||||
}
|
}
|
||||||
|
|
||||||
CDualshockController::~CDualshockController()
|
DualshockPad::~DualshockPad()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDualshockController::deviceDisconnected()
|
void DualshockPad::deviceDisconnected()
|
||||||
{
|
{
|
||||||
if (m_callback)
|
if (m_callback)
|
||||||
m_callback->controllerDisconnected();
|
m_callback->controllerDisconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDualshockController::initialCycle()
|
void DualshockPad::initialCycle()
|
||||||
{
|
{
|
||||||
uint8_t setupCommand[4] = {0x42, 0x0c, 0x00, 0x00}; //Tells controller to start sending changes on in pipe
|
uint8_t setupCommand[4] = {0x42, 0x0c, 0x00, 0x00}; //Tells controller to start sending changes on in pipe
|
||||||
if (!sendHIDReport(setupCommand, sizeof(setupCommand), 0x03F4))
|
if (!sendHIDReport(setupCommand, sizeof(setupCommand), 0x03F4))
|
||||||
|
@ -72,14 +72,12 @@ void CDualshockController::initialCycle()
|
||||||
m_btAddress[5 - i] = btAddr[i + 2]; // Copy into buffer reversed, so it is LSB first
|
m_btAddress[5 - i] = btAddr[i + 2]; // Copy into buffer reversed, so it is LSB first
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDualshockController::transferCycle()
|
void DualshockPad::transferCycle()
|
||||||
{
|
{
|
||||||
SDualshockControllerState state;
|
DualshockControllerState state;
|
||||||
size_t recvSz = receiveUSBInterruptTransfer(0, (uint8_t*)&state, 49);
|
size_t recvSz = receiveUSBInterruptTransfer((uint8_t*)&state, 49);
|
||||||
if (recvSz != 49)
|
if (recvSz != 49)
|
||||||
return;
|
return;
|
||||||
printf("\x1B[2J\x1B[H");
|
|
||||||
hexdump(&state, 49);
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
state.m_accelerometer[i] = be16toh(state.m_accelerometer[i]);
|
state.m_accelerometer[i] = be16toh(state.m_accelerometer[i]);
|
||||||
|
@ -132,7 +130,7 @@ void CDualshockController::transferCycle()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDualshockController::finalCycle()
|
void DualshockPad::finalCycle()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "boo/inputdev/GenericPad.hpp"
|
||||||
|
#include "boo/inputdev/DeviceToken.hpp"
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
|
||||||
|
GenericPad::GenericPad(DeviceToken* token)
|
||||||
|
: DeviceBase(token)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericPad::~GenericPad()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenericPad::deviceDisconnected()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
|
||||||
std::condition_variable m_initCond;
|
std::condition_variable m_initCond;
|
||||||
std::thread* m_thread;
|
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)
|
if (m_usbIntf)
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
|
||||||
return false;
|
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)
|
if (m_usbIntf)
|
||||||
{
|
{
|
|
@ -1,10 +1,11 @@
|
||||||
#include "IHIDDevice.hpp"
|
#include "IHIDDevice.hpp"
|
||||||
#include "inputdev/CDeviceToken.hpp"
|
#include "boo/inputdev/DeviceToken.hpp"
|
||||||
#include "inputdev/CDeviceBase.hpp"
|
#include "boo/inputdev/DeviceBase.hpp"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
#include <stropts.h>
|
#include <stropts.h>
|
||||||
#include <linux/usb/ch9.h>
|
#include <linux/usb/ch9.h>
|
||||||
|
@ -23,10 +24,10 @@ udev* GetUdev();
|
||||||
* Reference: http://tali.admingilde.org/linux-docbook/usb/ch07s06.html
|
* Reference: http://tali.admingilde.org/linux-docbook/usb/ch07s06.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class CHIDDeviceUdev final : public IHIDDevice
|
class HIDDeviceUdev final : public IHIDDevice
|
||||||
{
|
{
|
||||||
CDeviceToken& m_token;
|
DeviceToken& m_token;
|
||||||
CDeviceBase& m_devImp;
|
DeviceBase& m_devImp;
|
||||||
|
|
||||||
int m_devFd = 0;
|
int m_devFd = 0;
|
||||||
unsigned m_usbIntfInPipe = 0;
|
unsigned m_usbIntfInPipe = 0;
|
||||||
|
@ -38,7 +39,7 @@ class CHIDDeviceUdev final : public IHIDDevice
|
||||||
std::condition_variable m_initCond;
|
std::condition_variable m_initCond;
|
||||||
std::thread* m_thread;
|
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)
|
if (m_devFd)
|
||||||
{
|
{
|
||||||
|
@ -57,7 +58,7 @@ class CHIDDeviceUdev final : public IHIDDevice
|
||||||
return false;
|
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)
|
if (m_devFd)
|
||||||
{
|
{
|
||||||
|
@ -73,7 +74,7 @@ class CHIDDeviceUdev final : public IHIDDevice
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _threadProcUSBLL(CHIDDeviceUdev* device)
|
static void _threadProcUSBLL(HIDDeviceUdev* device)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
char errStr[256];
|
char errStr[256];
|
||||||
|
@ -93,22 +94,22 @@ class CHIDDeviceUdev final : public IHIDDevice
|
||||||
udev_device_unref(udevDev);
|
udev_device_unref(udevDev);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
usb_device_descriptor devDesc = {0};
|
usb_device_descriptor devDesc = {};
|
||||||
read(device->m_devFd, &devDesc, 1);
|
read(device->m_devFd, &devDesc, 1);
|
||||||
read(device->m_devFd, &devDesc.bDescriptorType, devDesc.bLength-1);
|
read(device->m_devFd, &devDesc.bDescriptorType, devDesc.bLength-1);
|
||||||
if (devDesc.bNumConfigurations)
|
if (devDesc.bNumConfigurations)
|
||||||
{
|
{
|
||||||
usb_config_descriptor confDesc = {0};
|
usb_config_descriptor confDesc = {};
|
||||||
read(device->m_devFd, &confDesc, 1);
|
read(device->m_devFd, &confDesc, 1);
|
||||||
read(device->m_devFd, &confDesc.bDescriptorType, confDesc.bLength-1);
|
read(device->m_devFd, &confDesc.bDescriptorType, confDesc.bLength-1);
|
||||||
if (confDesc.bNumInterfaces)
|
if (confDesc.bNumInterfaces)
|
||||||
{
|
{
|
||||||
usb_interface_descriptor intfDesc = {0};
|
usb_interface_descriptor intfDesc = {};
|
||||||
read(device->m_devFd, &intfDesc, 1);
|
read(device->m_devFd, &intfDesc, 1);
|
||||||
read(device->m_devFd, &intfDesc.bDescriptorType, intfDesc.bLength-1);
|
read(device->m_devFd, &intfDesc.bDescriptorType, intfDesc.bLength-1);
|
||||||
for (i=0 ; i<intfDesc.bNumEndpoints+1 ; ++i)
|
for (i=0 ; i<intfDesc.bNumEndpoints+1 ; ++i)
|
||||||
{
|
{
|
||||||
usb_endpoint_descriptor endpDesc = {0};
|
usb_endpoint_descriptor endpDesc = {};
|
||||||
read(device->m_devFd, &endpDesc, 1);
|
read(device->m_devFd, &endpDesc, 1);
|
||||||
read(device->m_devFd, &endpDesc.bDescriptorType, endpDesc.bLength-1);
|
read(device->m_devFd, &endpDesc.bDescriptorType, endpDesc.bLength-1);
|
||||||
if ((endpDesc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
|
if ((endpDesc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
|
||||||
|
@ -148,7 +149,7 @@ class CHIDDeviceUdev final : public IHIDDevice
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _threadProcBTLL(CHIDDeviceUdev* device)
|
static void _threadProcBTLL(HIDDeviceUdev* device)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
||||||
udev_device* udevDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.c_str());
|
udev_device* udevDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.c_str());
|
||||||
|
@ -167,7 +168,7 @@ class CHIDDeviceUdev final : public IHIDDevice
|
||||||
udev_device_unref(udevDev);
|
udev_device_unref(udevDev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _threadProcHID(CHIDDeviceUdev* device)
|
static void _threadProcHID(HIDDeviceUdev* device)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
||||||
udev_device* udevDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.c_str());
|
udev_device* udevDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.c_str());
|
||||||
|
@ -234,26 +235,29 @@ class CHIDDeviceUdev final : public IHIDDevice
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CHIDDeviceUdev(CDeviceToken& token, CDeviceBase& devImp)
|
HIDDeviceUdev(DeviceToken& token, DeviceBase& devImp)
|
||||||
: m_token(token),
|
: m_token(token),
|
||||||
m_devImp(devImp),
|
m_devImp(devImp),
|
||||||
m_devPath(token.getDevicePath())
|
m_devPath(token.getDevicePath())
|
||||||
{
|
{
|
||||||
devImp.m_hidDev = this;
|
devImp.m_hidDev = this;
|
||||||
std::unique_lock<std::mutex> lk(m_initMutex);
|
std::unique_lock<std::mutex> lk(m_initMutex);
|
||||||
CDeviceToken::TDeviceType dType = token.getDeviceType();
|
DeviceToken::TDeviceType dType = token.getDeviceType();
|
||||||
if (dType == CDeviceToken::DEVTYPE_USB)
|
if (dType == DeviceToken::DEVTYPE_USB)
|
||||||
m_thread = new std::thread(_threadProcUSBLL, this);
|
m_thread = new std::thread(_threadProcUSBLL, this);
|
||||||
else if (dType == CDeviceToken::DEVTYPE_BLUETOOTH)
|
else if (dType == DeviceToken::DEVTYPE_BLUETOOTH)
|
||||||
m_thread = new std::thread(_threadProcBTLL, this);
|
m_thread = new std::thread(_threadProcBTLL, this);
|
||||||
else if (dType == CDeviceToken::DEVTYPE_GENERICHID)
|
else if (dType == DeviceToken::DEVTYPE_GENERICHID)
|
||||||
m_thread = new std::thread(_threadProcHID, this);
|
m_thread = new std::thread(_threadProcHID, this);
|
||||||
else
|
else
|
||||||
throw std::runtime_error("invalid token supplied to device constructor");
|
{
|
||||||
|
fprintf(stderr, "invalid token supplied to device constructor");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
m_initCond.wait(lk);
|
m_initCond.wait(lk);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CHIDDeviceUdev()
|
~HIDDeviceUdev()
|
||||||
{
|
{
|
||||||
m_runningTransferLoop = false;
|
m_runningTransferLoop = false;
|
||||||
m_thread->join();
|
m_thread->join();
|
||||||
|
@ -263,9 +267,9 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp)
|
IHIDDevice* IHIDDeviceNew(DeviceToken& token, DeviceBase& devImp)
|
||||||
{
|
{
|
||||||
return new CHIDDeviceUdev(token, devImp);
|
return new HIDDeviceUdev(token, devImp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -33,7 +33,7 @@ class CHIDDeviceWinUSB final : public IHIDDevice
|
||||||
std::condition_variable m_initCond;
|
std::condition_variable m_initCond;
|
||||||
std::thread* m_thread;
|
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)
|
if (m_usbHandle)
|
||||||
{
|
{
|
||||||
|
@ -47,7 +47,7 @@ class CHIDDeviceWinUSB final : public IHIDDevice
|
||||||
return false;
|
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)
|
if (m_usbHandle)
|
||||||
{
|
{
|
|
@ -1,7 +1,9 @@
|
||||||
#include "inputdev/IHIDListener.hpp"
|
#include "boo/inputdev/IHIDListener.hpp"
|
||||||
#include "inputdev/CDeviceFinder.hpp"
|
#include "boo/inputdev/DeviceFinder.hpp"
|
||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
|
@ -15,16 +17,16 @@ udev* GetUdev()
|
||||||
return UDEV_INST;
|
return UDEV_INST;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CHIDListenerUdev final : public IHIDListener
|
class HIDListenerUdev final : public IHIDListener
|
||||||
{
|
{
|
||||||
CDeviceFinder& m_finder;
|
DeviceFinder& m_finder;
|
||||||
|
|
||||||
udev_monitor* m_udevMon;
|
udev_monitor* m_udevMon;
|
||||||
std::thread* m_udevThread;
|
std::thread* m_udevThread;
|
||||||
bool m_udevRunning;
|
bool m_udevRunning;
|
||||||
bool m_scanningEnabled;
|
bool m_scanningEnabled;
|
||||||
|
|
||||||
static void deviceConnected(CHIDListenerUdev* listener,
|
static void deviceConnected(HIDListenerUdev* listener,
|
||||||
udev_device* device)
|
udev_device* device)
|
||||||
{
|
{
|
||||||
if (!listener->m_scanningEnabled)
|
if (!listener->m_scanningEnabled)
|
||||||
|
@ -32,11 +34,11 @@ class CHIDListenerUdev final : public IHIDListener
|
||||||
|
|
||||||
/* Filter to USB/BT */
|
/* Filter to USB/BT */
|
||||||
const char* dt = udev_device_get_devtype(device);
|
const char* dt = udev_device_get_devtype(device);
|
||||||
CDeviceToken::TDeviceType type;
|
DeviceToken::TDeviceType type;
|
||||||
if (!strcmp(dt, "usb_device"))
|
if (!strcmp(dt, "usb_device"))
|
||||||
type = CDeviceToken::DEVTYPE_USB;
|
type = DeviceToken::DEVTYPE_USB;
|
||||||
else if (!strcmp(dt, "bluetooth_device"))
|
else if (!strcmp(dt, "bluetooth_device"))
|
||||||
type = CDeviceToken::DEVTYPE_BLUETOOTH;
|
type = DeviceToken::DEVTYPE_BLUETOOTH;
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -47,7 +49,7 @@ class CHIDListenerUdev final : public IHIDListener
|
||||||
|
|
||||||
int vid = 0, pid = 0;
|
int vid = 0, pid = 0;
|
||||||
udev_list_entry* attrs = udev_device_get_properties_list_entry(device);
|
udev_list_entry* attrs = udev_device_get_properties_list_entry(device);
|
||||||
#if 1
|
#if 0
|
||||||
udev_list_entry* att = NULL;
|
udev_list_entry* att = NULL;
|
||||||
udev_list_entry_foreach(att, attrs)
|
udev_list_entry_foreach(att, attrs)
|
||||||
{
|
{
|
||||||
|
@ -76,13 +78,13 @@ class CHIDListenerUdev final : public IHIDListener
|
||||||
if (producte)
|
if (producte)
|
||||||
product = udev_list_entry_get_value(producte);
|
product = udev_list_entry_get_value(producte);
|
||||||
|
|
||||||
if (!listener->m_finder._insertToken(CDeviceToken(type, vid, pid, manuf, product, devPath)))
|
if (!listener->m_finder._insertToken(DeviceToken(type, vid, pid, manuf, product, devPath)))
|
||||||
{
|
{
|
||||||
/* Matched-insertion failed; see if generic HID interface is available */
|
/* Matched-insertion failed; see if generic HID interface is available */
|
||||||
udev_list_entry* devInterfaces = NULL;
|
udev_list_entry* devInterfaces = NULL;
|
||||||
if (type == CDeviceToken::DEVTYPE_USB)
|
if (type == DeviceToken::DEVTYPE_USB)
|
||||||
devInterfaces = udev_list_entry_get_by_name(attrs, "ID_USB_INTERFACES");
|
devInterfaces = udev_list_entry_get_by_name(attrs, "ID_USB_INTERFACES");
|
||||||
else if (type == CDeviceToken::DEVTYPE_BLUETOOTH)
|
else if (type == DeviceToken::DEVTYPE_BLUETOOTH)
|
||||||
devInterfaces = udev_list_entry_get_by_name(attrs, "ID_BLUETOOTH_INTERFACES");
|
devInterfaces = udev_list_entry_get_by_name(attrs, "ID_BLUETOOTH_INTERFACES");
|
||||||
if (devInterfaces)
|
if (devInterfaces)
|
||||||
{
|
{
|
||||||
|
@ -100,7 +102,7 @@ class CHIDListenerUdev final : public IHIDListener
|
||||||
{
|
{
|
||||||
const char* hidPath = udev_list_entry_get_name(hidEnt);
|
const char* hidPath = udev_list_entry_get_name(hidEnt);
|
||||||
if (!listener->m_finder._hasToken(hidPath))
|
if (!listener->m_finder._hasToken(hidPath))
|
||||||
listener->m_finder._insertToken(CDeviceToken(CDeviceToken::DEVTYPE_GENERICHID,
|
listener->m_finder._insertToken(DeviceToken(DeviceToken::DEVTYPE_GENERICHID,
|
||||||
vid, pid, manuf, product, hidPath));
|
vid, pid, manuf, product, hidPath));
|
||||||
}
|
}
|
||||||
udev_enumerate_unref(hidEnum);
|
udev_enumerate_unref(hidEnum);
|
||||||
|
@ -109,14 +111,14 @@ class CHIDListenerUdev final : public IHIDListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void deviceDisconnected(CHIDListenerUdev* listener,
|
static void deviceDisconnected(HIDListenerUdev* listener,
|
||||||
udev_device* device)
|
udev_device* device)
|
||||||
{
|
{
|
||||||
const char* devPath = udev_device_get_syspath(device);
|
const char* devPath = udev_device_get_syspath(device);
|
||||||
listener->m_finder._removeToken(devPath);
|
listener->m_finder._removeToken(devPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _udevProc(CHIDListenerUdev* listener)
|
static void _udevProc(HIDListenerUdev* listener)
|
||||||
{
|
{
|
||||||
udev_monitor_enable_receiving(listener->m_udevMon);
|
udev_monitor_enable_receiving(listener->m_udevMon);
|
||||||
int fd = udev_monitor_get_fd(listener->m_udevMon);
|
int fd = udev_monitor_get_fd(listener->m_udevMon);
|
||||||
|
@ -140,14 +142,17 @@ class CHIDListenerUdev final : public IHIDListener
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CHIDListenerUdev(CDeviceFinder& finder)
|
HIDListenerUdev(DeviceFinder& finder)
|
||||||
: m_finder(finder)
|
: m_finder(finder)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Setup hotplug events */
|
/* Setup hotplug events */
|
||||||
m_udevMon = udev_monitor_new_from_netlink(GetUdev(), "udev");
|
m_udevMon = udev_monitor_new_from_netlink(GetUdev(), "udev");
|
||||||
if (!m_udevMon)
|
if (!m_udevMon)
|
||||||
throw std::runtime_error("unable to init udev_monitor");
|
{
|
||||||
|
fprintf(stderr, "unable to init udev_monitor");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "usb", "usb_device");
|
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "usb", "usb_device");
|
||||||
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "bluetooth", "bluetooth_device");
|
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "bluetooth", "bluetooth_device");
|
||||||
udev_monitor_filter_update(m_udevMon);
|
udev_monitor_filter_update(m_udevMon);
|
||||||
|
@ -163,9 +168,10 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~CHIDListenerUdev()
|
~HIDListenerUdev()
|
||||||
{
|
{
|
||||||
m_udevRunning = false;
|
m_udevRunning = false;
|
||||||
|
pthread_kill(m_udevThread->native_handle(), SIGINT);
|
||||||
m_udevThread->join();
|
m_udevThread->join();
|
||||||
delete m_udevThread;
|
delete m_udevThread;
|
||||||
udev_monitor_unref(m_udevMon);
|
udev_monitor_unref(m_udevMon);
|
||||||
|
@ -208,9 +214,9 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IHIDListener* IHIDListenerNew(CDeviceFinder& finder)
|
IHIDListener* IHIDListenerNew(DeviceFinder& finder)
|
||||||
{
|
{
|
||||||
return new CHIDListenerUdev(finder);
|
return new HIDListenerUdev(finder);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,17 +1,17 @@
|
||||||
#ifndef IHIDDEVICE_HPP
|
#ifndef IHIDDEVICE_HPP
|
||||||
#define IHIDDEVICE_HPP
|
#define IHIDDEVICE_HPP
|
||||||
|
|
||||||
#include "inputdev/CDeviceToken.hpp"
|
#include "boo/inputdev/DeviceToken.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
class IHIDDevice
|
class IHIDDevice
|
||||||
{
|
{
|
||||||
friend class CDeviceBase;
|
friend class DeviceBase;
|
||||||
virtual void _deviceDisconnected()=0;
|
virtual void _deviceDisconnected()=0;
|
||||||
virtual bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)=0;
|
virtual bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length)=0;
|
||||||
virtual size_t _receiveUSBInterruptTransfer(uint8_t pipe, 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, uint16_t message)=0;
|
virtual bool _sendHIDReport(const uint8_t* data, size_t length, uint16_t message)=0;
|
||||||
virtual size_t _recieveReport(const uint8_t* data, size_t length, uint16_t message){}
|
virtual size_t _recieveReport(const uint8_t* data, size_t length, uint16_t message){}
|
||||||
public:
|
public:
|
|
@ -0,0 +1 @@
|
||||||
|
#include "boo/inputdev/RevolutionPad.hpp"
|
|
@ -0,0 +1,182 @@
|
||||||
|
#include <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
#include "IApplication.hpp"
|
||||||
|
|
||||||
|
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||||
|
{
|
||||||
|
boo::IApplicationCallback* callback;
|
||||||
|
@public
|
||||||
|
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<std::string> 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<std::string>& 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];
|
||||||
|
appDelegate->aboutPanel = aboutPanel;
|
||||||
|
|
||||||
|
[app run];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void quit()
|
||||||
|
{
|
||||||
|
[NSApp terminate:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getProcessName() const
|
||||||
|
{
|
||||||
|
return m_pname;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string>& 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<std::string>& args)
|
||||||
|
{
|
||||||
|
if (!APP)
|
||||||
|
{
|
||||||
|
if (platform != IApplication::PLAT_COCOA &&
|
||||||
|
platform != IApplication::PLAT_AUTO)
|
||||||
|
return NULL;
|
||||||
|
APP = new CApplicationCocoa(cb, friendlyName, pname, args);
|
||||||
|
}
|
||||||
|
return APP;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,639 @@
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
#include <OpenGL/OpenGL.h>
|
||||||
|
#include <OpenGL/gl3.h>
|
||||||
|
#include "windowsys/IGraphicsContext.hpp"
|
||||||
|
#include "windowsys/IWindow.hpp"
|
||||||
|
|
||||||
|
/* AppKit applies OpenGL much differently than other platforms
|
||||||
|
* the NSOpenGLView class composes together all necessary
|
||||||
|
* OGL context members and provides the necessary event hooks
|
||||||
|
* for KB/Mouse/Touch events
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const NSOpenGLPixelFormatAttribute PF_RGBA8_ATTRS[] =
|
||||||
|
{
|
||||||
|
NSOpenGLPFAAccelerated,
|
||||||
|
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||||
|
NSOpenGLPFADoubleBuffer,
|
||||||
|
NSOpenGLPFAColorSize, 24,
|
||||||
|
NSOpenGLPFAAlphaSize, 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NSOpenGLPixelFormatAttribute PF_RGBA8_Z24_ATTRS[] =
|
||||||
|
{
|
||||||
|
NSOpenGLPFAAccelerated,
|
||||||
|
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||||
|
NSOpenGLPFADoubleBuffer,
|
||||||
|
NSOpenGLPFAColorSize, 24,
|
||||||
|
NSOpenGLPFAAlphaSize, 8,
|
||||||
|
NSOpenGLPFADepthSize, 24,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NSOpenGLPixelFormatAttribute PF_RGBAF32_ATTRS[] =
|
||||||
|
{
|
||||||
|
NSOpenGLPFAAccelerated,
|
||||||
|
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||||
|
NSOpenGLPFADoubleBuffer,
|
||||||
|
NSOpenGLPFAColorFloat,
|
||||||
|
NSOpenGLPFAColorSize, 96,
|
||||||
|
NSOpenGLPFAAlphaSize, 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NSOpenGLPixelFormatAttribute PF_RGBAF32_Z24_ATTRS[] =
|
||||||
|
{
|
||||||
|
NSOpenGLPFAAccelerated,
|
||||||
|
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||||
|
NSOpenGLPFADoubleBuffer,
|
||||||
|
NSOpenGLPFAColorFloat,
|
||||||
|
NSOpenGLPFAColorSize, 96,
|
||||||
|
NSOpenGLPFAAlphaSize, 32,
|
||||||
|
NSOpenGLPFADepthSize, 24,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NSOpenGLPixelFormatAttribute* PF_TABLE[] =
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
PF_RGBA8_ATTRS,
|
||||||
|
PF_RGBA8_Z24_ATTRS,
|
||||||
|
PF_RGBAF32_ATTRS,
|
||||||
|
PF_RGBAF32_Z24_ATTRS
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace boo {class CGraphicsContextCocoa;}
|
||||||
|
@interface CGraphicsContextCocoaInternal : NSOpenGLView
|
||||||
|
{
|
||||||
|
NSUInteger lastModifiers;
|
||||||
|
boo::CGraphicsContextCocoa* booContext;
|
||||||
|
}
|
||||||
|
- (id)initWithBooContext:(boo::CGraphicsContextCocoa*)bctx;
|
||||||
|
@end
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
|
||||||
|
class CGraphicsContextCocoa final : public IGraphicsContext
|
||||||
|
{
|
||||||
|
|
||||||
|
EGraphicsAPI m_api;
|
||||||
|
EPixelFormat m_pf;
|
||||||
|
IWindow* m_parentWindow;
|
||||||
|
CGraphicsContextCocoaInternal* m_nsContext;
|
||||||
|
NSOpenGLContext* m_nsShareContext;
|
||||||
|
|
||||||
|
public:
|
||||||
|
IWindowCallback* m_callback;
|
||||||
|
|
||||||
|
CGraphicsContextCocoa(EGraphicsAPI api, IWindow* parentWindow)
|
||||||
|
: m_api(api),
|
||||||
|
m_pf(PF_RGBA8),
|
||||||
|
m_parentWindow(parentWindow),
|
||||||
|
m_nsContext(NULL),
|
||||||
|
m_nsShareContext(NULL),
|
||||||
|
m_callback(NULL)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~CGraphicsContextCocoa()
|
||||||
|
{
|
||||||
|
[m_nsContext release];
|
||||||
|
[m_nsShareContext release];
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setCallback(IWindowCallback* cb)
|
||||||
|
{
|
||||||
|
m_callback = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
EGraphicsAPI getAPI() const
|
||||||
|
{
|
||||||
|
return m_api;
|
||||||
|
}
|
||||||
|
|
||||||
|
EPixelFormat getPixelFormat() const
|
||||||
|
{
|
||||||
|
return m_pf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPixelFormat(EPixelFormat pf)
|
||||||
|
{
|
||||||
|
if (pf > PF_RGBAF32_Z24)
|
||||||
|
return;
|
||||||
|
m_pf = pf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeContext()
|
||||||
|
{
|
||||||
|
if (m_nsShareContext)
|
||||||
|
return;
|
||||||
|
m_nsContext = [[CGraphicsContextCocoaInternal alloc] initWithBooContext:this];
|
||||||
|
[(NSWindow*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
IGraphicsContext* makeShareContext() const
|
||||||
|
{
|
||||||
|
NSOpenGLContext* nsctx;
|
||||||
|
if (m_nsContext)
|
||||||
|
{
|
||||||
|
nsctx = [[NSOpenGLContext alloc] initWithFormat:[m_nsContext pixelFormat]
|
||||||
|
shareContext:[m_nsContext openGLContext]];
|
||||||
|
}
|
||||||
|
else if (m_nsShareContext)
|
||||||
|
{
|
||||||
|
nsctx = [[NSOpenGLContext alloc] initWithFormat:[m_nsShareContext pixelFormat]
|
||||||
|
shareContext:m_nsShareContext];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
if (!nsctx)
|
||||||
|
return NULL;
|
||||||
|
CGraphicsContextCocoa* newCtx = new CGraphicsContextCocoa(m_api, NULL);
|
||||||
|
newCtx->m_nsShareContext = nsctx;
|
||||||
|
return newCtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeCurrent()
|
||||||
|
{
|
||||||
|
if (m_nsContext)
|
||||||
|
[[m_nsContext openGLContext] makeCurrentContext];
|
||||||
|
else if (m_nsShareContext)
|
||||||
|
[m_nsShareContext makeCurrentContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearCurrent()
|
||||||
|
{
|
||||||
|
[NSOpenGLContext clearCurrentContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
void swapBuffer()
|
||||||
|
{
|
||||||
|
[[m_nsContext openGLContext] flushBuffer];
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IGraphicsContext* _CGraphicsContextCocoaNew(IGraphicsContext::EGraphicsAPI api,
|
||||||
|
IWindow* parentWindow)
|
||||||
|
{
|
||||||
|
if (api != IGraphicsContext::API_OPENGL_3_3 && api != IGraphicsContext::API_OPENGL_4_2)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Create temporary context to query GL version */
|
||||||
|
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_RGBA8_ATTRS];
|
||||||
|
if (!nspf)
|
||||||
|
return NULL;
|
||||||
|
NSOpenGLContext* nsctx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:nil];
|
||||||
|
[nspf release];
|
||||||
|
if (!nsctx)
|
||||||
|
return NULL;
|
||||||
|
[nsctx makeCurrentContext];
|
||||||
|
const char* glVersion = (char*)glGetString(GL_VERSION);
|
||||||
|
unsigned major = 0;
|
||||||
|
unsigned minor = 0;
|
||||||
|
if (glVersion)
|
||||||
|
{
|
||||||
|
major = glVersion[0] - '0';
|
||||||
|
minor = glVersion[2] - '0';
|
||||||
|
}
|
||||||
|
[NSOpenGLContext clearCurrentContext];
|
||||||
|
[nsctx release];
|
||||||
|
if (!glVersion)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (major > 4 || (major == 4 && minor >= 2))
|
||||||
|
api = IGraphicsContext::API_OPENGL_4_2;
|
||||||
|
else if (major == 3 && minor >= 3)
|
||||||
|
if (api == IGraphicsContext::API_OPENGL_4_2)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return new CGraphicsContextCocoa(api, parentWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation CGraphicsContextCocoaInternal
|
||||||
|
- (id)initWithBooContext:(boo::CGraphicsContextCocoa*)bctx
|
||||||
|
{
|
||||||
|
lastModifiers = 0;
|
||||||
|
booContext = bctx;
|
||||||
|
boo::IGraphicsContext::EPixelFormat pf = bctx->getPixelFormat();
|
||||||
|
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[pf]];
|
||||||
|
self = [self initWithFrame:NSMakeRect(0, 0, 100, 100) pixelFormat:nspf];
|
||||||
|
[nspf release];
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)acceptsTouchEvents
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline boo::IWindowCallback::EModifierKey getMod(NSEventModifierFlags flags)
|
||||||
|
{
|
||||||
|
int ret = boo::IWindowCallback::MKEY_NONE;
|
||||||
|
if (flags & NSControlKeyMask)
|
||||||
|
ret |= boo::IWindowCallback::MKEY_CTRL;
|
||||||
|
if (flags & NSAlternateKeyMask)
|
||||||
|
ret |= boo::IWindowCallback::MKEY_ALT;
|
||||||
|
if (flags & NSShiftKeyMask)
|
||||||
|
ret |= boo::IWindowCallback::MKEY_SHIFT;
|
||||||
|
if (flags & NSCommandKeyMask)
|
||||||
|
ret |= boo::IWindowCallback::MKEY_COMMAND;
|
||||||
|
return static_cast<boo::IWindowCallback::EModifierKey>(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline boo::IWindowCallback::EMouseButton getButton(NSEvent* event)
|
||||||
|
{
|
||||||
|
NSInteger buttonNumber = event.buttonNumber;
|
||||||
|
if (buttonNumber == 3)
|
||||||
|
return boo::IWindowCallback::BUTTON_MIDDLE;
|
||||||
|
else if (buttonNumber == 4)
|
||||||
|
return boo::IWindowCallback::BUTTON_AUX1;
|
||||||
|
else if (buttonNumber == 5)
|
||||||
|
return boo::IWindowCallback::BUTTON_AUX2;
|
||||||
|
return boo::IWindowCallback::BUTTON_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseDown:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseDown(coord, boo::IWindowCallback::BUTTON_PRIMARY,
|
||||||
|
getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseUp:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseUp(coord, boo::IWindowCallback::BUTTON_PRIMARY,
|
||||||
|
getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)rightMouseDown:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseDown(coord, boo::IWindowCallback::BUTTON_SECONDARY,
|
||||||
|
getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)rightMouseUp:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseUp(coord, boo::IWindowCallback::BUTTON_SECONDARY,
|
||||||
|
getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)otherMouseDown:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
boo::IWindowCallback::EMouseButton button = getButton(theEvent);
|
||||||
|
if (!button)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseDown(coord, button, getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)otherMouseUp:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
boo::IWindowCallback::EMouseButton button = getButton(theEvent);
|
||||||
|
if (!button)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseUp(coord, button, getMod([theEvent modifierFlags]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseMoved:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||||
|
float pixelFactor = [[self window] backingScaleFactor];
|
||||||
|
NSRect frame = [self frame];
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
|
||||||
|
{(unsigned)liw.x, (unsigned)liw.y},
|
||||||
|
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
|
||||||
|
};
|
||||||
|
booContext->m_callback->mouseMove(coord);
|
||||||
|
}
|
||||||
|
- (void)mouseDragged:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
[self mouseMoved:theEvent];
|
||||||
|
}
|
||||||
|
- (void)rightMouseDragged:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
[self mouseMoved:theEvent];
|
||||||
|
}
|
||||||
|
- (void)otherMouseDragged:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
[self mouseMoved:theEvent];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)scrollWheel:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
boo::IWindowCallback::SScrollDelta scroll =
|
||||||
|
{
|
||||||
|
{(float)[theEvent scrollingDeltaX], (float)[theEvent scrollingDeltaY]},
|
||||||
|
(bool)[theEvent hasPreciseScrollingDeltas]
|
||||||
|
};
|
||||||
|
booContext->m_callback->scroll(scroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesBeganWithEvent:(NSEvent*)event
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseBegan inView:nil])
|
||||||
|
{
|
||||||
|
NSPoint pos = touch.normalizedPosition;
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{0, 0},
|
||||||
|
{0, 0},
|
||||||
|
{(float)pos.x, (float)pos.y}
|
||||||
|
};
|
||||||
|
booContext->m_callback->touchDown(coord, (uintptr_t)touch.identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesEndedWithEvent:(NSEvent*)event
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseEnded inView:nil])
|
||||||
|
{
|
||||||
|
NSPoint pos = touch.normalizedPosition;
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{0, 0},
|
||||||
|
{0, 0},
|
||||||
|
{(float)pos.x, (float)pos.y}
|
||||||
|
};
|
||||||
|
booContext->m_callback->touchUp(coord, (uintptr_t)touch.identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesMovedWithEvent:(NSEvent*)event
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseMoved inView:nil])
|
||||||
|
{
|
||||||
|
NSPoint pos = touch.normalizedPosition;
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{0, 0},
|
||||||
|
{0, 0},
|
||||||
|
{(float)pos.x, (float)pos.y}
|
||||||
|
};
|
||||||
|
booContext->m_callback->touchMove(coord, (uintptr_t)touch.identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesCancelledWithEvent:(NSEvent*)event
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseCancelled inView:nil])
|
||||||
|
{
|
||||||
|
NSPoint pos = touch.normalizedPosition;
|
||||||
|
boo::IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{0, 0},
|
||||||
|
{0, 0},
|
||||||
|
{(float)pos.x, (float)pos.y}
|
||||||
|
};
|
||||||
|
booContext->m_callback->touchUp(coord, (uintptr_t)touch.identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* keycodes for keys that are independent of keyboard layout*/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kVK_Return = 0x24,
|
||||||
|
kVK_Tab = 0x30,
|
||||||
|
kVK_Space = 0x31,
|
||||||
|
kVK_Delete = 0x33,
|
||||||
|
kVK_Escape = 0x35,
|
||||||
|
kVK_Command = 0x37,
|
||||||
|
kVK_Shift = 0x38,
|
||||||
|
kVK_CapsLock = 0x39,
|
||||||
|
kVK_Option = 0x3A,
|
||||||
|
kVK_Control = 0x3B,
|
||||||
|
kVK_RightShift = 0x3C,
|
||||||
|
kVK_RightOption = 0x3D,
|
||||||
|
kVK_RightControl = 0x3E,
|
||||||
|
kVK_Function = 0x3F,
|
||||||
|
kVK_F17 = 0x40,
|
||||||
|
kVK_VolumeUp = 0x48,
|
||||||
|
kVK_VolumeDown = 0x49,
|
||||||
|
kVK_Mute = 0x4A,
|
||||||
|
kVK_F18 = 0x4F,
|
||||||
|
kVK_F19 = 0x50,
|
||||||
|
kVK_F20 = 0x5A,
|
||||||
|
kVK_F5 = 0x60,
|
||||||
|
kVK_F6 = 0x61,
|
||||||
|
kVK_F7 = 0x62,
|
||||||
|
kVK_F3 = 0x63,
|
||||||
|
kVK_F8 = 0x64,
|
||||||
|
kVK_F9 = 0x65,
|
||||||
|
kVK_F11 = 0x67,
|
||||||
|
kVK_F13 = 0x69,
|
||||||
|
kVK_F16 = 0x6A,
|
||||||
|
kVK_F14 = 0x6B,
|
||||||
|
kVK_F10 = 0x6D,
|
||||||
|
kVK_F12 = 0x6F,
|
||||||
|
kVK_F15 = 0x71,
|
||||||
|
kVK_Help = 0x72,
|
||||||
|
kVK_Home = 0x73,
|
||||||
|
kVK_PageUp = 0x74,
|
||||||
|
kVK_ForwardDelete = 0x75,
|
||||||
|
kVK_F4 = 0x76,
|
||||||
|
kVK_End = 0x77,
|
||||||
|
kVK_F2 = 0x78,
|
||||||
|
kVK_PageDown = 0x79,
|
||||||
|
kVK_F1 = 0x7A,
|
||||||
|
kVK_LeftArrow = 0x7B,
|
||||||
|
kVK_RightArrow = 0x7C,
|
||||||
|
kVK_DownArrow = 0x7D,
|
||||||
|
kVK_UpArrow = 0x7E
|
||||||
|
};
|
||||||
|
static boo::IWindowCallback::ESpecialKey translateKeycode(short code)
|
||||||
|
{
|
||||||
|
switch (code) {
|
||||||
|
case kVK_F1:
|
||||||
|
return boo::IWindowCallback::KEY_F1;
|
||||||
|
case kVK_F2:
|
||||||
|
return boo::IWindowCallback::KEY_F2;
|
||||||
|
case kVK_F3:
|
||||||
|
return boo::IWindowCallback::KEY_F3;
|
||||||
|
case kVK_F4:
|
||||||
|
return boo::IWindowCallback::KEY_F4;
|
||||||
|
case kVK_F5:
|
||||||
|
return boo::IWindowCallback::KEY_F5;
|
||||||
|
case kVK_F6:
|
||||||
|
return boo::IWindowCallback::KEY_F6;
|
||||||
|
case kVK_F7:
|
||||||
|
return boo::IWindowCallback::KEY_F7;
|
||||||
|
case kVK_F8:
|
||||||
|
return boo::IWindowCallback::KEY_F8;
|
||||||
|
case kVK_F9:
|
||||||
|
return boo::IWindowCallback::KEY_F9;
|
||||||
|
case kVK_F10:
|
||||||
|
return boo::IWindowCallback::KEY_F10;
|
||||||
|
case kVK_F11:
|
||||||
|
return boo::IWindowCallback::KEY_F11;
|
||||||
|
case kVK_F12:
|
||||||
|
return boo::IWindowCallback::KEY_F12;
|
||||||
|
case kVK_Escape:
|
||||||
|
return boo::IWindowCallback::KEY_ESC;
|
||||||
|
case kVK_Return:
|
||||||
|
return boo::IWindowCallback::KEY_ENTER;
|
||||||
|
case kVK_Delete:
|
||||||
|
return boo::IWindowCallback::KEY_BACKSPACE;
|
||||||
|
case kVK_ForwardDelete:
|
||||||
|
return boo::IWindowCallback::KEY_DELETE;
|
||||||
|
case kVK_Home:
|
||||||
|
return boo::IWindowCallback::KEY_HOME;
|
||||||
|
case kVK_End:
|
||||||
|
return boo::IWindowCallback::KEY_END;
|
||||||
|
case kVK_PageUp:
|
||||||
|
return boo::IWindowCallback::KEY_PGUP;
|
||||||
|
case kVK_PageDown:
|
||||||
|
return boo::IWindowCallback::KEY_PGDOWN;
|
||||||
|
case kVK_LeftArrow:
|
||||||
|
return boo::IWindowCallback::KEY_LEFT;
|
||||||
|
case kVK_RightArrow:
|
||||||
|
return boo::IWindowCallback::KEY_RIGHT;
|
||||||
|
case kVK_UpArrow:
|
||||||
|
return boo::IWindowCallback::KEY_UP;
|
||||||
|
case kVK_DownArrow:
|
||||||
|
return boo::IWindowCallback::KEY_DOWN;
|
||||||
|
default:
|
||||||
|
return boo::IWindowCallback::KEY_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)keyDown:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSString* chars = theEvent.characters;
|
||||||
|
if ([chars length] == 0)
|
||||||
|
booContext->m_callback->specialKeyDown(translateKeycode(theEvent.keyCode),
|
||||||
|
getMod(theEvent.modifierFlags),
|
||||||
|
theEvent.isARepeat);
|
||||||
|
else
|
||||||
|
booContext->m_callback->charKeyDown([chars characterAtIndex:0],
|
||||||
|
getMod(theEvent.modifierFlags),
|
||||||
|
theEvent.isARepeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)keyUp:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSString* chars = theEvent.characters;
|
||||||
|
if ([chars length] == 0)
|
||||||
|
booContext->m_callback->specialKeyUp(translateKeycode(theEvent.keyCode),
|
||||||
|
getMod(theEvent.modifierFlags));
|
||||||
|
else
|
||||||
|
booContext->m_callback->charKeyUp([chars characterAtIndex:0],
|
||||||
|
getMod(theEvent.modifierFlags));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)flagsChanged:(NSEvent*)theEvent
|
||||||
|
{
|
||||||
|
if (!booContext->m_callback)
|
||||||
|
return;
|
||||||
|
NSUInteger modFlags = theEvent.modifierFlags;
|
||||||
|
bool isRepeat = theEvent.isARepeat;
|
||||||
|
if (modFlags != lastModifiers)
|
||||||
|
{
|
||||||
|
NSUInteger changedFlags = modFlags ^ lastModifiers;
|
||||||
|
|
||||||
|
NSUInteger downFlags = changedFlags & modFlags;
|
||||||
|
if (downFlags & NSControlKeyMask)
|
||||||
|
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_CTRL, isRepeat);
|
||||||
|
if (downFlags & NSAlternateKeyMask)
|
||||||
|
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_ALT, isRepeat);
|
||||||
|
if (downFlags & NSShiftKeyMask)
|
||||||
|
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_SHIFT, isRepeat);
|
||||||
|
if (downFlags & NSCommandKeyMask)
|
||||||
|
booContext->m_callback->modKeyDown(boo::IWindowCallback::MKEY_COMMAND, isRepeat);
|
||||||
|
|
||||||
|
NSUInteger upFlags = changedFlags & ~modFlags;
|
||||||
|
if (upFlags & NSControlKeyMask)
|
||||||
|
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_CTRL);
|
||||||
|
if (upFlags & NSAlternateKeyMask)
|
||||||
|
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_ALT);
|
||||||
|
if (upFlags & NSShiftKeyMask)
|
||||||
|
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_SHIFT);
|
||||||
|
if (upFlags & NSCommandKeyMask)
|
||||||
|
booContext->m_callback->modKeyUp(boo::IWindowCallback::MKEY_COMMAND);
|
||||||
|
|
||||||
|
lastModifiers = modFlags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
|
@ -0,0 +1,180 @@
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
#include "IApplication.hpp"
|
||||||
|
#include "windowsys/IWindow.hpp"
|
||||||
|
#include "windowsys/IGraphicsContext.hpp"
|
||||||
|
|
||||||
|
namespace boo {class CWindowCocoa;}
|
||||||
|
@interface CWindowCocoaInternal : NSWindow
|
||||||
|
{
|
||||||
|
boo::CWindowCocoa* booWindow;
|
||||||
|
}
|
||||||
|
- (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
|
||||||
|
{
|
||||||
|
|
||||||
|
CWindowCocoaInternal* m_nsWindow;
|
||||||
|
IGraphicsContext* m_gfxCtx;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CWindowCocoa(const std::string& title)
|
||||||
|
{
|
||||||
|
m_nsWindow = [[CWindowCocoaInternal alloc] initWithBooWindow:this title:title];
|
||||||
|
m_gfxCtx = _CGraphicsContextCocoaNew(IGraphicsContext::API_OPENGL_3_3, this);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
m_gfxCtx->_setCallback(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
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()] autorelease]];
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
float getVirtualPixelFactor() const
|
||||||
|
{
|
||||||
|
return [m_nsWindow backingScaleFactor];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFullscreen() const
|
||||||
|
{
|
||||||
|
return ([m_nsWindow styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFullscreen(bool fs)
|
||||||
|
{
|
||||||
|
if ((fs && !isFullscreen()) || (!fs && isFullscreen()))
|
||||||
|
[m_nsWindow toggleFullScreen:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
ETouchType getTouchType() const
|
||||||
|
{
|
||||||
|
return TOUCH_TRACKPAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t getPlatformHandle() const
|
||||||
|
{
|
||||||
|
return (uintptr_t)m_nsWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IWindow* _CWindowCocoaNew(const std::string& title)
|
||||||
|
{
|
||||||
|
return new CWindowCocoa(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation CWindowCocoaInternal
|
||||||
|
- (id)initWithBooWindow:(boo::CWindowCocoa *)bw title:(const std::string&)title
|
||||||
|
{
|
||||||
|
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
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS 1 /* STFU MSVC */
|
||||||
|
#define _WIN32_LEAN_AND_MEAN 1
|
||||||
|
#include <windows.h>
|
||||||
|
#include <initguid.h>
|
||||||
|
#include <Usbiodef.h>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#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<std::string> m_args;
|
||||||
|
std::unordered_map<HWND, IWindow*> m_allWindows;
|
||||||
|
bool m_singleInstance;
|
||||||
|
|
||||||
|
void _deletedWindow(IWindow* window)
|
||||||
|
{
|
||||||
|
m_allWindows.erase(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CApplicationWin32(const IApplicationCallback& callback,
|
||||||
|
const std::string& friendlyName,
|
||||||
|
const std::string& pname,
|
||||||
|
const std::vector<std::string>& args,
|
||||||
|
bool singleInstance)
|
||||||
|
: m_callback(callback),
|
||||||
|
m_friendlyName(friendlyName),
|
||||||
|
m_pname(pname),
|
||||||
|
m_args(args),
|
||||||
|
m_singleInstance(singleInstance)
|
||||||
|
{}
|
||||||
|
|
||||||
|
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<std::string>& 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<std::string>& args,
|
||||||
|
bool singleInstance)
|
||||||
|
{
|
||||||
|
if (!APP)
|
||||||
|
{
|
||||||
|
if (platform != IApplication::PLAT_WIN32 &&
|
||||||
|
platform != IApplication::PLAT_AUTO)
|
||||||
|
return NULL;
|
||||||
|
APP = new CApplicationWin32(cb, friendlyName, pname, args, singleInstance);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
#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 initializeContext()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IGraphicsContext* makeShareContext() const
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeCurrent()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearCurrent()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void swapBuffer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IGraphicsContext* _CGraphicsContextWin32New(IGraphicsContext::EGraphicsAPI api,
|
||||||
|
IWindow* parentWindow)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/* Meta-implementation for dynamically-constructing user's preferred
|
||||||
|
* platform interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define APPLICATION_UNIX_CPP
|
||||||
|
#include "ApplicationXCB.hpp"
|
||||||
|
#include "ApplicationWayland.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <dbus/dbus.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
std::unique_ptr<IApplication> ApplicationBootstrap(IApplication::EPlatformType platform,
|
||||||
|
IApplicationCallback& cb,
|
||||||
|
const std::string& uniqueName,
|
||||||
|
const std::string& friendlyName,
|
||||||
|
const std::string& pname,
|
||||||
|
const std::vector<std::string>& args,
|
||||||
|
bool singleInstance)
|
||||||
|
{
|
||||||
|
if (APP)
|
||||||
|
return std::unique_ptr<IApplication>();
|
||||||
|
if (platform == IApplication::PLAT_WAYLAND)
|
||||||
|
APP = new ApplicationWayland(cb, uniqueName, friendlyName, pname, args, singleInstance);
|
||||||
|
else if (platform == IApplication::PLAT_XCB ||
|
||||||
|
platform == IApplication::PLAT_AUTO)
|
||||||
|
APP = new ApplicationXCB(cb, uniqueName, friendlyName, pname, args, singleInstance);
|
||||||
|
else
|
||||||
|
return std::unique_ptr<IApplication>();
|
||||||
|
return std::unique_ptr<IApplication>(APP);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
#ifndef APPLICATION_UNIX_CPP
|
||||||
|
#error This file may only be included from CApplicationUnix.cpp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "boo/IApplication.hpp"
|
||||||
|
|
||||||
|
#include <dbus/dbus.h>
|
||||||
|
DBusConnection* registerDBus(const char* appName, bool& isFirst);
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
|
||||||
|
IWindow* _CWindowWaylandNew(const std::string& title);
|
||||||
|
|
||||||
|
class ApplicationWayland final : public IApplication
|
||||||
|
{
|
||||||
|
IApplicationCallback& m_callback;
|
||||||
|
const std::string m_uniqueName;
|
||||||
|
const std::string m_friendlyName;
|
||||||
|
const std::string m_pname;
|
||||||
|
const std::vector<std::string> m_args;
|
||||||
|
bool m_singleInstance;
|
||||||
|
|
||||||
|
void _deletedWindow(IWindow* window)
|
||||||
|
{
|
||||||
|
(void)window;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ApplicationWayland(IApplicationCallback& callback,
|
||||||
|
const std::string& uniqueName,
|
||||||
|
const std::string& friendlyName,
|
||||||
|
const std::string& pname,
|
||||||
|
const std::vector<std::string>& args,
|
||||||
|
bool singleInstance)
|
||||||
|
: m_callback(callback),
|
||||||
|
m_uniqueName(uniqueName),
|
||||||
|
m_friendlyName(friendlyName),
|
||||||
|
m_pname(pname),
|
||||||
|
m_args(args),
|
||||||
|
m_singleInstance(singleInstance)
|
||||||
|
{}
|
||||||
|
|
||||||
|
EPlatformType getPlatformType() const
|
||||||
|
{
|
||||||
|
return PLAT_WAYLAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void quit()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getUniqueName() const
|
||||||
|
{
|
||||||
|
return m_uniqueName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getFriendlyName() const
|
||||||
|
{
|
||||||
|
return m_friendlyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getProcessName() const
|
||||||
|
{
|
||||||
|
return m_pname;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string>& getArgs() const
|
||||||
|
{
|
||||||
|
return m_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWindow* newWindow(const std::string& title)
|
||||||
|
{
|
||||||
|
return _CWindowWaylandNew(title);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,334 @@
|
||||||
|
#ifndef APPLICATION_UNIX_CPP
|
||||||
|
#error This file may only be included from CApplicationUnix.cpp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "boo/IApplication.hpp"
|
||||||
|
|
||||||
|
#define explicit explicit_c
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_event.h>
|
||||||
|
#include <xkbcommon/xkbcommon-x11.h>
|
||||||
|
#include <xcb/xkb.h>
|
||||||
|
#include <xcb/xinput.h>
|
||||||
|
#undef explicit
|
||||||
|
|
||||||
|
#include <dbus/dbus.h>
|
||||||
|
DBusConnection* registerDBus(const char* appName, bool& isFirst);
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
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->event;
|
||||||
|
}
|
||||||
|
case XCB_KEY_RELEASE:
|
||||||
|
{
|
||||||
|
xcb_key_release_event_t* ev = (xcb_key_release_event_t*)event;
|
||||||
|
windowEvent = true;
|
||||||
|
return ev->event;
|
||||||
|
}
|
||||||
|
case XCB_BUTTON_PRESS:
|
||||||
|
{
|
||||||
|
xcb_button_press_event_t* ev = (xcb_button_press_event_t*)event;
|
||||||
|
windowEvent = true;
|
||||||
|
return ev->event;
|
||||||
|
}
|
||||||
|
case XCB_BUTTON_RELEASE:
|
||||||
|
{
|
||||||
|
xcb_button_release_event_t* ev = (xcb_button_release_event_t*)event;
|
||||||
|
windowEvent = true;
|
||||||
|
return ev->event;
|
||||||
|
}
|
||||||
|
case XCB_MOTION_NOTIFY:
|
||||||
|
{
|
||||||
|
xcb_motion_notify_event_t* ev = (xcb_motion_notify_event_t*)event;
|
||||||
|
windowEvent = true;
|
||||||
|
return ev->event;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
windowEvent = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWindow* _CWindowXCBNew(const std::string& title, xcb_connection_t* conn);
|
||||||
|
|
||||||
|
class ApplicationXCB final : public IApplication
|
||||||
|
{
|
||||||
|
IApplicationCallback& m_callback;
|
||||||
|
const std::string m_uniqueName;
|
||||||
|
const std::string m_friendlyName;
|
||||||
|
const std::string m_pname;
|
||||||
|
const std::vector<std::string> m_args;
|
||||||
|
|
||||||
|
/* DBus single-instance */
|
||||||
|
bool m_singleInstance;
|
||||||
|
DBusConnection* m_dbus = NULL;
|
||||||
|
|
||||||
|
/* All windows */
|
||||||
|
std::unordered_map<xcb_window_t, IWindow*> m_windows;
|
||||||
|
|
||||||
|
xcb_connection_t* m_xcbConn = NULL;
|
||||||
|
bool m_running;
|
||||||
|
|
||||||
|
void _deletedWindow(IWindow* window)
|
||||||
|
{
|
||||||
|
m_windows.erase((xcb_window_t)window->getPlatformHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ApplicationXCB(IApplicationCallback& callback,
|
||||||
|
const std::string& uniqueName,
|
||||||
|
const std::string& friendlyName,
|
||||||
|
const std::string& pname,
|
||||||
|
const std::vector<std::string>& args,
|
||||||
|
bool singleInstance)
|
||||||
|
: m_callback(callback),
|
||||||
|
m_uniqueName(uniqueName),
|
||||||
|
m_friendlyName(friendlyName),
|
||||||
|
m_pname(pname),
|
||||||
|
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
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~ApplicationXCB()
|
||||||
|
{
|
||||||
|
xcb_disconnect(m_xcbConn);
|
||||||
|
}
|
||||||
|
|
||||||
|
EPlatformType getPlatformType() const
|
||||||
|
{
|
||||||
|
return PLAT_XCB;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
if (!m_xcbConn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
xcb_generic_event_t* event;
|
||||||
|
m_running = true;
|
||||||
|
m_callback.appLaunched(this);
|
||||||
|
xcb_flush(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)
|
||||||
|
{
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
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<std::string> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_callback.appQuitting(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void quit()
|
||||||
|
{
|
||||||
|
m_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getUniqueName() const
|
||||||
|
{
|
||||||
|
return m_uniqueName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getFriendlyName() const
|
||||||
|
{
|
||||||
|
return m_friendlyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getProcessName() const
|
||||||
|
{
|
||||||
|
return m_pname;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string>& getArgs() const
|
||||||
|
{
|
||||||
|
return m_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWindow* newWindow(const std::string& title)
|
||||||
|
{
|
||||||
|
IWindow* newWindow = _CWindowXCBNew(title, m_xcbConn);
|
||||||
|
m_windows[(xcb_window_t)newWindow->getPlatformHandle()] = newWindow;
|
||||||
|
return newWindow;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include "boo/IGraphicsContext.hpp"
|
||||||
|
#include "boo/IWindow.hpp"
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
|
||||||
|
struct GraphicsContextWayland : IGraphicsContext
|
||||||
|
{
|
||||||
|
|
||||||
|
EGraphicsAPI m_api;
|
||||||
|
EPixelFormat m_pf;
|
||||||
|
IWindow* m_parentWindow;
|
||||||
|
|
||||||
|
public:
|
||||||
|
IWindowCallback* m_callback;
|
||||||
|
|
||||||
|
GraphicsContextWayland(EGraphicsAPI api, IWindow* parentWindow)
|
||||||
|
: m_api(api),
|
||||||
|
m_pf(PF_RGBA8),
|
||||||
|
m_parentWindow(parentWindow)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~GraphicsContextWayland()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setCallback(IWindowCallback* cb)
|
||||||
|
{
|
||||||
|
m_callback = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
EGraphicsAPI getAPI() const
|
||||||
|
{
|
||||||
|
return m_api;
|
||||||
|
}
|
||||||
|
|
||||||
|
EPixelFormat getPixelFormat() const
|
||||||
|
{
|
||||||
|
return m_pf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPixelFormat(EPixelFormat pf)
|
||||||
|
{
|
||||||
|
if (pf > PF_RGBAF32_Z24)
|
||||||
|
return;
|
||||||
|
m_pf = pf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeContext()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IGraphicsContext* _GraphicsContextWaylandNew(IGraphicsContext::EGraphicsAPI api,
|
||||||
|
IWindow* parentWindow)
|
||||||
|
{
|
||||||
|
return new GraphicsContextWayland(api, parentWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
#include "boo/IGraphicsContext.hpp"
|
||||||
|
#include "boo/IWindow.hpp"
|
||||||
|
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/glx.h>
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#include <GL/glcorearb.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
|
||||||
|
struct GraphicsContextXCB : 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;
|
||||||
|
|
||||||
|
std::thread* m_commandThread = NULL;
|
||||||
|
|
||||||
|
public:
|
||||||
|
IWindowCallback* m_callback;
|
||||||
|
|
||||||
|
GraphicsContextXCB(EGraphicsAPI api, IWindow* parentWindow, xcb_connection_t* conn, uint32_t& visualIdOut)
|
||||||
|
: m_api(api),
|
||||||
|
m_pf(PF_RGBA8),
|
||||||
|
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 ; i<fbconfigs->num_FB_configs ; ++i)
|
||||||
|
{
|
||||||
|
struct conf_prop* configProps = &props[fbconfigs->num_properties * i];
|
||||||
|
uint32_t fbconfId, visualId, depthSize, colorSize, doubleBuffer;
|
||||||
|
for (uint32_t j=0 ; j<fbconfigs->num_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)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "unable to find suitable pixel format");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
visualIdOut = m_visualid;
|
||||||
|
}
|
||||||
|
|
||||||
|
~GraphicsContextXCB()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setCallback(IWindowCallback* cb)
|
||||||
|
{
|
||||||
|
m_callback = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
EGraphicsAPI getAPI() const
|
||||||
|
{
|
||||||
|
return m_api;
|
||||||
|
}
|
||||||
|
|
||||||
|
EPixelFormat getPixelFormat() const
|
||||||
|
{
|
||||||
|
return m_pf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPixelFormat(EPixelFormat pf)
|
||||||
|
{
|
||||||
|
if (pf > PF_RGBAF32_Z24)
|
||||||
|
return;
|
||||||
|
m_pf = pf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeContext()
|
||||||
|
{
|
||||||
|
m_glxWindow = xcb_generate_id(m_xcbConn);
|
||||||
|
xcb_glx_create_window(m_xcbConn, 0, m_fbconfig,
|
||||||
|
m_parentWindow->getPlatformHandle(),
|
||||||
|
m_glxWindow, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IGraphicsContext* _GraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api,
|
||||||
|
IWindow* parentWindow, xcb_connection_t* conn,
|
||||||
|
uint32_t& visualIdOut)
|
||||||
|
{
|
||||||
|
return new GraphicsContextXCB(api, parentWindow, conn, visualIdOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
#include "boo/IWindow.hpp"
|
||||||
|
#include "boo/IGraphicsContext.hpp"
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
|
||||||
|
IGraphicsContext* _CGraphicsContextWaylandNew(IGraphicsContext::EGraphicsAPI api,
|
||||||
|
IWindow* parentWindow);
|
||||||
|
|
||||||
|
struct WindowWayland : IWindow
|
||||||
|
{
|
||||||
|
WindowWayland(const std::string& title)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~WindowWayland()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t getPlatformHandle() const
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ETouchType getTouchType() const
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IWindow* _CWindowWaylandNew(const std::string& title)
|
||||||
|
{
|
||||||
|
return new WindowWayland(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,770 @@
|
||||||
|
#include "boo/IWindow.hpp"
|
||||||
|
#include "boo/IGraphicsContext.hpp"
|
||||||
|
#include "boo/IApplication.hpp"
|
||||||
|
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_event.h>
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
#include <xcb/xcb_keysyms.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <xcb/xinput.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define XK_MISCELLANY
|
||||||
|
#define XK_XKB_KEYS
|
||||||
|
#define XK_LATIN1
|
||||||
|
#include <X11/keysymdef.h>
|
||||||
|
|
||||||
|
#define REF_DPMM 3.7824 /* 96 DPI */
|
||||||
|
#define FS_ATOM "_NET_WM_STATE_FULLSCREEN"
|
||||||
|
|
||||||
|
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;
|
||||||
|
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 detail)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
if (detail == 1)
|
||||||
|
retval = IWindowCallback::BUTTON_PRIMARY;
|
||||||
|
else if (detail == 3)
|
||||||
|
retval = IWindowCallback::BUTTON_SECONDARY;
|
||||||
|
else if (detail == 2)
|
||||||
|
retval = IWindowCallback::BUTTON_MIDDLE;
|
||||||
|
else if (detail == 8)
|
||||||
|
retval = IWindowCallback::BUTTON_AUX1;
|
||||||
|
else if (detail == 9)
|
||||||
|
retval =
|
||||||
|
IWindowCallback::BUTTON_AUX2;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define INTERN_ATOM(var, conn, name, if_exists) \
|
||||||
|
do {\
|
||||||
|
xcb_intern_atom_cookie_t cookie = \
|
||||||
|
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); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
struct XCBAtoms
|
||||||
|
{
|
||||||
|
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_key_symbols_t* m_keySyms = NULL;
|
||||||
|
XCBAtoms(xcb_connection_t* conn)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static XCBAtoms* 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* _GraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api,
|
||||||
|
IWindow* parentWindow, xcb_connection_t* conn,
|
||||||
|
uint32_t& visualIdOut);
|
||||||
|
|
||||||
|
struct WindowXCB : IWindow
|
||||||
|
{
|
||||||
|
xcb_connection_t* m_xcbConn;
|
||||||
|
xcb_window_t m_windowId;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WindowXCB(const std::string& title, xcb_connection_t* conn)
|
||||||
|
: m_xcbConn(conn), m_callback(NULL)
|
||||||
|
{
|
||||||
|
if (!S_ATOMS)
|
||||||
|
S_ATOMS = new XCBAtoms(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 = _GraphicsContextXCBNew(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);
|
||||||
|
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,
|
||||||
|
colormap,
|
||||||
|
XCB_NONE
|
||||||
|
};
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
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] = {
|
||||||
|
S_ATOMS->m_wmDeleteWindow,
|
||||||
|
};
|
||||||
|
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();
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Initialize context */
|
||||||
|
xcb_map_window(m_xcbConn, m_windowId);
|
||||||
|
xcb_flush(m_xcbConn);
|
||||||
|
|
||||||
|
m_gfxCtx->initializeContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
~WindowXCB()
|
||||||
|
{
|
||||||
|
APP->_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 (unsigned i=0 ; i<reply->length/4 ; ++i)
|
||||||
|
{
|
||||||
|
if ((xcb_atom_t)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 _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_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;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case XCB_CONFIGURE_NOTIFY:
|
||||||
|
{
|
||||||
|
xcb_configure_notify_event_t* ev = (xcb_configure_notify_event_t*)event;
|
||||||
|
if (ev->width && ev->height)
|
||||||
|
{
|
||||||
|
m_wx = ev->x;
|
||||||
|
m_wy = ev->y;
|
||||||
|
m_ww = ev->width;
|
||||||
|
m_wh = ev->height;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case XCB_BUTTON_PRESS:
|
||||||
|
{
|
||||||
|
xcb_button_press_event_t* ev = (xcb_button_press_event_t*)event;
|
||||||
|
if (m_callback)
|
||||||
|
{
|
||||||
|
int button = translateButton(ev->detail);
|
||||||
|
if (button)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
if (m_callback)
|
||||||
|
{
|
||||||
|
int button = translateButton(ev->detail);
|
||||||
|
if (button)
|
||||||
|
{
|
||||||
|
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:
|
||||||
|
{
|
||||||
|
xcb_motion_notify_event_t* ev = (xcb_motion_notify_event_t*)event;
|
||||||
|
if (m_callback)
|
||||||
|
{
|
||||||
|
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->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<<i))
|
||||||
|
{
|
||||||
|
if (i == m_hScrollValuator)
|
||||||
|
{
|
||||||
|
newScroll[0] = fp3232val(&valuatorVals[cv]);
|
||||||
|
didScroll = true;
|
||||||
|
}
|
||||||
|
else if (i == m_vScrollValuator)
|
||||||
|
{
|
||||||
|
newScroll[1] = fp3232val(&valuatorVals[cv]);
|
||||||
|
didScroll = true;
|
||||||
|
}
|
||||||
|
++cv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IWindowCallback::SScrollDelta scrollDelta =
|
||||||
|
{
|
||||||
|
{newScroll[0] - m_hScrollLast, newScroll[1] - m_vScrollLast},
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
|
m_hScrollLast = newScroll[0];
|
||||||
|
m_vScrollLast = newScroll[1];
|
||||||
|
|
||||||
|
if (m_callback && didScroll)
|
||||||
|
{
|
||||||
|
unsigned event_x = ev->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<<i))
|
||||||
|
{
|
||||||
|
vals[i] = fp3232val(&valuatorVals[cv]);
|
||||||
|
++cv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IWindowCallback::STouchCoord coord =
|
||||||
|
{
|
||||||
|
{vals[0], vals[1]}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_callback)
|
||||||
|
m_callback->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<<i))
|
||||||
|
{
|
||||||
|
vals[i] = fp3232val(&valuatorVals[cv]);
|
||||||
|
++cv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IWindowCallback::STouchCoord coord =
|
||||||
|
{
|
||||||
|
{vals[0], vals[1]}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_callback)
|
||||||
|
m_callback->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<<i))
|
||||||
|
{
|
||||||
|
vals[i] = fp3232val(&valuatorVals[cv]);
|
||||||
|
++cv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IWindowCallback::STouchCoord coord =
|
||||||
|
{
|
||||||
|
{vals[0], vals[1]}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_callback)
|
||||||
|
m_callback->touchUp(coord, ev->detail);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ETouchType getTouchType() const
|
||||||
|
{
|
||||||
|
return m_touchType;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IWindow* _CWindowXCBNew(const std::string& title, xcb_connection_t* conn)
|
||||||
|
{
|
||||||
|
return new WindowXCB(title, conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
75
libBoo.pri
75
libBoo.pri
|
@ -1,75 +0,0 @@
|
||||||
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/inputdev/CDolphinSmashAdapter.hpp \
|
|
||||||
$$PWD/include/inputdev/CRevolutionPad.hpp \
|
|
||||||
$$PWD/include/inputdev/CCafeProPad.hpp \
|
|
||||||
$$PWD/include/inputdev/CDualshockPad.hpp \
|
|
||||||
$$PWD/include/inputdev/CGenericPad.hpp \
|
|
||||||
$$PWD/include/inputdev/CDeviceFinder.hpp \
|
|
||||||
$$PWD/include/inputdev/CDeviceToken.hpp \
|
|
||||||
$$PWD/include/inputdev/CDeviceBase.hpp \
|
|
||||||
$$PWD/include/inputdev/IHIDListener.hpp \
|
|
||||||
$$PWD/src/inputdev/IHIDDevice.hpp \
|
|
||||||
$$PWD/include/inputdev/SDeviceSignature.hpp
|
|
||||||
|
|
||||||
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 \
|
|
||||||
$$PWD/src/inputdev/CDualshockPad.cpp \
|
|
||||||
$$PWD/src/inputdev/CGenericPad.cpp \
|
|
||||||
$$PWD/src/inputdev/CDeviceBase.cpp \
|
|
||||||
$$PWD/src/inputdev/SDeviceSignature.cpp
|
|
||||||
|
|
||||||
unix:!macx {
|
|
||||||
HEADERS += \
|
|
||||||
$$PWD/include/x11/CGLXContext.hpp
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
$$PWD/src/x11/CGLXContext.cpp
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
win32 {
|
|
||||||
HEADERS += \
|
|
||||||
$$PWD/include/win/CWGLContext.hpp
|
|
||||||
SOURCES += \
|
|
||||||
$$PWD/src/win/CWGLContext.cpp \
|
|
||||||
$$PWD/src/inputdev/CHIDListenerWinUSB.cpp \
|
|
||||||
$$PWD/src/inputdev/CHIDDeviceWinUSB.cpp
|
|
||||||
}
|
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD/include
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include "CInputDeferredRelay.hpp"
|
|
|
@ -1 +0,0 @@
|
||||||
#include "CInputRelay.hpp"
|
|
|
@ -1,3 +0,0 @@
|
||||||
#include "CQtOpenGLWindow.hpp"
|
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include "IRetraceWaiter.hpp"
|
|
|
@ -1,16 +0,0 @@
|
||||||
#include "CSurface.hpp"
|
|
||||||
|
|
||||||
namespace boo
|
|
||||||
{
|
|
||||||
|
|
||||||
ISurface* CSurfaceNewWindow()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ISurface* CSurfaceNewQWidget()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
#include "inputdev/CCafeProPad.hpp"
|
|
|
@ -1,73 +0,0 @@
|
||||||
#include "inputdev/CDeviceBase.hpp"
|
|
||||||
#include "inputdev/CDeviceToken.hpp"
|
|
||||||
#include "IHIDDevice.hpp"
|
|
||||||
#include <cstdarg>
|
|
||||||
|
|
||||||
namespace boo
|
|
||||||
{
|
|
||||||
|
|
||||||
CDeviceBase::CDeviceBase(CDeviceToken* token)
|
|
||||||
: m_token(token), m_hidDev(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CDeviceBase::~CDeviceBase()
|
|
||||||
{
|
|
||||||
delete m_hidDev;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDeviceBase::_deviceDisconnected()
|
|
||||||
{
|
|
||||||
deviceDisconnected();
|
|
||||||
m_token = NULL;
|
|
||||||
if (m_hidDev)
|
|
||||||
{
|
|
||||||
m_hidDev->_deviceDisconnected();
|
|
||||||
delete m_hidDev;
|
|
||||||
m_hidDev = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDeviceBase::closeDevice()
|
|
||||||
{
|
|
||||||
if (m_token)
|
|
||||||
m_token->_deviceClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDeviceBase::deviceError(const char* error, ...)
|
|
||||||
{
|
|
||||||
va_list vl;
|
|
||||||
va_start(vl, error);
|
|
||||||
vfprintf(stderr, error, vl);
|
|
||||||
va_end(vl);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDeviceBase::sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
|
|
||||||
{
|
|
||||||
if (m_hidDev)
|
|
||||||
return m_hidDev->_sendUSBInterruptTransfer(pipe, data, length);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t CDeviceBase::receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)
|
|
||||||
{
|
|
||||||
if (m_hidDev)
|
|
||||||
return m_hidDev->_receiveUSBInterruptTransfer(pipe, data, length);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDeviceBase::sendHIDReport(const uint8_t* data, size_t length, uint16_t message)
|
|
||||||
{
|
|
||||||
if (m_hidDev)
|
|
||||||
return m_hidDev->_sendHIDReport(data, length, message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t CDeviceBase::receiveReport(uint8_t* data, size_t length, uint16_t message)
|
|
||||||
{
|
|
||||||
if (m_hidDev)
|
|
||||||
return m_hidDev->_recieveReport(data, length, message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
#include "inputdev/CGenericPad.hpp"
|
|
||||||
#include "inputdev/CDeviceToken.hpp"
|
|
||||||
|
|
||||||
namespace boo
|
|
||||||
{
|
|
||||||
|
|
||||||
CGenericPad::CGenericPad(CDeviceToken* token)
|
|
||||||
: CDeviceBase(token)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CGenericPad::~CGenericPad()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGenericPad::deviceDisconnected()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
#include "inputdev/CRevolutionPad.hpp"
|
|
|
@ -1,67 +0,0 @@
|
||||||
#ifdef __APPLE__
|
|
||||||
#include "CCGLContext.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
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
|
|
|
@ -1,4 +0,0 @@
|
||||||
#ifdef _WIN32
|
|
||||||
#include "win/CWGLContext.hpp"
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,63 +0,0 @@
|
||||||
#if !defined(__APPLE__) && (defined(__linux__) || defined(BSD))
|
|
||||||
#include "x11/CGLXContext.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
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))
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
add_executable(booTest main.cpp)
|
||||||
|
target_link_libraries(booTest Boo ${BOO_SYS_LIBS})
|
231
test/main.cpp
231
test/main.cpp
|
@ -1,49 +1,34 @@
|
||||||
#define _CRT_SECURE_NO_WARNINGS 1
|
|
||||||
|
|
||||||
#if __APPLE__
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <iostream>
|
#include <boo/boo.hpp>
|
||||||
#include <boo.hpp>
|
|
||||||
#if _WIN32
|
|
||||||
#define _WIN32_LEAN_AND_MEAN 1
|
|
||||||
#include <windows.h>
|
|
||||||
#include <initguid.h>
|
|
||||||
#include <Usbiodef.h>
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
class CDolphinSmashAdapterCallback : public IDolphinSmashAdapterCallback
|
class DolphinSmashAdapterCallback : public IDolphinSmashAdapterCallback
|
||||||
{
|
{
|
||||||
void controllerConnected(unsigned idx, EDolphinControllerType type)
|
void controllerConnected(unsigned idx, EDolphinControllerType)
|
||||||
{
|
{
|
||||||
printf("CONTROLLER %u CONNECTED\n", idx);
|
printf("CONTROLLER %u CONNECTED\n", idx);
|
||||||
}
|
}
|
||||||
void controllerDisconnected(unsigned idx, EDolphinControllerType type)
|
void controllerDisconnected(unsigned idx, EDolphinControllerType)
|
||||||
{
|
{
|
||||||
printf("CONTROLLER %u DISCONNECTED\n", idx);
|
printf("CONTROLLER %u DISCONNECTED\n", idx);
|
||||||
}
|
}
|
||||||
void controllerUpdate(unsigned idx, EDolphinControllerType type,
|
void controllerUpdate(unsigned idx, EDolphinControllerType,
|
||||||
const SDolphinControllerState& state)
|
const DolphinControllerState& state)
|
||||||
{
|
{
|
||||||
printf("CONTROLLER %u UPDATE %d %d\n", idx, state.m_leftStick[0], state.m_leftStick[1]);
|
printf("CONTROLLER %u UPDATE %d %d\n", idx, state.m_leftStick[0], state.m_leftStick[1]);
|
||||||
printf(" %d %d\n", state.m_rightStick[0], state.m_rightStick[1]);
|
printf(" %d %d\n", state.m_rightStick[0], state.m_rightStick[1]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDualshockControllerCallback : public IDualshockControllerCallback
|
class DualshockPadCallback : public IDualshockControllerCallback
|
||||||
{
|
{
|
||||||
void controllerDisconnected()
|
void controllerDisconnected()
|
||||||
{
|
{
|
||||||
printf("CONTROLLER DISCONNECTED\n");
|
printf("CONTROLLER DISCONNECTED\n");
|
||||||
}
|
}
|
||||||
void controllerUpdate(const SDualshockControllerState& state)
|
void controllerUpdate(const DualshockControllerState& state)
|
||||||
{
|
{
|
||||||
static time_t timeTotal;
|
static time_t timeTotal;
|
||||||
static time_t lastTime = 0;
|
static time_t lastTime = 0;
|
||||||
|
@ -64,7 +49,6 @@ class CDualshockControllerCallback : public IDualshockControllerCallback
|
||||||
{
|
{
|
||||||
if (timeDif >= 1) // wait 30 seconds before issuing another rumble event
|
if (timeDif >= 1) // wait 30 seconds before issuing another rumble event
|
||||||
{
|
{
|
||||||
std::cout << "RUMBLE" << std::endl;
|
|
||||||
ctrl->startRumble(DS3_MOTOR_LEFT);
|
ctrl->startRumble(DS3_MOTOR_LEFT);
|
||||||
ctrl->startRumble(DS3_MOTOR_RIGHT, 100);
|
ctrl->startRumble(DS3_MOTOR_RIGHT, 100);
|
||||||
lastTime = timeTotal;
|
lastTime = timeTotal;
|
||||||
|
@ -80,34 +64,34 @@ class CDualshockControllerCallback : public IDualshockControllerCallback
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CTestDeviceFinder : public CDeviceFinder
|
class TestDeviceFinder : public DeviceFinder
|
||||||
{
|
{
|
||||||
CDolphinSmashAdapter* smashAdapter = NULL;
|
|
||||||
CDualshockController* ds3 = nullptr;
|
DolphinSmashAdapter* smashAdapter = NULL;
|
||||||
CDolphinSmashAdapterCallback m_cb;
|
DualshockPad* ds3 = nullptr;
|
||||||
CDualshockControllerCallback m_ds3CB;
|
DolphinSmashAdapterCallback m_cb;
|
||||||
|
DualshockPadCallback m_ds3CB;
|
||||||
public:
|
public:
|
||||||
CTestDeviceFinder()
|
TestDeviceFinder()
|
||||||
: CDeviceFinder({"CDolphinSmashAdapter",
|
: DeviceFinder({typeid(DolphinSmashAdapter)})
|
||||||
"CDualshockController"})
|
|
||||||
{}
|
{}
|
||||||
void deviceConnected(CDeviceToken& tok)
|
void deviceConnected(DeviceToken& tok)
|
||||||
{
|
{
|
||||||
smashAdapter = dynamic_cast<CDolphinSmashAdapter*>(tok.openAndGetDevice());
|
smashAdapter = dynamic_cast<DolphinSmashAdapter*>(tok.openAndGetDevice());
|
||||||
if (smashAdapter)
|
if (smashAdapter)
|
||||||
{
|
{
|
||||||
smashAdapter->setCallback(&m_cb);
|
smashAdapter->setCallback(&m_cb);
|
||||||
smashAdapter->startRumble(0);
|
smashAdapter->startRumble(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ds3 = dynamic_cast<CDualshockController*>(tok.openAndGetDevice());
|
ds3 = dynamic_cast<DualshockPad*>(tok.openAndGetDevice());
|
||||||
if (ds3)
|
if (ds3)
|
||||||
{
|
{
|
||||||
ds3->setCallback(&m_ds3CB);
|
ds3->setCallback(&m_ds3CB);
|
||||||
ds3->setLED(DS3_LED_1);
|
ds3->setLED(DS3_LED_1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void deviceDisconnected(CDeviceToken&, CDeviceBase* device)
|
void deviceDisconnected(DeviceToken&, DeviceBase* device)
|
||||||
{
|
{
|
||||||
if (smashAdapter == device)
|
if (smashAdapter == device)
|
||||||
{
|
{
|
||||||
|
@ -122,111 +106,102 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#if _WIN32
|
struct CTestWindowCallback : IWindowCallback
|
||||||
|
|
||||||
/* This simple 'test' console app needs a full windows
|
|
||||||
* message loop for receiving device connection events
|
|
||||||
*/
|
|
||||||
static const DEV_BROADCAST_DEVICEINTERFACE_A HOTPLUG_CONF =
|
|
||||||
{
|
{
|
||||||
sizeof(DEV_BROADCAST_DEVICEINTERFACE_A),
|
void mouseDown(const SWindowCoord& coord, EMouseButton button, EModifierKey mods)
|
||||||
DBT_DEVTYP_DEVICEINTERFACE,
|
{
|
||||||
0,
|
fprintf(stderr, "Mouse Down %d (%f,%f)\n", button, coord.norm[0], coord.norm[1]);
|
||||||
GUID_DEVINTERFACE_USB_DEVICE
|
}
|
||||||
|
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 Scroll (%f,%f) (%f,%f)\n", coord.norm[0], coord.norm[1], scroll.delta[0], scroll.delta[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 STouchCoord& coord, uintptr_t tid)
|
||||||
|
{
|
||||||
|
//fprintf(stderr, "Touch Up %16lX (%f,%f)\n", tid, coord.coord[0], coord.coord[1]);
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
LRESULT CALLBACK WindowProc(
|
|
||||||
_In_ HWND hwnd,
|
struct TestApplicationCallback : IApplicationCallback
|
||||||
_In_ UINT uMsg,
|
|
||||||
_In_ WPARAM wParam,
|
|
||||||
_In_ LPARAM lParam
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
switch (uMsg)
|
IWindow* mainWindow = NULL;
|
||||||
|
boo::TestDeviceFinder devFinder;
|
||||||
|
CTestWindowCallback windowCallback;
|
||||||
|
void appLaunched(IApplication* app)
|
||||||
{
|
{
|
||||||
case WM_CREATE:
|
mainWindow = app->newWindow("YAY!");
|
||||||
/* Register hotplug notification with windows */
|
mainWindow->setCallback(&windowCallback);
|
||||||
RegisterDeviceNotificationA(hwnd, (LPVOID)&HOTPLUG_CONF, DEVICE_NOTIFY_WINDOW_HANDLE);
|
mainWindow->showWindow();
|
||||||
return 0;
|
devFinder.startScanning();
|
||||||
|
|
||||||
case WM_DEVICECHANGE:
|
|
||||||
return boo::CDeviceFinder::winDevChangedHandler(wParam, lParam);
|
|
||||||
|
|
||||||
default:
|
|
||||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
|
||||||
}
|
}
|
||||||
}
|
void appQuitting(IApplication*)
|
||||||
|
|
||||||
int APIENTRY wWinMain(
|
|
||||||
_In_ HINSTANCE hInstance,
|
|
||||||
_In_ HINSTANCE,
|
|
||||||
_In_ LPTSTR,
|
|
||||||
_In_ int
|
|
||||||
)
|
|
||||||
{
|
|
||||||
AllocConsole();
|
|
||||||
freopen("CONOUT$", "w", stdout);
|
|
||||||
|
|
||||||
WNDCLASS wndClass =
|
|
||||||
{
|
{
|
||||||
0,
|
delete mainWindow;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
void appFilesOpen(IApplication*, const std::vector<std::string>& paths)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "OPENING: ");
|
||||||
|
for (const std::string& path : paths)
|
||||||
|
fprintf(stderr, "%s ", path.c_str());
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
int main(int argc, const char** argv)
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
{
|
||||||
|
boo::TestApplicationCallback appCb;
|
||||||
boo::CTestDeviceFinder finder;
|
std::unique_ptr<boo::IApplication> app =
|
||||||
finder.startScanning();
|
ApplicationBootstrap(boo::IApplication::PLAT_AUTO,
|
||||||
|
appCb, "rwk", "RWK", argc, argv);
|
||||||
#if 0
|
app->run();
|
||||||
boo::IGraphicsContext* ctx = new boo::CGraphicsContext;
|
printf("IM DYING!!\n");
|
||||||
|
|
||||||
if (ctx->create())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if __APPLE__
|
|
||||||
CFRunLoopRun();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
//delete ctx;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
SOURCES += \
|
|
||||||
$$PWD/main.cpp
|
|
||||||
|
|
||||||
win32:SOURCES +=
|
|
Loading…
Reference in New Issue