Compare commits

...

36 Commits

Author SHA1 Message Date
39990e587b Update CMakeLists.txt 2024-05-23 19:33:53 -04:00
Redacted
51d370e045 Update CMakeLists.txt 2024-05-22 20:34:33 -04:00
Redacted
4ee4cafad7 Update CMakeLists.txt 2024-05-22 20:15:36 -04:00
maxbyte9p
e1c0cdd1a2 Fixed left and right shift scan codes 2024-05-22 13:51:57 -04:00
maxbyte9p
7b149594fe Make window start as a floating window because fuck i3 2024-05-22 13:39:22 -04:00
Redacted
350b12aa6d Update CMakeLists.txt 2024-05-22 12:19:16 -04:00
a8da7b6bdf Update 2024-05-22 07:23:57 -07:00
50ccfe3860 Update J3ML 2024-05-21 13:16:06 -04:00
orange bowler hat
3572ef01cd More Windows Update
Several minor changes to code and build setup
Demo runs now
2024-05-13 23:14:04 +01:00
orange bowler hat
664d213c04 Several smaller updates
Windows version of ReWindow now compiling
Added to gitignore
2024-05-13 13:40:11 +01:00
d3a971d598 Fix 2024-05-08 22:15:28 -04:00
orange bowler hat
52e1b6eb00 More Windows compatibility
Almost everything addressed

Couldn't figure out where the process handle is stored, if it is

Some cpp problems about CursorStyle classes. I tried several ways to solve this but nothing seemed to work so I'm really not sure what its actually complaining about now
2024-05-09 00:00:32 +01:00
orange bowler hat
f47e6bc786 Lets try that last one again
Comments as previous commit
2024-05-03 23:57:40 +01:00
orange bowler hat
1d9169679f Updates to windows version
Many changes to flesh out windows version of ReWindow.
Incomplete, not compiled or tested.
Almost certainly won't work as is but a lot closer to a functioning Windows version
2024-05-03 23:49:35 +01:00
Redacted
a7b7de93dd fix cmake & vsync 2024-04-30 14:45:43 -07:00
orange bowler hat
124cbedf4d Updates to windows version (Thanks Steven)
Many changes to flesh out windows version of ReWindow.
Incomplete, not compiled or tested.
Almost certainly won't work as is but a lot closer to a functioning Windows version
2024-04-29 19:13:25 -04:00
orange bowler hat
4db3b5f908 Updates to windows version
Many changes to flesh out windows version of ReWindow.
Incomplete, not compiled or tested.
Almost certainly won't work as is but a lot closer to a functioning Windows version
2024-04-29 23:03:35 +01:00
9a4a4dddcc Merge remote-tracking branch 'origin/main' 2024-04-09 16:38:49 -04:00
04fa303a81 Migrate to J3ML Release 1 2024-04-09 16:38:39 -04:00
4facfb11fa Update window.cpp
vsync fix
2024-03-26 11:47:59 -04:00
ef257765fe Migrate to J3ML v20 2024-03-21 13:05:09 -04:00
5696dd4ed8 Un-break 2024-02-24 08:42:42 -05:00
Redacted
9f0a511022 Update CMakeLists.txt 2024-02-24 07:48:37 -05:00
ffe49e4c67 Implement static GetMouseCoordinates() ? 2024-02-22 00:31:04 -05:00
28f904783f Fix SIGILL 2024-02-21 23:46:42 -05:00
6969568549 Attempt to fix broken integration 2024-02-21 23:38:12 -05:00
bcc74ea3d4 Integrate Event module 2024-02-21 23:12:36 -05:00
ef57fb0732 Implement RWindow::isKeyDown 2024-02-21 20:21:37 -05:00
2930391ee4 Implement CursorStyles, minor refactors 2024-02-21 20:10:06 -05:00
b1dfab70a1 Lil Cleanup 2024-02-21 05:37:12 -05:00
bdc1427626 Clear TODOs 2024-02-21 05:35:20 -05:00
158fafaa79 Implement Window::getCursorPos, also fixed Window::getPos 2024-02-21 05:35:08 -05:00
426b02b3ea Migrate to latest J3ML 2024-02-20 03:52:24 -05:00
227ecdb64c Implementing Window::GetSize() 2024-02-14 20:38:26 -05:00
089b110b87 Implementing more of the Windows/X11 KeyMap 2024-02-13 20:24:06 -05:00
7e8a1b4030 Remove JGL dependency 2024-02-13 19:59:02 -05:00
16 changed files with 1134 additions and 494 deletions

2
.gitignore vendored
View File

