Merge pull request 'virtual-window' (#3) from virtual-window into main

Reviewed-on: #3
This commit is contained in:
2024-01-25 19:43:58 -05:00
9 changed files with 390 additions and 115 deletions

View File

@@ -40,7 +40,9 @@ endif()
include_directories("include")
add_library(ReWindowLibrary SHARED ${SOURCES}
include/rewindow/data/X11Scancodes.h
include/rewindow/types/key.h)
include/rewindow/types/key.h
include/rewindow/data/WindowsScancodes.h
)
# Why god???
set_target_properties(ReWindowLibrary PROPERTIES LINKER_LANGUAGE CXX)

View File

@@ -0,0 +1,95 @@
#pragma once
enum class WindowsScancode {
Nothing = 0,
ESCAPE = 0x01,
ONE = 0x02,
TWO = 0x03,
THREE = 0x04,
FOUR = 0x05,
FIVE = 0x06,
SIX = 0x07,
SEVEN = 0x08,
EIGHT = 0x09,
NINE = 0x0A,
ZERO = 0x0B,
MINUS = 0x0C,
EQUALS = 0x0D,
BACKSPACE = 0x0E,
TAB = 0x0F,
Q = 0x10,
W = 0x11,
E = 0x12,
R = 0x13,
T = 0x14,
Y = 0x15,
U = 0x16,
I = 0x17,
O = 0x18,
P = 0x19,
LEFT_BRACKET = 0x1A,
RIGHT_BRACKET = 0x1B,
ENTER = 0x1C,
CTRL = 0x1D,
A = 0x1E,
S = 0x1F,
D = 0x20,
F = 0x21,
G = 0x22,
H = 0x23,
J = 0x24,
K = 0x25,
L = 0x26,
SEMICOLON = 0x27,
SINGLEQUOTE = 0x28,
GRAVE = 0x29,
LEFT_SHIFT = 0x2A,
BACKSLASH = 0x2B,
Z = 0x2C,
X = 0x2D,
C = 0x2E,
V = 0x2F,
B = 0x30,
N = 0x30,
M = 0x32,
COMMA = 0x33,
PERIOD = 0x34,
SLASH = 0x35,
RIGHT_SHIFT = 0x36,
PRINTSCREEN = 0x37,
ALT = 0x38,
SPACE = 0x39,
CAPS_LOCK = 0x3A,
F1 = 0x3B,
F2 = 0x3C,
F3 = 0x3D,
F4 = 0x3E,
F5 = 0x3F,
F6 = 0x40,
F7 = 0x41,
F8 = 0x42,
F9 = 0x43,
F10 = 0x44,
NUM_LOCK = 0x45,
SCROLL_LOCK = 0x46,
HOME = 0x47,
UP_ARROW = 0x48,
LEFT_ARROW,
DOWN_ARROW,
RIGHT_ARROW,
PAGE_UP = 0x49,
NUMPAD_MINUS = 0x4A,
NUMPAD_4 = 0x4B,
NUMPAD_5 = 0x4C,
NUMPAD_6 = 0x4D,
NUMPAD_PLUS = 0x4E,
NUMPAD_ONE = 0x4F,
NUMPAD_TWO = 0x50,
NUMPAD_THREE = 0x51,
NUMPAD_ZERO = 0x52,
DELETE = 0x53,
F11 = 0x85,
F12 = 0x86, // FIX
};

View File

