mirror of
https://github.com/AxioDL/boo.git
synced 2025-12-09 21:47:57 +00:00
New code style refactor
This commit is contained in:
@@ -11,74 +11,62 @@
|
||||
#include <cstdio>
|
||||
|
||||
/* No icon by default */
|
||||
extern "C" const uint8_t MAINICON_NETWM[] __attribute__ ((weak)) = {};
|
||||
extern "C" const size_t MAINICON_NETWM_SZ __attribute__ ((weak)) = 0;
|
||||
extern "C" const uint8_t MAINICON_NETWM[] __attribute__((weak)) = {};
|
||||
extern "C" const size_t MAINICON_NETWM_SZ __attribute__((weak)) = 0;
|
||||
|
||||
DBusConnection* RegisterDBus(const char* appName, bool& isFirst)
|
||||
{
|
||||
isFirst = true;
|
||||
DBusError err = {};
|
||||
dbus_error_init(&err);
|
||||
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;
|
||||
/* 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;
|
||||
/* 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
|
||||
{
|
||||
namespace boo {
|
||||
|
||||
IApplication* APP = nullptr;
|
||||
int ApplicationRun(IApplication::EPlatformType platform,
|
||||
IApplicationCallback& cb,
|
||||
std::string_view uniqueName,
|
||||
std::string_view friendlyName,
|
||||
std::string_view pname,
|
||||
const std::vector<std::string>& args,
|
||||
std::string_view gfxApi,
|
||||
uint32_t samples,
|
||||
uint32_t anisotropy,
|
||||
bool deepColor,
|
||||
bool singleInstance)
|
||||
{
|
||||
std::string thrName = std::string(friendlyName) + " Main";
|
||||
logvisor::RegisterThreadName(thrName.c_str());
|
||||
if (APP)
|
||||
return 1;
|
||||
if (platform == IApplication::EPlatformType::Wayland)
|
||||
APP = new ApplicationWayland(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor, singleInstance);
|
||||
else if (platform == IApplication::EPlatformType::Xlib ||
|
||||
platform == IApplication::EPlatformType::Auto)
|
||||
APP = new ApplicationXlib(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor, singleInstance);
|
||||
else
|
||||
return 1;
|
||||
int ret = APP->run();
|
||||
delete APP;
|
||||
APP = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, std::string_view uniqueName,
|
||||
std::string_view friendlyName, std::string_view pname, const std::vector<std::string>& args,
|
||||
std::string_view gfxApi, uint32_t samples, uint32_t anisotropy, bool deepColor,
|
||||
bool singleInstance) {
|
||||
std::string thrName = std::string(friendlyName) + " Main";
|
||||
logvisor::RegisterThreadName(thrName.c_str());
|
||||
if (APP)
|
||||
return 1;
|
||||
if (platform == IApplication::EPlatformType::Wayland)
|
||||
APP = new ApplicationWayland(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor,
|
||||
singleInstance);
|
||||
else if (platform == IApplication::EPlatformType::Xlib || platform == IApplication::EPlatformType::Auto)
|
||||
APP = new ApplicationXlib(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor,
|
||||
singleInstance);
|
||||
else
|
||||
return 1;
|
||||
int ret = APP->run();
|
||||
delete APP;
|
||||
APP = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace boo
|
||||
|
||||
@@ -7,81 +7,47 @@
|
||||
#include <dbus/dbus.h>
|
||||
DBusConnection* RegisterDBus(const char* appName, bool& isFirst);
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
namespace boo {
|
||||
|
||||
std::shared_ptr<IWindow> _WindowWaylandNew(std::string_view 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;
|
||||
}
|
||||
|
||||
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,
|
||||
std::string_view uniqueName,
|
||||
std::string_view friendlyName,
|
||||
std::string_view pname,
|
||||
const std::vector<std::string>& args,
|
||||
std::string_view gfxApi,
|
||||
uint32_t samples,
|
||||
uint32_t anisotropy,
|
||||
bool deepColor,
|
||||
bool singleInstance)
|
||||
: m_callback(callback),
|
||||
m_uniqueName(uniqueName),
|
||||
m_friendlyName(friendlyName),
|
||||
m_pname(pname),
|
||||
m_args(args),
|
||||
m_singleInstance(singleInstance)
|
||||
{
|
||||
(void)m_callback;
|
||||
(void)m_singleInstance;
|
||||
}
|
||||
|
||||
EPlatformType getPlatformType() const
|
||||
{
|
||||
return EPlatformType::Wayland;
|
||||
}
|
||||
|
||||
int run()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ApplicationWayland(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName,
|
||||
std::string_view pname, const std::vector<std::string>& args, std::string_view gfxApi,
|
||||
uint32_t samples, uint32_t anisotropy, bool deepColor, bool singleInstance)
|
||||
: m_callback(callback)
|
||||
, m_uniqueName(uniqueName)
|
||||
, m_friendlyName(friendlyName)
|
||||
, m_pname(pname)
|
||||
, m_args(args)
|
||||
, m_singleInstance(singleInstance) {
|
||||
(void)m_callback;
|
||||
(void)m_singleInstance;
|
||||
}
|
||||
|
||||
std::string_view getUniqueName() const
|
||||
{
|
||||
return m_uniqueName;
|
||||
}
|
||||
EPlatformType getPlatformType() const { return EPlatformType::Wayland; }
|
||||
|
||||
std::string_view getFriendlyName() const
|
||||
{
|
||||
return m_friendlyName;
|
||||
}
|
||||
|
||||
std::string_view getProcessName() const
|
||||
{
|
||||
return m_pname;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getArgs() const
|
||||
{
|
||||
return m_args;
|
||||
}
|
||||
|
||||
std::shared_ptr<IWindow> newWindow(std::string_view title)
|
||||
{
|
||||
return _WindowWaylandNew(title);
|
||||
}
|
||||
int run() { return 0; }
|
||||
|
||||
std::string_view getUniqueName() const { return m_uniqueName; }
|
||||
|
||||
std::string_view getFriendlyName() const { return m_friendlyName; }
|
||||
|
||||
std::string_view getProcessName() const { return m_pname; }
|
||||
|
||||
const std::vector<std::string>& getArgs() const { return m_args; }
|
||||
|
||||
std::shared_ptr<IWindow> newWindow(std::string_view title) { return _WindowWaylandNew(title); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace boo
|
||||
|
||||
@@ -33,567 +33,484 @@ DBusConnection* RegisterDBus(const char* appName, bool& isFirst);
|
||||
#include "boo/graphicsdev/Vulkan.hpp"
|
||||
#endif
|
||||
|
||||
namespace boo
|
||||
{
|
||||
namespace boo {
|
||||
static logvisor::Module Log("boo::ApplicationXlib");
|
||||
XlibCursors X_CURSORS;
|
||||
|
||||
int XINPUT_OPCODE = 0;
|
||||
|
||||
static Window GetWindowOfEvent(XEvent* event, bool& windowEvent)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case SelectionRequest:
|
||||
{
|
||||
static Window GetWindowOfEvent(XEvent* event, bool& windowEvent) {
|
||||
switch (event->type) {
|
||||
case SelectionRequest: {
|
||||
windowEvent = true;
|
||||
return event->xselectionrequest.owner;
|
||||
}
|
||||
case ClientMessage: {
|
||||
windowEvent = true;
|
||||
return event->xclient.window;
|
||||
}
|
||||
case Expose: {
|
||||
windowEvent = true;
|
||||
return event->xexpose.window;
|
||||
}
|
||||
case ConfigureNotify: {
|
||||
windowEvent = true;
|
||||
return event->xconfigure.window;
|
||||
}
|
||||
case KeyPress:
|
||||
case KeyRelease: {
|
||||
windowEvent = true;
|
||||
return event->xkey.window;
|
||||
}
|
||||
case ButtonPress:
|
||||
case ButtonRelease: {
|
||||
windowEvent = true;
|
||||
return event->xbutton.window;
|
||||
}
|
||||
case MotionNotify: {
|
||||
windowEvent = true;
|
||||
return event->xmotion.window;
|
||||
}
|
||||
case EnterNotify:
|
||||
case LeaveNotify: {
|
||||
windowEvent = true;
|
||||
return event->xcrossing.window;
|
||||
}
|
||||
case FocusIn:
|
||||
case FocusOut: {
|
||||
windowEvent = true;
|
||||
return event->xfocus.window;
|
||||
}
|
||||
case GenericEvent: {
|
||||
if (event->xgeneric.extension == XINPUT_OPCODE) {
|
||||
switch (event->xgeneric.evtype) {
|
||||
case XI_Motion:
|
||||
case XI_TouchBegin:
|
||||
case XI_TouchUpdate:
|
||||
case XI_TouchEnd: {
|
||||
XIDeviceEvent* ev = (XIDeviceEvent*)event;
|
||||
windowEvent = true;
|
||||
return event->xselectionrequest.owner;
|
||||
return ev->event;
|
||||
}
|
||||
}
|
||||
}
|
||||
case ClientMessage:
|
||||
{
|
||||
windowEvent = true;
|
||||
return event->xclient.window;
|
||||
}
|
||||
case Expose:
|
||||
{
|
||||
windowEvent = true;
|
||||
return event->xexpose.window;
|
||||
}
|
||||
case ConfigureNotify:
|
||||
{
|
||||
windowEvent = true;
|
||||
return event->xconfigure.window;
|
||||
}
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
{
|
||||
windowEvent = true;
|
||||
return event->xkey.window;
|
||||
}
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
{
|
||||
windowEvent = true;
|
||||
return event->xbutton.window;
|
||||
}
|
||||
case MotionNotify:
|
||||
{
|
||||
windowEvent = true;
|
||||
return event->xmotion.window;
|
||||
}
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
{
|
||||
windowEvent = true;
|
||||
return event->xcrossing.window;
|
||||
}
|
||||
case FocusIn:
|
||||
case FocusOut:
|
||||
{
|
||||
windowEvent = true;
|
||||
return event->xfocus.window;
|
||||
}
|
||||
case GenericEvent:
|
||||
{
|
||||
if (event->xgeneric.extension == XINPUT_OPCODE)
|
||||
{
|
||||
switch (event->xgeneric.evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_TouchBegin:
|
||||
case XI_TouchUpdate:
|
||||
case XI_TouchEnd:
|
||||
{
|
||||
XIDeviceEvent* ev = (XIDeviceEvent*)event;
|
||||
windowEvent = true;
|
||||
return ev->event;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
windowEvent = false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
windowEvent = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<IWindow> _WindowXlibNew(std::string_view title,
|
||||
Display* display, void* xcbConn,
|
||||
int defaultScreen, XIM xIM, XIMStyle bestInputStyle, XFontSet fontset,
|
||||
GLXContext lastCtx, void* vulkanHandle, GLContext* glCtx);
|
||||
|
||||
static XIMStyle ChooseBetterStyle(XIMStyle style1, XIMStyle style2)
|
||||
{
|
||||
XIMStyle s,t;
|
||||
XIMStyle preedit = XIMPreeditArea | XIMPreeditCallbacks |
|
||||
XIMPreeditPosition | XIMPreeditNothing | XIMPreeditNone;
|
||||
XIMStyle status = XIMStatusArea | XIMStatusCallbacks |
|
||||
XIMStatusNothing | XIMStatusNone;
|
||||
if (style1 == 0) return style2;
|
||||
if (style2 == 0) return style1;
|
||||
if ((style1 & (preedit | status)) == (style2 & (preedit | status)))
|
||||
return style1;
|
||||
s = style1 & preedit;
|
||||
t = style2 & preedit;
|
||||
if (s != t) {
|
||||
if (s | t | XIMPreeditCallbacks)
|
||||
return (s == XIMPreeditCallbacks)?style1:style2;
|
||||
else if (s | t | XIMPreeditPosition)
|
||||
return (s == XIMPreeditPosition)?style1:style2;
|
||||
else if (s | t | XIMPreeditArea)
|
||||
return (s == XIMPreeditArea)?style1:style2;
|
||||
else if (s | t | XIMPreeditNothing)
|
||||
return (s == XIMPreeditNothing)?style1:style2;
|
||||
}
|
||||
else { /* if preedit flags are the same, compare status flags */
|
||||
s = style1 & status;
|
||||
t = style2 & status;
|
||||
if (s | t | XIMStatusCallbacks)
|
||||
return (s == XIMStatusCallbacks)?style1:style2;
|
||||
else if (s | t | XIMStatusArea)
|
||||
return (s == XIMStatusArea)?style1:style2;
|
||||
else if (s | t | XIMStatusNothing)
|
||||
return (s == XIMStatusNothing)?style1:style2;
|
||||
}
|
||||
return 0;
|
||||
std::shared_ptr<IWindow> _WindowXlibNew(std::string_view title, Display* display, void* xcbConn, int defaultScreen,
|
||||
XIM xIM, XIMStyle bestInputStyle, XFontSet fontset, GLXContext lastCtx,
|
||||
void* vulkanHandle, GLContext* glCtx);
|
||||
|
||||
static XIMStyle ChooseBetterStyle(XIMStyle style1, XIMStyle style2) {
|
||||
XIMStyle s, t;
|
||||
XIMStyle preedit = XIMPreeditArea | XIMPreeditCallbacks | XIMPreeditPosition | XIMPreeditNothing | XIMPreeditNone;
|
||||
XIMStyle status = XIMStatusArea | XIMStatusCallbacks | XIMStatusNothing | XIMStatusNone;
|
||||
if (style1 == 0)
|
||||
return style2;
|
||||
if (style2 == 0)
|
||||
return style1;
|
||||
if ((style1 & (preedit | status)) == (style2 & (preedit | status)))
|
||||
return style1;
|
||||
s = style1 & preedit;
|
||||
t = style2 & preedit;
|
||||
if (s != t) {
|
||||
if (s | t | XIMPreeditCallbacks)
|
||||
return (s == XIMPreeditCallbacks) ? style1 : style2;
|
||||
else if (s | t | XIMPreeditPosition)
|
||||
return (s == XIMPreeditPosition) ? style1 : style2;
|
||||
else if (s | t | XIMPreeditArea)
|
||||
return (s == XIMPreeditArea) ? style1 : style2;
|
||||
else if (s | t | XIMPreeditNothing)
|
||||
return (s == XIMPreeditNothing) ? style1 : style2;
|
||||
} else { /* if preedit flags are the same, compare status flags */
|
||||
s = style1 & status;
|
||||
t = style2 & status;
|
||||
if (s | t | XIMStatusCallbacks)
|
||||
return (s == XIMStatusCallbacks) ? style1 : style2;
|
||||
else if (s | t | XIMStatusArea)
|
||||
return (s == XIMStatusArea) ? style1 : style2;
|
||||
else if (s | t | XIMStatusNothing)
|
||||
return (s == XIMStatusNothing) ? style1 : style2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
class ApplicationXlib 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;
|
||||
GLContext m_glContext;
|
||||
|
||||
/* DBus single-instance */
|
||||
bool m_singleInstance;
|
||||
DBusConnection* m_dbus = nullptr;
|
||||
class ApplicationXlib 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;
|
||||
GLContext m_glContext;
|
||||
|
||||
/* All windows */
|
||||
std::unordered_map<Window, std::weak_ptr<IWindow>> m_windows;
|
||||
/* DBus single-instance */
|
||||
bool m_singleInstance;
|
||||
DBusConnection* m_dbus = nullptr;
|
||||
|
||||
Display* m_xDisp = nullptr;
|
||||
XIM m_xIM = nullptr;
|
||||
XFontSet m_fontset = nullptr;
|
||||
XIMStyle m_bestStyle = 0;
|
||||
int m_xDefaultScreen = 0;
|
||||
int m_x11Fd, m_dbusFd, m_maxFd;
|
||||
/* All windows */
|
||||
std::unordered_map<Window, std::weak_ptr<IWindow>> m_windows;
|
||||
|
||||
Display* m_xDisp = nullptr;
|
||||
XIM m_xIM = nullptr;
|
||||
XFontSet m_fontset = nullptr;
|
||||
XIMStyle m_bestStyle = 0;
|
||||
int m_xDefaultScreen = 0;
|
||||
int m_x11Fd, m_dbusFd, m_maxFd;
|
||||
|
||||
#if BOO_HAS_VULKAN
|
||||
/* Vulkan enable */
|
||||
xcb_connection_t* m_xcbConn;
|
||||
/* Vulkan enable */
|
||||
xcb_connection_t* m_xcbConn;
|
||||
|
||||
void* m_vkHandle = nullptr;
|
||||
PFN_vkGetInstanceProcAddr m_getVkProc = 0;
|
||||
bool loadVk()
|
||||
{
|
||||
const char filename[] = "libvulkan.so";
|
||||
void *handle, *symbol;
|
||||
void* m_vkHandle = nullptr;
|
||||
PFN_vkGetInstanceProcAddr m_getVkProc = 0;
|
||||
bool loadVk() {
|
||||
const char filename[] = "libvulkan.so";
|
||||
void *handle, *symbol;
|
||||
|
||||
#ifdef UNINSTALLED_LOADER
|
||||
handle = dlopen(UNINSTALLED_LOADER, RTLD_LAZY);
|
||||
if (!handle)
|
||||
handle = dlopen(filename, RTLD_LAZY);
|
||||
handle = dlopen(UNINSTALLED_LOADER, RTLD_LAZY);
|
||||
if (!handle)
|
||||
handle = dlopen(filename, RTLD_LAZY);
|
||||
#else
|
||||
handle = dlopen(filename, RTLD_LAZY);
|
||||
handle = dlopen(filename, RTLD_LAZY);
|
||||
#endif
|
||||
|
||||
if (handle)
|
||||
symbol = dlsym(handle, "vkGetInstanceProcAddr");
|
||||
if (handle)
|
||||
symbol = dlsym(handle, "vkGetInstanceProcAddr");
|
||||
|
||||
if (!handle || !symbol) {
|
||||
if (!handle || !symbol) {
|
||||
|
||||
if (handle)
|
||||
dlclose(handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_vkHandle = handle;
|
||||
m_getVkProc = reinterpret_cast<PFN_vkGetInstanceProcAddr>(symbol);
|
||||
return true;
|
||||
if (handle)
|
||||
dlclose(handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_vkHandle = handle;
|
||||
m_getVkProc = reinterpret_cast<PFN_vkGetInstanceProcAddr>(symbol);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void _deletedWindow(IWindow* window)
|
||||
{
|
||||
m_windows.erase((Window)window->getPlatformHandle());
|
||||
}
|
||||
|
||||
|
||||
void _deletedWindow(IWindow* window) { m_windows.erase((Window)window->getPlatformHandle()); }
|
||||
|
||||
public:
|
||||
ApplicationXlib(IApplicationCallback& callback,
|
||||
std::string_view uniqueName,
|
||||
std::string_view friendlyName,
|
||||
std::string_view pname,
|
||||
const std::vector<std::string>& args,
|
||||
std::string_view gfxApi,
|
||||
uint32_t samples,
|
||||
uint32_t anisotropy,
|
||||
bool deepColor,
|
||||
bool singleInstance)
|
||||
: m_callback(callback),
|
||||
m_uniqueName(uniqueName),
|
||||
m_friendlyName(friendlyName),
|
||||
m_pname(pname),
|
||||
m_args(args),
|
||||
m_singleInstance(singleInstance)
|
||||
{
|
||||
m_glContext.m_sampleCount = samples;
|
||||
m_glContext.m_anisotropy = anisotropy;
|
||||
m_glContext.m_deepColor = deepColor;
|
||||
ApplicationXlib(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName,
|
||||
std::string_view pname, const std::vector<std::string>& args, std::string_view gfxApi,
|
||||
uint32_t samples, uint32_t anisotropy, bool deepColor, bool singleInstance)
|
||||
: m_callback(callback)
|
||||
, m_uniqueName(uniqueName)
|
||||
, m_friendlyName(friendlyName)
|
||||
, m_pname(pname)
|
||||
, m_args(args)
|
||||
, m_singleInstance(singleInstance) {
|
||||
m_glContext.m_sampleCount = samples;
|
||||
m_glContext.m_anisotropy = anisotropy;
|
||||
m_glContext.m_deepColor = deepColor;
|
||||
#if BOO_HAS_VULKAN
|
||||
g_VulkanContext.m_sampleCountColor = samples;
|
||||
g_VulkanContext.m_sampleCountDepth = samples;
|
||||
g_VulkanContext.m_anisotropy = anisotropy;
|
||||
g_VulkanContext.m_deepColor = deepColor;
|
||||
g_VulkanContext.m_sampleCountColor = samples;
|
||||
g_VulkanContext.m_sampleCountDepth = samples;
|
||||
g_VulkanContext.m_anisotropy = anisotropy;
|
||||
g_VulkanContext.m_deepColor = deepColor;
|
||||
|
||||
/* Check for Vulkan presence and preference */
|
||||
bool tryVulkan = true;
|
||||
if (!gfxApi.compare("OpenGL"))
|
||||
tryVulkan = false;
|
||||
for (const std::string& arg : args)
|
||||
{
|
||||
if (!arg.compare("--gl"))
|
||||
{
|
||||
tryVulkan = false;
|
||||
break;
|
||||
}
|
||||
if (!arg.compare("--vulkan"))
|
||||
{
|
||||
tryVulkan = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Check for Vulkan presence and preference */
|
||||
bool tryVulkan = true;
|
||||
if (!gfxApi.compare("OpenGL"))
|
||||
tryVulkan = false;
|
||||
for (const std::string& arg : args) {
|
||||
if (!arg.compare("--gl")) {
|
||||
tryVulkan = false;
|
||||
break;
|
||||
}
|
||||
if (!arg.compare("--vulkan")) {
|
||||
tryVulkan = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tryVulkan)
|
||||
loadVk();
|
||||
if (tryVulkan)
|
||||
loadVk();
|
||||
|
||||
if (m_getVkProc)
|
||||
Log.report(logvisor::Info, "using Vulkan renderer");
|
||||
else
|
||||
if (m_getVkProc)
|
||||
Log.report(logvisor::Info, "using Vulkan renderer");
|
||||
else
|
||||
#endif
|
||||
Log.report(logvisor::Info, "using OpenGL renderer");
|
||||
Log.report(logvisor::Info, "using OpenGL renderer");
|
||||
|
||||
/* DBus single instance registration */
|
||||
bool isFirst;
|
||||
m_dbus = RegisterDBus(uniqueName.data(), 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");
|
||||
/* DBus single instance registration */
|
||||
bool isFirst;
|
||||
m_dbus = RegisterDBus(uniqueName.data(), 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);
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
if (!XInitThreads())
|
||||
{
|
||||
Log.report(logvisor::Fatal, "X doesn't support multithreading");
|
||||
return;
|
||||
}
|
||||
if (!XInitThreads()) {
|
||||
Log.report(logvisor::Fatal, "X doesn't support multithreading");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Program is portable to all locales */
|
||||
setlocale(LC_ALL, "");
|
||||
/* Program is portable to all locales */
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
/* Open Xlib Display */
|
||||
m_xDisp = XOpenDisplay(0);
|
||||
if (!m_xDisp)
|
||||
{
|
||||
Log.report(logvisor::Fatal, "Can't open X display");
|
||||
return;
|
||||
}
|
||||
/* Open Xlib Display */
|
||||
m_xDisp = XOpenDisplay(0);
|
||||
if (!m_xDisp) {
|
||||
Log.report(logvisor::Fatal, "Can't open X display");
|
||||
return;
|
||||
}
|
||||
|
||||
#if BOO_HAS_VULKAN
|
||||
/* Cast Display to XCB connection for vulkan */
|
||||
m_xcbConn = XGetXCBConnection(m_xDisp);
|
||||
if (!m_xcbConn)
|
||||
{
|
||||
Log.report(logvisor::Fatal, "Can't cast Display to XCB connection for Vulkan");
|
||||
return;
|
||||
}
|
||||
/* Cast Display to XCB connection for vulkan */
|
||||
m_xcbConn = XGetXCBConnection(m_xDisp);
|
||||
if (!m_xcbConn) {
|
||||
Log.report(logvisor::Fatal, "Can't cast Display to XCB connection for Vulkan");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Configure locale */
|
||||
if (!XSupportsLocale()) {
|
||||
Log.report(logvisor::Fatal, "X does not support locale %s.",
|
||||
setlocale(LC_ALL, nullptr));
|
||||
return;
|
||||
}
|
||||
if (XSetLocaleModifiers("") == nullptr)
|
||||
Log.report(logvisor::Warning, "Cannot set locale modifiers.");
|
||||
/* Configure locale */
|
||||
if (!XSupportsLocale()) {
|
||||
Log.report(logvisor::Fatal, "X does not support locale %s.", setlocale(LC_ALL, nullptr));
|
||||
return;
|
||||
}
|
||||
if (XSetLocaleModifiers("") == nullptr)
|
||||
Log.report(logvisor::Warning, "Cannot set locale modifiers.");
|
||||
|
||||
if ((m_xIM = XOpenIM(m_xDisp, nullptr, nullptr, nullptr)))
|
||||
{
|
||||
char** missing_charsets;
|
||||
int num_missing_charsets = 0;
|
||||
char* default_string;
|
||||
m_fontset = XCreateFontSet(m_xDisp,
|
||||
"-adobe-helvetica-*-r-*-*-*-120-*-*-*-*-*-*,\
|
||||
if ((m_xIM = XOpenIM(m_xDisp, nullptr, nullptr, nullptr))) {
|
||||
char** missing_charsets;
|
||||
int num_missing_charsets = 0;
|
||||
char* default_string;
|
||||
m_fontset = XCreateFontSet(m_xDisp,
|
||||
"-adobe-helvetica-*-r-*-*-*-120-*-*-*-*-*-*,\
|
||||
-misc-fixed-*-r-*-*-*-130-*-*-*-*-*-*",
|
||||
&missing_charsets, &num_missing_charsets,
|
||||
&default_string);
|
||||
&missing_charsets, &num_missing_charsets, &default_string);
|
||||
|
||||
/* figure out which styles the IM can support */
|
||||
XIMStyles* im_supported_styles;
|
||||
XIMStyle app_supported_styles;
|
||||
XGetIMValues(m_xIM, XNQueryInputStyle, &im_supported_styles, nullptr);
|
||||
/* set flags for the styles our application can support */
|
||||
app_supported_styles = XIMPreeditNone | XIMPreeditNothing | XIMPreeditPosition;
|
||||
app_supported_styles |= XIMStatusNone | XIMStatusNothing;
|
||||
/*
|
||||
* now look at each of the IM supported styles, and
|
||||
* chose the "best" one that we can support.
|
||||
*/
|
||||
for (int i=0 ; i<im_supported_styles->count_styles ; ++i)
|
||||
{
|
||||
XIMStyle style = im_supported_styles->supported_styles[i];
|
||||
if ((style & app_supported_styles) == style) /* if we can handle it */
|
||||
m_bestStyle = ChooseBetterStyle(style, m_bestStyle);
|
||||
}
|
||||
/* if we couldn't support any of them, print an error and exit */
|
||||
if (m_bestStyle == 0)
|
||||
{
|
||||
Log.report(logvisor::Fatal, "interaction style not supported.");
|
||||
return;
|
||||
}
|
||||
XFree(im_supported_styles);
|
||||
}
|
||||
|
||||
m_xDefaultScreen = DefaultScreen(m_xDisp);
|
||||
X_CURSORS.m_pointer = XCreateFontCursor(m_xDisp, XC_left_ptr);
|
||||
X_CURSORS.m_hArrow = XCreateFontCursor(m_xDisp, XC_sb_h_double_arrow);
|
||||
X_CURSORS.m_vArrow = XCreateFontCursor(m_xDisp, XC_sb_v_double_arrow);
|
||||
X_CURSORS.m_ibeam = XCreateFontCursor(m_xDisp, XC_xterm);
|
||||
X_CURSORS.m_crosshairs = XCreateFontCursor(m_xDisp, XC_cross);
|
||||
X_CURSORS.m_wait = XCreateFontCursor(m_xDisp, XC_watch);
|
||||
|
||||
/* The xkb extension requests that the X server does not
|
||||
* send repeated keydown events when a key is held */
|
||||
XkbQueryExtension(m_xDisp, &XINPUT_OPCODE, nullptr, nullptr, nullptr, nullptr);
|
||||
XkbSetDetectableAutoRepeat(m_xDisp, True, nullptr);
|
||||
|
||||
/* Get file descriptors of xcb and dbus interfaces */
|
||||
m_x11Fd = ConnectionNumber(m_xDisp);
|
||||
dbus_connection_get_unix_fd(m_dbus, &m_dbusFd);
|
||||
m_maxFd = MAX(m_x11Fd, m_dbusFd);
|
||||
|
||||
XFlush(m_xDisp);
|
||||
/* figure out which styles the IM can support */
|
||||
XIMStyles* im_supported_styles;
|
||||
XIMStyle app_supported_styles;
|
||||
XGetIMValues(m_xIM, XNQueryInputStyle, &im_supported_styles, nullptr);
|
||||
/* set flags for the styles our application can support */
|
||||
app_supported_styles = XIMPreeditNone | XIMPreeditNothing | XIMPreeditPosition;
|
||||
app_supported_styles |= XIMStatusNone | XIMStatusNothing;
|
||||
/*
|
||||
* now look at each of the IM supported styles, and
|
||||
* chose the "best" one that we can support.
|
||||
*/
|
||||
for (int i = 0; i < im_supported_styles->count_styles; ++i) {
|
||||
XIMStyle style = im_supported_styles->supported_styles[i];
|
||||
if ((style & app_supported_styles) == style) /* if we can handle it */
|
||||
m_bestStyle = ChooseBetterStyle(style, m_bestStyle);
|
||||
}
|
||||
/* if we couldn't support any of them, print an error and exit */
|
||||
if (m_bestStyle == 0) {
|
||||
Log.report(logvisor::Fatal, "interaction style not supported.");
|
||||
return;
|
||||
}
|
||||
XFree(im_supported_styles);
|
||||
}
|
||||
|
||||
~ApplicationXlib()
|
||||
{
|
||||
for (auto& p : m_windows)
|
||||
if (auto w = p.second.lock())
|
||||
w->_cleanup();
|
||||
m_xDefaultScreen = DefaultScreen(m_xDisp);
|
||||
X_CURSORS.m_pointer = XCreateFontCursor(m_xDisp, XC_left_ptr);
|
||||
X_CURSORS.m_hArrow = XCreateFontCursor(m_xDisp, XC_sb_h_double_arrow);
|
||||
X_CURSORS.m_vArrow = XCreateFontCursor(m_xDisp, XC_sb_v_double_arrow);
|
||||
X_CURSORS.m_ibeam = XCreateFontCursor(m_xDisp, XC_xterm);
|
||||
X_CURSORS.m_crosshairs = XCreateFontCursor(m_xDisp, XC_cross);
|
||||
X_CURSORS.m_wait = XCreateFontCursor(m_xDisp, XC_watch);
|
||||
|
||||
/* The xkb extension requests that the X server does not
|
||||
* send repeated keydown events when a key is held */
|
||||
XkbQueryExtension(m_xDisp, &XINPUT_OPCODE, nullptr, nullptr, nullptr, nullptr);
|
||||
XkbSetDetectableAutoRepeat(m_xDisp, True, nullptr);
|
||||
|
||||
/* Get file descriptors of xcb and dbus interfaces */
|
||||
m_x11Fd = ConnectionNumber(m_xDisp);
|
||||
dbus_connection_get_unix_fd(m_dbus, &m_dbusFd);
|
||||
m_maxFd = MAX(m_x11Fd, m_dbusFd);
|
||||
|
||||
XFlush(m_xDisp);
|
||||
}
|
||||
|
||||
~ApplicationXlib() {
|
||||
for (auto& p : m_windows)
|
||||
if (auto w = p.second.lock())
|
||||
w->_cleanup();
|
||||
|
||||
#if BOO_HAS_VULKAN
|
||||
g_VulkanContext.destroyDevice();
|
||||
g_VulkanContext.destroyDevice();
|
||||
#endif
|
||||
|
||||
if (m_fontset)
|
||||
XFreeFontSet(m_xDisp, m_fontset);
|
||||
if (m_xIM)
|
||||
XCloseIM(m_xIM);
|
||||
XCloseDisplay(m_xDisp);
|
||||
}
|
||||
|
||||
EPlatformType getPlatformType() const
|
||||
{
|
||||
return EPlatformType::Xlib;
|
||||
}
|
||||
|
||||
/* Empty handler for SIGINT */
|
||||
static void _sigint(int) {}
|
||||
if (m_fontset)
|
||||
XFreeFontSet(m_xDisp, m_fontset);
|
||||
if (m_xIM)
|
||||
XCloseIM(m_xIM);
|
||||
XCloseDisplay(m_xDisp);
|
||||
}
|
||||
|
||||
int run()
|
||||
{
|
||||
if (!m_xDisp)
|
||||
return 1;
|
||||
EPlatformType getPlatformType() const { return EPlatformType::Xlib; }
|
||||
|
||||
/* SIGINT will be used to cancel main thread when client thread ends
|
||||
* (also enables graceful quitting via ctrl-c) */
|
||||
pthread_t mainThread = pthread_self();
|
||||
struct sigaction s;
|
||||
s.sa_handler = _sigint;
|
||||
sigemptyset(&s.sa_mask);
|
||||
s.sa_flags = 0;
|
||||
sigaction(SIGINT, &s, nullptr);
|
||||
sigaction(SIGUSR2, &s, nullptr);
|
||||
/* Empty handler for SIGINT */
|
||||
static void _sigint(int) {}
|
||||
|
||||
sigset_t waitmask, origmask;
|
||||
sigemptyset(&waitmask);
|
||||
sigaddset(&waitmask, SIGINT);
|
||||
sigaddset(&waitmask, SIGUSR2);
|
||||
pthread_sigmask(SIG_BLOCK, &waitmask, &origmask);
|
||||
int run() {
|
||||
if (!m_xDisp)
|
||||
return 1;
|
||||
|
||||
/* Spawn client thread */
|
||||
int clientReturn = INT_MIN;
|
||||
std::mutex initmt;
|
||||
std::condition_variable initcv;
|
||||
std::unique_lock<std::mutex> outerLk(initmt);
|
||||
std::thread clientThread([&]()
|
||||
{
|
||||
std::unique_lock<std::mutex> innerLk(initmt);
|
||||
innerLk.unlock();
|
||||
initcv.notify_one();
|
||||
std::string thrName = std::string(getFriendlyName()) + " Client";
|
||||
logvisor::RegisterThreadName(thrName.c_str());
|
||||
clientReturn = m_callback.appMain(this);
|
||||
pthread_kill(mainThread, SIGUSR2);
|
||||
});
|
||||
initcv.wait(outerLk);
|
||||
/* SIGINT will be used to cancel main thread when client thread ends
|
||||
* (also enables graceful quitting via ctrl-c) */
|
||||
pthread_t mainThread = pthread_self();
|
||||
struct sigaction s;
|
||||
s.sa_handler = _sigint;
|
||||
sigemptyset(&s.sa_mask);
|
||||
s.sa_flags = 0;
|
||||
sigaction(SIGINT, &s, nullptr);
|
||||
sigaction(SIGUSR2, &s, nullptr);
|
||||
|
||||
/* Begin application event loop */
|
||||
while (clientReturn == INT_MIN)
|
||||
{
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(m_x11Fd, &fds);
|
||||
FD_SET(m_dbusFd, &fds);
|
||||
if (pselect(m_maxFd+1, &fds, NULL, NULL, NULL, &origmask) < 0)
|
||||
{
|
||||
/* SIGINT/SIGUSR2 handled here */
|
||||
if (errno == EINTR)
|
||||
break;
|
||||
}
|
||||
sigset_t waitmask, origmask;
|
||||
sigemptyset(&waitmask);
|
||||
sigaddset(&waitmask, SIGINT);
|
||||
sigaddset(&waitmask, SIGUSR2);
|
||||
pthread_sigmask(SIG_BLOCK, &waitmask, &origmask);
|
||||
|
||||
if (FD_ISSET(m_x11Fd, &fds))
|
||||
{
|
||||
bool needsQuit = false;
|
||||
/* Spawn client thread */
|
||||
int clientReturn = INT_MIN;
|
||||
std::mutex initmt;
|
||||
std::condition_variable initcv;
|
||||
std::unique_lock<std::mutex> outerLk(initmt);
|
||||
std::thread clientThread([&]() {
|
||||
std::unique_lock<std::mutex> innerLk(initmt);
|
||||
innerLk.unlock();
|
||||
initcv.notify_one();
|
||||
std::string thrName = std::string(getFriendlyName()) + " Client";
|
||||
logvisor::RegisterThreadName(thrName.c_str());
|
||||
clientReturn = m_callback.appMain(this);
|
||||
pthread_kill(mainThread, SIGUSR2);
|
||||
});
|
||||
initcv.wait(outerLk);
|
||||
|
||||
XLockDisplay(m_xDisp);
|
||||
while (XPending(m_xDisp))
|
||||
{
|
||||
XEvent event;
|
||||
XNextEvent(m_xDisp, &event);
|
||||
if (XFilterEvent(&event, None)) continue;
|
||||
bool windowEvent;
|
||||
Window evWindow = GetWindowOfEvent(&event, windowEvent);
|
||||
if (windowEvent)
|
||||
{
|
||||
auto window = m_windows.find(evWindow);
|
||||
if (window != m_windows.end())
|
||||
if (std::shared_ptr<IWindow> w = window->second.lock())
|
||||
if (w->_incomingEvent(&event) && m_windows.size() == 1)
|
||||
{
|
||||
needsQuit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
XUnlockDisplay(m_xDisp);
|
||||
/* Begin application event loop */
|
||||
while (clientReturn == INT_MIN) {
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(m_x11Fd, &fds);
|
||||
FD_SET(m_dbusFd, &fds);
|
||||
if (pselect(m_maxFd + 1, &fds, NULL, NULL, NULL, &origmask) < 0) {
|
||||
/* SIGINT/SIGUSR2 handled here */
|
||||
if (errno == EINTR)
|
||||
break;
|
||||
}
|
||||
|
||||
if (needsQuit)
|
||||
break;
|
||||
}
|
||||
if (FD_ISSET(m_x11Fd, &fds)) {
|
||||
bool needsQuit = false;
|
||||
|
||||
if (FD_ISSET(m_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);
|
||||
if (clientThread.joinable())
|
||||
clientThread.join();
|
||||
|
||||
return clientReturn;
|
||||
}
|
||||
|
||||
std::string_view getUniqueName() const
|
||||
{
|
||||
return m_uniqueName;
|
||||
}
|
||||
|
||||
std::string_view getFriendlyName() const
|
||||
{
|
||||
return m_friendlyName;
|
||||
}
|
||||
|
||||
std::string_view getProcessName() const
|
||||
{
|
||||
return m_pname;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getArgs() const
|
||||
{
|
||||
return m_args;
|
||||
}
|
||||
|
||||
std::shared_ptr<IWindow> newWindow(std::string_view title)
|
||||
{
|
||||
XLockDisplay(m_xDisp);
|
||||
#if BOO_HAS_VULKAN
|
||||
std::shared_ptr<IWindow> newWindow = _WindowXlibNew(title, m_xDisp, m_xcbConn, m_xDefaultScreen, m_xIM,
|
||||
m_bestStyle, m_fontset, m_lastGlxCtx, (void*)m_getVkProc, &m_glContext);
|
||||
#else
|
||||
std::shared_ptr<IWindow> newWindow = _WindowXlibNew(title, m_xDisp, nullptr, m_xDefaultScreen, m_xIM,
|
||||
m_bestStyle, m_fontset, m_lastGlxCtx, nullptr, &m_glContext);
|
||||
#endif
|
||||
m_windows[(Window)newWindow->getPlatformHandle()] = newWindow;
|
||||
while (XPending(m_xDisp)) {
|
||||
XEvent event;
|
||||
XNextEvent(m_xDisp, &event);
|
||||
if (XFilterEvent(&event, None))
|
||||
continue;
|
||||
bool windowEvent;
|
||||
Window evWindow = GetWindowOfEvent(&event, windowEvent);
|
||||
if (windowEvent) {
|
||||
auto window = m_windows.find(evWindow);
|
||||
if (window != m_windows.end())
|
||||
if (std::shared_ptr<IWindow> w = window->second.lock())
|
||||
if (w->_incomingEvent(&event) && m_windows.size() == 1) {
|
||||
needsQuit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
XUnlockDisplay(m_xDisp);
|
||||
return newWindow;
|
||||
|
||||
if (needsQuit)
|
||||
break;
|
||||
}
|
||||
|
||||
if (FD_ISSET(m_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Last GLX context */
|
||||
GLXContext m_lastGlxCtx = nullptr;
|
||||
m_callback.appQuitting(this);
|
||||
if (clientThread.joinable())
|
||||
clientThread.join();
|
||||
|
||||
return clientReturn;
|
||||
}
|
||||
|
||||
std::string_view getUniqueName() const { return m_uniqueName; }
|
||||
|
||||
std::string_view getFriendlyName() const { return m_friendlyName; }
|
||||
|
||||
std::string_view getProcessName() const { return m_pname; }
|
||||
|
||||
const std::vector<std::string>& getArgs() const { return m_args; }
|
||||
|
||||
std::shared_ptr<IWindow> newWindow(std::string_view title) {
|
||||
XLockDisplay(m_xDisp);
|
||||
#if BOO_HAS_VULKAN
|
||||
std::shared_ptr<IWindow> newWindow = _WindowXlibNew(title, m_xDisp, m_xcbConn, m_xDefaultScreen, m_xIM, m_bestStyle,
|
||||
m_fontset, m_lastGlxCtx, (void*)m_getVkProc, &m_glContext);
|
||||
#else
|
||||
std::shared_ptr<IWindow> newWindow = _WindowXlibNew(title, m_xDisp, nullptr, m_xDefaultScreen, m_xIM, m_bestStyle,
|
||||
m_fontset, m_lastGlxCtx, nullptr, &m_glContext);
|
||||
#endif
|
||||
m_windows[(Window)newWindow->getPlatformHandle()] = newWindow;
|
||||
XUnlockDisplay(m_xDisp);
|
||||
return newWindow;
|
||||
}
|
||||
|
||||
/* Last GLX context */
|
||||
GLXContext m_lastGlxCtx = nullptr;
|
||||
};
|
||||
|
||||
void _XlibUpdateLastGlxCtx(GLXContext lastGlxCtx)
|
||||
{
|
||||
static_cast<ApplicationXlib*>(APP)->m_lastGlxCtx = lastGlxCtx;
|
||||
}
|
||||
|
||||
}
|
||||
void _XlibUpdateLastGlxCtx(GLXContext lastGlxCtx) { static_cast<ApplicationXlib*>(APP)->m_lastGlxCtx = lastGlxCtx; }
|
||||
|
||||
} // namespace boo
|
||||
|
||||
@@ -5,246 +5,115 @@
|
||||
#include <X11/Xlib.h>
|
||||
#undef None
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
struct GraphicsContextWayland : IGraphicsContext
|
||||
{
|
||||
namespace boo {
|
||||
|
||||
EGraphicsAPI m_api;
|
||||
EPixelFormat m_pf;
|
||||
IWindow* m_parentWindow;
|
||||
struct GraphicsContextWayland : IGraphicsContext {
|
||||
|
||||
EGraphicsAPI m_api;
|
||||
EPixelFormat m_pf;
|
||||
IWindow* m_parentWindow;
|
||||
|
||||
public:
|
||||
IWindowCallback* m_callback;
|
||||
IWindowCallback* m_callback;
|
||||
|
||||
GraphicsContextWayland(EGraphicsAPI api, IWindow* parentWindow)
|
||||
: m_api(api),
|
||||
m_pf(EPixelFormat::RGBA8),
|
||||
m_parentWindow(parentWindow)
|
||||
{}
|
||||
GraphicsContextWayland(EGraphicsAPI api, IWindow* parentWindow)
|
||||
: m_api(api), m_pf(EPixelFormat::RGBA8), m_parentWindow(parentWindow) {}
|
||||
|
||||
~GraphicsContextWayland()
|
||||
{
|
||||
~GraphicsContextWayland() {}
|
||||
|
||||
}
|
||||
void _setCallback(IWindowCallback* cb) { m_callback = cb; }
|
||||
|
||||
void _setCallback(IWindowCallback* cb)
|
||||
{
|
||||
m_callback = cb;
|
||||
}
|
||||
EGraphicsAPI getAPI() const { return m_api; }
|
||||
|
||||
EGraphicsAPI getAPI() const
|
||||
{
|
||||
return m_api;
|
||||
}
|
||||
EPixelFormat getPixelFormat() const { return m_pf; }
|
||||
|
||||
EPixelFormat getPixelFormat() const
|
||||
{
|
||||
return m_pf;
|
||||
}
|
||||
void setPixelFormat(EPixelFormat pf) {
|
||||
if (pf > EPixelFormat::RGBAF32_Z24)
|
||||
return;
|
||||
m_pf = pf;
|
||||
}
|
||||
|
||||
void setPixelFormat(EPixelFormat pf)
|
||||
{
|
||||
if (pf > EPixelFormat::RGBAF32_Z24)
|
||||
return;
|
||||
m_pf = pf;
|
||||
}
|
||||
bool initializeContext(void*) { return false; }
|
||||
|
||||
bool initializeContext(void*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
void makeCurrent() {}
|
||||
|
||||
void makeCurrent()
|
||||
{
|
||||
}
|
||||
void postInit() {}
|
||||
|
||||
void postInit()
|
||||
{
|
||||
}
|
||||
IGraphicsCommandQueue* getCommandQueue() { return nullptr; }
|
||||
|
||||
IGraphicsCommandQueue* getCommandQueue()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
IGraphicsDataFactory* getDataFactory() { return nullptr; }
|
||||
|
||||
IGraphicsDataFactory* getDataFactory()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
IGraphicsDataFactory* getMainContextDataFactory() { return nullptr; }
|
||||
|
||||
IGraphicsDataFactory* getMainContextDataFactory()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IGraphicsDataFactory* getLoadContextDataFactory()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void present()
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct WindowWayland : IWindow
|
||||
{
|
||||
GraphicsContextWayland m_gfxCtx;
|
||||
|
||||
WindowWayland(std::string_view title)
|
||||
: m_gfxCtx(IGraphicsContext::EGraphicsAPI::OpenGL3_3, this)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~WindowWayland()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void setCallback(IWindowCallback* cb)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void closeWindow()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void showWindow()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void hideWindow()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string getTitle()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void setTitle(std::string_view title)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void setCursor(EMouseCursor cursor)
|
||||
{
|
||||
}
|
||||
|
||||
void setWaitCursor(bool wait)
|
||||
{
|
||||
}
|
||||
|
||||
void setWindowFrameDefault()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void setWindowFrame(float x, float y, float w, float h)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void setWindowFrame(int x, int y, int w, int h)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float getVirtualPixelFactor() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setStyle(EWindowStyle /*style*/)
|
||||
{}
|
||||
|
||||
EWindowStyle getStyle() const
|
||||
{
|
||||
return EWindowStyle::None;
|
||||
}
|
||||
|
||||
bool isFullscreen() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void setFullscreen(bool fs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void claimKeyboardFocus(const int coord[2])
|
||||
{
|
||||
}
|
||||
|
||||
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz)
|
||||
{
|
||||
return std::unique_ptr<uint8_t[]>();
|
||||
}
|
||||
|
||||
void waitForRetrace()
|
||||
{
|
||||
}
|
||||
|
||||
uintptr_t getPlatformHandle() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ETouchType getTouchType() const
|
||||
{
|
||||
return ETouchType::None;
|
||||
}
|
||||
|
||||
|
||||
IGraphicsCommandQueue* getCommandQueue()
|
||||
{
|
||||
return m_gfxCtx.getCommandQueue();
|
||||
}
|
||||
|
||||
IGraphicsDataFactory* getDataFactory()
|
||||
{
|
||||
return m_gfxCtx.getDataFactory();
|
||||
}
|
||||
|
||||
IGraphicsDataFactory* getMainContextDataFactory()
|
||||
{
|
||||
return m_gfxCtx.getMainContextDataFactory();
|
||||
}
|
||||
|
||||
IGraphicsDataFactory* getLoadContextDataFactory()
|
||||
{
|
||||
return m_gfxCtx.getLoadContextDataFactory();
|
||||
}
|
||||
IGraphicsDataFactory* getLoadContextDataFactory() { return nullptr; }
|
||||
|
||||
void present() {}
|
||||
};
|
||||
|
||||
std::shared_ptr<IWindow> _WindowWaylandNew(std::string_view title)
|
||||
{
|
||||
return std::make_shared<WindowWayland>(title);
|
||||
}
|
||||
|
||||
}
|
||||
struct WindowWayland : IWindow {
|
||||
GraphicsContextWayland m_gfxCtx;
|
||||
|
||||
WindowWayland(std::string_view title) : m_gfxCtx(IGraphicsContext::EGraphicsAPI::OpenGL3_3, this) {}
|
||||
|
||||
~WindowWayland() {}
|
||||
|
||||
void setCallback(IWindowCallback* cb) {}
|
||||
|
||||
void closeWindow() {}
|
||||
|
||||
void showWindow() {}
|
||||
|
||||
void hideWindow() {}
|
||||
|
||||
std::string getTitle() { return ""; }
|
||||
|
||||
void setTitle(std::string_view title) {}
|
||||
|
||||
void setCursor(EMouseCursor cursor) {}
|
||||
|
||||
void setWaitCursor(bool wait) {}
|
||||
|
||||
void setWindowFrameDefault() {}
|
||||
|
||||
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const {}
|
||||
|
||||
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const {}
|
||||
|
||||
void setWindowFrame(float x, float y, float w, float h) {}
|
||||
|
||||
void setWindowFrame(int x, int y, int w, int h) {}
|
||||
|
||||
float getVirtualPixelFactor() const { return 0; }
|
||||
|
||||
void setStyle(EWindowStyle /*style*/) {}
|
||||
|
||||
EWindowStyle getStyle() const { return EWindowStyle::None; }
|
||||
|
||||
bool isFullscreen() const { return false; }
|
||||
|
||||
void setFullscreen(bool fs) {}
|
||||
|
||||
void claimKeyboardFocus(const int coord[2]) {}
|
||||
|
||||
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) { return false; }
|
||||
|
||||
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) { return std::unique_ptr<uint8_t[]>(); }
|
||||
|
||||
void waitForRetrace() {}
|
||||
|
||||
uintptr_t getPlatformHandle() const { return 0; }
|
||||
|
||||
ETouchType getTouchType() const { return ETouchType::None; }
|
||||
|
||||
IGraphicsCommandQueue* getCommandQueue() { return m_gfxCtx.getCommandQueue(); }
|
||||
|
||||
IGraphicsDataFactory* getDataFactory() { return m_gfxCtx.getDataFactory(); }
|
||||
|
||||
IGraphicsDataFactory* getMainContextDataFactory() { return m_gfxCtx.getMainContextDataFactory(); }
|
||||
|
||||
IGraphicsDataFactory* getLoadContextDataFactory() { return m_gfxCtx.getLoadContextDataFactory(); }
|
||||
};
|
||||
|
||||
std::shared_ptr<IWindow> _WindowWaylandNew(std::string_view title) { return std::make_shared<WindowWayland>(title); }
|
||||
|
||||
} // namespace boo
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,19 +2,16 @@
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
namespace boo {
|
||||
|
||||
struct XlibCursors
|
||||
{
|
||||
Cursor m_pointer;
|
||||
Cursor m_hArrow;
|
||||
Cursor m_vArrow;
|
||||
Cursor m_ibeam;
|
||||
Cursor m_crosshairs;
|
||||
Cursor m_wait;
|
||||
struct XlibCursors {
|
||||
Cursor m_pointer;
|
||||
Cursor m_hArrow;
|
||||
Cursor m_vArrow;
|
||||
Cursor m_ibeam;
|
||||
Cursor m_crosshairs;
|
||||
Cursor m_wait;
|
||||
};
|
||||
extern XlibCursors X_CURSORS;
|
||||
|
||||
}
|
||||
|
||||
} // namespace boo
|
||||
|
||||
Reference in New Issue
Block a user