@@ -1,2 +1,4 @@
/cmake-build-debug
/.idea
build/*
.vscode/*

View File

@@ -10,10 +10,6 @@ endif()
set(CMAKE_CXX_STANDARD 20)
if (WIN32)
set(CMAKE_CXX_FLAGS "-municode")
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
@@ -21,45 +17,65 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(cmake/CPM.cmake)
CPMAddPackage(
NAME J3ML
URL https://git.redacted.cc/josh/j3ml/archive/Prerelease-14.zip
NAME J3ML
URL https://git.redacted.cc/josh/j3ml/archive/Release-7.zip
)
CPMAddPackage(
NAME JGL
URL https://git.redacted.cc/josh/JGL/archive/pre-1.zip
NAME Event
URL https://git.redacted.cc/josh/Event/archive/Release-5.zip
)
find_package(OpenGL REQUIRED)
include_directories({$OPENGL_INCLUDE_DIRS} ${J3ML_SOURCE_DIR}/include)
include_directories(${OPENGL_INCLUDE_DIRS})
include_directories(${J3ML_SOURCE_DIR}/include)
file(GLOB_RECURSE HEADERS "include/*.h" "include/*.hpp")
if(UNIX AND NOT APPLE)
file(GLOB_RECURSE SOURCES "src/linux/*.cpp")
file(GLOB_RECURSE SOURCES "src/rewindow/*.cpp" "src/linux/*.cpp")
endif()
if(WIN32)
file(GLOB_RECURSE SOURCES "src/windows/*.cpp")
file(GLOB_RECURSE SOURCES "src/rewindow/*.cpp" "src/windows/*.cpp")
endif()
include_directories("include")
add_library(ReWindowLibrary SHARED ${SOURCES}
include/rewindow/data/X11Scancodes.h
include/rewindow/types/key.h
include/rewindow/data/WindowsScancodes.h
src/rewindow/types/key.cpp
src/rewindow/types/window.cpp
)
if(UNIX)
add_library(ReWindowLibrary SHARED ${SOURCES})
endif()
if(WIN32)
add_library(ReWindowLibrary STATIC ${SOURCES})
endif()
target_include_directories(ReWindowLibrary PUBLIC ${Event_SOURCE_DIR}/include)
# Why god???
set_target_properties(ReWindowLibrary PROPERTIES LINKER_LANGUAGE CXX)
if(UNIX AND NOT APPLE)
target_link_libraries(ReWindowLibrary PUBLIC X11 J3ML ${OPENGL_LIBRARIES})
target_link_libraries(ReWindowLibrary PUBLIC X11)
target_link_libraries(ReWindowLibrary PUBLIC ${OPENGL_LIBRARIES})
target_link_libraries(ReWindowLibrary PUBLIC J3ML)
target_link_libraries(ReWindowLibrary PUBLIC Event)
add_executable(ReWindowLibraryDemo main.cpp)
target_include_directories(ReWindowLibraryDemo PRIVATE ${JGL_SOURCE_DIR}/include)
#target_include_directories(ReWindowLibraryDemo PRIVATE ${JGL_SOURCE_DIR}/include)
target_link_libraries(ReWindowLibraryDemo PUBLIC ReWindowLibrary)
target_link_libraries(ReWindowLibraryDemo PRIVATE JGL)
#target_link_libraries(ReWindowLibraryDemo PRIVATE JGL)
endif()
if(WIN32)
#target_compile_options(ReWindowLibrary PRIVATE -Wno-multichar)
target_link_libraries(ReWindowLibrary PUBLIC ${OPENGL_LIBRARIES})
target_link_libraries(ReWindowLibrary PUBLIC J3ML)
target_link_libraries(ReWindowLibrary PUBLIC Event)
add_executable(ReWindowLibraryDemo main.cpp)
#target_compile_options(ReWindowLibraryDemo PRIVATE)
target_link_libraries(ReWindowLibraryDemo PUBLIC ReWindowLibrary)
endif()

98
build/CMakeCache.txt Normal file
View File

@@ -0,0 +1,98 @@
# This is the CMakeCache file.
# For build in directory: d:/Work/ReWindow/build
# It was generated by CMake: C:/Program Files/CMake/bin/cmake.exe
# You can edit this file to change values found and used by cmake.
# If you do not want to change any of the values, simply exit the editor.
# If you do want to change a value, simply edit, save, and exit the editor.
# The syntax for the file is as follows:
# KEY:TYPE=VALUE
# KEY is the name of a variable in the cache.
# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
# VALUE is the current value for the KEY.
########################
# EXTERNAL cache entries
########################
//Value Computed by CMake.
CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=D:/Work/ReWindow/build/CMakeFiles/pkgRedirects
//Program used to build from makefiles.
CMAKE_MAKE_PROGRAM:STRING=nmake
//Value Computed by CMake
CMAKE_PROJECT_DESCRIPTION:STATIC=
//Value Computed by CMake
CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
//Value Computed by CMake
CMAKE_PROJECT_NAME:STATIC=ReWindowLibrary
//Value Computed by CMake
CMAKE_PROJECT_VERSION:STATIC=1.0
//Value Computed by CMake
CMAKE_PROJECT_VERSION_MAJOR:STATIC=1
//Value Computed by CMake
CMAKE_PROJECT_VERSION_MINOR:STATIC=0
//Value Computed by CMake
CMAKE_PROJECT_VERSION_PATCH:STATIC=
//Value Computed by CMake
CMAKE_PROJECT_VERSION_TWEAK:STATIC=
//Value Computed by CMake
ReWindowLibrary_BINARY_DIR:STATIC=D:/Work/ReWindow/build
//Value Computed by CMake
ReWindowLibrary_IS_TOP_LEVEL:STATIC=ON
//Value Computed by CMake
ReWindowLibrary_SOURCE_DIR:STATIC=D:/Work/ReWindow
########################
# INTERNAL cache entries
########################
//This is the directory where this CMakeCache.txt was created
CMAKE_CACHEFILE_DIR:INTERNAL=d:/Work/ReWindow/build
//Major version of cmake used to create the current loaded cache
CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
//Minor version of cmake used to create the current loaded cache
CMAKE_CACHE_MINOR_VERSION:INTERNAL=29
//Patch version of cmake used to create the current loaded cache
CMAKE_CACHE_PATCH_VERSION:INTERNAL=2
//Path to CMake executable.
CMAKE_COMMAND:INTERNAL=C:/Program Files/CMake/bin/cmake.exe
//Path to cpack program executable.
CMAKE_CPACK_COMMAND:INTERNAL=C:/Program Files/CMake/bin/cpack.exe
//Path to ctest program executable.
CMAKE_CTEST_COMMAND:INTERNAL=C:/Program Files/CMake/bin/ctest.exe
//Path to cache edit program executable.
CMAKE_EDIT_COMMAND:INTERNAL=C:/Program Files/CMake/bin/cmake-gui.exe
//Name of external makefile project generator.
CMAKE_EXTRA_GENERATOR:INTERNAL=
//Name of generator.
CMAKE_GENERATOR:INTERNAL=NMake Makefiles
//Generator instance identifier.
CMAKE_GENERATOR_INSTANCE:INTERNAL=
//Name of generator platform.
CMAKE_GENERATOR_PLATFORM:INTERNAL=
//Name of generator toolset.
CMAKE_GENERATOR_TOOLSET:INTERNAL=
//Source directory with the top level CMakeLists.txt file for this
// project
CMAKE_HOME_DIRECTORY:INTERNAL=D:/Work/ReWindow
//ADVANCED property for variable: CMAKE_MAKE_PROGRAM
CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1
//number of local generators
CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1
//Platform information initialized
CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1
//Path to CMake installation.
CMAKE_ROOT:INTERNAL=C:/Program Files/CMake/share/cmake-3.29

View File

@@ -0,0 +1,15 @@
set(CMAKE_HOST_SYSTEM "Windows-10.0.15063")
set(CMAKE_HOST_SYSTEM_NAME "Windows")
set(CMAKE_HOST_SYSTEM_VERSION "10.0.15063")
set(CMAKE_HOST_SYSTEM_PROCESSOR "AMD64")
set(CMAKE_SYSTEM "Windows-10.0.15063")
set(CMAKE_SYSTEM_NAME "Windows")
set(CMAKE_SYSTEM_VERSION "10.0.15063")
set(CMAKE_SYSTEM_PROCESSOR "AMD64")
set(CMAKE_CROSSCOMPILING "FALSE")
set(CMAKE_SYSTEM_LOADED 1)

View File

@@ -0,0 +1,11 @@
---
events:
-
kind: "message-v1"
backtrace:
- "C:/Program Files/CMake/share/cmake-3.29/Modules/CMakeDetermineSystem.cmake:205 (message)"
- "CMakeLists.txt:2 (project)"
message: |
The system is: Windows - 10.0.15063 - AMD64
...

View File

@@ -0,0 +1 @@
# This file is generated by cmake for dependency checking of the CMakeCache.txt file

View File

@@ -101,9 +101,10 @@ enum class X11Scancode {
F8 = 74,
F9 = 75,
F10 = 76,
F11 = 77,
F12 = 78,
F11 = 95,
F12 = 96,
PRINT = 107,
SCROLL_LOCK = 78,
BREAK = 127,
};

View File

@@ -0,0 +1,80 @@
#pragma once
#if __linux__
#include <X11/cursorfont.h>
#endif
namespace ReWindow
{
#if __linux__
enum class X11CursorStyle
{
Default = XC_left_ptr,
X = XC_X_cursor,
Arrow = XC_arrow,
IBeam = XC_xterm,
BottomLeftCorner = XC_bottom_left_corner,
BottomRightCorner = XC_bottom_right_corner,
BottomSide = XC_bottom_side,
Dot = XC_dot,
DoubleArrow = XC_double_arrow,
Exchange = XC_exchange,
Hand = XC_hand2,
LeftSide = XC_left_side,
Plus = XC_plus,
RightSide = XC_right_side,
Pencil = XC_pencil
};
class CursorStyle {
public:
X11CursorStyle X11Cursor;
CursorStyle(X11CursorStyle style) : X11Cursor(style) {}
};
namespace Cursors {
static const CursorStyle Default {X11CursorStyle::Default};
static const CursorStyle X {X11CursorStyle::X};
static const CursorStyle Arrow {X11CursorStyle::Arrow};
static const CursorStyle IBeam {X11CursorStyle::IBeam};
static const CursorStyle BottomLeftCorner {X11CursorStyle::BottomLeftCorner};
static const CursorStyle BottomRightCorner {X11CursorStyle::BottomRightCorner};
static const CursorStyle BottomSide {X11CursorStyle::BottomSide};
static const CursorStyle Dot {X11CursorStyle::Dot};
static const CursorStyle DoubleArrow {X11CursorStyle::DoubleArrow};
static const CursorStyle Exchange {X11CursorStyle::Exchange};
static const CursorStyle Hand {X11CursorStyle::Hand};
static const CursorStyle LeftSide {X11CursorStyle::LeftSide};
static const CursorStyle Plus {X11CursorStyle::Plus};
static const CursorStyle RightSide {X11CursorStyle::RightSide};
static const CursorStyle Pencil {X11CursorStyle::Pencil};
}
#else
// https://learn.microsoft.com/en-us/windows/win32/menurc/about-cursors
enum WindowsCursorStyle {
Arrow,
IBeam,
Wait,
Cross,
Hand,
AppStarting,
};
class CursorStyle {
public:
WindowsCursorStyle WindowsCursor;
CursorStyle (WindowsCursorStyle style): WindowsCursor(style) {}
};
namespace Cursors {
static const CursorStyle Default {WindowsCursorStyle::Arrow};
static const CursorStyle Arrow {WindowsCursorStyle::Arrow};
static const CursorStyle IBeam {WindowsCursorStyle::IBeam};
static const CursorStyle Cross {WindowsCursorStyle::Cross};
static const CursorStyle Wait {WindowsCursorStyle::Wait};
static const CursorStyle Hand {WindowsCursorStyle::Hand};
static const CursorStyle AppStarting {WindowsCursorStyle::AppStarting};
}
#endif
}

View File

@@ -1,81 +0,0 @@
#pragma once
#include <chrono>
#include <functional>
template <typename ... Args>
class Event;
template <typename ... Args>
class EventConnection {
private:
using delegate = std::function<void(Args...)>;
public:
EventConnection(Event<Args...> *creator, delegate cb) : owner(creator), callback(std::move(cb)) {}
bool Disconnect(); // Breaks the event connection, but does not destroy the instance
void Invoke(Args... e);
private:
Event<Args...> * owner;
delegate callback;
bool active = true;
};
template <typename ... Args>
class Event {
public:
using delegate = std::function<void(Args...)>;
using connection = EventConnection<Args ...>;
using event_ptr = std::shared_ptr<connection>;
public:
void Await(Args& ... arg);
void Invoke(Args... args);
void operator()(Args... args);
connection Connect(delegate callback);
void Disconnect(connection &conn);
connection operator+=(delegate callback);
private:
std::vector<event_ptr> listeners;
uint64_t listenerCounter = 0;
};
template<typename... Args>
EventConnection<Args...> Event<Args...>::operator+=(Event::delegate callback) { return Connect(callback); }
template<typename... Args>
void Event<Args...>::operator()(Args... args) { Invoke(args...);}
template <typename... Args>
void EventConnection<Args...>::Invoke(Args... e) { callback(e...); }
template <typename ... Args>
bool EventConnection<Args...>::Disconnect() {
if (active) {
owner->Disconnect(this);
active = false;
return true;
}
return false;
}
template <typename ... Args>
void Event<Args...>::Invoke(Args... args) {
for (event_ptr &connection_ptr: this->listeners) {
connection_ptr->Invoke(args...);
}
}
template <typename ... Args>
EventConnection<Args...> Event<Args...>::Connect(delegate callback)
{
event_ptr retval(new connection(this, callback));
this->listeners.push_back(retval);
return *retval;
}
template <typename ... Args>
void Event<Args...>::Disconnect(connection &conn) {
listeners.erase(std::remove(listeners.begin(), listeners.end(), 99), listeners.end());
}

View File

@@ -2,11 +2,11 @@
// ~DAWSH
#pragma once
#include <vector>
#include <J3ML/LinearAlgebra/Vector2.h>
#include <stdexcept>
#include <iostream>
#if __linux__
#include <X11/X.h>
@@ -15,14 +15,14 @@
#include "rewindow/data/X11Scancodes.h"
#include "rewindow/data/WindowsScancodes.h"
using Vector2 = LinearAlgebra::Vector2;
using J3ML::LinearAlgebra::Vector2;
class Key
{
private:
static std::vector<Key> keyboard;
public:
inline static std::vector<Key> GetKeyboard();
static std::vector<Key> GetKeyboard();
Key();
Key(char charcode, X11Scancode scancode, WindowsScancode wSc);
char CharCode;
@@ -35,6 +35,7 @@ public:
};
namespace Keys {
// TODO: Encode both Uppercase and Lowercase version for each keymap
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};
@@ -49,16 +50,27 @@ namespace Keys {
static const Key F11 {'\u000f', X11Scancode::F11, WindowsScancode::F11};
static const Key F12 {'\u000f', X11Scancode::F12, WindowsScancode::F12};
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 NumPad1 {'\b', X11Scancode::KP_1, WindowsScancode::NUMPAD_ONE};
static const Key NumPad2 {'\b', X11Scancode::KP_2, WindowsScancode::NUMPAD_TWO};
static const Key NumPad3 {'\b', X11Scancode::KP_3, WindowsScancode::NUMPAD_THREE};
static const Key NumPad4 {'\b', X11Scancode::KP_4, WindowsScancode::NUMPAD_ONE};
static const Key NumPad5 {'\b', X11Scancode::KP_5, WindowsScancode::NUMPAD_ONE};
static const Key NumPad6 {'\b', X11Scancode::KP_6, WindowsScancode::NUMPAD_ONE};
static const Key NumPad7 {'\b', X11Scancode::KP_7, WindowsScancode::NUMPAD_ONE};
static const Key NumPad8 {'\b', X11Scancode::KP_8, WindowsScancode::NUMPAD_ONE};
static const Key NumPad9 {'\b', X11Scancode::KP_9, WindowsScancode::NUMPAD_ONE};
static const Key NumPad0 {'\b', X11Scancode::KP_0, WindowsScancode::NUMPAD_ONE};
static const Key One {'1', X11Scancode::ONE, WindowsScancode::ONE};
static const Key Two {'2', X11Scancode::TWO, WindowsScancode::TWO};
static const Key Three {'3', X11Scancode::THREE, WindowsScancode::THREE};
static const Key Four {'4', X11Scancode::FOUR, WindowsScancode::FOUR};
static const Key Five {'5', X11Scancode::FIVE, WindowsScancode::FIVE};
static const Key Six {'6', X11Scancode::SIX, WindowsScancode::SIX};
static const Key Seven {'7', X11Scancode::SEVEN, WindowsScancode::SEVEN};
static const Key Eight {'8', X11Scancode::EIGHT, WindowsScancode::EIGHT};
static const Key Nine {'9', X11Scancode::NINE, WindowsScancode::NINE};
static const Key Zero {'0', X11Scancode::ZERO, WindowsScancode::ZERO};
static const Key Q {'Q', X11Scancode::Q, WindowsScancode::Q};
static const Key W {'W', X11Scancode::W, WindowsScancode::W};
@@ -96,19 +108,35 @@ namespace Keys {
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;
static const Key Space {' ', X11Scancode::SPACE, WindowsScancode::SPACE};
static const Key LControl {'\\', X11Scancode::LEFT_CTRL, WindowsScancode::CTRL};
static const Key RControl {'\\', X11Scancode::RIGHT_CONTROL, WindowsScancode::CTRL};
static const Key LAlt {'\\', X11Scancode::LEFT_ALT, WindowsScancode::ALT};
static const Key RAlt {'\\', X11Scancode::RIGHT_ALT, WindowsScancode::ALT};
static const Key LShift {'\\', X11Scancode::LEFT_SHIFT, WindowsScancode::LEFT_SHIFT};
static const Key RShift {'\\', X11Scancode::RIGHT_SHIFT, WindowsScancode::RIGHT_SHIFT};
// 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};
static const Key Super {'\000a', X11Scancode::SUPER, WindowsScancode::Nothing};
static const Key Backspace {'\b', X11Scancode::BACKSPACE, WindowsScancode::BACKSPACE};
static const Key LeftBracket {'[', X11Scancode::OPENING_SQUARE_BRACKET, WindowsScancode::LEFT_BRACKET};
static const Key RightBracket {']', X11Scancode::CLOSING_SQUARE_BRACKET, WindowsScancode::RIGHT_BRACKET};
}
class GamepadButton {};
class MouseButton {};
using J3ML::LinearAlgebra::Vector2;
class InputService {
public:
@@ -123,8 +151,6 @@ namespace GamepadButtons {
static const GamepadButton B;
}
namespace MouseButtons
{
static const MouseButton Left;
@@ -134,10 +160,10 @@ namespace MouseButtons
static const MouseButton Side2;
}
static MouseButton GetMouseButtonFromXButton(unsigned int button)
{
switch(button)
{
#if __linux__
static MouseButton GetMouseButtonFromXButton(unsigned int button) {
switch(button) {
case Button1: return MouseButtons::Left;
case Button2: return MouseButtons::Right;
case Button3: return MouseButtons::Middle;
@@ -151,19 +177,24 @@ static MouseButton GetMouseButtonFromXButton(unsigned int button)
}
}
static Key GetKeyFromX11Scancode(X11Scancode code)
{
static Key GetKeyFromX11Scancode(X11Scancode code) {
for (auto& key : Key::GetKeyboard()) {
if (key.x11ScanCode == code)
return key;
}
throw std::runtime_error("Unavaliable Scancode: " + std::to_string((int)code));
std::cout << "Unavaliable Scancode: " + std::to_string((int)code) << std::endl;
return Keys::Space;
}
static Key GetKeyFromWindowsScancode(WindowsScancode code)
{
#else
static Key GetKeyFromWindowsScancode(WindowsScancode code) {
for (auto& key : Key::GetKeyboard()) {
if (key.winScanCode == code)
return key;
}
throw std::runtime_error("Unavaliable Scancode: " + std::to_string((int)code));
std::cout << "Unavaliable Scancode: " + std::to_string((int)code) << std::endl;
return Keys::Space;
}
#endif

View File

@@ -2,11 +2,17 @@
#include <cstdint>
#include <vector>
#include <memory>
#include <rewindow/types/event.h>
#include <Event.h>
#include <functional>
#include <map>
#include <thread>
#include <rewindow/types/key.h>
#if WIN32
#include <windows.h>
#include <windowsx.h>
#include <wingdi.h>
#endif
#if __linux__
#include <X11/Xlib.h>
@@ -15,219 +21,247 @@
#include <GL/glx.h>
#endif
#include <rewindow/types/cursors.h>
using namespace std::chrono_literals;
using precision_clock = std::chrono::high_resolution_clock;
using precision_timestamp = precision_clock::time_point;
enum class RWindowFlags: uint8_t {
IN_FOCUS = 0,
FULLSCREEN = 1,
RESIZABLE = 2,
VSYNC = 4
IN_FOCUS,
FULLSCREEN,
RESIZABLE,
VSYNC,
QUIT,
MAX_FLAG
};
enum class RenderingAPI: uint8_t {
OPENGL = 0,
//Vulkan is unimplemented.
VULKAN = 1,
OPENGL = 0,
//Vulkan is unimplemented.
VULKAN = 1,
};
enum class CursorStyle
{
Default,
X,
Arrow,
IBeam,
BottomLeftCorner,
BottomRightCorner,
BottomSide,
Dot,
DoubleArrow,
Exchange,
Hand,
LeftSide,
Plus,
RightSide,
};
enum class KeyState { Pressed, Released };
enum class KeyState {Pressed, Released};
namespace ReWindow
{
using LinearAlgebra::Vector2;
using J3ML::LinearAlgebra::Vector2;
class TimestampedEvent {
private:
class TimestampedEvent {
private:
public:
precision_timestamp Timestamp;
TimestampedEvent() : Timestamp(precision_clock::now())
{ }
};
public:
precision_timestamp Timestamp;
TimestampedEvent() : Timestamp(precision_clock::now())
{ }
};
class RWindowEvent : public TimestampedEvent {
public:
RWindowEvent() : TimestampedEvent() { }
};
const RWindowEvent EmptyRWindowEvent;
class RWindowEvent : public TimestampedEvent {
public:
RWindowEvent() : TimestampedEvent() { }
};
const RWindowEvent EmptyRWindowEvent;
namespace WindowEvents
{
class KeyboardState {
public:
std::map<Key, bool> PressedKeys;
};
namespace WindowEvents
{
class KeyboardState {
public:
std::map<Key, bool> PressedKeys;
};
class GamepadState {
public:
std::map<GamepadButton, bool> PressedButtons;
};
class GamepadState {
public:
std::map<GamepadButton, bool> PressedButtons;
};
class InputState {
public:
KeyboardState Keyboard;
GamepadState Gamepad;
};
class InputState {
public:
KeyboardState Keyboard;
GamepadState Gamepad;
};
class KeyboardEvent : public RWindowEvent {
public:
Key key;
KeyState state;
KeyboardEvent(Key key, KeyState state) : RWindowEvent(), key(key), state(state) {}
};
class MouseEvent : public RWindowEvent {};
class GamepadEvent : public RWindowEvent {};
class KeyboardEvent : public RWindowEvent {
public:
Key key;
KeyState state;
KeyboardEvent(Key key, KeyState state) : RWindowEvent(), key(key), state(state) {}
};
class MouseEvent : public RWindowEvent {};
class GamepadEvent : public RWindowEvent {};
class MouseMoveEvent : public MouseEvent {
public:
Vector2 Position;
Vector2 Delta;
MouseMoveEvent(const Vector2 &pos) : MouseEvent(), Position(pos)
{}
MouseMoveEvent(int x, int y) : MouseEvent(), Position(Vector2(x, y))
{}
};
class MouseMoveEvent : public MouseEvent {
public:
Vector2 Position;
Vector2 Delta;
MouseMoveEvent(const Vector2 &pos) : MouseEvent(), Position(pos)
{}
MouseMoveEvent(int x, int y) : MouseEvent(), Position(Vector2(x, y))
{}
};
class KeyDownEvent : public KeyboardEvent {
public:
KeyDownEvent(Key key) : KeyboardEvent(key, KeyState::Pressed) {}
};
class KeyDownEvent : public KeyboardEvent {
public:
KeyDownEvent(Key key) : KeyboardEvent(key, KeyState::Pressed) {}
};
class KeyUpEvent : public KeyboardEvent {
public:
KeyUpEvent(Key key) : KeyboardEvent(key, KeyState::Released) {}
};
class KeyUpEvent : public KeyboardEvent {
public:
KeyUpEvent(Key key) : KeyboardEvent(key, KeyState::Released) {}
};
class MouseButtonDownEvent : public MouseEvent {
public:
MouseButton Button;
};
class MouseButtonDownEvent : public MouseEvent {
public:
MouseButton Button;
};
class MouseButtonUpEvent : public MouseEvent {
public:
MouseButton Button;
};
}
class MouseButtonUpEvent : public MouseEvent {
public:
MouseButton Button;
};
using namespace WindowEvents;
class WindowResizeRequestEvent : public RWindowEvent
{
public:
Vector2 Size;
};
}
class RWindow {
using namespace WindowEvents;
private:
bool flags[4];
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;
// TODO: Integrate J3ML
Event<MouseMoveEvent&> mouseMoved;
Event<MouseButton> mouseBtnPressed;
Event<MouseButton> mouseBtnReleased;
Event<KeyDownEvent> onKeyboardPress;
Event<KeyUpEvent> onKeyboardRelease;
class RWindow {
public:
virtual void OnFocusLost(const RWindowEvent& e) {}
virtual void OnFocusGain(const RWindowEvent& e) {}
virtual void OnRefresh(float elapsed) {}
virtual void OnResizeSuccess() {}
virtual bool OnResizeRequest() {}
virtual void OnKeyDownEvent(const KeyDownEvent&) {}
virtual void OnKeyUpEvent(const KeyUpEvent&) {}
virtual void OnMouseMove(const MouseMoveEvent&) {}
virtual void OnMouseButtonDown(const MouseButtonDownEvent&) {}
virtual void OnMouseButtonUp(const MouseButtonUpEvent&) {}
#pragma region Callbacks
/// Bindable Non-intrusive event handlers
/// Use these when you can't override the base window class
Event<RWindowEvent> OnFocusLostEvent;
Event<RWindowEvent> OnFocusGainEvent;
Event<float> OnRefreshEvent;
Event<WindowResizeRequestEvent> OnResizeRequestEvent;
Event<KeyDownEvent> OnKeyDownEvent;
Event<KeyUpEvent> OnKeyUpEvent;
Event<MouseMoveEvent> OnMouseMoveEvent;
Event<MouseButtonDownEvent> OnMouseButtonDownEvent;
Event<MouseButtonUpEvent> OnMouseButtonUpEvent;
#pragma endregion
#pragma region Overrides
virtual void OnFocusLost(const RWindowEvent& e) {}
virtual void OnFocusGain(const RWindowEvent& e) {}
virtual void OnRefresh(float elapsed) {}
virtual void OnResizeSuccess() {}
virtual bool OnResizeRequest(const WindowResizeRequestEvent& e) { return true;}
virtual void OnKeyDown(const KeyDownEvent&) {}
virtual void OnKeyUp(const KeyUpEvent&) {}
virtual void OnMouseMove(const MouseMoveEvent&) {}
virtual void OnMouseButtonDown(const MouseButtonDownEvent&) {}
virtual void OnMouseButtonUp(const MouseButtonUpEvent&) {}
#pragma endregion
RWindow();
RWindow(const std::string& title, int width, int height);
RWindow(const std::string& title, int width, int height, RenderingAPI renderer);
Vector2 GetMouseCoordinates() const {
return getCursorPos();
}
void liftKey (Key key) {
currentKeyboard.PressedKeys[key] = false;
auto event = ReWindow::WindowEvents::KeyUpEvent(key);
OnKeyUp(event);
}
void pressKey (Key key) {
currentKeyboard.PressedKeys[key] = true;
auto eventData = KeyDownEvent(key);
OnKeyDown(eventData);
}
#ifndef __linux___
//RWindow(HINSTANCE hInst);
void setRect (int nx, int ny, int nw, int nh) {
setPos(nx, ny);
width = nw;
height = nh;
}
#endif
void setRenderer(RenderingAPI api);
void Open();
void Close();
void CloseAndReopenInPlace();
// TODO: Must be implemented from scratch as a Motif Window in x11
void MessageBox();
bool isFocused() const;
bool isFullscreen() const;
bool isResizable() const;
bool isVsyncEnabled() const;
bool isAlive() const;
void setMouseVisible(bool visible);
void setMouseLocked();
void setMouseCenter();
void restoreMouseFromLastCenter(); // Feels nicer for users
bool isKeyDown(Key key) const;
bool isMouseButtonDown(MouseButton button) const;
void setFullscreen(bool fs);
void setResizable(bool resizable);
void setVsyncEnabled(bool);
void setTitle(const std::string& title);
std::string getTitle() const;
void fullscreen();
void restoreFromFullscreen();
bool getFlag(RWindowFlags flag) const;
void setFlag(RWindowFlags flag, bool state);
//void init(RenderingAPI api, const char* title, int width, int height, bool vsync);
void destroyWindow();
void pollEvents();
void refresh();
void setSize(int width, int height);
void setSize(const Vector2& size);
/// Returns the position of the window's top-left corner relative to the display
Vector2 getPos() const;
Vector2 getSize() const;
void setPos(int x, int y);
void setPos(const Vector2& pos);
Vector2 getCursorPos() const;
void raise() const;
void lower() const;
void setCursorStyle(CursorStyle style) const;
void setCursorCustomIcon() const;
static void glSwapBuffers();
//Initialize to false because it's not guaranteed that they will be cleared first
private:
Vector2 lastKnownWindowSize {0, 0};
bool flags[5];
std::vector<RWindowEvent> eventLog;
KeyboardState currentKeyboard; // Current Frame's Keyboard State
KeyboardState previousKeyboard; // Previous Frame's Keyboard State
bool fullscreenmode = false;
std::string title;
#ifndef __linux__
int x;
int y;
#endif
int width;
int height;
RenderingAPI renderer;
bool open = false;
bool resizable;
};
RWindow();
class WindowsImplementationRWindow: public RWindow {
};
// TODO: Must be implemented from scratch as a Motif Window in x11
void MessageBox();
bool isFocused() 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 setFullscreen(bool fs);
void setResizable(bool resizable);
void setVsyncEnabled(bool);
void setTitle(const std::string& title);
void fullscreen();
void restoreFromFullscreen();
bool getFlag(RWindowFlags flag) const;
void setFlag(RWindowFlags flag, bool state);
void init(RenderingAPI api, const char* title, int width, int height, bool vsync);
void destroyWindow();
void pollEvents();
void refresh();
void setSize(int width, int height);
void setSize(const Vector2& size);
Vector2 getPos() const;
Vector2 getSize() const;
void setPos(int x, int y);
void setPos(const Vector2& pos);
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
};
class WindowsImplementationRWindow : public RWindow
{
};
class X11ImplementationRWindow : public RWindow
{
};
class X11ImplementationRWindow: public RWindow {
};
}

164
main.cpp
View File

@@ -1,52 +1,75 @@
#include <iostream>
#include <rewindow/types/window.h>
#include <JGL/JGL.h>
#if __linux__
void KeyDown(const ReWindow::WindowEvents::KeyDownEvent& e)
{
std::cout << e.key.CharCode << " pressed" << std::endl;
}
Vector2 mouse_pos;
std::ostream& operator<<(std::ostream& os, const Vector2& v)
{
return os << "{" << v.x << ", " << v.y << "}";
// TODO: Move to J3ML::LinearAlgebra::Vector2
std::ostream& operator<<(std::ostream& os, const Vector2& v) {
return os << "{" << v.x << ", " << v.y << "}";
}
class MyWindow : public ReWindow::RWindow {
public:
MyWindow(const std::string& title, int w, int h) : ReWindow::RWindow(title, w, h)
{}
class MyWindow : public ReWindow::RWindow
{
public:
void OnMouseMove(const ReWindow::MouseMoveEvent& e) override
{
std::cout << "Mouse Moved: " << e.Position << " @ " << std::endl;
}
void OnRefresh(float elapsed) override
{
JGL::J2D::FillRect2D(JGL::Colors::White, {400.f, 400.f}, {200.f, 200.f});
glSwapBuffers();
}
void OnMouseMove(const ReWindow::MouseMoveEvent& e) override {
}
void OnKeyDown(const ReWindow::KeyDownEvent& e) override {
}
void OnRefresh(float elapsed) override {
glSwapBuffers ();
auto pos = getCursorPos ();
//std::cout << pos.x << ", " << pos.y << std::endl;
#if __linux__
if (isKeyDown(Keys::L)) {
this->setCursorStyle (ReWindow::Cursors::Pencil);
}
else this->setCursorStyle (ReWindow::Cursors::Default);
#else
if (isKeyDown (Keys::L)) {
this->setCursorStyle (ReWindow::Cursors::Cross);
}
else this->setCursorStyle (ReWindow::Cursors::Arrow);
#endif
}
bool OnResizeRequest(const ReWindow::WindowResizeRequestEvent& e) override {
std::cout << "resized to " << e.Size.x << ", " << e.Size.y << std::endl;
return true;
}
};
#if __linux__
int main() {
auto* window = new MyWindow();
window->init(RenderingAPI::OPENGL, "name",100,100, true);
window->setFlag(RWindowFlags::RESIZABLE, false);
auto* window = new MyWindow("Test Window", 600, 480);
window->onKeyboardPress += KeyDown;
window->onKeyboardRelease += [&](ReWindow::WindowEvents::KeyUpEvent e)
{
if (e.key == Keys::F)
window->setFullscreen(!window->isFullscreen());
};
window->setRenderer(RenderingAPI::OPENGL);
window->Open();
while (window->isAlive()) {
window->pollEvents();
window->refresh();
}
// TODO: Cannot set flags until after window is open
// Make this work somehow
window->setFullscreen(false);
window->setVsyncEnabled(false);
window->setResizable(false);
window->OnKeyDownEvent += [&] (ReWindow::KeyDownEvent e)
{
if (e.key == Keys::LeftArrow)
{
std::cout << "Left Arrow Hit" << std::endl;
}
};
while (window->isAlive()) {
window->pollEvents();
window->refresh();
}
}
#endif
@@ -58,67 +81,22 @@ int main() {
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int wmain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow) {
auto* window = new MyWindow ("Test Window", 600, 480);
window->raise ();
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
auto* window = new RWindow();
window->init(RenderingAPI::OPENGL, "mame", 100, 100);
window->setFlag
window->OnKeyDownEvent += [&] (ReWindow::KeyDownEvent e) {
if (e.key == Keys::LeftArrow) {
std::cout << "Left Arrow Hit" << std::endl;
}
};
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
while (window->isAlive()) {
window->pollEvents();
window->refresh();
}
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0,
CLASS_NAME,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent Window
NULL, // Menu
hInstance, // Instancehandle
NULL
);
if (hwnd == NULL)
return 0;
ShowWindow(hwnd, nCmdShow);
// Run the message loop
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// All painting occurs here, between BeginPaint and EndPaint
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
return 0;
}
#endif

View File

@@ -1 +0,0 @@
#include "../include/rewindow/types/event.h"

View File

@@ -4,10 +4,14 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <cstdlib>
#include <cstring>
#include <thread>
#include "rewindow/types/cursors.h"
#include "../../include/rewindow/types/window.h"
// TODO: Move all "global" members to be instantiated class members of Window
// Doing this would break the intended "Platform-Specific" Encapsulation
@@ -22,48 +26,41 @@ XVisualInfo* visual;
XSetWindowAttributes xSetWindowAttributes;
XWindowAttributes windowAttributes;
Atom wmDeleteWindow;
// Make it start as floating because fuck tiling WMs
Atom windowTypeAtom;
Atom windowTypeUtilityAtom;
XSizeHints hints;
GLXContext glContext;
namespace ReWindow {
RWindow::RWindow() : flags(false,false,false,false) {
RWindow::RWindow() {
title = "ReWindow Application";
width = 640;
height = 480;
//RWindow::singleton = this;
}
RWindow::RWindow(const std::string& title, int width, int height) : flags(false,false,false,false) {
this->title = title;
this->width = width;
this->height = height;
//RWindow::singleton = this;
}
RWindow::RWindow(const std::string& title, int width, int height, RenderingAPI renderer) :
title(title), width(width), height(height), renderer(renderer)
{
//RWindow::singleton = this;
}
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, bool vsync) {
if (api == RenderingAPI::OPENGL) {
xSetWindowAttributes.border_pixel = BlackPixel(display, defaultScreen);
xSetWindowAttributes.background_pixel = BlackPixel(display, defaultScreen);
xSetWindowAttributes.override_redirect = True;
xSetWindowAttributes.event_mask = ExposureMask;
setVsyncEnabled(vsync);
GLint glAttributes[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None};
visual = glXChooseVisual(display, defaultScreen, glAttributes);
glContext = glXCreateContext(display, visual, nullptr, GL_TRUE);
vsync = sync;
xSetWindowAttributes.colormap = XCreateColormap(display, RootWindow(display, defaultScreen), visual->visual,
AllocNone);
window = XCreateWindow(display, RootWindow(display, defaultScreen), 0, 0, width, height, 0, visual->depth,
InputOutput, visual->visual, CWBackPixel | CWColormap | CWBorderPixel | NoEventMask,
&xSetWindowAttributes);
XSelectInput(display, window,
ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
PointerMotionMask |
PointerMotionHintMask | FocusChangeMask | StructureNotifyMask | SubstructureRedirectMask |
SubstructureNotifyMask | CWColormap);
XMapWindow(display, window);
XStoreName(display, window, title);
wmDeleteWindow = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, window, &wmDeleteWindow, 1);
glXMakeCurrent(display, window, glContext);
setVsyncEnabled(vsync);
} else {exit(0);}
}
void RWindow::destroyWindow() {
XDestroySubwindows(display, window);
@@ -76,31 +73,11 @@ namespace ReWindow {
// TODO: Implement refresh time keeping
OnRefresh(0.f);
// TODO: Check if mouse coords have changed, only then fire OnMouseMove event
Vector2 mouse_coords = getCursorPos();
Window root = XDefaultRootWindow(display);
Window root_return;
Window child_return;
int root_x_ret;
int root_y_ret;
int win_x_ret;
int win_y_ret;
uint32_t mask_return;
unsigned m;
bool mouseAvailable = XQueryPointer(display, root, &root_return, &child_return, &root_x_ret, &root_y_ret, &win_x_ret, &win_y_ret, &mask_return);
if (mouseAvailable)
{
// TODO: process retrieved mouse coordinates
// TODO: normalize coordinates from displaySpace to windowSpace
// TODO: fire mouse movement event
//std::cout << win_x_ret << ", " << win_y_ret << std::endl;
Vector2 mouse_coords_raw = {(float)win_x_ret, (float)win_y_ret};
auto window_pos = getPos();
Vector2 mouse_coords = mouse_coords_raw - window_pos;
auto eventData = MouseMoveEvent(mouse_coords);
OnMouseMove(eventData);
}
auto eventData = MouseMoveEvent(mouse_coords);
OnMouseMove(eventData);
std::this_thread::sleep_for(1ms);
}
@@ -138,7 +115,7 @@ namespace ReWindow {
if (xev.type == FocusIn) {
XAutoRepeatOff(display);
focusGained.Invoke();
//focusGained.Invoke();
RWindowEvent event {};
OnFocusGain(event);
setFlag(RWindowFlags::IN_FOCUS, true);
@@ -146,7 +123,7 @@ namespace ReWindow {
if (xev.type == FocusOut) {
XAutoRepeatOn(display);
focusLost.Invoke();
//focusLost.Invoke();
RWindowEvent event {};
OnFocusLost(event);
setFlag(RWindowFlags::IN_FOCUS, false);
@@ -155,19 +132,14 @@ namespace ReWindow {
if (xev.type == KeyRelease) {
auto scancode = (X11Scancode) xev.xkey.keycode;
auto key = GetKeyFromX11Scancode(scancode);
currentKeyboard.PressedKeys[key] = false;
KeyUpEvent eventData = KeyUpEvent(key);
OnKeyUpEvent(eventData);
liftKey (key);
}
if (xev.type == KeyPress) {
auto scancode = (X11Scancode) xev.xkey.keycode;
auto key = GetKeyFromX11Scancode(scancode);
currentKeyboard.PressedKeys[key] = true;
KeyDownEvent eventData = KeyDownEvent(key);
OnKeyDownEvent(eventData);
eventLog.push_back(eventData);
pressKey (key);
//eventLog.push_back(eventData);
}
if (xev.type == ButtonRelease) {
@@ -190,30 +162,72 @@ namespace ReWindow {
if (xev.type == Expose) {
}
// NOTE: This event is functionally useless, as it only informs of the very beginning and end of a mouse movement.
if (xev.type == MotionNotify)
{
//auto eventData = MouseMoveEvent(xev.xmotion.x, xev.xmotion.y);
//OnMouseMove(eventData);
}
if (xev.type == ResizeRequest)
{
auto eventData = WindowResizeRequestEvent();
lastKnownWindowSize = eventData.Size;
eventData.Size = {(float)xev.xresizerequest.width, (float)xev.xresizerequest.height};
lastKnownWindowSize = eventData.Size;
OnResizeRequest(eventData);
}
}
previousKeyboard = currentKeyboard;
}
// Might make the window go off the screen on some window managers.
void RWindow::setSize(int width, int height)
void RWindow::setSize(int newWidth, int newHeight)
{
if (!getFlag(RWindowFlags::RESIZABLE))
return;
this->width = newWidth;
this->height = newHeight;
XResizeWindow(display, window, width, height);
}
void RWindow::setSize(const Vector2& size)
{
this->width = size.x;
this->height = size.y;
this->setSize(size.x, size.y);
}
Vector2 RWindow::getCursorPos() const {
Window root = XDefaultRootWindow(display);
Window root_return;
Window child_return;
int root_x_ret;
int root_y_ret;
int win_x_ret;
int win_y_ret;
uint32_t mask_return;
unsigned m;
bool mouseAvailable = XQueryPointer(display, window, &root_return, &child_return, &root_x_ret, &root_y_ret, &win_x_ret, &win_y_ret, &mask_return);
if (mouseAvailable)
{
// TODO: process retrieved mouse coordinates
// TODO: normalize coordinates from displaySpace to windowSpace
// TODO: fire mouse movement event
//std::cout << win_x_ret << ", " << win_y_ret << std::endl;
// TODO: Compensate for height of window TitleBar + window border width
float window_border_width = 2;
float window_titlebar_height = 18;
Vector2 mouse_coords_raw = {(float)win_x_ret+window_border_width, (float)win_y_ret+window_titlebar_height};
auto window_pos = getPos();
return mouse_coords_raw - window_pos;
}
return Vector2::Zero;
}
// TODO: implement integer vector2/3 types
Vector2 RWindow::getSize() const
{
@@ -224,8 +238,9 @@ namespace ReWindow {
// TODO: implement integer vector2/3 types
Vector2 RWindow::getPos() const
{
auto root = XDefaultRootWindow(display);
XGetWindowAttributes(display,root,&windowAttributes);
XGetWindowAttributes(display,window,&windowAttributes);
return {(float)windowAttributes.x, (float)windowAttributes.y};
}
@@ -253,6 +268,7 @@ namespace ReWindow {
}
void RWindow::setResizable(bool resizable) {
this->resizable = resizable;
this->setFlag(RWindowFlags::RESIZABLE, resizable);
}
@@ -304,11 +320,92 @@ namespace ReWindow {
}
void RWindow::setVsyncEnabled(bool b) {
PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalEXT");
glXSwapIntervalEXT(display, None, b);
glXSwapIntervalEXT(display, window, b);
}
bool RWindow::isFullscreen() const {
return fullscreenmode;
}
void RWindow::setCursorStyle(CursorStyle style) const {
u32 x11_cursor_resolved_enum = static_cast<u32>(style.X11Cursor);
Cursor c = XCreateFontCursor(display, x11_cursor_resolved_enum);
XDefineCursor(display, window, c);
}
void RWindow::Open() {
xSetWindowAttributes.border_pixel = BlackPixel(display, defaultScreen);
xSetWindowAttributes.background_pixel = BlackPixel(display, defaultScreen);
xSetWindowAttributes.override_redirect = True;
xSetWindowAttributes.event_mask = ExposureMask;
//setVsyncEnabled(vsync);
if (renderer == RenderingAPI::OPENGL)
{
GLint glAttributes[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None};
visual = glXChooseVisual(display, defaultScreen, glAttributes);
glContext = glXCreateContext(display, visual, nullptr, GL_TRUE);
}
xSetWindowAttributes.colormap = XCreateColormap(display, RootWindow(display, defaultScreen), visual->visual,
AllocNone);
window = XCreateWindow(display, RootWindow(display, defaultScreen), 0, 0, width, height, 0, visual->depth,
InputOutput, visual->visual, CWBackPixel | CWColormap | CWBorderPixel | NoEventMask,
&xSetWindowAttributes);
// Set window to floating because fucking tiling WMs
windowTypeAtom = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
windowTypeUtilityAtom = XInternAtom(display, "_NET_WM_WINDOW_TYPE_UTILITY", False);
XChangeProperty(display, window, windowTypeAtom, XA_ATOM, 32, PropModeReplace,
(unsigned char *)&windowTypeUtilityAtom, 1);
//
XSelectInput(display, window,
ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
PointerMotionMask |
PointerMotionHintMask | FocusChangeMask | StructureNotifyMask | SubstructureRedirectMask |
SubstructureNotifyMask | CWColormap | ResizeRequest | ResizeRedirectMask);
XMapWindow(display, window);
XStoreName(display, window, title.c_str());
wmDeleteWindow = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, window, &wmDeleteWindow, 1);
if (renderer == RenderingAPI::OPENGL)
{
glXMakeCurrent(display, window, glContext);
}
//setVsyncEnabled(vsync);
open = true;
}
void RWindow::setTitle(const std::string &title) {
this->title = title;
XStoreName(display, window, title.c_str());
}
std::string RWindow::getTitle() const {
return this->title;
}
bool RWindow::isKeyDown(Key key) const {
if (!currentKeyboard.PressedKeys.contains(key))
return false;
return currentKeyboard.PressedKeys.at(key);
}
// TODO: Implement MouseButton map
bool RWindow::isMouseButtonDown(MouseButton button) const
{
return false;
}
}
void RWindow::setRenderer(RenderingAPI api) {
renderer = api;
}
// TODO: Implement ControllerButton map
}

View File

View File

@@ -1,31 +1,389 @@
#include <rewindow/types/window.h>
#include <rewindow/types/cursors.h>
#include <GL/gl.h>
typedef BOOL (APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK ReWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
ReWindow::RWindow* subject = (ReWindow::RWindow*) GetWindowLongPtrA (hwnd, GWLP_USERDATA);
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage (0);
break;
LPTSTR szClassName = TEXT("GenericProgramWindowClass");
case WM_SETFOCUS: {
ReWindow::RWindowEvent event {};
subject->OnFocusGain (event);
subject->setFlag (RWindowFlags::IN_FOCUS, true);
break;
}
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
case WM_KILLFOCUS: {
ReWindow::RWindowEvent event {};
subject->OnFocusLost (event);
subject->setFlag (RWindowFlags::IN_FOCUS, false);
break;
}
HWND hwnd;
case WM_KEYDOWN: {
auto key = GetKeyFromWindowsScancode ((WindowsScancode) wParam);
subject->pressKey (key);
break;
}
RWindow::RWindow()
{
hwnd = CreateWindow();
case WM_KEYUP: {
auto key = GetKeyFromWindowsScancode ((WindowsScancode) wParam);
subject->liftKey (key);
break;
}
case WM_LBUTTONDOWN: {
auto event = ReWindow::WindowEvents::MouseButtonDownEvent();
event.Button = MouseButtons::Left;
subject->OnMouseButtonDown(event);
break;
}
case WM_RBUTTONDOWN: {
auto event = ReWindow::WindowEvents::MouseButtonDownEvent();
event.Button = MouseButtons::Right;
subject->OnMouseButtonDown(event);
break;
}
case WM_MBUTTONDOWN: {
auto event = ReWindow::WindowEvents::MouseButtonDownEvent();
event.Button = MouseButtons::Middle;
subject->OnMouseButtonDown(event);
break;
}
case WM_LBUTTONUP: {
auto event = ReWindow::WindowEvents::MouseButtonUpEvent();
event.Button = MouseButtons::Left;
subject->OnMouseButtonUp(event);
break;
}
case WM_RBUTTONUP: {
auto event = ReWindow::WindowEvents::MouseButtonUpEvent();
event.Button = MouseButtons::Right;
subject->OnMouseButtonUp(event);
break;
}
case WM_MBUTTONUP: {
auto event = ReWindow::WindowEvents::MouseButtonUpEvent();
event.Button = MouseButtons::Middle;
subject->OnMouseButtonUp(event);
break;
}
case WM_MOUSEMOVE: {
auto event = ReWindow::WindowEvents::MouseMoveEvent (GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam));
subject->OnMouseMove(event);
break;
}
case WM_SHOWWINDOW:
if (wParam) {
// as for Expose event in linux
}
break;
case WM_WINDOWPOSCHANGED: {
WINDOWPOS *pos = (WINDOWPOS *) lParam;
subject->setRect (pos->x, pos->y, pos->cx, pos->cy);
auto event = ReWindow::WindowEvents::WindowResizeRequestEvent();
event.Size = {(float) pos->cx, (float) pos->cy};
subject->OnResizeRequest (event);
break;
}
default:
return DefWindowProcA (hwnd, uMsg, wParam, lParam);
}
return TRUE;
}
static HWND hwnd = NULL;
static HDC hdc = NULL;
static ATOM reClass = 0;
static HGLRC glrc = NULL;
static DEVMODEA mode;
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 registerClass () {
if (!reClass) {
HINSTANCE module = GetModuleHandleA (NULL);
WNDCLASSA rewc = {CS_HREDRAW | CS_VREDRAW,
ReWindowProc, 0, 0, module, NULL, LoadCursor (NULL, IDC_ARROW),
(HBRUSH) GetStockObject (BLACK_BRUSH), NULL, "ReWindowClass"
};
reClass = RegisterClassA (&rewc);
}
}
void RWindow::lower() const {
ReWindow::RWindow::RWindow() {
registerClass ();
}
for (int num = 0; num < (int) RWindowFlags::MAX_FLAG; ++num) {
flags[num] = false;
}
hwnd = CreateWindowA ("ReWindowClass", "ReWindow", WS_TILEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL, 0);
SetWindowLongPtrA (hwnd, GWLP_USERDATA, (LONG_PTR) this);
}
ReWindow::RWindow::RWindow (const std::string& title, int width, int height) {
registerClass ();
for (int num = 0; num < (int) RWindowFlags::MAX_FLAG; ++num) {
flags[num] = false;
}
hwnd = CreateWindowA ("ReWindowClass", title.c_str (), WS_TILEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, width, height,
NULL, NULL, NULL, 0);
SetWindowLongPtrA (hwnd, GWLP_USERDATA, (LONG_PTR) this);
}
void ReWindow::RWindow::raise() const {
SetForegroundWindow (hwnd);
SetActiveWindow (hwnd);
SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
ShowWindow (hwnd, SW_SHOW);
// Redraw to prevent the window blank
RedrawWindow (hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
void ReWindow::RWindow::lower() const {
ShowWindow (hwnd, SW_MINIMIZE);
}
void ReWindow::RWindow::destroyWindow() {
if (hwnd) {
if (hdc) {
if (glrc) {
wglMakeCurrent (NULL, NULL);
wglDeleteContext (glrc);
}
ReleaseDC (hwnd, hdc);
}
DestroyWindow (hwnd);
}
delete this;
}
void ReWindow::RWindow::refresh() {
// TODO: Implement refresh time keeping
OnRefresh (0.f);
// TODO: Check if mouse coords have changed, only then fire OnMouseMove event
Vector2 mouse_coords = getCursorPos();
auto eventData = MouseMoveEvent(mouse_coords);
OnMouseMove(eventData);
std::this_thread::sleep_for(1ms);
}
bool ReWindow::RWindow::getFlag (RWindowFlags flag) const {
return (flags[(int) flag]);
}
void ReWindow::RWindow::setFlag (RWindowFlags flag, bool state) {
DWORD style = GetWindowLongA (hwnd, GWL_STYLE);
flags[(int) flag] = state;
if (flag == RWindowFlags::RESIZABLE) {
if (style & WS_THICKFRAME) {
if (!state) {
style &= ~WS_THICKFRAME;
SetWindowLongA (hwnd, GWL_STYLE, style);
}
}
else {
if (state) {
style |= WS_THICKFRAME;
SetWindowLongA (hwnd, GWL_STYLE, style);
}
}
}
}
void ReWindow::RWindow::pollEvents() {
MSG msg;
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
setFlag (RWindowFlags::QUIT, true);
}
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
// Might make the window go off the screen on some window managers.
void ReWindow::RWindow::setSize (int w, int h) {
if (!getFlag (RWindowFlags::RESIZABLE)) return;
MoveWindow (hwnd, x, y, w, h, TRUE);
}
void ReWindow::RWindow::setSize(const Vector2& size) {
if (!getFlag (RWindowFlags::RESIZABLE)) return;
MoveWindow (hwnd, x, y, size.x, size.y, TRUE);
}
Vector2 ReWindow::RWindow::getCursorPos() const {
POINT pos;
GetCursorPos (&pos);
// TODO: normalize coordinates from displaySpace to windowSpace
// TODO: fire mouse movement event
//std::cout << win_x_ret << ", " << win_y_ret << std::endl;
// TODO: Compensate for height of window TitleBar + window border width
Vector2 mouse_coords_raw = {(float) pos.x, (float) pos.y};
auto window_pos = getPos();
return mouse_coords_raw - window_pos;
}
// TODO: implement integer vector2/3 types
Vector2 ReWindow::RWindow::getSize() const {
return {(float) width, (float) height};
}
// TODO: implement integer vector2/3 types
Vector2 ReWindow::RWindow::getPos() const {
return Vector2 ((float) x, (float) y);
}
void ReWindow::RWindow::setPos(int nx, int ny) {
MoveWindow (hwnd, nx, ny, width, height, TRUE);
}
void ReWindow::RWindow::setPos(const Vector2& pos) {
MoveWindow (hwnd, pos.x, pos.y, width, height, TRUE);
}
void ReWindow::RWindow::glSwapBuffers() {
SwapBuffers (hdc);
}
bool ReWindow::RWindow::isResizable() const {
return this->getFlag (RWindowFlags::RESIZABLE);
}
bool ReWindow::RWindow::isAlive() const {
return !getFlag (RWindowFlags::QUIT);
}
void ReWindow::RWindow::setResizable(bool resizable) {
this->resizable = resizable;
this->setFlag(RWindowFlags::RESIZABLE, resizable);
}
void ReWindow::RWindow::setFullscreen(bool fs) {
if (fs) {
fullscreen();
}
else restoreFromFullscreen();
}
void ReWindow::RWindow::fullscreen() {
DEVMODEA screen = {sizeof (DEVMODEA)};
screen.dmBitsPerPel = 32;
screen.dmPelsWidth = width;
screen.dmPelsHeight = height;
screen.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (ChangeDisplaySettingsA (&screen, 0) == DISP_CHANGE_SUCCESSFUL) {
fullscreenmode = true;
}
}
void ReWindow::RWindow::restoreFromFullscreen() {
if (ChangeDisplaySettingsA (&mode, 0) == DISP_CHANGE_SUCCESSFUL) {
fullscreenmode = false;
}
}
void ReWindow::RWindow::setVsyncEnabled (bool b) {
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
wglSwapIntervalEXT(b);
}
bool ReWindow::RWindow::isFullscreen() const {
return fullscreenmode;
}
void ReWindow::RWindow::setCursorStyle (CursorStyle style) const {
int idcs[] ={32512, 32513, 32514, 325123, 32649, 32650};
SetClassLongPtr (hwnd, GCLP_HCURSOR, (LONG_PTR) LoadCursor (NULL, MAKEINTRESOURCE (idcs[style.WindowsCursor])));
}
void ReWindow::RWindow::Open() {
if (hwnd) {
hdc = GetDC (hwnd);
PIXELFORMATDESCRIPTOR pfd = {
sizeof (PIXELFORMATDESCRIPTOR),
1, PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW,
PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 32,
0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0
};
int ipf = ChoosePixelFormat (hdc, &pfd);
if (ipf) {
SetPixelFormat (hdc, ipf, &pfd);
glrc = wglCreateContext (hdc);
if (glrc) {
wglMakeCurrent (hdc, glrc);
EnumDisplaySettingsA (NULL, ENUM_CURRENT_SETTINGS, &mode);
open = true;
}
}
}
}
void ReWindow::RWindow::setTitle (const std::string &title) {
this->title = title;
SetWindowTextA (hwnd, title.c_str ());
}
std::string ReWindow::RWindow::getTitle () const {
return this->title;
}
bool ReWindow::RWindow::isKeyDown (Key key) const {
auto find = currentKeyboard.PressedKeys.find (key);
if (find != currentKeyboard.PressedKeys.end ()) {
return currentKeyboard.PressedKeys.at (key);
}
return false;
}
// TODO: Implement MouseButton map
bool ReWindow::RWindow::isMouseButtonDown(MouseButton button) const {
return false;
}
void ReWindow::RWindow::setRenderer (RenderingAPI api) {
renderer = api;
}