@@ -1,3 +1,6 @@
// @file X11Scancodes.h
// @
#pragma once
enum class X11Scancode {
@@ -88,19 +91,19 @@ enum class X11Scancode {
SUPER = 133,
LEFT_CTRL = 37,
ESCAPE = 9,
FUNCTION_ONE = 67,
FUNCTION_TWO = 68,
FUNCTION_THREE = 69,
FUNCTION_FOUR = 70,
FUNCTION_FIVE = 71,
FUNCTION_SIX = 72,
FUNCTION_SEVEN = 73,
FUNCTION_EIGHT = 74,
FUNCTION_NINE = 75,
FUNCTION_TEN = 76,
FUNCTION_ELEVEN = 77,
FUNCTION_TWELVE = 78,
F1 = 67,
F2 = 68,
F3 = 69,
F4 = 70,
F5 = 71,
F6 = 72,
F7 = 73,
F8 = 74,
F9 = 75,
F10 = 76,
F11 = 77,
F12 = 78,
PRINT = 107,
SCROLL_LOCK = 78,
BREAK = 127,
};
};

View File

@@ -12,9 +12,6 @@
//This is also the x11 scancodes.
template <typename ... Args>
class Event;

View File

@@ -5,6 +5,7 @@
#include <vector>
#include <J3ML/LinearAlgebra/Vector2.h>
#include "rewindow/data/X11Scancodes.h"
#include "rewindow/data/WindowsScancodes.h"
using Vector2 = LinearAlgebra::Vector2;
@@ -15,76 +16,86 @@ private:
public:
inline static std::vector<Key> GetKeyboard();
Key();
Key(char charcode, X11Scancode scancode);
Key(char charcode, X11Scancode scancode, WindowsScancode wSc);
char CharCode;
X11Scancode x11ScanCode;
WindowsScancode winScanCode;
bool operator==(const Key& rhs) const;
bool operator<(const Key& rhs) const;
Key(const Key&) = default;
};
namespace Keys {
static const Key Escape;
static const Key F1;
static const Key F2;
static const Key F3;
static const Key F4;
static const Key F5;
static const Key F6;
static const Key F7;
static const Key F8;
static const Key F9;
static const Key F10;
static const Key F11;
static const Key F12;
static const Key Escape {'\b', X11Scancode::ESCAPE, WindowsScancode::ESCAPE};
static const Key F1 {'\u000f', X11Scancode::F1, WindowsScancode::F1};
static const Key F2 {'\u000f', X11Scancode::F2, WindowsScancode::F2};
static const Key F3 {'\u000f', X11Scancode::F3, WindowsScancode::F3};
static const Key F4 {'\u000f', X11Scancode::F4, WindowsScancode::F4};
static const Key F5 {'\u000f', X11Scancode::F5, WindowsScancode::F5};
static const Key F6 {'\u000f', X11Scancode::F6, WindowsScancode::F6};
static const Key F7 {'\u000f', X11Scancode::F7, WindowsScancode::F7};
static const Key F8 {'\u000f', X11Scancode::F8, WindowsScancode::F8};
static const Key F9 {'\u000f', X11Scancode::F9, WindowsScancode::F9};
static const Key F10 {'\u000f', X11Scancode::F10, WindowsScancode::F10};
static const Key F11 {'\u000f', X11Scancode::F11, WindowsScancode::F11};
static const Key F12 {'\u000f', X11Scancode::F12, WindowsScancode::F12};
static const Key NumPad1;
static const Key NumPad2;
static const Key NumPad3;
static const Key NumPad4;
static const Key NumPad5;
static const Key NumPad6;
static const Key NumPad7;
static const Key NumPad8;
static const Key NumPad9;
static const Key NumPad0;
static const Key NumPad1 {'\b', X11Scancode::ONE, WindowsScancode::NUMPAD_ONE};
static const Key NumPad2 {'\b', X11Scancode::ONE, WindowsScancode::NUMPAD_ONE};
static const Key NumPad3 {'\b', X11Scancode::ONE, WindowsScancode::NUMPAD_ONE};
static const Key NumPad4 {'\b', X11Scancode::ONE, WindowsScancode::NUMPAD_ONE};
static const Key NumPad5 {'\b', X11Scancode::ONE, WindowsScancode::NUMPAD_ONE};
static const Key NumPad6 {'\b', X11Scancode::ONE, WindowsScancode::NUMPAD_ONE};
static const Key NumPad7 {'\b', X11Scancode::ONE, WindowsScancode::NUMPAD_ONE};
static const Key NumPad8 {'\b', X11Scancode::ONE, WindowsScancode::NUMPAD_ONE};
static const Key NumPad9 {'\b', X11Scancode::ONE, WindowsScancode::NUMPAD_ONE};
static const Key NumPad0 {'\b', X11Scancode::ONE, WindowsScancode::NUMPAD_ONE};
static const Key Q {'Q', X11Scancode::Q};
static const Key W {'W', X11Scancode::W};
static const Key E {'E', X11Scancode::E};
static const Key R {'R', X11Scancode::R};
static const Key T;
static const Key Y;
static const Key U;
static const Key I;
static const Key O;
static const Key P;
static const Key A;
static const Key S;
static const Key D;
static const Key F;
static const Key G;
static const Key H;
static const Key J;
static const Key K;
static const Key L;
static const Key Semicolon;
static const Key Comma;
static const Key Enter;
static const Key Minus;
static const Key Equals;
static const Key Tilde;
static const Key Z;
static const Key X;
static const Key C;
static const Key V;
static const Key B;
static const Key N;
static const Key M;
static const Key Period;
static const Key Slash;
static const Key Q {'Q', X11Scancode::Q, WindowsScancode::Q};
static const Key W {'W', X11Scancode::W, WindowsScancode::W};
static const Key E {'E', X11Scancode::E, WindowsScancode::E};
static const Key R {'R', X11Scancode::R, WindowsScancode::R};
static const Key T {'T', X11Scancode::T, WindowsScancode::T};
static const Key Y {'Y', X11Scancode::Y, WindowsScancode::Y};
static const Key U {'U', X11Scancode::U, WindowsScancode::U};
static const Key I {'I', X11Scancode::I, WindowsScancode::I};
static const Key O {'O', X11Scancode::O, WindowsScancode::O};
static const Key P {'P', X11Scancode::P, WindowsScancode::P};
static const Key A {'A', X11Scancode::A, WindowsScancode::A};
static const Key S {'S', X11Scancode::S, WindowsScancode::S};
static const Key D {'D', X11Scancode::D, WindowsScancode::D};
static const Key F {'F', X11Scancode::F, WindowsScancode::F};
static const Key G {'G', X11Scancode::G, WindowsScancode::G};
static const Key H {'H', X11Scancode::H, WindowsScancode::H};
static const Key J {'J', X11Scancode::J, WindowsScancode::J};
static const Key K {'K', X11Scancode::K, WindowsScancode::K};
static const Key L {'L', X11Scancode::L, WindowsScancode::L};
static const Key Semicolon {';', X11Scancode::SEMICOLON, WindowsScancode::SEMICOLON};
static const Key SingeQuote {'\'', X11Scancode::SINGLEQUOTE, WindowsScancode::SEMICOLON};
static const Key Enter {'\n', X11Scancode::RETURN, WindowsScancode::ENTER};
//static const Key KeyPadEnter {'\n', X11Scancode::KP_RETURN};
static const Key Minus {'-', X11Scancode::MINUS, WindowsScancode::MINUS};
//static const Key KeyPadMinus {'-', X11Scancode::KP_MINUS};
static const Key Equals {'=', X11Scancode::EQUALS, WindowsScancode::EQUALS};
static const Key Z {'Z', X11Scancode::Z, WindowsScancode::Z};
static const Key X {'X', X11Scancode::X, WindowsScancode::X};
static const Key C {'C', X11Scancode::C, WindowsScancode::C};
static const Key V {'V', X11Scancode::V, WindowsScancode::V};
static const Key B {'B', X11Scancode::B, WindowsScancode::B};
static const Key N {'N', X11Scancode::N, WindowsScancode::N};
static const Key M {'M', X11Scancode::M, WindowsScancode::M};
static const Key Period {'.', X11Scancode::PERIOD, WindowsScancode::PERIOD};
static const Key ForwardSlash {'/', X11Scancode::SLASH, WindowsScancode::SLASH};
static const Key BackSlash {'\\', X11Scancode::BACKSLASH, WindowsScancode::BACKSLASH};
static const Key LShift;
static const Key RShift;
// TODO: Get the right character codes for these
static const Key UpArrow {'\u000a', X11Scancode::UP, WindowsScancode::UP_ARROW};
static const Key DownArrow {'\u000a', X11Scancode::DOWN, WindowsScancode::DOWN_ARROW};
static const Key LeftArrow {'\u000a', X11Scancode::LEFT, WindowsScancode::LEFT_ARROW};
static const Key RightArrow {'\u000a', X11Scancode::RIGHT, WindowsScancode::RIGHT_ARROW};
}
class GamepadButton {};
@@ -112,14 +123,21 @@ namespace MouseButtons
static const MouseButton Middle;
static const MouseButton Side1;
static const MouseButton Side2;
}
static Key GetKeyFromX11Scancode(X11Scancode code)
{
for (auto& key : Key::GetKeyboard()) {
if (key.x11ScanCode == code)
return key;
}
}
throw "Unavaliable Scancode: " + std::to_string((int)code);
}
static Key GetKeyFromWindowsScancode(WindowsScancode code)
{
for (auto& key : Key::GetKeyboard()) {
if (key.winScanCode == code)
return key;
}
throw "Unavaliable Scancode: " + std::to_string((int)code);
}

