mirror of
https://github.com/AxioDL/boo.git
synced 2025-07-04 20:25:54 +00:00
much work on XCB events
This commit is contained in:
parent
c357c9d91f
commit
a70cc2c9d1
@ -78,7 +78,7 @@ public:
|
|||||||
virtual void mouseMove(const SWindowCoord& coord)
|
virtual void mouseMove(const SWindowCoord& coord)
|
||||||
{(void)coord;}
|
{(void)coord;}
|
||||||
virtual void scroll(const SScrollDelta& scroll)
|
virtual void scroll(const SScrollDelta& scroll)
|
||||||
{(void)scroll;};
|
{(void)scroll;}
|
||||||
|
|
||||||
virtual void touchDown(const SWindowCoord& coord, uintptr_t tid)
|
virtual void touchDown(const SWindowCoord& coord, uintptr_t tid)
|
||||||
{(void)coord;(void)tid;}
|
{(void)coord;(void)tid;}
|
||||||
@ -123,8 +123,9 @@ public:
|
|||||||
virtual bool isFullscreen() const=0;
|
virtual bool isFullscreen() const=0;
|
||||||
virtual void setFullscreen(bool fs)=0;
|
virtual void setFullscreen(bool fs)=0;
|
||||||
|
|
||||||
virtual void* getPlatformHandle() const=0;
|
virtual uintptr_t getPlatformHandle() const=0;
|
||||||
|
virtual void _incomingEvent(void* event) {(void)event;}
|
||||||
|
|
||||||
enum ETouchType
|
enum ETouchType
|
||||||
{
|
{
|
||||||
TOUCH_NONE = 0,
|
TOUCH_NONE = 0,
|
||||||
|
@ -26,9 +26,11 @@ SOURCES += \
|
|||||||
$$PWD/src/inputdev/SDeviceSignature.cpp
|
$$PWD/src/inputdev/SDeviceSignature.cpp
|
||||||
|
|
||||||
unix:!macx {
|
unix:!macx {
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/src/CApplicationXCB.hpp \
|
||||||
|
$$PWD/src/CApplicationWayland.hpp
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/src/CApplicationXCB.cpp \
|
$$PWD/src/CApplicationUnix.cpp \
|
||||||
$$PWD/src/CApplicationWayland.cpp \
|
|
||||||
$$PWD/src/windowsys/CWindowXCB.cpp \
|
$$PWD/src/windowsys/CWindowXCB.cpp \
|
||||||
$$PWD/src/windowsys/CWindowWayland.cpp \
|
$$PWD/src/windowsys/CWindowWayland.cpp \
|
||||||
$$PWD/src/windowsys/CGraphicsContextXCB.cpp \
|
$$PWD/src/windowsys/CGraphicsContextXCB.cpp \
|
||||||
|
@ -3,7 +3,7 @@ CONFIG += console
|
|||||||
#QMAKE_CXXFLAGS -= -std=c++0x
|
#QMAKE_CXXFLAGS -= -std=c++0x
|
||||||
#CONFIG += c++11
|
#CONFIG += c++11
|
||||||
unix:QMAKE_CXXFLAGS += -std=c++11 -stdlib=libc++
|
unix:QMAKE_CXXFLAGS += -std=c++11 -stdlib=libc++
|
||||||
unix:LIBS += -std=c++11 -stdlib=libc++ -lc++abi
|
unix:LIBS += -std=c++11 -stdlib=libc++ -lc++abi -lxcb -lxcb-xkb -lxcb-keysyms -lxkbcommon -lxkbcommon-x11
|
||||||
|
|
||||||
win32:LIBS += Setupapi.lib winusb.lib User32.lib /SUBSYSTEM:Windows
|
win32:LIBS += Setupapi.lib winusb.lib User32.lib /SUBSYSTEM:Windows
|
||||||
|
|
||||||
|
@ -40,6 +40,11 @@ public:
|
|||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void quit()
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& getProcessName() const
|
const std::string& getProcessName() const
|
||||||
|
@ -4,10 +4,68 @@
|
|||||||
|
|
||||||
#include "IApplication.hpp"
|
#include "IApplication.hpp"
|
||||||
|
|
||||||
|
#define explicit explicit_c
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xkbcommon/xkbcommon-x11.h>
|
||||||
|
#include <xcb/xkb.h>
|
||||||
|
#undef explicit
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static xcb_window_t getWindowOfEvent(xcb_generic_event_t* event, bool& windowEvent)
|
||||||
|
{
|
||||||
|
switch (event->response_type & ~0x80)
|
||||||
|
{
|
||||||
|
case XCB_EXPOSE:
|
||||||
|
{
|
||||||
|
xcb_expose_event_t* ev = (xcb_expose_event_t*)event;
|
||||||
|
windowEvent = true;
|
||||||
|
return ev->window;
|
||||||
|
}
|
||||||
|
case XCB_CONFIGURE_NOTIFY:
|
||||||
|
{
|
||||||
|
xcb_configure_notify_event_t* ev = (xcb_configure_notify_event_t*)event;
|
||||||
|
windowEvent = true;
|
||||||
|
return ev->window;
|
||||||
|
}
|
||||||
|
case XCB_KEY_PRESS:
|
||||||
|
{
|
||||||
|
xcb_key_press_event_t* ev = (xcb_key_press_event_t*)event;
|
||||||
|
windowEvent = true;
|
||||||
|
return ev->root;
|
||||||
|
}
|
||||||
|
case XCB_KEY_RELEASE:
|
||||||
|
{
|
||||||
|
xcb_key_release_event_t* ev = (xcb_key_release_event_t*)event;
|
||||||
|
windowEvent = true;
|
||||||
|
return ev->root;
|
||||||
|
}
|
||||||
|
case XCB_BUTTON_PRESS:
|
||||||
|
{
|
||||||
|
xcb_button_press_event_t* ev = (xcb_button_press_event_t*)event;
|
||||||
|
windowEvent = true;
|
||||||
|
return ev->root;
|
||||||
|
}
|
||||||
|
case XCB_BUTTON_RELEASE:
|
||||||
|
{
|
||||||
|
xcb_button_release_event_t* ev = (xcb_button_release_event_t*)event;
|
||||||
|
windowEvent = true;
|
||||||
|
return ev->root;
|
||||||
|
}
|
||||||
|
case XCB_MOTION_NOTIFY:
|
||||||
|
{
|
||||||
|
xcb_motion_notify_event_t* ev = (xcb_motion_notify_event_t*)event;
|
||||||
|
windowEvent = true;
|
||||||
|
return ev->root;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
windowEvent = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IWindow* _CWindowXCBNew(const std::string& title);
|
IWindow* _CWindowXCBNew(const std::string& title, xcb_connection_t* conn);
|
||||||
|
|
||||||
class CApplicationXCB final : public IApplication
|
class CApplicationXCB final : public IApplication
|
||||||
{
|
{
|
||||||
@ -15,10 +73,16 @@ class CApplicationXCB final : public IApplication
|
|||||||
const std::string m_friendlyName;
|
const std::string m_friendlyName;
|
||||||
const std::string m_pname;
|
const std::string m_pname;
|
||||||
const std::vector<std::string> m_args;
|
const std::vector<std::string> m_args;
|
||||||
|
|
||||||
|
/* All windows */
|
||||||
|
std::unordered_map<xcb_window_t, IWindow*> m_windows;
|
||||||
|
|
||||||
|
xcb_connection_t* m_xcbConn;
|
||||||
|
bool m_running;
|
||||||
|
|
||||||
void _deletedWindow(IWindow* window)
|
void _deletedWindow(IWindow* window)
|
||||||
{
|
{
|
||||||
(void)window;
|
m_windows.erase((xcb_window_t)window->getPlatformHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -30,7 +94,25 @@ public:
|
|||||||
m_friendlyName(friendlyName),
|
m_friendlyName(friendlyName),
|
||||||
m_pname(pname),
|
m_pname(pname),
|
||||||
m_args(args)
|
m_args(args)
|
||||||
{}
|
{
|
||||||
|
m_xcbConn = xcb_connect(NULL, NULL);
|
||||||
|
|
||||||
|
/* The convoluted xkb extension requests that the X server does not
|
||||||
|
* send repeated keydown events when a key is held */
|
||||||
|
xkb_x11_setup_xkb_extension(m_xcbConn,
|
||||||
|
XKB_X11_MIN_MAJOR_XKB_VERSION,
|
||||||
|
XKB_X11_MIN_MINOR_XKB_VERSION,
|
||||||
|
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
|
||||||
|
NULL, NULL, NULL, NULL);
|
||||||
|
xcb_xkb_per_client_flags(m_xcbConn, XCB_XKB_ID_USE_CORE_KBD,
|
||||||
|
XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT,
|
||||||
|
XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
~CApplicationXCB()
|
||||||
|
{
|
||||||
|
xcb_disconnect(m_xcbConn);
|
||||||
|
}
|
||||||
|
|
||||||
EPlatformType getPlatformType() const
|
EPlatformType getPlatformType() const
|
||||||
{
|
{
|
||||||
@ -39,7 +121,23 @@ public:
|
|||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
|
xcb_generic_event_t* event;
|
||||||
|
while (m_running && (event = xcb_wait_for_event(m_xcbConn)))
|
||||||
|
{
|
||||||
|
bool windowEvent;
|
||||||
|
xcb_window_t evWindow = getWindowOfEvent(event, windowEvent);
|
||||||
|
if (windowEvent)
|
||||||
|
{
|
||||||
|
IWindow* window = m_windows[evWindow];
|
||||||
|
|
||||||
|
}
|
||||||
|
free(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void quit()
|
||||||
|
{
|
||||||
|
m_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& getProcessName() const
|
const std::string& getProcessName() const
|
||||||
@ -54,7 +152,9 @@ public:
|
|||||||
|
|
||||||
IWindow* newWindow(const std::string& title)
|
IWindow* newWindow(const std::string& title)
|
||||||
{
|
{
|
||||||
return _CWindowXCBNew(title);
|
IWindow* newWindow = _CWindowXCBNew(title, m_xcbConn);
|
||||||
|
m_windows[(xcb_window_t)newWindow->getPlatformHandle()] = newWindow;
|
||||||
|
return newWindow;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,9 +118,9 @@ public:
|
|||||||
return TOUCH_TRACKPAD;
|
return TOUCH_TRACKPAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* getPlatformHandle() const
|
uintptr_t getPlatformHandle() const
|
||||||
{
|
{
|
||||||
return m_nsWindow;
|
return (uintptr_t)m_nsWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -76,6 +76,11 @@ public:
|
|||||||
void setFullscreen(bool fs)
|
void setFullscreen(bool fs)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t getPlatformHandle() const
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ETouchType getTouchType() const
|
ETouchType getTouchType() const
|
||||||
|
@ -1,8 +1,133 @@
|
|||||||
#include "windowsys/IWindow.hpp"
|
#include "windowsys/IWindow.hpp"
|
||||||
#include "windowsys/IGraphicsContext.hpp"
|
#include "windowsys/IGraphicsContext.hpp"
|
||||||
|
#include "IApplication.hpp"
|
||||||
|
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
#include <xcb/xcb_keysyms.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.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
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static uint32_t translateKeysym(xcb_keysym_t sym, int& specialSym, int& modifierSym)
|
||||||
|
{
|
||||||
|
specialSym = IWindowCallback::KEY_NONE;
|
||||||
|
modifierSym = IWindowCallback::MKEY_NONE;
|
||||||
|
if (sym >= XK_F1 && sym <= XK_F12)
|
||||||
|
specialSym = IWindowCallback::KEY_F1 + sym - XK_F1;
|
||||||
|
else if (sym == XK_Escape)
|
||||||
|
specialSym = IWindowCallback::KEY_ESC;
|
||||||
|
else if (sym == XK_Return)
|
||||||
|
specialSym = IWindowCallback::KEY_ENTER;
|
||||||
|
else if (sym == XK_BackSpace)
|
||||||
|
specialSym = IWindowCallback::KEY_BACKSPACE;
|
||||||
|
else if (sym == XK_Insert)
|
||||||
|
specialSym = IWindowCallback::KEY_INSERT;
|
||||||
|
else if (sym == XK_Delete)
|
||||||
|
specialSym = IWindowCallback::KEY_DELETE;
|
||||||
|
else if (sym == XK_Home)
|
||||||
|
specialSym = IWindowCallback::KEY_HOME;
|
||||||
|
else if (sym == XK_End)
|
||||||
|
specialSym = IWindowCallback::KEY_END;
|
||||||
|
else if (sym == XK_Page_Up)
|
||||||
|
specialSym = IWindowCallback::KEY_PGUP;
|
||||||
|
else if (sym == XK_Page_Down)
|
||||||
|
specialSym = IWindowCallback::KEY_PGDOWN;
|
||||||
|
else if (sym == XK_Left)
|
||||||
|
specialSym = IWindowCallback::KEY_LEFT;
|
||||||
|
else if (sym == XK_Right)
|
||||||
|
specialSym = IWindowCallback::KEY_RIGHT;
|
||||||
|
else if (sym == XK_Up)
|
||||||
|
specialSym = IWindowCallback::KEY_UP;
|
||||||
|
else if (sym == XK_Down)
|
||||||
|
specialSym = IWindowCallback::KEY_DOWN;
|
||||||
|
else if (sym == XK_Shift_L || sym == XK_Shift_R)
|
||||||
|
modifierSym = IWindowCallback::MKEY_SHIFT;
|
||||||
|
else if (sym == XK_Control_L || sym == XK_Control_R)
|
||||||
|
modifierSym = IWindowCallback::MKEY_CTRL;
|
||||||
|
else if (sym == XK_Alt_L || sym == XK_Alt_R)
|
||||||
|
modifierSym = IWindowCallback::MKEY_ALT;
|
||||||
|
else
|
||||||
|
return xkb_keysym_to_utf32(sym);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int translateModifiers(unsigned state)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
if (state & XCB_MOD_MASK_SHIFT)
|
||||||
|
retval |= IWindowCallback::MKEY_SHIFT;
|
||||||
|
if (state & XCB_MOD_MASK_CONTROL)
|
||||||
|
retval |= IWindowCallback::MKEY_CTRL;
|
||||||
|
if (state & XCB_MOD_MASK_1)
|
||||||
|
retval |= IWindowCallback::MKEY_ALT;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int translateButton(unsigned state)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
if (state & XCB_BUTTON_MASK_1)
|
||||||
|
retval = IWindowCallback::BUTTON_PRIMARY;
|
||||||
|
else if (state & XCB_BUTTON_MASK_2)
|
||||||
|
retval = IWindowCallback::BUTTON_SECONDARY;
|
||||||
|
else if (state & XCB_BUTTON_MASK_3)
|
||||||
|
retval = IWindowCallback::BUTTON_MIDDLE;
|
||||||
|
else if (state & XCB_BUTTON_MASK_4)
|
||||||
|
retval = IWindowCallback::BUTTON_AUX1;
|
||||||
|
else if (state & XCB_BUTTON_MASK_5)
|
||||||
|
retval = IWindowCallback::BUTTON_AUX2;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define INTERN_ATOM(var, conn, name) \
|
||||||
|
do {\
|
||||||
|
xcb_intern_atom_cookie_t cookie = \
|
||||||
|
xcb_intern_atom(conn, 0, sizeof(#name), #name); \
|
||||||
|
xcb_intern_atom_reply_t* reply = \
|
||||||
|
xcb_intern_atom_reply(conn, cookie, NULL); \
|
||||||
|
var = reply->atom; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
struct SXCBAtoms
|
||||||
|
{
|
||||||
|
xcb_atom_t m_netwmState = 0;
|
||||||
|
xcb_atom_t m_netwmStateFullscreen = 0;
|
||||||
|
xcb_atom_t m_netwmStateAdd = 0;
|
||||||
|
xcb_atom_t m_netwmStateRemove = 0;
|
||||||
|
xcb_key_symbols_t* m_keySyms = NULL;
|
||||||
|
SXCBAtoms(xcb_connection_t* conn)
|
||||||
|
{
|
||||||
|
INTERN_ATOM(m_netwmState, conn, _NET_WM_STATE);
|
||||||
|
INTERN_ATOM(m_netwmStateFullscreen, conn, _NET_WM_STATE_FULLSCREEN);
|
||||||
|
INTERN_ATOM(m_netwmStateAdd, conn, _NET_WM_STATE_ADD);
|
||||||
|
INTERN_ATOM(m_netwmStateRemove, conn, _NET_WM_STATE_REMOVE);
|
||||||
|
m_keySyms = xcb_key_symbols_alloc(conn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static SXCBAtoms* S_ATOMS = NULL;
|
||||||
|
|
||||||
|
static void genFrameDefault(xcb_screen_t* screen, int* xOut, int* yOut, int* wOut, int* hOut)
|
||||||
|
{
|
||||||
|
float width = screen->width_in_pixels * 2.0 / 3.0;
|
||||||
|
float height = screen->height_in_pixels * 2.0 / 3.0;
|
||||||
|
*xOut = (screen->width_in_pixels - width) / 2.0;
|
||||||
|
*yOut = (screen->height_in_pixels - height) / 2.0;
|
||||||
|
*wOut = width;
|
||||||
|
*hOut = height;
|
||||||
|
}
|
||||||
|
|
||||||
IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api,
|
IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api,
|
||||||
IWindow* parentWindow);
|
IWindow* parentWindow);
|
||||||
@ -10,84 +135,303 @@ IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api,
|
|||||||
class CWindowXCB final : public IWindow
|
class CWindowXCB final : public IWindow
|
||||||
{
|
{
|
||||||
|
|
||||||
|
xcb_connection_t* m_xcbConn;
|
||||||
|
xcb_window_t m_windowId;
|
||||||
|
IGraphicsContext* m_gfxCtx;
|
||||||
|
IWindowCallback* m_callback;
|
||||||
|
|
||||||
|
/* Cached window rectangle (to avoid repeated X queries) */
|
||||||
|
int m_wx, m_wy, m_ww, m_wh;
|
||||||
|
float m_pixelFactor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CWindowXCB(const std::string& title)
|
CWindowXCB(const std::string& title, xcb_connection_t* conn)
|
||||||
|
: m_xcbConn(conn), m_callback(NULL)
|
||||||
{
|
{
|
||||||
|
if (!S_ATOMS)
|
||||||
|
S_ATOMS = new SXCBAtoms(conn);
|
||||||
|
m_windowId = xcb_generate_id(conn);
|
||||||
|
|
||||||
|
/* Default screen */
|
||||||
|
xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(m_xcbConn)).data;
|
||||||
|
m_pixelFactor = screen->width_in_pixels / (float)screen->width_in_millimeters / REF_DPMM;
|
||||||
|
|
||||||
|
/* Create window */
|
||||||
|
int x, y, w, h;
|
||||||
|
genFrameDefault(screen, &x, &y, &w, &h);
|
||||||
|
uint32_t valueMasks[] =
|
||||||
|
{
|
||||||
|
XCB_NONE,
|
||||||
|
XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE |
|
||||||
|
XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
|
||||||
|
XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE |
|
||||||
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY
|
||||||
|
};
|
||||||
|
xcb_create_window(m_xcbConn, 0, m_windowId, 0, x, y, w, h, 10, 0, screen->root_visual,
|
||||||
|
XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK, valueMasks);
|
||||||
|
|
||||||
|
/* Set the title of the window */
|
||||||
|
const char* c_title = title.c_str();
|
||||||
|
xcb_change_property(m_xcbConn, XCB_PROP_MODE_REPLACE, m_windowId,
|
||||||
|
XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
|
||||||
|
strlen(c_title), c_title);
|
||||||
|
|
||||||
|
/* Set the title of the window icon */
|
||||||
|
xcb_change_property(m_xcbConn, XCB_PROP_MODE_REPLACE, m_windowId,
|
||||||
|
XCB_ATOM_WM_ICON_NAME, XCB_ATOM_STRING, 8,
|
||||||
|
strlen(c_title), c_title);
|
||||||
|
|
||||||
|
/* Construct graphics context */
|
||||||
|
m_gfxCtx = _CGraphicsContextXCBNew(IGraphicsContext::API_OPENGL_3_3, this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~CWindowXCB()
|
~CWindowXCB()
|
||||||
{
|
{
|
||||||
|
IApplicationInstance()->_deletedWindow(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCallback(IWindowCallback* cb)
|
void setCallback(IWindowCallback* cb)
|
||||||
{
|
{
|
||||||
|
m_callback = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void showWindow()
|
void showWindow()
|
||||||
{
|
{
|
||||||
|
xcb_map_window(m_xcbConn, m_windowId);
|
||||||
|
xcb_flush(m_xcbConn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hideWindow()
|
void hideWindow()
|
||||||
{
|
{
|
||||||
|
xcb_unmap_window(m_xcbConn, m_windowId);
|
||||||
|
xcb_flush(m_xcbConn);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getTitle()
|
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)
|
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()
|
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
|
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)
|
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
|
float getVirtualPixelFactor() const
|
||||||
{
|
{
|
||||||
|
return m_pixelFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFullscreen() const
|
bool isFullscreen() const
|
||||||
{
|
{
|
||||||
|
xcb_get_property_cookie_t cookie =
|
||||||
|
xcb_get_property(m_xcbConn, 0, m_windowId, S_ATOMS->m_netwmState, XCB_ATOM_ATOM, 0, 32);
|
||||||
|
xcb_get_property_reply_t* reply =
|
||||||
|
xcb_get_property_reply(m_xcbConn, cookie, NULL);
|
||||||
|
char* props = (char*)xcb_get_property_value(reply);
|
||||||
|
char fullscreen = false;
|
||||||
|
for (int i ; i<reply->length/4 ; ++i)
|
||||||
|
{
|
||||||
|
if (props[i] == S_ATOMS->m_netwmStateFullscreen)
|
||||||
|
{
|
||||||
|
fullscreen = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(reply);
|
||||||
|
return fullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFullscreen(bool fs)
|
void setFullscreen(bool fs)
|
||||||
{
|
{
|
||||||
|
xcb_client_message_event_t fsEvent =
|
||||||
|
{
|
||||||
|
XCB_CLIENT_MESSAGE,
|
||||||
|
32,
|
||||||
|
0,
|
||||||
|
m_windowId,
|
||||||
|
S_ATOMS->m_netwmState
|
||||||
|
};
|
||||||
|
fsEvent.data.data32[0] = fs ? S_ATOMS->m_netwmStateAdd : S_ATOMS->m_netwmStateRemove;
|
||||||
|
fsEvent.data.data32[1] = S_ATOMS->m_netwmStateFullscreen;
|
||||||
|
xcb_send_event(m_xcbConn, 0, m_windowId,
|
||||||
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
||||||
|
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
|
||||||
|
(const char*)&fsEvent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t getPlatformHandle() const
|
||||||
|
{
|
||||||
|
return (uintptr_t)m_windowId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _incomingEvent(void* e)
|
||||||
|
{
|
||||||
|
xcb_generic_event_t* event = (xcb_generic_event_t*)e;
|
||||||
|
switch (event->response_type & ~0x80)
|
||||||
|
{
|
||||||
|
case XCB_EXPOSE:
|
||||||
|
{
|
||||||
|
xcb_expose_event_t* ev = (xcb_expose_event_t*)event;
|
||||||
|
m_wx = ev->x;
|
||||||
|
m_wy = ev->y;
|
||||||
|
m_ww = ev->width;
|
||||||
|
m_wh = ev->height;
|
||||||
|
}
|
||||||
|
case XCB_CONFIGURE_NOTIFY:
|
||||||
|
{
|
||||||
|
xcb_configure_notify_event_t* ev = (xcb_configure_notify_event_t*)event;
|
||||||
|
m_wx = ev->x;
|
||||||
|
m_wy = ev->y;
|
||||||
|
m_ww = ev->width;
|
||||||
|
m_wh = ev->height;
|
||||||
|
}
|
||||||
|
case XCB_KEY_PRESS:
|
||||||
|
{
|
||||||
|
xcb_key_press_event_t* ev = (xcb_key_press_event_t*)event;
|
||||||
|
if (m_callback)
|
||||||
|
{
|
||||||
|
int specialKey;
|
||||||
|
int modifierKey;
|
||||||
|
wchar_t charCode = translateKeysym(xcb_key_press_lookup_keysym(S_ATOMS->m_keySyms, ev, 0),
|
||||||
|
specialKey, modifierKey);
|
||||||
|
int modifierMask = translateModifiers(ev->state);
|
||||||
|
if (charCode)
|
||||||
|
m_callback->charKeyDown(charCode,
|
||||||
|
(IWindowCallback::EModifierKey)modifierMask, false);
|
||||||
|
else if (specialKey)
|
||||||
|
m_callback->specialKeyDown((IWindowCallback::ESpecialKey)specialKey,
|
||||||
|
(IWindowCallback::EModifierKey)modifierMask, false);
|
||||||
|
else if (modifierKey)
|
||||||
|
m_callback->modKeyDown((IWindowCallback::EModifierKey)modifierKey, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case XCB_KEY_RELEASE:
|
||||||
|
{
|
||||||
|
xcb_key_release_event_t* ev = (xcb_key_release_event_t*)event;
|
||||||
|
if (m_callback)
|
||||||
|
{
|
||||||
|
int specialKey;
|
||||||
|
int modifierKey;
|
||||||
|
wchar_t charCode = translateKeysym(xcb_key_release_lookup_keysym(S_ATOMS->m_keySyms, ev, 0),
|
||||||
|
specialKey, modifierKey);
|
||||||
|
int modifierMask = translateModifiers(ev->state);
|
||||||
|
if (charCode)
|
||||||
|
m_callback->charKeyUp(charCode,
|
||||||
|
(IWindowCallback::EModifierKey)modifierMask);
|
||||||
|
else if (specialKey)
|
||||||
|
m_callback->specialKeyUp((IWindowCallback::ESpecialKey)specialKey,
|
||||||
|
(IWindowCallback::EModifierKey)modifierMask);
|
||||||
|
else if (modifierKey)
|
||||||
|
m_callback->modKeyUp((IWindowCallback::EModifierKey)modifierKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case XCB_BUTTON_PRESS:
|
||||||
|
{
|
||||||
|
xcb_button_press_event_t* ev = (xcb_button_press_event_t*)event;
|
||||||
|
int button = translateButton(ev->state);
|
||||||
|
if (m_callback && button)
|
||||||
|
{
|
||||||
|
int modifierMask = translateModifiers(ev->state);
|
||||||
|
IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)ev->root_x, (unsigned)ev->root_y},
|
||||||
|
{(unsigned)(ev->root_x / m_pixelFactor), (unsigned)(ev->root_y / m_pixelFactor)},
|
||||||
|
{ev->root_x / (float)m_ww, ev->root_y / (float)m_wh}
|
||||||
|
};
|
||||||
|
m_callback->mouseDown(coord, (IWindowCallback::EMouseButton)button,
|
||||||
|
(IWindowCallback::EModifierKey)modifierMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case XCB_BUTTON_RELEASE:
|
||||||
|
{
|
||||||
|
xcb_button_release_event_t* ev = (xcb_button_release_event_t*)event;
|
||||||
|
int button = translateButton(ev->state);
|
||||||
|
if (m_callback && button)
|
||||||
|
{
|
||||||
|
int modifierMask = translateModifiers(ev->state);
|
||||||
|
IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)ev->root_x, (unsigned)ev->root_y},
|
||||||
|
{(unsigned)(ev->root_x / m_pixelFactor), (unsigned)(ev->root_y / m_pixelFactor)},
|
||||||
|
{ev->root_x / (float)m_ww, ev->root_y / (float)m_wh}
|
||||||
|
};
|
||||||
|
m_callback->mouseUp(coord, (IWindowCallback::EMouseButton)button,
|
||||||
|
(IWindowCallback::EModifierKey)modifierMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case XCB_MOTION_NOTIFY:
|
||||||
|
{
|
||||||
|
xcb_motion_notify_event_t* ev = (xcb_motion_notify_event_t*)event;
|
||||||
|
if (m_callback)
|
||||||
|
{
|
||||||
|
IWindowCallback::SWindowCoord coord =
|
||||||
|
{
|
||||||
|
{(unsigned)ev->root_x, (unsigned)ev->root_y},
|
||||||
|
{(unsigned)(ev->root_x / m_pixelFactor), (unsigned)(ev->root_y / m_pixelFactor)},
|
||||||
|
{ev->root_x / (float)m_ww, ev->root_y / (float)m_wh}
|
||||||
|
};
|
||||||
|
m_callback->mouseMove(coord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ETouchType getTouchType() const
|
ETouchType getTouchType() const
|
||||||
{
|
{
|
||||||
|
return TOUCH_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IWindow* _CWindowXCBNew(const std::string& title)
|
IWindow* _CWindowXCBNew(const std::string& title, xcb_connection_t* conn)
|
||||||
{
|
{
|
||||||
return new CWindowXCB(title);
|
return new CWindowXCB(title, conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user