Dirty trick to not expose platform specific variables.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m2s
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m2s
This commit is contained in:
@@ -51,47 +51,13 @@ public:
|
||||
bool& operator[](const MouseButton& btn);
|
||||
};
|
||||
|
||||
#ifdef __linux__
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
//TODO Interfaces to hide the need for this.
|
||||
struct XVars {
|
||||
Window window;
|
||||
XEvent xev;
|
||||
Display* display;
|
||||
int defaultScreen;
|
||||
XVisualInfo* visual;
|
||||
XSetWindowAttributes xSetWindowAttributes;
|
||||
XWindowAttributes windowAttributes;
|
||||
Atom wmDeleteWindow;
|
||||
Atom windowTypeAtom;
|
||||
Atom windowTypeUtilityAtom;
|
||||
XSizeHints hints;
|
||||
Cursor invisible_cursor = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
struct WIN32Vars {
|
||||
HINSTANCE hInstance;
|
||||
HWND hwnd;
|
||||
HDC hdc;
|
||||
};
|
||||
#endif
|
||||
|
||||
/// RWindow is a class implementation of a platform-independent window abstraction.
|
||||
/// This library also provides abstractions for user-input devices, and their interaction with the window.
|
||||
class ReWindow::RWindow {
|
||||
protected:
|
||||
#ifdef __linux__
|
||||
XVars xVars;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
WIN32Vars w32Vars;
|
||||
#endif
|
||||
class Platform;
|
||||
Platform* platform;
|
||||
inline static RWindow* extant;
|
||||
|
||||
int width = 1280;
|
||||
int height = 720;
|
||||
@@ -147,7 +113,7 @@ public:
|
||||
void SetFlag(WindowFlag flag, bool state);
|
||||
|
||||
/// The default constructor does not set any members, and are left uninitialized.
|
||||
RWindow() = default;
|
||||
RWindow();
|
||||
/// Constructs a window by explicitly setting the title, width, height, and optionally; rendering API, fullscreen, resizable, and vsync.
|
||||
/// @param wTitle The window title text.
|
||||
/// @param wWidth
|
||||
@@ -162,7 +128,7 @@ public:
|
||||
/// @note If the window handle is not already destroyed, it will be done here.
|
||||
virtual ~RWindow();
|
||||
|
||||
static RWindow* GetExtant();
|
||||
static RWindow* GetExtant() { return extant; };
|
||||
|
||||
/// Bindables are provided for hooking into window instances conveniently, without the need to derive and override for simple use cases.
|
||||
Event<> OnOpenEvent;
|
||||
|
@@ -2,8 +2,26 @@
|
||||
#include <ReWindow/Logger.h>
|
||||
#include <GL/glx.h>
|
||||
#include <dlfcn.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
using namespace ReWindow;
|
||||
class ReWindow::RWindow::Platform {
|
||||
public:
|
||||
Window window;
|
||||
XEvent xev;
|
||||
Display* display;
|
||||
int defaultScreen;
|
||||
XVisualInfo* visual;
|
||||
XSetWindowAttributes xSetWindowAttributes;
|
||||
XWindowAttributes windowAttributes;
|
||||
Atom wmDeleteWindow;
|
||||
Atom windowTypeAtom;
|
||||
Atom windowTypeUtilityAtom;
|
||||
XSizeHints hints;
|
||||
Cursor invisible_cursor = 0;
|
||||
};
|
||||
|
||||
void* glx_lib = nullptr;
|
||||
void* opengl_lib = nullptr;
|
||||
@@ -42,13 +60,13 @@ GLXContext gl_context;
|
||||
|
||||
|
||||
void OpenGLWindow::SwapBuffers() {
|
||||
OpenGL::glXSwapBuffers(xVars.display,xVars.window);
|
||||
OpenGL::glXSwapBuffers(platform->display,platform->window);
|
||||
}
|
||||
|
||||
void OpenGLWindow::SetVsyncEnabled(bool state) {
|
||||
PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
|
||||
glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) OpenGL::glXGetProcAddressARB((const GLubyte *) "glXSwapIntervalEXT");
|
||||
glXSwapIntervalEXT(xVars.display, xVars.window, state);
|
||||
glXSwapIntervalEXT(platform->display, platform->window, state);
|
||||
}
|
||||
|
||||
std::string OpenGLWindow::GetGraphicsDriverVendor() {
|
||||
@@ -59,13 +77,13 @@ bool OpenGLWindow::Open() {
|
||||
if (!OpenGL::constructor_success)
|
||||
return false;
|
||||
|
||||
xVars.display = XOpenDisplay(nullptr);
|
||||
xVars.defaultScreen = DefaultScreen(xVars.display);
|
||||
platform->display = XOpenDisplay(nullptr);
|
||||
platform->defaultScreen = DefaultScreen(platform->display);
|
||||
|
||||
xVars.xSetWindowAttributes.border_pixel = BlackPixel(xVars.display, xVars.defaultScreen);
|
||||
xVars.xSetWindowAttributes.background_pixel = BlackPixel(xVars.display, xVars.defaultScreen);
|
||||
xVars.xSetWindowAttributes.override_redirect = True;
|
||||
xVars.xSetWindowAttributes.event_mask = ExposureMask;
|
||||
platform->xSetWindowAttributes.border_pixel = BlackPixel(platform->display, platform->defaultScreen);
|
||||
platform->xSetWindowAttributes.background_pixel = BlackPixel(platform->display, platform->defaultScreen);
|
||||
platform->xSetWindowAttributes.override_redirect = True;
|
||||
platform->xSetWindowAttributes.event_mask = ExposureMask;
|
||||
|
||||
auto glXCreateContextAttribsARB = (OpenGL::glXCreateContextAttribsARBProc) OpenGL::glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB");
|
||||
XVisualInfo* vi = nullptr;
|
||||
@@ -73,13 +91,13 @@ bool OpenGLWindow::Open() {
|
||||
// Fallback to the old way if you somehow don't have this.
|
||||
if (!glXCreateContextAttribsARB) {
|
||||
GLint glAttributes[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None};
|
||||
xVars.visual = OpenGL::glXChooseVisual(xVars.display, xVars.defaultScreen, glAttributes);
|
||||
gl_context = OpenGL::glXCreateContext(xVars.display, xVars.visual, nullptr, GL_TRUE);
|
||||
xVars.window = XCreateWindow(xVars.display, RootWindow(xVars.display, xVars.defaultScreen), 0, 0, width, height, 0, xVars.visual->depth,
|
||||
InputOutput, xVars.visual->visual, CWBackPixel | CWColormap | CWBorderPixel | NoEventMask, &xVars.xSetWindowAttributes);
|
||||
platform->visual = OpenGL::glXChooseVisual(platform->display, platform->defaultScreen, glAttributes);
|
||||
gl_context = OpenGL::glXCreateContext(platform->display, platform->visual, nullptr, GL_TRUE);
|
||||
platform->window = XCreateWindow(platform->display, RootWindow(platform->display, platform->defaultScreen), 0, 0, width, height, 0, platform->visual->depth,
|
||||
InputOutput, platform->visual->visual, CWBackPixel | CWColormap | CWBorderPixel | NoEventMask, &platform->xSetWindowAttributes);
|
||||
Logger::Debug("Created OpenGL Context with glXCreateContext.");
|
||||
|
||||
if (!xVars.window)
|
||||
if (!platform->window)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -94,50 +112,50 @@ bool OpenGLWindow::Open() {
|
||||
};
|
||||
|
||||
int fb_count;
|
||||
GLXFBConfig* fb_configurations = OpenGL::glXChooseFBConfig(xVars.display, xVars.defaultScreen, visual_attributes, &fb_count);
|
||||
GLXFBConfig* fb_configurations = OpenGL::glXChooseFBConfig(platform->display, platform->defaultScreen, visual_attributes, &fb_count);
|
||||
if (!fb_configurations || fb_count == 0)
|
||||
return false;
|
||||
|
||||
GLXFBConfig best_fbc = fb_configurations[0];
|
||||
vi = OpenGL::glXGetVisualFromFBConfig(xVars.display, best_fbc);
|
||||
vi = OpenGL::glXGetVisualFromFBConfig(platform->display, best_fbc);
|
||||
|
||||
if (!vi)
|
||||
return false;
|
||||
|
||||
xVars.xSetWindowAttributes.colormap = XCreateColormap(xVars.display, RootWindow(xVars.display, vi->screen), vi->visual, AllocNone);
|
||||
xVars.window = XCreateWindow(xVars.display, RootWindow(xVars.display, vi->screen), 0, 0, width, height, 0, vi->depth, InputOutput,
|
||||
vi->visual, CWBackPixel | CWColormap | CWBorderPixel, &xVars.xSetWindowAttributes);
|
||||
platform->xSetWindowAttributes.colormap = XCreateColormap(platform->display, RootWindow(platform->display, vi->screen), vi->visual, AllocNone);
|
||||
platform->window = XCreateWindow(platform->display, RootWindow(platform->display, vi->screen), 0, 0, width, height, 0, vi->depth, InputOutput,
|
||||
vi->visual, CWBackPixel | CWColormap | CWBorderPixel, &platform->xSetWindowAttributes);
|
||||
|
||||
// TODO allow the user to specify what OpenGL version they want.
|
||||
int context_attributes[] { GLX_CONTEXT_MAJOR_VERSION_ARB, gl_major, GLX_CONTEXT_MINOR_VERSION_ARB, gl_minor, None };
|
||||
gl_context = glXCreateContextAttribsARB(xVars.display, best_fbc, nullptr, True, context_attributes);
|
||||
gl_context = glXCreateContextAttribsARB(platform->display, best_fbc, nullptr, True, context_attributes);
|
||||
XFree(fb_configurations);
|
||||
Logger::Debug("Created OpenGL Context with glXCreateContextAttribsARB");
|
||||
}
|
||||
|
||||
if (!gl_context)
|
||||
return false;
|
||||
if (!OpenGL::glXMakeCurrent(xVars.display, xVars.window, gl_context))
|
||||
if (!OpenGL::glXMakeCurrent(platform->display, platform->window, gl_context))
|
||||
return false;
|
||||
|
||||
if (vi)
|
||||
XFree(vi);
|
||||
|
||||
XSelectInput(xVars.display, xVars.window, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
|
||||
XSelectInput(platform->display, platform->window, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
|
||||
PointerMotionHintMask | FocusChangeMask | StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask | CWColormap );
|
||||
|
||||
XMapWindow(xVars.display, xVars.window);
|
||||
XStoreName(xVars.display, xVars.window, title.c_str());
|
||||
XMapWindow(platform->display, platform->window);
|
||||
XStoreName(platform->display, platform->window, title.c_str());
|
||||
|
||||
xVars.windowTypeAtom = XInternAtom(xVars.display, "_NET_WM_WINDOW_TYPE", False);
|
||||
xVars.windowTypeUtilityAtom = XInternAtom(xVars.display, "_NET_WM_WINDOW_TYPE_UTILITY", False);
|
||||
XChangeProperty(xVars.display, xVars.window, xVars.windowTypeAtom, XA_ATOM, 32, PropModeReplace, (unsigned char*) &xVars.windowTypeUtilityAtom, 1);
|
||||
platform->windowTypeAtom = XInternAtom(platform->display, "_NET_WM_WINDOW_TYPE", False);
|
||||
platform->windowTypeUtilityAtom = XInternAtom(platform->display, "_NET_WM_WINDOW_TYPE_UTILITY", False);
|
||||
XChangeProperty(platform->display, platform->window, platform->windowTypeAtom, XA_ATOM, 32, PropModeReplace, (unsigned char*) &platform->windowTypeUtilityAtom, 1);
|
||||
|
||||
xVars.wmDeleteWindow = XInternAtom(xVars.display, "WM_DELETE_WINDOW", False);
|
||||
XSetWMProtocols(xVars.display, xVars.window, &xVars.wmDeleteWindow, 1);
|
||||
platform->wmDeleteWindow = XInternAtom(platform->display, "WM_DELETE_WINDOW", False);
|
||||
XSetWMProtocols(platform->display, platform->window, &platform->wmDeleteWindow, 1);
|
||||
|
||||
XGetWindowAttributes(xVars.display, xVars.window, &xVars.windowAttributes);
|
||||
render_area_position = { xVars.windowAttributes.x, xVars.windowAttributes.y };
|
||||
XGetWindowAttributes(platform->display, platform->window, &platform->windowAttributes);
|
||||
render_area_position = { platform->windowAttributes.x, platform->windowAttributes.y };
|
||||
|
||||
open = true;
|
||||
processOnOpen();
|
||||
|
@@ -1,11 +1,29 @@
|
||||
#include <ReWindow/types/Window.h>
|
||||
#include <ReWindow/Logger.h>
|
||||
#include <dlfcn.h>
|
||||
#include <set>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vulkan_xlib.h>
|
||||
#include <set>
|
||||
|
||||
using namespace ReWindow;
|
||||
class ReWindow::RWindow::Platform {
|
||||
public:
|
||||
Window window;
|
||||
XEvent xev;
|
||||
Display* display;
|
||||
int defaultScreen;
|
||||
XVisualInfo* visual;
|
||||
XSetWindowAttributes xSetWindowAttributes;
|
||||
XWindowAttributes windowAttributes;
|
||||
Atom wmDeleteWindow;
|
||||
Atom windowTypeAtom;
|
||||
Atom windowTypeUtilityAtom;
|
||||
XSizeHints hints;
|
||||
Cursor invisible_cursor = 0;
|
||||
};
|
||||
|
||||
namespace Vulkan {
|
||||
bool constructor_success = false;
|
||||
@@ -43,13 +61,13 @@ bool VulkanWindow::Open() {
|
||||
if (!Vulkan::constructor_success)
|
||||
return false;
|
||||
|
||||
xVars.display = XOpenDisplay(nullptr);
|
||||
xVars.defaultScreen = DefaultScreen(xVars.display);
|
||||
platform->display = XOpenDisplay(nullptr);
|
||||
platform->defaultScreen = DefaultScreen(platform->display);
|
||||
|
||||
xVars.xSetWindowAttributes.border_pixel = BlackPixel(xVars.display, xVars.defaultScreen);
|
||||
xVars.xSetWindowAttributes.background_pixel = BlackPixel(xVars.display, xVars.defaultScreen);
|
||||
xVars.xSetWindowAttributes.override_redirect = True;
|
||||
xVars.xSetWindowAttributes.event_mask = ExposureMask;
|
||||
platform->xSetWindowAttributes.border_pixel = BlackPixel(platform->display, platform->defaultScreen);
|
||||
platform->xSetWindowAttributes.background_pixel = BlackPixel(platform->display, platform->defaultScreen);
|
||||
platform->xSetWindowAttributes.override_redirect = True;
|
||||
platform->xSetWindowAttributes.event_mask = ExposureMask;
|
||||
|
||||
vulkan_application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
vulkan_application_info.pApplicationName = title.c_str();
|
||||
@@ -74,21 +92,21 @@ bool VulkanWindow::Open() {
|
||||
|
||||
LoadVulkanInstancedFunctions(vulkan_context);
|
||||
XVisualInfo visual_info_t{};
|
||||
visual_info_t.screen = xVars.defaultScreen;
|
||||
visual_info_t.screen = platform->defaultScreen;
|
||||
int visual_count;
|
||||
XVisualInfo* vi = XGetVisualInfo(xVars.display, VisualScreenMask, &visual_info_t, &visual_count);
|
||||
XVisualInfo* vi = XGetVisualInfo(platform->display, VisualScreenMask, &visual_info_t, &visual_count);
|
||||
|
||||
if (!vi)
|
||||
return false;
|
||||
|
||||
Colormap colormap = XCreateColormap(xVars.display, RootWindow(xVars.display, vi->screen), vi->visual, AllocNone);
|
||||
xVars.xSetWindowAttributes.colormap = colormap;
|
||||
Colormap colormap = XCreateColormap(platform->display, RootWindow(platform->display, vi->screen), vi->visual, AllocNone);
|
||||
platform->xSetWindowAttributes.colormap = colormap;
|
||||
|
||||
xVars.window = XCreateWindow(xVars.display, RootWindow(xVars.display, vi->screen),
|
||||
platform->window = XCreateWindow(platform->display, RootWindow(platform->display, vi->screen),
|
||||
0, 0, width, height, 0, vi->depth, InputOutput,
|
||||
vi->visual, CWBackPixel | CWColormap | CWBorderPixel, &xVars.xSetWindowAttributes);
|
||||
vi->visual, CWBackPixel | CWColormap | CWBorderPixel, &platform->xSetWindowAttributes);
|
||||
|
||||
if (!xVars.window) {
|
||||
if (!platform->window) {
|
||||
Logger::Error("Failed to create X11 window for Vulkan.");
|
||||
return false;
|
||||
}
|
||||
@@ -97,8 +115,8 @@ bool VulkanWindow::Open() {
|
||||
|
||||
VkXlibSurfaceCreateInfoKHR surface_create_info{};
|
||||
surface_create_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||
surface_create_info.dpy = xVars.display;
|
||||
surface_create_info.window = xVars. window;
|
||||
surface_create_info.dpy = platform->display;
|
||||
surface_create_info.window = platform-> window;
|
||||
|
||||
if (Vulkan::vkCreateXlibSurfaceKHR(vulkan_context, &surface_create_info, nullptr, &vulkan_surface) != VK_SUCCESS) {
|
||||
Logger::Error("Failed to create Vulkan X11 surface.");
|
||||
@@ -191,20 +209,20 @@ bool VulkanWindow::Open() {
|
||||
|
||||
|
||||
|
||||
XSelectInput(xVars.display, xVars.window, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
|
||||
XSelectInput(platform->display, platform->window, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
|
||||
PointerMotionHintMask | FocusChangeMask | StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask | CWColormap );
|
||||
XMapWindow(xVars.display, xVars.window);
|
||||
XStoreName(xVars.display, xVars.window, title.c_str());
|
||||
XMapWindow(platform->display, platform->window);
|
||||
XStoreName(platform->display, platform->window, title.c_str());
|
||||
|
||||
xVars.windowTypeAtom = XInternAtom(xVars.display, "_NET_WM_WINDOW_TYPE", False);
|
||||
xVars.windowTypeUtilityAtom = XInternAtom(xVars.display, "_NET_WM_WINDOW_TYPE_UTILITY", False);
|
||||
XChangeProperty(xVars.display, xVars.window, xVars.windowTypeAtom, XA_ATOM, 32, PropModeReplace, (unsigned char*) &xVars.windowTypeUtilityAtom, 1);
|
||||
platform->windowTypeAtom = XInternAtom(platform->display, "_NET_WM_WINDOW_TYPE", False);
|
||||
platform->windowTypeUtilityAtom = XInternAtom(platform->display, "_NET_WM_WINDOW_TYPE_UTILITY", False);
|
||||
XChangeProperty(platform->display, platform->window, platform->windowTypeAtom, XA_ATOM, 32, PropModeReplace, (unsigned char*) &platform->windowTypeUtilityAtom, 1);
|
||||
|
||||
xVars.wmDeleteWindow = XInternAtom(xVars.display, "WM_DELETE_WINDOW", False);
|
||||
XSetWMProtocols(xVars.display, xVars.window, &xVars.wmDeleteWindow, 1);
|
||||
platform->wmDeleteWindow = XInternAtom(platform->display, "WM_DELETE_WINDOW", False);
|
||||
XSetWMProtocols(platform->display, platform->window, &platform->wmDeleteWindow, 1);
|
||||
|
||||
XGetWindowAttributes(xVars.display, xVars.window, &xVars.windowAttributes);
|
||||
render_area_position = { xVars.windowAttributes.x, xVars.windowAttributes.y };
|
||||
XGetWindowAttributes(platform->display, platform->window, &platform->windowAttributes);
|
||||
render_area_position = { platform->windowAttributes.x, platform->windowAttributes.y };
|
||||
|
||||
open = true;
|
||||
processOnOpen();
|
||||
|
@@ -3,32 +3,61 @@
|
||||
#include <ReWindow/types/Window.h>
|
||||
#include <ReWindow/types/Cursors.h>
|
||||
#include <ReWindow/Logger.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
class ReWindow::RWindow::Platform {
|
||||
public:
|
||||
Window window;
|
||||
XEvent xev;
|
||||
Display* display;
|
||||
int defaultScreen;
|
||||
XVisualInfo* visual;
|
||||
XSetWindowAttributes xSetWindowAttributes;
|
||||
XWindowAttributes windowAttributes;
|
||||
Atom wmDeleteWindow;
|
||||
Atom windowTypeAtom;
|
||||
Atom windowTypeUtilityAtom;
|
||||
XSizeHints hints;
|
||||
Cursor invisible_cursor = 0;
|
||||
};
|
||||
|
||||
ReWindow::IPair position = {0, 0};
|
||||
bool should_poll_x_for_mouse_pos = true;
|
||||
|
||||
using namespace ReWindow;
|
||||
|
||||
RWindow::RWindow() {
|
||||
platform = new Platform();
|
||||
extant = this;
|
||||
}
|
||||
|
||||
IPair position;
|
||||
RWindow::RWindow(const std::string& wTitle, int wWidth, int wHeight, bool wFullscreen, bool wResizable, bool wVsync)
|
||||
: title(wTitle), width(wWidth), height(wHeight), fullscreen_mode(wFullscreen), resizable(wResizable), vsync(wVsync),
|
||||
flags{false,wFullscreen,wResizable,wVsync} {
|
||||
platform = new Platform();
|
||||
extant = this;
|
||||
}
|
||||
|
||||
void RWindow::Raise() {
|
||||
Logger::Debug(std::format("Raising window '{}'", this->title));
|
||||
// Get the position of the renderable area relative to the rest of the window.
|
||||
XGetWindowAttributes(xVars.display, xVars.window, &xVars.windowAttributes);
|
||||
render_area_position = { xVars.windowAttributes.x, xVars.windowAttributes.y };
|
||||
XRaiseWindow(xVars.display, xVars.window);
|
||||
XGetWindowAttributes(platform->display, platform->window, &platform->windowAttributes);
|
||||
render_area_position = { platform->windowAttributes.x, platform->windowAttributes.y };
|
||||
XRaiseWindow(platform->display, platform->window);
|
||||
}
|
||||
|
||||
void RWindow::Lower()
|
||||
{
|
||||
Logger::Debug(std::format("Lowering window '{}'", this->title));
|
||||
XLowerWindow(xVars.display, xVars.window);
|
||||
XLowerWindow(platform->display, platform->window);
|
||||
}
|
||||
|
||||
void RWindow::DestroyOSWindowHandle() {
|
||||
Logger::Debug(std::format("Destroying window '{}'", this->title));
|
||||
XDestroySubwindows(xVars.display, xVars.window);
|
||||
XDestroySubwindows(platform->display, platform->window);
|
||||
Logger::Debug(std::format("Destroyed window '{}'", this->title));
|
||||
XDestroyWindow(xVars.display, xVars.window);
|
||||
XDestroyWindow(platform->display, platform->window);
|
||||
|
||||
system("xset r on"); // Re-set X-server parameter to enable key-repeat.
|
||||
|
||||
@@ -39,125 +68,125 @@ void RWindow::DestroyOSWindowHandle() {
|
||||
|
||||
void RWindow::SetCursorVisible(bool cursor_enable) {
|
||||
cursor_visible = cursor_enable;
|
||||
if (xVars.invisible_cursor == 0) {
|
||||
Pixmap blank_pixmap = XCreatePixmap(xVars.display, xVars.window, 1, 1, 1);
|
||||
if (platform->invisible_cursor == 0) {
|
||||
Pixmap blank_pixmap = XCreatePixmap(platform->display, platform->window, 1, 1, 1);
|
||||
XColor dummy; dummy.pixel = 0; dummy.red = 0; dummy.flags = 0;
|
||||
xVars.invisible_cursor = XCreatePixmapCursor(xVars.display, blank_pixmap, blank_pixmap, &dummy, &dummy, 0, 0);
|
||||
XFreePixmap(xVars.display, blank_pixmap);
|
||||
platform->invisible_cursor = XCreatePixmapCursor(platform->display, blank_pixmap, blank_pixmap, &dummy, &dummy, 0, 0);
|
||||
XFreePixmap(platform->display, blank_pixmap);
|
||||
}
|
||||
|
||||
if (!cursor_enable)
|
||||
XDefineCursor(xVars.display, xVars.window, xVars.invisible_cursor);
|
||||
XDefineCursor(platform->display, platform->window, platform->invisible_cursor);
|
||||
|
||||
if (cursor_enable)
|
||||
XUndefineCursor(xVars.display, xVars.window);
|
||||
XUndefineCursor(platform->display, platform->window);
|
||||
}
|
||||
|
||||
void RWindow::SetResizable(bool sizable) {
|
||||
XGetWindowAttributes(xVars.display, xVars.window, &xVars.windowAttributes);
|
||||
XGetWindowAttributes(platform->display, platform->window, &platform->windowAttributes);
|
||||
|
||||
|
||||
this->resizable = sizable;
|
||||
if (!sizable)
|
||||
{
|
||||
Logger::Debug("Once you've done this you cannot make it resizable again.");
|
||||
xVars.hints.flags = PMinSize | PMaxSize;
|
||||
xVars.hints.min_width = xVars.hints.max_width = xVars.windowAttributes.width;
|
||||
xVars.hints.min_height = xVars.hints.max_height = xVars.windowAttributes.height;
|
||||
XSetWMNormalHints(xVars.display, xVars.window, &xVars.hints);
|
||||
platform->hints.flags = PMinSize | PMaxSize;
|
||||
platform->hints.min_width = platform->hints.max_width = platform->windowAttributes.width;
|
||||
platform->hints.min_height = platform->hints.max_height = platform->windowAttributes.height;
|
||||
XSetWMNormalHints(platform->display, platform->window, &platform->hints);
|
||||
}
|
||||
//this->SetFlag(WindowFlag::RESIZABLE, resizable);
|
||||
|
||||
}
|
||||
|
||||
void RWindow::SetFlag(WindowFlag flag, bool state) {
|
||||
XGetWindowAttributes(xVars.display, xVars.window, &xVars.windowAttributes);
|
||||
XGetWindowAttributes(platform->display, platform->window, &platform->windowAttributes);
|
||||
flags[(int) flag] = state;
|
||||
//Once you've done this you cannot make it resizable again.
|
||||
if (flag == WindowFlag::RESIZABLE && !state) {
|
||||
Logger::Debug("Once you've done this you cannot make it resizable again.");
|
||||
xVars.hints.flags = PMinSize | PMaxSize;
|
||||
xVars.hints.min_width = xVars.hints.max_width = xVars.windowAttributes.width;
|
||||
xVars.hints.min_height = xVars.hints.max_height = xVars.windowAttributes.height;
|
||||
XSetWMNormalHints(xVars.display, xVars.window, &xVars.hints);
|
||||
platform->hints.flags = PMinSize | PMaxSize;
|
||||
platform->hints.min_width = platform->hints.max_width = platform->windowAttributes.width;
|
||||
platform->hints.min_height = platform->hints.max_height = platform->windowAttributes.height;
|
||||
XSetWMNormalHints(platform->display, platform->window, &platform->hints);
|
||||
}
|
||||
Logger::Debug(std::format("Set flag '{}' to state '{}' for window '{}'", WindowFlagToStr(flag), state, this->title));
|
||||
}
|
||||
|
||||
void RWindow::PollEvents() {
|
||||
while(XPending(xVars.display)) {
|
||||
XNextEvent(xVars.display, &xVars.xev);
|
||||
while(XPending(platform->display)) {
|
||||
XNextEvent(platform->display, &platform->xev);
|
||||
|
||||
if (xVars.xev.type == ClientMessage)
|
||||
if (platform->xev.type == ClientMessage)
|
||||
Logger::Info(std::format("Event '{}'", "ClientMessage"));
|
||||
|
||||
if (xVars.xev.xclient.message_type == XInternAtom(xVars.display, "WM_PROTOCOLS", False) && static_cast<Atom>(xVars.xev.xclient.data.l[0]) == xVars.wmDeleteWindow) {
|
||||
if (platform->xev.xclient.message_type == XInternAtom(platform->display, "WM_PROTOCOLS", False) && static_cast<Atom>(platform->xev.xclient.data.l[0]) == platform->wmDeleteWindow) {
|
||||
Close();
|
||||
}
|
||||
|
||||
if (xVars.xev.type == FocusIn) {
|
||||
if (platform->xev.type == FocusIn) {
|
||||
Logger::Debug(std::format("Event'{}'", "FocusIn"));
|
||||
XAutoRepeatOff(xVars.display);
|
||||
XAutoRepeatOff(platform->display);
|
||||
SetFlag(WindowFlag::IN_FOCUS, true);
|
||||
|
||||
if (!cursor_visible)
|
||||
XDefineCursor(xVars.display, xVars.window, xVars.invisible_cursor);
|
||||
XDefineCursor(platform->display, platform->window, platform->invisible_cursor);
|
||||
|
||||
// Get the position of the renderable area relative to the rest of the window.
|
||||
XGetWindowAttributes(xVars.display, xVars.window, &xVars.windowAttributes);
|
||||
render_area_position = { xVars.windowAttributes.x, xVars.windowAttributes.y };
|
||||
XGetWindowAttributes(platform->display, platform->window, &platform->windowAttributes);
|
||||
render_area_position = { platform->windowAttributes.x, platform->windowAttributes.y };
|
||||
processFocusIn();
|
||||
}
|
||||
|
||||
if (xVars.xev.type == FocusOut) {
|
||||
if (platform->xev.type == FocusOut) {
|
||||
Logger::Debug(std::format("Event '{}'", "FocusOut"));
|
||||
XAutoRepeatOn(xVars.display);
|
||||
XAutoRepeatOn(platform->display);
|
||||
|
||||
SetFlag(WindowFlag::IN_FOCUS, false);
|
||||
if (!cursor_visible)
|
||||
XUndefineCursor(xVars.display, xVars.window);
|
||||
XUndefineCursor(platform->display, platform->window);
|
||||
|
||||
processFocusOut();
|
||||
}
|
||||
|
||||
if (xVars.xev.type == KeyRelease) {
|
||||
if (platform->xev.type == KeyRelease) {
|
||||
Logger::Debug(std::format("Event '{}'", "KeyRelease"));
|
||||
auto scancode = (X11Scancode) xVars.xev.xkey.keycode;
|
||||
auto scancode = (X11Scancode) platform->xev.xkey.keycode;
|
||||
auto key = GetKeyFromX11Scancode(scancode);
|
||||
processKeyRelease(key);
|
||||
}
|
||||
|
||||
if (xVars.xev.type == KeyPress) {
|
||||
if (platform->xev.type == KeyPress) {
|
||||
Logger::Debug(std::format("Event '{}'", "KeyPress"));
|
||||
auto scancode = (X11Scancode) xVars.xev.xkey.keycode;
|
||||
auto scancode = (X11Scancode) platform->xev.xkey.keycode;
|
||||
auto key = GetKeyFromX11Scancode(scancode);
|
||||
processKeyPress(key);
|
||||
}
|
||||
|
||||
if (xVars.xev.type == ButtonRelease) {
|
||||
if (platform->xev.type == ButtonRelease) {
|
||||
|
||||
// Mouse Wheel fires both the ButtonPress and ButtonRelease instantaneously.
|
||||
// Therefore, we handle it as a specific MouseWheel event rather than a MouseButton event,
|
||||
// and only call on ButtonPress, otherwise it will appear to duplicate the mouse wheel scroll.
|
||||
if (xVars.xev.xbutton.button != 4 && xVars.xev.xbutton.button != 5) {
|
||||
MouseButton button = GetMouseButtonFromXButton(xVars.xev.xbutton.button);
|
||||
if (platform->xev.xbutton.button != 4 && platform->xev.xbutton.button != 5) {
|
||||
MouseButton button = GetMouseButtonFromXButton(platform->xev.xbutton.button);
|
||||
Logger::Debug(std::format("Event '{}'", "ButtonRelease"));
|
||||
processMouseRelease(button);
|
||||
}
|
||||
}
|
||||
|
||||
if (xVars.xev.type == ButtonPress) {
|
||||
if (platform->xev.type == ButtonPress) {
|
||||
|
||||
// Mouse Wheel fires both the ButtonPress and ButtonRelease instantaneously.
|
||||
// Therefore, we handle it as a specific MouseWheel event rather than a MouseButton event,
|
||||
// and only call on ButtonPress, otherwise it will appear to duplicate the mouse wheel scroll.
|
||||
if (xVars.xev.xbutton.button == 4) {
|
||||
if (platform->xev.xbutton.button == 4) {
|
||||
processMouseWheel(-1);
|
||||
} else if (xVars.xev.xbutton.button == 5) {
|
||||
} else if (platform->xev.xbutton.button == 5) {
|
||||
processMouseWheel(1);
|
||||
} else
|
||||
{
|
||||
MouseButton button = GetMouseButtonFromXButton(xVars.xev.xbutton.button);
|
||||
MouseButton button = GetMouseButtonFromXButton(platform->xev.xbutton.button);
|
||||
|
||||
Logger::Debug(std::format("Event: MouseButtonPress {}", button.Mnemonic));
|
||||
|
||||
@@ -165,26 +194,26 @@ void RWindow::PollEvents() {
|
||||
}
|
||||
}
|
||||
|
||||
if (xVars.xev.type == Expose)
|
||||
if (platform->xev.type == Expose)
|
||||
{
|
||||
Logger::Debug(std::format("Event '{}'", "Expose"));
|
||||
}
|
||||
|
||||
// NOTE: This event is functionally useless, as it only informs of the very beginning and end of a mouse movement.
|
||||
if (xVars.xev.type == MotionNotify)
|
||||
if (platform->xev.type == MotionNotify)
|
||||
{
|
||||
Logger::Debug(std::format("Event '{}'", "MotionNotify"));
|
||||
}
|
||||
|
||||
if (xVars.xev.type == ConfigureNotify) {
|
||||
if (this->width != xVars.xev.xconfigurerequest.width || this->height != xVars.xev.xconfigurerequest.height) {
|
||||
if (platform->xev.type == ConfigureNotify) {
|
||||
if (this->width != platform->xev.xconfigurerequest.width || this->height != platform->xev.xconfigurerequest.height) {
|
||||
Logger::Debug(std::format("Event '{}'", "ResizeRequest"));
|
||||
|
||||
this->width = xVars.xev.xconfigurerequest.width;
|
||||
this->height = xVars.xev.xconfigurerequest.height;
|
||||
this->width = platform->xev.xconfigurerequest.width;
|
||||
this->height = platform->xev.xconfigurerequest.height;
|
||||
|
||||
auto eventData = WindowResizeRequestEvent();
|
||||
eventData.Size = { xVars.xev.xconfigurerequest.width, xVars.xev.xconfigurerequest.height };
|
||||
eventData.Size = { platform->xev.xconfigurerequest.width, platform->xev.xconfigurerequest.height };
|
||||
lastKnownWindowSize = eventData.Size;
|
||||
|
||||
OnResizeRequest(eventData);
|
||||
@@ -192,8 +221,8 @@ void RWindow::PollEvents() {
|
||||
}
|
||||
|
||||
//Window Moved.
|
||||
if (position.x != xVars.xev.xconfigurerequest.x || position.y != xVars.xev.xconfigurerequest.y)
|
||||
position = { xVars.xev.xconfigurerequest.x, xVars.xev.xconfigurerequest.y };
|
||||
if (position.x != platform->xev.xconfigurerequest.x || position.y != platform->xev.xconfigurerequest.y)
|
||||
position = { platform->xev.xconfigurerequest.x, platform->xev.xconfigurerequest.y };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -208,8 +237,8 @@ void RWindow::SetSize(int newWidth, int newHeight) {
|
||||
|
||||
this->width = newWidth;
|
||||
this->height = newHeight;
|
||||
XResizeWindow(xVars.display, xVars.window, newWidth, newHeight);
|
||||
XFlush(xVars.display);
|
||||
XResizeWindow(platform->display, platform->window, newWidth, newHeight);
|
||||
XFlush(platform->display);
|
||||
Logger::Info(std::format("Set size for '{}' to {} x {}", this->title, newWidth, newHeight));
|
||||
}
|
||||
|
||||
@@ -221,10 +250,10 @@ IPair RWindow::GetAccurateMouseCoordinates() const {
|
||||
uint32_t mask_return;
|
||||
|
||||
// This seems to be relative to the top left corner of the renderable area.
|
||||
bool mouseAvailable = XQueryPointer(xVars.display, xVars.window, &root_return, &child_return, &root_x_ret, &root_y_ret, &win_x_ret, &win_y_ret, &mask_return);
|
||||
bool mouseAvailable = XQueryPointer(platform->display, platform->window, &root_return, &child_return, &root_x_ret, &root_y_ret, &win_x_ret, &win_y_ret, &mask_return);
|
||||
|
||||
if (mouseAvailable) {
|
||||
// TODO: normalize coordinates from xVars.displaySpace to windowSpace
|
||||
// TODO: normalize coordinates from platform->displaySpace to windowSpace
|
||||
// TODO: fire mouse movement event
|
||||
IPair m_coords = { win_x_ret, win_y_ret };
|
||||
return m_coords;
|
||||
@@ -248,7 +277,7 @@ IPair RWindow::GetPos() const {
|
||||
}
|
||||
|
||||
void RWindow::SetPos(int x, int y) {
|
||||
XMoveWindow(xVars.display, xVars.window, x, y);
|
||||
XMoveWindow(platform->display, platform->window, x, y);
|
||||
position = {x, y};
|
||||
}
|
||||
|
||||
@@ -261,19 +290,19 @@ void RWindow::Fullscreen() {
|
||||
fullscreen_mode = true;
|
||||
|
||||
XEvent xev;
|
||||
Atom wm_state = XInternAtom(xVars.display, "_NET_WM_STATE", true);
|
||||
Atom wm_fullscreen = XInternAtom(xVars.display, "_NET_WM_STATE_FULLSCREEN", true);
|
||||
Atom wm_state = XInternAtom(platform->display, "_NET_WM_STATE", true);
|
||||
Atom wm_fullscreen = XInternAtom(platform->display, "_NET_WM_STATE_FULLSCREEN", true);
|
||||
|
||||
XChangeProperty(xVars.display, xVars.window, wm_state, XA_ATOM, 32, PropModeReplace, (unsigned char *)&wm_fullscreen, 1);
|
||||
XChangeProperty(platform->display, platform->window, wm_state, XA_ATOM, 32, PropModeReplace, (unsigned char *)&wm_fullscreen, 1);
|
||||
memset(&xev, 0, sizeof(xev));
|
||||
xev.type = ClientMessage;
|
||||
xev.xclient.window = xVars.window;
|
||||
xev.xclient.window = platform->window;
|
||||
xev.xclient.message_type = wm_state;
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = 1; // _NET_WM_STATE_ADD
|
||||
xev.xclient.data.l[1] = fullscreen_mode;
|
||||
xev.xclient.data.l[2] = 0;
|
||||
XSendEvent(xVars.display, DefaultRootWindow(xVars.display), False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
|
||||
XSendEvent(platform->display, DefaultRootWindow(platform->display), False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
|
||||
Logger::Debug(std::format("Fullscreened '{}'", this->title));
|
||||
}
|
||||
|
||||
@@ -281,29 +310,29 @@ void RWindow::RestoreFromFullscreen() {
|
||||
Logger::Debug(std::format("Restoring '{}' from Fullscreen", this->title));
|
||||
fullscreen_mode = false;
|
||||
XEvent xev;
|
||||
Atom wm_state = XInternAtom(xVars.display, "_NET_WM_STATE", False);
|
||||
Atom fullscreen = XInternAtom(xVars.display, "_NET_WM_STATE_FULLSCREEN", False);
|
||||
Atom wm_state = XInternAtom(platform->display, "_NET_WM_STATE", False);
|
||||
Atom fullscreen = XInternAtom(platform->display, "_NET_WM_STATE_FULLSCREEN", False);
|
||||
memset(&xev, 0, sizeof(xev));
|
||||
xev.type = ClientMessage;
|
||||
xev.xclient.window = xVars.window;
|
||||
xev.xclient.window = platform->window;
|
||||
xev.xclient.message_type = wm_state;
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = 0; // _NET_WM_STATE_REMOVE
|
||||
xev.xclient.data.l[1] = fullscreen_mode;
|
||||
xev.xclient.data.l[2] = 0;
|
||||
XSendEvent(xVars.display, DefaultRootWindow(xVars.display), False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
|
||||
XSendEvent(platform->display, DefaultRootWindow(platform->display), False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
|
||||
Logger::Debug(std::format("Restored '{}' from Fullscreen", this->title));
|
||||
}
|
||||
|
||||
void RWindow::SetCursorStyle(CursorStyle style) const {
|
||||
auto x11_cursor_resolved_enum = (unsigned int) style.X11Cursor;
|
||||
Cursor c = XCreateFontCursor(xVars.display, x11_cursor_resolved_enum);
|
||||
XDefineCursor(xVars.display, xVars.window, c);
|
||||
Cursor c = XCreateFontCursor(platform->display, x11_cursor_resolved_enum);
|
||||
XDefineCursor(platform->display, platform->window, c);
|
||||
}
|
||||
|
||||
void RWindow::SetTitle(const std::string& title) {
|
||||
this->title = title;
|
||||
XStoreName(xVars.display, xVars.window, title.c_str());
|
||||
XStoreName(platform->display, platform->window, title.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
@@ -16,15 +16,6 @@ std::string WindowFlagToStr(WindowFlag flag) {
|
||||
|
||||
using namespace ReWindow;
|
||||
|
||||
|
||||
static RWindow* extant;
|
||||
|
||||
RWindow::RWindow(const std::string& wTitle, int wWidth, int wHeight, bool wFullscreen, bool wResizable, bool wVsync)
|
||||
: title(wTitle), width(wWidth), height(wHeight), fullscreen_mode(wFullscreen), resizable(wResizable), vsync(wVsync),
|
||||
flags{false,wFullscreen,wResizable,wVsync} {
|
||||
extant = this;
|
||||
}
|
||||
|
||||
RWindow::~RWindow() {
|
||||
if (open)
|
||||
DestroyOSWindowHandle();
|
||||
@@ -282,18 +273,11 @@ bool RWindow::IsFocused() const {
|
||||
DestroyOSWindowHandle();
|
||||
}
|
||||
|
||||
RWindow * RWindow::GetExtant() {
|
||||
return extant;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RWindow::ForceCloseAndTerminateProgram() {
|
||||
ForceClose();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
bool MouseState::IsDown(const MouseButton &btn) const {
|
||||
if (btn == MouseButtons::Left) return Buttons.LMB;
|
||||
if (btn == MouseButtons::Right) return Buttons.RMB;
|
||||
|
Reference in New Issue
Block a user