View File

@@ -30,6 +30,24 @@ enum class RenderingAPI: uint8_t {
VULKAN = 1,
};
enum class CursorStyle
{
Default,
X,
Arrow,
IBeam,
BottomLeftCorner,
BottomRightCorner,
BottomSide,
Dot,
DoubleArrow,
Exchange,
Hand,
LeftSide,
Plus,
RightSide,
};
using namespace std::chrono_literals;
using precision_clock = std::chrono::high_resolution_clock;
using precision_timestamp = precision_clock::time_point;
@@ -54,7 +72,7 @@ enum class KeyState { Pressed, Released };
class KeyboardState {
public:
std::map<X11Scancode, bool> PressedKeys;
std::map<Key, bool> PressedKeys;
};
class GamepadState {
@@ -68,8 +86,6 @@ public:
GamepadState Gamepad;
};
class KeyboardEvent : public RWindowEvent {
public:
Key key;
@@ -102,6 +118,7 @@ private:
std::vector<RWindowEvent> eventLog;
KeyboardState currentKeyboard; // Current Frame's Keyboard State
KeyboardState previousKeyboard; // Previous Frame's Keyboard State
bool fullscreenmode = false;
public:
Event<> focusGained;
Event<> focusLost;
@@ -112,27 +129,46 @@ public:
Event<KeyDownEvent> onKeyboardPress;
Event<KeyUpEvent> onKeyboardRelease;
virtual void OnFocusLost(const RWindowEvent& e) {}
virtual void OnFocusGain(const RWindowEvent& e) {}
virtual void OnMouseMove(const MouseEvent& e) {}
virtual void OnRefresh(float elapsed) {}
virtual void OnResizeSuccess() {}
virtual bool OnResizeRequest() {}
// TODO: Must be implemented from scratch as a Motif Window in x11
void MessageBox();
bool isFocused() const;
bool isFullscreen() const;
bool isFullscreen() const
{
return fullscreenmode;
}
bool isResizable() const;
bool isVsyncEnabled() const;
bool isAlive() const;
void setMouseVisible(bool visible);
void setMouseLocked();
void setMouseCenter();
void restoreMouseFromLastCenter(); // Feels nicer for users
void setFocused(bool);
void setFullscreen(bool);
void setResizable(bool);
void setFullscreen(bool fs);
void setResizable(bool resizable);
void setVsyncEnabled(bool);
void setTitle(const std::string& title);
void fullscreen();
void restoreFromFullscreen();
bool getFlag(RWindowFlags flag);
bool getFlag(RWindowFlags flag) const;
void setFlag(RWindowFlags flag, bool state);
void init(RenderingAPI api, const char* title, int width, int height);
void destroyWindow();
void pollEvents();
void refresh();
void setSize(int width, int height);
std::unique_ptr<int[]> getPos();
std::unique_ptr<int[]> getSize();
@@ -141,8 +177,17 @@ public:
bool mouseButtonDown(MouseButton buttoncode);
KeyDownEvent getEvent(X11Scancode scancode);
MouseButtonDownEvent getEvent(MouseButton buttoncode);
void raise() const;
void lower() const;
void setCursor(CursorStyle style) const;
// TODO: Implement
// void setCursor(Icon* icon) const;
static void glSwapBuffers();
//Initialize to false because it's not guaranteed that they will be cleared first
RWindow() : flags(false,false,false,false) {}
RWindow();
};

View File

@@ -2,25 +2,27 @@
#include "include/rewindow/types/window.h"
#if __linux__
void KeyDown(KeyDownEvent e)
{
std::cout << e.key.CharCode << " pressed" << std::endl;
}
int main() {
auto* window = new(RWindow);
auto* window = new RWindow();
window->init(RenderingAPI::OPENGL, "name",100,100);
window->setFlag(RWindowFlags::RESIZABLE, false);
while (true) {
window->pollEvents();
if (window->keyDown(X11Scancode::A)) {
std::cout << "A" << std::endl;
//std::cout << (int64_t) window->getEvent(X11Scancode::A).empty() << std::endl;
}
//if (window->mouseButtonDown(MOUSEBUTTONCODE::LEFT_CLICK))
//std::cout << window->mouseButtonDown(MOUSEBUTTONCODE::LEFT_CLICK) << std::endl;
//std::cout << window->eventLog.size() << std::endl;
//window->resize(800,600);
//std::cout << window->getPos()[1] << std::endl;
//auto* d = new(KeyDownEvent);
//d->key = SCANCODE::A;
//window->eventLog.push_back(d);
window->onKeyboardPress += KeyDown;
window->onKeyboardRelease += [&](KeyUpEvent e)
{
if (e.key == Keys::F)
window->setFullscreen(!window->isFullscreen());
};
while (window->isAlive()) {
window->pollEvents();
window->refresh();
}
}
@@ -28,15 +30,15 @@ int main() {
#ifdef WIN32
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
auto* window = new RWindow();
window->init(RenderingAPI::OPENGL, "mame", 100, 100);
window->setFlag
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";

View File

@@ -1,6 +1,15 @@
#include <iostream>
#include <rewindow/types/window.h>
#include <rewindow/data/WindowsScancodes.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
// TODO: Move all "global" members to be instantiated class members of Window
Window window;
XEvent xev;
Display* display = XOpenDisplay(nullptr);
@@ -23,12 +32,22 @@ Key::Key() {
keyboard.push_back(*this);
}
Key::Key(char charcode, X11Scancode scancode)
: CharCode(charcode), x11ScanCode(scancode)
Key::Key(char charcode, X11Scancode scancode, WindowsScancode sc)
: CharCode(charcode), x11ScanCode(scancode), winScanCode(sc)
{
keyboard.push_back(*this);
}
bool Key::operator==(const Key &rhs) const {
return (this->CharCode == rhs.CharCode);
}
bool Key::operator<(const Key &rhs) const {
return (this->CharCode < rhs.CharCode);
}
void RWindow::raise() const { XRaiseWindow(display, window); }
void RWindow::lower() const { XLowerWindow(display, window); }
void RWindow::init(RenderingAPI api, const char* title, int width, int height) {
if (api == RenderingAPI::OPENGL) {
@@ -66,7 +85,12 @@ void RWindow::destroyWindow() {
delete this;
}
bool RWindow::getFlag(RWindowFlags flag) {
void RWindow::refresh() {
}
bool RWindow::getFlag(RWindowFlags flag) const
{
if (flags[(int)flag])
return true;
return false;
@@ -109,8 +133,8 @@ void RWindow::pollEvents() {
if (xev.type == KeyRelease) {
auto scancode = (X11Scancode) xev.xkey.keycode;
currentKeyboard.PressedKeys[scancode] = false;
auto key = GetKeyFromX11Scancode(scancode);
currentKeyboard.PressedKeys[key] = false;
KeyUpEvent eventData = KeyUpEvent(key);
onKeyboardRelease.Invoke(eventData);
@@ -131,7 +155,7 @@ void RWindow::pollEvents() {
//The keycodes won't be the same :shrug:
auto scancode = (X11Scancode) xev.xkey.keycode;
auto key = GetKeyFromX11Scancode(scancode);
currentKeyboard.PressedKeys[scancode] = true;
currentKeyboard.PressedKeys[key] = true;
KeyDownEvent eventData = KeyDownEvent(key);
onKeyboardPress.Invoke(eventData);
eventLog.push_back(eventData);
@@ -199,7 +223,7 @@ void RWindow::setPos(int x, int y) {
}
bool RWindow::keyDown(X11Scancode scancode) {
return currentKeyboard.PressedKeys[scancode];
return currentKeyboard.PressedKeys[GetKeyFromX11Scancode(scancode)];
/*for (auto & ev : eventLog) {
if (auto *e = dynamic_cast<KeyDownEvent *>(ev)) {
if (e->key == scancode) { return true;}
@@ -240,3 +264,62 @@ void RWindow::glSwapBuffers() {
glXSwapBuffers(display,window);
}
bool RWindow::isResizable() const {
return this->getFlag(RWindowFlags::RESIZABLE);
}
bool RWindow::isAlive() const {
return true;
}
void RWindow::setResizable(bool resizable) {
this->setFlag(RWindowFlags::RESIZABLE, resizable);
}
RWindow::RWindow() : flags(false,false,false,false) {}
void RWindow::setFullscreen(bool fs) {
if (fs)
fullscreen();
else
restoreFromFullscreen();
}
void RWindow::fullscreen() {
fullscreenmode = true;
XEvent xev;
Atom wm_state = XInternAtom (display, "_NET_WM_STATE", true );
Atom wm_fullscreen = XInternAtom (display, "_NET_WM_STATE_FULLSCREEN", true );
XChangeProperty(display, window, wm_state, XA_ATOM, 32,
PropModeReplace, (unsigned char *)&wm_fullscreen, 1);
memset(&xev, 0, sizeof(xev));
xev.type = ClientMessage;
xev.xclient.window = 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] = fullscreenmode;
xev.xclient.data.l[2] = 0;
XSendEvent(display, DefaultRootWindow(display), False,
SubstructureNotifyMask | SubstructureRedirectMask, &xev);
}
void RWindow::restoreFromFullscreen() {
fullscreenmode = false;
XEvent xev;
Atom wm_state = XInternAtom(display, "_NET_WM_STATE", False);
Atom fullscreen = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", False);
memset(&xev, 0, sizeof(xev));
xev.type = ClientMessage;
xev.xclient.window = 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] = fullscreenmode;
xev.xclient.data.l[2] = 0;
XSendEvent(display, DefaultRootWindow(display), False,
SubstructureNotifyMask | SubstructureRedirectMask, &xev);
}

View File

@@ -1 +1,31 @@
#include "../../include/rewindow/types/window.h"
#include <rewindow/types/window.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LPTSTR szClassName = TEXT("GenericProgramWindowClass");
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
HWND hwnd;
RWindow::RWindow()
{
hwnd = CreateWindow();
}
void RWindow::raise() const {
SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); // Restore
SetForegroundWindow(hwnd);
SetActiveWindow(hwnd);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
// Redraw to prevent the window blank
RedrawWindow(hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
void RWindow::lower() const {
}