Compare commits

...

147 Commits

Author SHA1 Message Date
35b09cb026 Implement rolling average (last 5 frames) of FPS
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m48s
2024-10-04 14:19:10 -04:00
6bd9ec0eb8 Adjust member-variable signatures on window class
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m55s
2024-10-04 12:30:40 -04:00
ae073b3a96 Another one
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m22s
2024-09-30 23:49:11 -04:00
48091496d5 Overlooked a stupid in refresh_rate calculation.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m27s
2024-09-30 23:41:39 -04:00
c202ca5c84 Migrate timekeeping-related member variables to protected scope.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m43s
2024-09-30 23:35:06 -04:00
c5f94b7c49 More small refactors.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 2m32s
2024-09-26 12:38:58 -04:00
b351577a20 Refactors
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m53s
2024-09-26 00:39:05 -05:00
fb3a77e2e3 Implement timekeeping for OnRefresh, fix duplicate event firing.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 2m11s
2024-09-24 21:40:00 -04:00
b96dd03af1 Update window.cpp
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m34s
Only ask X11 where the cursor is once per frame.
2024-09-21 12:38:19 -04:00
3e99394b6f Performance speedup.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 2m17s
2024-09-20 13:35:07 -04:00
5b10e55f83 Update window.cpp
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 5m46s
speedup for resize event.
2024-09-20 08:44:38 -04:00
c0dc56bc8c Update main.cpp
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m30s
fix for msvc
2024-09-14 22:11:50 -04:00
a62c576d14 event and jlog update
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m35s
2024-09-12 20:54:42 -04:00
92b567e48f fix https://git.redacted.cc/Redacted/ReWindow.git using rebitch
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m26s
2024-08-26 19:48:17 -04:00
maxine
3617d610ea Merge pull request 'brokenbullshit' (#12) from brokenbullshit into main
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m56s
Reviewed-on: #12
2024-08-23 11:01:00 -04:00
9500681420 fixed to use new JLog and Event APIs. New ReWindow specific logger too. Should be able to toggle it on and off in programs that use ReWindow as a dependency and still have other loggers working.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 6m48s
2024-08-23 11:02:03 -04:00
bf41652336 Update CMakeLists.txt
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 5m39s
Still broken but closer I guess.
2024-08-22 12:45:54 -04:00
68ae72e6be broken SHIT
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 6m13s
2024-08-22 12:00:26 -04:00
a4b68a5abc Update display.cpp
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 6m21s
both displays
2024-08-13 13:21:22 -04:00
1345669c32 Add Aspect ratio output
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 6m31s
2024-08-13 12:52:57 -04:00
9d51ac0026 Test Info Output Format
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
2024-08-13 12:48:27 -04:00
edb2e29246 poll for graphics modes.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 4m48s
2024-08-13 12:41:29 -04:00
bed600d4d4 Make resizing on windows actually send the event.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m36s
2024-08-10 23:43:15 -04:00
acf66ae909 When the cursor is hidden, Still show it on the title bar (WINDOWS)
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m25s
2024-08-09 19:01:38 -04:00
c319acfffb Set cursor visible (Linux)
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 24m43s
2024-08-08 20:43:27 -04:00
9b810101a4 Set cursor visible (windows)
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m32s
2024-08-08 20:26:25 -04:00
4c616d68af make it actually work kkthx
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m4s
2024-08-08 14:49:08 -04:00
4571016c4c Update window.h
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m9s
2024-08-08 14:33:14 -04:00
a8c85a29dd idk
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 5m27s
2024-08-08 14:24:15 -04:00
483b5dadad WINDOZEEEEEEEEEEEEEEEEEEEEEEEEEEEE
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m11s
2024-08-07 23:49:11 -04:00
9565bfeef9 Merge remote-tracking branch 'origin/main'
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m27s
2024-08-05 18:28:35 -04:00
e1fc2f289f Migrated to J3ML 2.4 2024-08-05 18:28:30 -04:00
7bc90af3d5 Update
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 4m10s
2024-08-05 13:35:39 -04:00
d9ee8ebedc Update window.cpp
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 4m1s
2024-08-05 11:58:29 -04:00
94e61aa2ea Changed MouseButton::operator==() to compare buttons via their ButtonIndices instead of CharCodes
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m16s
2024-07-30 16:41:37 -04:00
c95ad0ee0d Accidentally lost invokation of OnMouseMoveEvent, so we're re-adding it.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 4m29s
2024-07-30 15:02:45 -04:00
3b3d1ba197 should be all deps for ubuntu
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m32s
2024-07-29 20:19:04 -04:00
1542224ffc Merge remote-tracking branch 'refs/remotes/origin/main'
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 48s
reci shit
2024-07-29 20:15:03 -04:00
8d92abdecf use ubuntu names 2024-07-29 20:14:51 -04:00
9247472a13 use ubuntu names
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
2024-07-29 20:08:42 -04:00
7e5d85c88a Merge pull request 'Input Class Refactoring' (#11) from litandbased_refactors into main
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 50s
Reviewed-on: #11
2024-07-29 20:08:00 -04:00
7dad83bbc1 reci test
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 45s
2024-07-29 20:07:32 -04:00
c18fd72b74 reci test
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 43s
2024-07-29 20:06:36 -04:00
663109da75 reci 2024-07-29 20:02:52 -04:00
c7a2b42f1d Implement operator == on MouseButton class 2024-07-29 19:53:50 -04:00
1f81c0b843 More small refactoring 2024-07-29 18:54:56 -04:00
c25983a87d Random refactoring of the input systems. 2024-07-29 18:22:23 -04:00
1b02dcc364 Small oopsie. 2024-07-17 00:44:10 -04:00
254f991c49 Made sure all event raisers were implemented, implemented getLastKnownResize() 2024-07-17 00:41:56 -04:00
b4c4827c9c Adding dev notes and documenting the public API. 2024-07-15 13:01:27 -04:00
ebf939d747 Add missing keys 2024-07-03 12:15:17 -04:00
04c82df9c5 Fix window resize on windows 2024-07-02 12:41:32 -04:00
2f0cedcd04 Windows smh 2024-07-01 14:58:55 -04:00
a215d9f398 Merge branch 'latest' of https://git.redacted.cc/Redacted/ReWindow into latest 2024-06-28 19:39:41 -04:00
a3697cd022 Refactor 2024-06-28 19:39:20 -04:00
68a1f52515 Refactor 2024-06-28 19:32:45 -04:00
Redacted
8f8eabfe47 Update CMakeLists.txt 2024-06-26 23:27:20 -04:00
Redacted
a4ec53fdd9 Update CMakeLists.txt 2024-06-26 23:25:18 -04:00
c0ecb08a3b Update window.cpp
Fix use after free
2024-06-21 16:24:38 -04:00
7d2921f598 Started adding DEBUG logging to library code. Wrote RWindowFlagToStr function for better logging capabilities. 2024-06-19 16:15:29 -04:00
850fe4aabb Redid some log formatting. 2024-06-19 15:02:51 -04:00
80904cf4b1 Added DEBUG logging to main.cpp. Implemented getWidth and getSize for RWindow. 2024-06-19 14:59:17 -04:00
b6bb00e0de Updated to use jlog prerelease-8. Adjusted as necessary. 2024-06-19 13:58:47 -04:00
cb03a67f17 fix OnKeyDown 2024-06-18 21:19:38 -04:00
Redacted
f8f9e78dab Update CMakeLists.txt 2024-06-18 14:30:34 -04:00
214c3e72fd Update window.cpp
key repeat fix
2024-06-18 14:03:25 -04:00
f6b9bae45f Winblows keydown & keyup 2024-06-18 10:38:17 -07:00
074f0235c0 Merge branch 'windows-test' 2024-06-18 02:25:38 -04:00
adec224701 Push 2024-06-18 01:15:23 -04:00
5b8788f94f Restructure 2024-06-17 22:50:38 -04:00
56fdc3d90b gut 2024-06-17 22:15:20 -04:00
3adef96da7 initial 2024-06-16 23:35:10 -07:00
2956c0b350 Initial commit 2024-06-16 20:39:13 -07:00
50a7e2cfe1 Fix "ISO C++ 11 does not allow converting from string literal to char*" 2024-06-16 21:52:15 -04:00
10a63d738c Update main.cpp 2024-06-16 20:47:54 -04:00
maxbyte9p
b914e9b563 updated CMakeLists.txt to use jlog prerelease-3. Made input event logging use SDEBUG from jlog prerelease-3 2024-06-15 21:17:04 -04:00
maxbyte9p
4fb237f11a Incorporated jlog for input event logging. Side mouse button reading possibly having issues. 2024-06-14 16:23:21 -04:00
maxbyte9p
dfbf018807 made CharCode char* for printing the funny unicode arrows for arrow keys 2024-06-14 15:19:26 -04:00
ee5b2f18cd lol 2024-06-11 20:12:32 -04:00
4336b2bfc9 Revert "Maybe?"
This reverts commit 4d587f9448.
2024-06-11 20:12:03 -04:00
4d587f9448 Maybe? 2024-06-11 20:02:22 -04:00
maxbyte9p
b73cc46ecb Gamepad scancodes harvested from some Xbox controller clone. 2024-06-07 16:15:27 -04:00
Redacted
f5be8b2707 Update CMakeLists.txt 2024-06-01 19:33:59 -04:00
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
f0bf6c5871 Fix public linkage of JGL turning into build dependency for entire lib 2024-02-13 17:25:36 -05:00
46e947eb77 Fully Deprecate GLM 2024-02-13 16:28:29 -05:00
fe6638c4be Technically working, however values are incorrect (So is result of RWindow::getPos()) 2024-02-07 16:11:42 -05:00
70e41a56cb XError Kekekek 2024-02-07 15:05:24 -05:00
scientiist
3306c6acba Implement MouseDelta check (WIP) 2024-02-07 11:40:54 -06:00
scientiist
01eed78c48 Implement Mouse Input (TODO: Event only fires when mouse **begins** and **stops** moving) 2024-02-07 08:29:53 -06:00
scientiist
ef7e8b1211 Fix fucked up header 2024-02-07 05:29:33 -06:00
432d1818f3 Refactoring 2024-02-06 23:37:46 -05:00
983428f69d Merge All Branches 2024-01-25 20:10:46 -05:00
1336297ac0 Merge pull request 'vsync-test' (#4) from vsync-test into main
Reviewed-on: #4
2024-01-25 20:02:42 -05:00
103c5b2001 Merge remote-tracking branch 'origin/vsync-test' into vsync-test
# Conflicts:
#	CMakeLists.txt
#	include/rewindow/data/X11Scancodes.h
#	include/rewindow/types/event.h
#	include/rewindow/types/key.h
#	include/rewindow/types/window.h
#	main.cpp
#	src/linux/window.cpp
2024-01-25 20:02:02 -05:00
89a6fa57b6 Update window.cpp 2024-01-25 20:01:30 -05:00
04ced07c18 Update window.cpp
Fixed a problem that'd cause setting vsync to behave strangely and overlays to crash.
2024-01-25 20:00:05 -05:00
353def8ba9 update 2024-01-25 19:55:57 -05:00
c3605a052f Update CMakeLists.txt 2024-01-25 19:54:52 -05:00
d122da68fd vsync test 2024-01-25 19:54:50 -05:00
b49f44855f Merge pull request 'virtual-window' (#3) from virtual-window into main
Reviewed-on: #3
2024-01-25 19:43:58 -05:00
7343a95a45 Update window.cpp 2024-01-24 22:16:29 -05:00
62568e3252 Update window.cpp 2024-01-24 22:09:58 -05:00
ae5aebae5e Tryna Implement Fullscreen 2024-01-24 20:19:39 -05:00
2714c41167 Refactoring 2024-01-24 19:28:53 -05:00
668d7869fe Update window.cpp
Fixed a problem that'd cause setting vsync to behave strangely and overlays to crash.
2024-01-24 06:22:34 -05:00
7320f07d0e Fix 2024-01-22 04:29:50 -05:00
364504ae5c update 2024-01-21 12:58:38 -05:00
6f8fbf18bd Implementing WindowsScancodes 2024-01-05 13:02:30 -05:00
10a8105f71 Implementing WindowsScancodes 2024-01-05 12:47:25 -05:00
eed5f10413 Implementing X11Scancodes 2024-01-04 17:26:41 -05:00
6afccc34a5 Implementing Stuff 2024-01-04 07:29:59 -05:00
33 changed files with 2349 additions and 344 deletions

View File

@@ -0,0 +1,23 @@
name: Run ReCI Build Test
run-name: Run ReCI Build Test For ${{ gitea.repository }}.
on: [push]
jobs:
Explore-Gitea-Actions:
runs-on: ubuntu-22.04
env:
RECI_GIT: https://git.redacted.cc/maxine/ReCI
RECI: /RECI
steps:
- run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event."
- run: echo "This job is now running on a ${{ runner.os }} server hosted by Gitea!"
- run: echo "The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
- name: Check out repository code
uses: actions/checkout@v3
- run: echo "The ${{ gitea.repository }} repository has been cloned to the runner."
- run: echo "The workflow is now ready to run your tests on the runner."
- run: echo "Install toolchain and run ReCI build test"
- run: apt-get update && apt-get install -y lua5.3 git && git clone $RECI_GIT $RECI
- run: lua $RECI/reci.lua -f $RECI/scripts/buildtools.reci -f reci/scripts/builddeps.reci -f $RECI/scripts/buildtest.reci
- run: echo this exists so I can run the reci test
- run: echo "This job's status is ${{ job.status }}."

2
.gitignore vendored
View File

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

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.20)
cmake_minimum_required(VERSION 3.18..3.27)
project(ReWindowLibrary
VERSION 1.0
LANGUAGES CXX
@@ -10,37 +10,72 @@ 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")
# Enable Package Managers
# include(cmake/CPM.cmake)
include(cmake/CPM.cmake)
CPMAddPackage(
NAME J3ML
URL https://git.redacted.cc/josh/j3ml/archive/Release-3.1.zip
)
CPMAddPackage(
NAME Event
URL https://git.redacted.cc/josh/Event/archive/Release-12.zip
)
CPMAddPackage(
NAME jlog
URL https://git.redacted.cc/josh/jlog/archive/Prerelease-16.zip
)
find_package(OpenGL REQUIRED)
include_directories({$OPENGL_INCLUDE_DIRS})
include_directories(${OPENGL_INCLUDE_DIRS})
include_directories(${J3ML_SOURCE_DIR}/include)
include_directories(${jlog_SOURCE_DIR}/include)
file(GLOB_RECURSE HEADERS "include/*.h" "include/*.hpp")
file(GLOB_RECURSE HEADERS "include/logger/*.h" "include/logger/*.hpp")
if(UNIX AND NOT APPLE)
file(GLOB_RECURSE SOURCES "src/linux/*.cpp")
file(GLOB_RECURSE SOURCES "src/types/*.cpp" "src/platform/linux/*.cpp" "src/platform/shared/*.cpp" "src/logger/*.cpp" )
endif()
if(WIN32)
file(GLOB_RECURSE SOURCES "src/windows/*.cpp")
file(GLOB_RECURSE SOURCES "src/types/*.cpp" "src/platform/windows/*.cpp" "src/platform/shared/*.cpp" "src/logger/*.cpp")
endif()
include_directories("include")
add_library(ReWindowLibrary SHARED ${SOURCES})
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 ${OPENGL_LIBRARIES})
target_link_libraries(ReWindowLibrary PUBLIC X11 Xrandr J3ML Event jlog ${OPENGL_LIBRARIES})
target_link_libraries(ReWindowLibrary PUBLIC)
add_executable(ReWindowLibraryDemo main.cpp)
target_link_libraries(ReWindowLibraryDemo PUBLIC ReWindowLibrary)
endif()
if(WIN32)
endif()
target_compile_options(ReWindowLibrary PUBLIC /utf-8)
target_link_libraries(ReWindowLibrary PUBLIC J3ML Event jlog ${OPENGL_LIBRARIES})
add_executable(ReWindowLibraryDemo main.cpp)
target_link_libraries(ReWindowLibraryDemo PUBLIC ReWindowLibrary)
endif()

View File

@@ -11,7 +11,8 @@ A library which allows easily creating and managing a window and it's events ac
Install dependencies
```bash
dnf install cmake make gcc-g++ libX11 libX11-devel
Fedora/RHEL: dnf install cmake make gcc-g++ libX11 libX11-devel mesa-libGL-devel
Ubuntu/Debian: apt-get install cmake make gcc g++ libx11-6 libx11-dev libgl-dev libxrandr-dev
```
Clone the repository
@@ -30,4 +31,4 @@ Run it
```bash
./ReWindowDemo
```
```

24
cmake/CPM.cmake Normal file
View File

@@ -0,0 +1,24 @@
# SPDX-License-Identifier: MIT
#
# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors
set(CPM_DOWNLOAD_VERSION 0.38.7)
set(CPM_HASH_SUM "83e5eb71b2bbb8b1f2ad38f1950287a057624e385c238f6087f94cdfc44af9c5")
if(CPM_SOURCE_CACHE)
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
else()
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
endif()
# Expand relative path. This is important if the provided path contains a tilde (~)
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
file(DOWNLOAD
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM}
)
include(${CPM_DOWNLOAD_LOCATION})

View File

@@ -0,0 +1,57 @@
// @file GamepadScancodes.h
// @
#pragma once
/*
* These scancodes were obtained from some knockoff Xbox controller from PowerA.
* I expect these to be fairly generic, so it's a good base to start from.
*
* Something to keep in mind is the seperation here. On Linux linux/joystick.h
* is used to read controller inputs. It's a generic driver/library/whatever the
* fuck it's called.
*
* 2 constants are defined in linux/joystick.h
*
* JS_EVENT_BUTTON
* JS_EVENT_AXIS
*
* This is why I made seperate enum classes. Both the Axis and the Button scancode
* count start from 0x00. Having this seperation is easier to work with.
*
* I may write a program in the future to let us harvest scancodes from controllers.
* I hacked up some C code to get the scancodes for this one without the annoying
* stick drift spamming the screen, so with a little more work I could probably turn
* it into a generic test program
*
* P.S Windows is gonna make this slightly more annoying and different from what I've
* seen.
*
* - Maxine
*/
enum class GamepadScancode_AXIS {
ABS_X = 0x00, // Xbox Left Thumbstick Axis
ABS_Y = 0x01, // <-'
ABS_Z = 0x02, // Xbox Left Trigger Axis
ABS_RX = 0x03, // Xbox Right Thumbstick Axis
ABS_RY = 0x04, // <-'
ABS_RZ = 0x05, // Xbox Right Trigger Axis (I know strange ain't it?)
ABS_HAT0X = 0x06, // Xbox DPad Axis (The Dpad is basically seen as a 3rd thumbstick)
ABS_HAT0Y = 0x07, // <-'
}
enum class GamepadScancode_BTN {
BTN_SOUTH = 0x00 // Xbox A Button
BTN_EAST = 0x01 // Xbox B Button
BTN_WEST = 0x02 // Xbox X Button
BTN_NORTH = 0x03 // Xbox Y Button
BTN_TL = 0x04, // Xbox Left Bumper
BTN_TR = 0x05, // Xbox Right Bumper
BTN_START = 0x06, // Xbox Start Button
BTN_SELECT = 0x07, // Xbox Select Button
BTN_HOME = 0x08, // Xbox Home/Logo Button
BTN_THUMBL = 0x09, // Xbox Left Thumstick Button
BTN_THUMBR = 0x0a, // Xbox Right Thumbstick Button
}

View File

@@ -0,0 +1,107 @@
#pragma once
enum class WindowsScancode {
Nothing = 0,
ESCAPE = 0x1B, // VK_ESCAPE
ONE = 0x31, // '1'
TWO = 0x32, // '2'
THREE = 0x33, // '3'
FOUR = 0x34, // '4'
FIVE = 0x35, // '5'
SIX = 0x36, // '6'
SEVEN = 0x37, // '7'
EIGHT = 0x38, // '8'
NINE = 0x39, // '9'
ZERO = 0x30, // '0'
MINUS = 0xBD, // VK_OEM_MINUS
EQUALS = 0xBB, // VK_OEM_PLUS
BACKSPACE = 0x08, // VK_BACK
TAB = 0x09, // VK_TAB
Q = 0x51, // 'Q'
W = 0x57, // 'W'
E = 0x45, // 'E'
R = 0x52, // 'R'
T = 0x54, // 'T'
Y = 0x59, // 'Y'
U = 0x55, // 'U'
I = 0x49, // 'I'
O = 0x4F, // 'O'
P = 0x50, // 'P'
LEFT_BRACKET = 0xDB, // VK_OEM_4
RIGHT_BRACKET = 0xDD, // VK_OEM_6
ENTER = 0x0D, // VK_RETURN
CTRL = 0x11, // VK_CONTROL
A = 0x41, // 'A'
S = 0x53, // 'S'
D = 0x44, // 'D'
F = 0x46, // 'F'
G = 0x47, // 'G'
H = 0x48, // 'H'
J = 0x4A, // 'J'
K = 0x4B, // 'K'
L = 0x4C, // 'L'
SEMICOLON = 0xBA, // VK_OEM_1
SINGLEQUOTE = 0xDE, // VK_OEM_7
GRAVE = 0xC0, // VK_OEM_3
LEFT_SHIFT = 0x10, // VK_LSHIFT
BACKSLASH = 0xDC, // VK_OEM_5
Z = 0x5A, // 'Z'
X = 0x58, // 'X'
C = 0x43, // 'C'
V = 0x56, // 'V'
B = 0x42, // 'B'
N = 0x4E, // 'N'
M = 0x4D, // 'M'
PERIOD = 0xBE, // VK_OEM_PERIOD
SLASH = 0xBF, // VK_OEM_2
RIGHT_SHIFT = 0xA1, // VK_RSHIFT
PRINTSCREEN = 0x2C, // VK_SNAPSHOT
ALT = 0x12, // VK_MENU
SPACE = 0x20, // VK_SPACE
CAPS_LOCK = 0x14, // VK_CAPITAL
F1 = 0x70, // VK_F1
F2 = 0x71, // VK_F2
F3 = 0x72, // VK_F3
F4 = 0x73, // VK_F4
F5 = 0x74, // VK_F5
F6 = 0x75, // VK_F6
F7 = 0x76, // VK_F7
F8 = 0x77, // VK_F8
F9 = 0x78, // VK_F9
F10 = 0x79, // VK_F10
NUM_LOCK = 0x90, // VK_NUMLOCK
SCROLL_LOCK = 0x91, // VK_SCROLL
HOME = 0x24, // VK_HOME
UP_ARROW = 0x26, // VK_UP
PAGE_UP = 0x21, // VK_PRIOR
LEFT_ARROW = 0x25, // VK_LEFT
DOWN_ARROW = 0x28, // VK_DOWN
RIGHT_ARROW = 0x27, // VK_RIGHT
END = 0x23, // VK_END
PAGE_DOWN = 0x22, // VK_NEXT
INSERT = 0x2D, // VK_INSERT
DEL = 0x2E, // VK_DELETE
F11 = 0x7A, // VK_F11
F12 = 0x7B, // VK_F12
NUMPAD_ZERO = 0x60, // VK_NUMPAD0
NUMPAD_ONE = 0x61, // VK_NUMPAD1
NUMPAD_TWO = 0x62, // VK_NUMPAD2
NUMPAD_THREE = 0x63, // VK_NUMPAD3
NUMPAD_FOUR = 0x64, // VK_NUMPAD4
NUMPAD_FIVE = 0x65, // VK_NUMPAD5
NUMPAD_SIX = 0x66, // VK_NUMPAD6
NUMPAD_SEVEN = 0x67, // VK_NUMPAD7
NUMPAD_EIGHT = 0x68, // VK_NUMPAD8
NUMPAD_NINE = 0x69, // VK_NUMPAD9
NUMPAD_PLUS = 0x6B, // VK_ADD
NUMPAD_MINUS = 0x6D, // VK_SUBTRACT
NUMPAD_ASTERISK = 0x6A,
NUMPAD_SLASH = 0x6F,
NUMPAD_PERIOD = 0x6E, // VK_DECIMAL
NUMPAD_ENTER = 0x0D, // VK_RETURN
SUPER = 0x5B,
COMMA = 0xBC,
MENU = 93,
BREAK = 0x13
};

View File

@@ -1,11 +1,9 @@
#pragma once
#if __linux__
#include <X11/Xlib.h>
#include <chrono>
#endif
// @file X11Scancodes.h
// @
//This is also the x11 scancodes.
enum class SCANCODE {
#pragma once
enum class X11Scancode {
KP_0 = 90,
KP_1 = 87,
KP_2 = 88,
@@ -26,9 +24,10 @@ enum class SCANCODE {
PAGEUP = 112,
PAGEDOWN = 117,
HOME = 110,
MENU = 135,
END = 115,
INSERT = 118,
DELETE = 119,
DEL = 119,
UP = 111,
DOWN = 116,
LEFT = 113,
@@ -93,54 +92,20 @@ enum class SCANCODE {
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 = 95,
F12 = 96,
PRINT = 107,
SCROLL_LOCK = 78,
BREAK = 127,
};
enum class MOUSEBUTTONCODE {
LEFT_CLICK = 1,
MIDDLE_CLICK = 2,
RIGHT_CLICK = 3,
SCROLL_UP = 4,
SCROLL_DOWN = 5,
SIDE_FORWARD = 9,
SIDE_BACK = 8
};
class RWindowEvent {
private:
std::chrono::high_resolution_clock::time_point timePoint;
public:
std::chrono::high_resolution_clock::time_point timeStamp();
virtual ~RWindowEvent() = default;
virtual bool empty();
RWindowEvent() {
timePoint = std::chrono::high_resolution_clock::now();
}
};
const RWindowEvent EmptyRWindowEvent;
class KeyDownEvent : public RWindowEvent {
public:
SCANCODE key;
};
const KeyDownEvent EmptyKeyDownEvent{};
class MouseButtonDownEvent : public RWindowEvent {
public:
MOUSEBUTTONCODE button;
};
const MouseButtonDownEvent EmptyMouseButtonDownEvent{};

View File

@@ -0,0 +1,10 @@
#pragma once
#include "jlog/Logger.hpp"
namespace ReWindow::Logger {
using namespace jlog;
extern GenericLogger Fatal;
extern GenericLogger Debug;
}

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

@@ -0,0 +1,39 @@
#pragma once
#include <vector>
#include <J3ML/J3ML.hpp>
namespace ReWindow {
class FullscreenGraphicsMode;
class Display;
}
///A given graphics mode that a display supports.
///Upon startup, We'll poll the display server for this.
class ReWindow::FullscreenGraphicsMode {
private:
u32 width;
u32 height;
short refresh_rate;
public:
FullscreenGraphicsMode() = default;
FullscreenGraphicsMode(u32 width, u32 height, short refresh_rate);
[[nodiscard]] u32 getWidth() const;
[[nodiscard]] u32 getHeight() const;
[[nodiscard]] float getRefreshRate() const;
};
///Refers to a particular monitor the user has.
class ReWindow::Display {
private:
///* The graphics mode of the display when our program was started. The primary use for this
///* is so that if the user has selected a different mode in-game we can restore the old mode upon exit. *///
FullscreenGraphicsMode default_graphics_mode{};
///All graphics modes that a given display supports.
std::vector<FullscreenGraphicsMode> graphics_modes;
public:
Display() = default;
Display(const FullscreenGraphicsMode& default_graphics_mode, const std::vector<FullscreenGraphicsMode>& graphics_modes);
FullscreenGraphicsMode getDefaultGraphicsMode();
std::vector<FullscreenGraphicsMode> getGraphicsModes();
static std::vector<Display> getDisplaysFromWindowManager();
};

View File

@@ -0,0 +1,26 @@
/// ReWindowLibrary
/// A C++20 Library for creating and managing windows in a platform-independent manner
/// Developed and Maintained by the boys @ Redacted Software.
/// (c) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file gamepad.h
/// @desc A class that models the functionality of a gamepad / controller device.
/// @edit 2024-07-29
#pragma once
namespace ReWindow
{
class InputDevice {}; // TODO: Remember to break InputDevice into it's own file and not define it twice!!!
class Gamepad : public InputDevice
{
};
class XboxGamepad : public Gamepad {};
class PS4Gamepad : public Gamepad {};
}

View File

@@ -0,0 +1,75 @@
/// ReWindowLibrary
/// A C++20 Library for creating and managing windows in a platform-independent manner
/// Developed and Maintained by the boys @ Redacted Software.
/// (c) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file gamepadbutton.h
/// @desc GamepadButton class and enumerations to define standard buttons found on a Gamepad
/// @edit 2024-07-29
#include <string>
#include <J3ML/LinearAlgebra.hpp>
class GamepadButton {
protected:
std::string mnemonic_btn_code;
public:
explicit GamepadButton(const std::string& mnemonic) : mnemonic_btn_code(mnemonic) { }
[[nodiscard]] std::string GetMnemonicButtonCode() const { return mnemonic_btn_code; }
/// Compares two GamepadButtons by their mnemonic button codes, not their activation state.
bool operator ==(const GamepadButton& rhs) const;
};
class GamepadTrigger {
public:
/// Returns a float value between 0-1 representing how much the trigger has been pushed in by.
/// (0 being unpressed, 1 being fully pressed)
float GetActuation() const;
/// TODO: Might be more appropriate in the Gamepad class representation.
void SetActuationThreshold(float minimum = 0.01f) const;
};
class GamepadThumbstick
{
public:
/// Returns a Vector2 value representing the x,y coordinates of the joystick, with 0,0 being the center (at rest).
/// This vector ranges from length = 0 to length = 1 (i.e. the unit circle).
[[nodiscard]] Vector2 GetPosition() const;
/// Sets the deadzone range of the thumbstick.
/// Deadzone controls how far the stick must be moved before any movement is actually reported.
/// This is because the thumbstick at-rest will often still report movement.
/// If gamecode is architected to use the thumbstick position as a direction, without factoring in magnitude, this would cause problems.
void SetDeadzone(float minimum = 0.01f) const;
};
using J3ML::LinearAlgebra::Vector2;
namespace GamepadButtons {
static const GamepadButton X {"X"};
static const GamepadButton Y {"Y"};
static const GamepadButton A {"A"};
static const GamepadButton B {"B"};
static const auto Triangle = Y;
static const auto Square = X;
static const auto Circle = A;
static const auto Cross = B;
static const GamepadButton LeftBumper {"LB"};
static const GamepadButton RightBumper {"RB"};
}
namespace GamepadTriggers
{
static const GamepadTrigger Left;
static const GamepadTrigger Right;
}

View File

@@ -0,0 +1,155 @@
//
// ~DAWSH
#pragma once
#include <vector>
#include <stdexcept>
#include <iostream>
#include <string>
#include <rewindow/data/X11Scancodes.h>
#include <rewindow/data/WindowsScancodes.h>
#include <J3ML/LinearAlgebra.hpp>
class Key
{
private:
//CLion on Linux falsely marks this as being wrong.
static inline std::vector<Key> keyboard{};
public:
static std::vector<Key> GetKeyboard();
Key();
Key(const char* charcode, X11Scancode scancode, WindowsScancode wSc);
const char* CharCode;
X11Scancode x11ScanCode;
WindowsScancode winScanCode;
bool operator==(const Key& rhs) const;
bool operator<(const Key& rhs) const;
Key(const Key&) = default;
};
namespace Keys {
// TODO: Encode both Uppercase and Lowercase version for each keymap
static const Key Escape {"ESC", X11Scancode::ESCAPE, WindowsScancode::ESCAPE};
static const Key F1 {"F1", X11Scancode::F1, WindowsScancode::F1};
static const Key F2 {"F2", X11Scancode::F2, WindowsScancode::F2};
static const Key F3 {"F3", X11Scancode::F3, WindowsScancode::F3};
static const Key F4 {"F4", X11Scancode::F4, WindowsScancode::F4};
static const Key F5 {"F5", X11Scancode::F5, WindowsScancode::F5};
static const Key F6 {"F6", X11Scancode::F6, WindowsScancode::F6};
static const Key F7 {"F7", X11Scancode::F7, WindowsScancode::F7};
static const Key F8 {"F8", X11Scancode::F8, WindowsScancode::F8};
static const Key F9 {"F9", X11Scancode::F9, WindowsScancode::F9};
static const Key F10 {"F10", X11Scancode::F10, WindowsScancode::F10};
static const Key F11 {"F11", X11Scancode::F11, WindowsScancode::F11};
static const Key F12 {"F12", X11Scancode::F12, WindowsScancode::F12};
static const Key Print {"PRINT", X11Scancode::PRINT, WindowsScancode::PRINTSCREEN};
static const Key ScrollLock {"SCROLL_LOCK", X11Scancode::SCROLL_LOCK, WindowsScancode::SCROLL_LOCK};
static const Key Break {"BREAK", X11Scancode::BREAK, WindowsScancode::BREAK};
//TODO On Windows, Return & KP_RETURN are the same thing.
static const Key NumPadReturn {"KP_↵", X11Scancode::KP_RETURN, WindowsScancode::NUMPAD_ENTER};
static const Key NumPadPlus {"KP_+", X11Scancode::KP_PLUS, WindowsScancode::NUMPAD_PLUS};
static const Key NumPadMinus {"KP_-", X11Scancode::KP_MINUS, WindowsScancode::NUMPAD_MINUS};
static const Key NumPadAsterisk {"KP_*", X11Scancode::KP_ASTERISK, WindowsScancode::NUMPAD_ASTERISK};
static const Key NumPadForwardSlash {"KP_/", X11Scancode::KP_SLASH, WindowsScancode::NUMPAD_SLASH};
static const Key NumPadPeriod {"KP_.", X11Scancode::KP_PERIOD, WindowsScancode::NUMPAD_PERIOD};
static const Key NumPadNumLock {"KP_NUMLOCK", X11Scancode::KP_NUMLOCK, WindowsScancode::NUM_LOCK};
static const Key NumPad1 {"KP_1", X11Scancode::KP_1, WindowsScancode::NUMPAD_ONE};
static const Key NumPad2 {"KP_2", X11Scancode::KP_2, WindowsScancode::NUMPAD_TWO};
static const Key NumPad3 {"KP_3", X11Scancode::KP_3, WindowsScancode::NUMPAD_THREE};
static const Key NumPad4 {"KP_4", X11Scancode::KP_4, WindowsScancode::NUMPAD_FOUR};
static const Key NumPad5 {"KP_5", X11Scancode::KP_5, WindowsScancode::NUMPAD_FIVE};
static const Key NumPad6 {"KP_6", X11Scancode::KP_6, WindowsScancode::NUMPAD_SIX};
static const Key NumPad7 {"KP_7", X11Scancode::KP_7, WindowsScancode::NUMPAD_SEVEN};
static const Key NumPad8 {"kP_8", X11Scancode::KP_8, WindowsScancode::NUMPAD_EIGHT};
static const Key NumPad9 {"KP_9", X11Scancode::KP_9, WindowsScancode::NUMPAD_NINE};
static const Key NumPad0 {"KP_0", X11Scancode::KP_0, WindowsScancode::NUMPAD_ZERO};
static const Key Grave {"`", X11Scancode::GRAVE, WindowsScancode::GRAVE};
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 Minus {"-", X11Scancode::MINUS, WindowsScancode::MINUS};
static const Key Equals {"+", X11Scancode::EQUALS, WindowsScancode::EQUALS};
static const Key Backspace {"", X11Scancode::BACKSPACE, WindowsScancode::BACKSPACE};
static const Key Tab {"", X11Scancode::TAB, WindowsScancode::TAB};
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 LeftBracket {"[", X11Scancode::OPENING_SQUARE_BRACKET, WindowsScancode::LEFT_BRACKET};
static const Key RightBracket {"]", X11Scancode::CLOSING_SQUARE_BRACKET, WindowsScancode::RIGHT_BRACKET};
static const Key BackSlash {"\\", X11Scancode::BACKSLASH, WindowsScancode::BACKSLASH};
static const Key CapsLock = {"CAPS", X11Scancode::CAPSLOCK, WindowsScancode::CAPS_LOCK};
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::SINGLEQUOTE};
static const Key Return {"", X11Scancode::RETURN, WindowsScancode::ENTER};
static const Key LeftShift {"", X11Scancode::LEFT_SHIFT, WindowsScancode::LEFT_SHIFT};
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 Comma = {",", X11Scancode::COMMA, WindowsScancode::COMMA};
static const Key Period {".", X11Scancode::PERIOD, WindowsScancode::PERIOD};
static const Key ForwardSlash {"/", X11Scancode::SLASH, WindowsScancode::SLASH};
static const Key LeftControl {"LCTRL", X11Scancode::LEFT_CTRL, WindowsScancode::CTRL};
static const Key Super {"", X11Scancode::SUPER, WindowsScancode::SUPER};
static const Key LeftAlt {"🄰", X11Scancode::LEFT_ALT, WindowsScancode::ALT};
static const Key Space {" ", X11Scancode::SPACE, WindowsScancode::SPACE};
static const Key RightAlt {"R🄰", X11Scancode::RIGHT_ALT, WindowsScancode::ALT};
static const Key Menu = {"", X11Scancode::MENU, WindowsScancode::MENU};
static const Key RightControl {"RCTRL", X11Scancode::RIGHT_CONTROL, WindowsScancode::CTRL};
static const Key RightShift {"R⇧", X11Scancode::RIGHT_SHIFT, WindowsScancode::RIGHT_SHIFT};
static const Key Insert {"INSERT", X11Scancode::INSERT, WindowsScancode::INSERT};
static const Key Home {"HOME", X11Scancode::HOME, WindowsScancode::HOME};
static const Key PageUp {"PAGEUP", X11Scancode::PAGEUP, WindowsScancode::PAGE_UP};
static const Key Delete {"DELETE", X11Scancode::DEL, WindowsScancode::DEL};
static const Key End {"End", X11Scancode::END, WindowsScancode::END};
static const Key PageDown {"PAGEDOWN", X11Scancode::PAGEDOWN, WindowsScancode::PAGE_DOWN};
static const Key UpArrow {reinterpret_cast<const char*>(u8""), X11Scancode::UP, WindowsScancode::UP_ARROW};
static const Key DownArrow {reinterpret_cast<const char*>(u8""), X11Scancode::DOWN, WindowsScancode::DOWN_ARROW};
static const Key LeftArrow {reinterpret_cast<const char*>(u8""), X11Scancode::LEFT, WindowsScancode::LEFT_ARROW};
static const Key RightArrow {reinterpret_cast<const char*>(u8""), X11Scancode::RIGHT, WindowsScancode::RIGHT_ARROW};
}
Key GetKeyFromX11Scancode(X11Scancode code);
Key GetKeyFromWindowsScancode(WindowsScancode code);

View File

@@ -0,0 +1,22 @@
/// ReWindowLibrary
/// A C++20 Library for creating and managing windows in a platform-independent manner
/// Developed and Maintained by the boys @ Redacted Software.
/// (c) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file keyboard.h
/// @desc A class that models the functionality of a keyboard device.
/// @edit 2024-07-29
#pragma once
namespace ReWindow
{
class InputDevice {};
class Keyboard : public InputDevice
{
};
}

View File

@@ -0,0 +1,26 @@
/// ReWindowLibrary
/// A C++20 Library for creating and managing windows in a platform-independent manner
/// Developed and Maintained by the boys @ Redacted Software.
/// (c) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file keyboard.h
/// @desc A class that models the functionality of a mouse / pointer device.
/// @edit 2024-07-29
#pragma once
namespace ReWindow
{
class InputDevice {}; // TODO: Remember to break InputDevice into it's own file and not define it twice!!!
class Pointer : public InputDevice {};
class Mouse : public Pointer
{
};
}

View File

@@ -0,0 +1,38 @@
/// ReWindowLibrary
/// A C++20 Library for creating and managing windows in a platform-independent manner
/// Developed and Maintained by the boys @ Redacted Software.
/// (c) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file mousebutton.hpp
/// @desc MouseButton class and defined MouseButtons.
/// @edit 2024-07-29
#pragma once
class MouseButton {
public:
MouseButton();
explicit MouseButton(const char* charcode, unsigned int index);
const char* CharCode;
unsigned int ButtonIndex;
bool operator == (const MouseButton& mb) const;
};
namespace MouseButtons
{
static const MouseButton Left {"l", 1};
static const MouseButton Right {"r", 2};
static const MouseButton Middle {"m", 3};
static const MouseButton MWheelUp {"1", 4};
static const MouseButton MWheelDown {"2", 5};
static const MouseButton Mouse4 {"4", 8};
static const MouseButton Mouse5 {"5", 9};
static const MouseButton Unimplemented {"u", 0};
}
MouseButton GetMouseButtonFromXButton(unsigned int button);

View File

@@ -1,50 +1,344 @@
#pragma once
#include <cstdint>
#include <vector>
#include <memory>
#include "event.h"
#include <Event.h>
#include <EventConnection.h> // TODO: Fix this shit to where we don't need to include both files they should just be bundled together
#include <map>
#include <thread>
#include <rewindow/types/key.h>
#include <rewindow/types/cursors.h>
#include <rewindow/types/mousebutton.h>
#include <rewindow/types/gamepadbutton.h>
#include <J3ML/LinearAlgebra.hpp>
#if __linux__
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/gl.h>
#include <GL/glx.h>
#endif
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 = 3
IN_FOCUS,
FULLSCREEN,
RESIZABLE,
VSYNC,
QUIT,
MAX_FLAG
};
std::string RWindowFlagToStr(RWindowFlags flag);
enum class RenderingAPI: uint8_t {
OPENGL = 0,
//Vulkan is unimplemented.
VULKAN = 1,
OPENGL = 0,
//Vulkan is unimplemented.
VULKAN = 1,
};
class RWindow {
private:
bool flags[4];
std::vector<RWindowEvent*> events;
public:
bool getFlag(RWindowFlags flag);
void setFlag(RWindowFlags flag, bool state);
void init(RenderingAPI api, const char* title, int width, int height, bool vsync);
static void setVsyncEnabled(bool b);
void destroyWindow();
void pollEvents();
void setSize(int width, int height);
std::unique_ptr<int[]> getPos();
std::unique_ptr<int[]> getSize();
void setPos(int x, int y);
bool keyDown(SCANCODE scancode);
bool mouseButtonDown(MOUSEBUTTONCODE buttoncode);
KeyDownEvent getEvent(SCANCODE scancode);
MouseButtonDownEvent getEvent(MOUSEBUTTONCODE buttoncode);
static void glSwapBuffers();
//Initialize to false because it's not guaranteed that they will be cleared first
RWindow() : flags(false,false,false,false) {}
enum class KeyState {Pressed, Released};
};
namespace ReWindow
{
using J3ML::LinearAlgebra::Vector2;
class TimestampedEvent {
private:
public:
precision_timestamp Timestamp;
TimestampedEvent() : Timestamp(precision_clock::now())
{ }
};
class RWindowEvent : public TimestampedEvent {
public:
RWindowEvent() : TimestampedEvent() { }
};
const RWindowEvent EmptyRWindowEvent;
namespace WindowEvents {
class KeyboardState {
public:
std::map<Key, bool> PressedKeys;
};
class GamepadState {
public:
std::map<GamepadButton, bool> PressedButtons;
};
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 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 KeyUpEvent : public KeyboardEvent {
public:
KeyUpEvent(Key key) : KeyboardEvent(key, KeyState::Released) {}
};
class MouseButtonDownEvent : public MouseEvent {
public:
MouseButton Button;
MouseButtonDownEvent() = default;
MouseButtonDownEvent(MouseButton Button) : MouseEvent() {}
};
class MouseButtonUpEvent : public MouseEvent {
public:
MouseButton Button;
MouseButtonUpEvent() = default;
MouseButtonUpEvent(MouseButton Button) : MouseEvent() {}
};
class WindowResizeRequestEvent : public RWindowEvent
{
public:
Vector2 Size;
};
}
using namespace WindowEvents;
/// General To Do List
/// TODO: Clean up public API to express the cross-platform, multi-graphics-mode ethos of this project.
///
class RWindow {
public:
/// We keep and support both mechanisms for extending behavior to suit:
/// 1. Derived windows with added functionality.
/// 2. Binding functions to a pre-existing window.
#pragma region Callbacks
/// Bindable Non-intrusive event handlers
/// Use these when you can't override the base window class
Event<> OnOpenEvent;
Event<> OnClosingEvent;
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
/// Intrusive virtual methods intended to be overridden in a derived class.
/// Do not stuff any logic into these. Someone WILL override it and forget to call the base.
/// Called upon the window requesting to open.
virtual void OnOpen() {}
/// Called right before the window closes.
virtual void OnClosing() {}
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
/// The default constructor sets a default size and window title.
RWindow();
/// Constructs a window by explicitly setting title, width and height.
RWindow(const std::string& title, int width, int height);
/// Constructs a window as above with the additional argument of explicitly setting which render API is to be used.
RWindow(const std::string& title, int width, int height, RenderingAPI renderer);
/// Returns a Vector2 representing mouse coordinates relative to the top-left corner of the window.
Vector2 GetMouseCoordinates() const;
/// Sets which rendering API is to be used with this window.
void setRenderer(RenderingAPI api);
/// Initializes all state with the window manager and rendering API, then opens the window.
void Open();
/// Cleans up and closes the window without destroying the handle.
void Close();
void CloseAndReopenInPlace();
void MessageBox(); // TODO: Must be implemented from scratch as a Motif Window in x11
/// Returns whether the window currently has mouse and/or keyboard focus.
[[nodiscard]] bool isFocused() const;
[[nodiscard]] bool isFullscreen() const;
[[nodiscard]] bool isResizable() const;
[[nodiscard]] bool isVsyncEnabled() const;
[[nodiscard]] bool isAlive() const; // TODO: Always returns true.
[[nodiscard]] bool isKeyDown(Key key) const;
[[nodiscard]] bool isMouseButtonDown(MouseButton button) const;
void setFullscreen(bool fs);
void setResizable(bool resizable);
void setVsyncEnabled(bool);
void setTitle(const std::string& title);
[[nodiscard]] std::string getTitle() const;
[[nodiscard]] int getWidth() const; // Honestly no idea if we'll keep these or still go with getSize.
[[nodiscard]] int getHeight() const; // getSize wasn't working for me for logging. -maxine
void setSizeWithoutEvent(const Vector2& size); //AAAAAHHHHHHHHH WINDOZE MAKING THINGS DIFFICULT :/ - Redacted.
// TODO: Move out of public API, consumers should use setFullscreen()
void fullscreen();
// TODO: Move out of public API, consumers should use setFullscreen()
void restoreFromFullscreen();
// TODO: Josh hates parameter-flags, it's not 1995 :/
bool getFlag(RWindowFlags flag) const;
// TODO: Josh hates parameter-flags, it's not 1995 :/
void setFlag(RWindowFlags flag, bool state);
//void init(RenderingAPI api, const char* title, int width, int height, bool vsync);
/// Tells the underlying window manager to destroy this window and drop the handle.
/// The window, in theory, can not be re-opened after this.
/// TODO: Create a destructor and move to there?
/// TODO: What's the semantic difference between this and Close()?
void destroyWindow();
/// Reads events from the underlying window manager.
/// TODO: Move out of public API, consumers should call refresh or ideally an update() call.
void pollEvents();
/// Updates the window and handles timing internally.
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;
// I want to know why this is made platform specific. Is that even necessary? -maxine
// Because each OS / WM implements it with a different API. - josh
// If we stored ourselves a copy (accurately) of the window's size, we could implement it into the shared layer
// But this is at BEST, unreliable.
Vector2 getSize() const;
/// Returns the position of the "renderable area" of the window relative to it's top left corner.
/// (used to account for the width or the border & title bar).
Vector2 getPositionOfRenderableArea() const;
void setPos(int x, int y);
void setPos(const Vector2& pos);
Vector2 getCursorPos() const;
/// Pull the window to the top, such that it is displayed on top of everything else.
/// NOTE: The implementation is window-manager defined, and thus there is no guarantee of it always working.
void raise() const;
/// Push the window lower, such that it is effectively hidden behind other windows.
/// NOTE: The implementation is window-manager defined, and thus there is no guarantee of it always working.
void lower() const;
void setCursorStyle(CursorStyle style) const;
void setCursorCustomIcon() const;
void setCursorLocked();
void setCursorCenter();
void restoreCursorFromLastCenter(); // Feels nicer for users
///Hides the cursor when it's inside of our window.
///Useful for 3D game camera.
void setCursorVisible(bool cursor_enable);
bool getCursorVisible();
/// Calls OpenGL's SwapBuffers routine.
/// NOTE: This is only used when the underlying rendering API is set to OpenGL.
static void glSwapBuffers();
Vector2 getLastKnownResize() const;
void setLastKnownWindowSize(const Vector2& size);
protected:
float delta_time = 0.f;
float refresh_rate = 0.f;
unsigned int refresh_count = 0;
bool cursor_visible = true;
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 = "Redacted Window";
int width = 1280;
int height = 720;
RenderingAPI renderer = RenderingAPI::OPENGL;
bool open = false;
bool resizable = true;
Vector2 mouse_coords = {0, 0};
Vector2 last_mouse_coords = {0, 0};
// TODO: Implement ringbuffer / circular vector class of some sort.
float refresh_rate_prev_1 = 0.f;
float refresh_rate_prev_2 = 0.f;
float refresh_rate_prev_3 = 0.f;
float refresh_rate_prev_4 = 0.f;
float refresh_rate_prev_5 = 0.f;
float avg_refresh_rate = 0.0f;
private:
/// Returns the most accurate and recent available mouse coordinates.
/// @note Call this version at most **once** per-frame. It polls the X-Window server and therefore is quite slow.
/// @see getCursorPos();
Vector2 GetAccurateMouseCoordinates() const;
/// Executes event handlers for keyboard rele;ase events.
void processKeyRelease (Key key);
/// Executes event handlers for keyboard press events.
void processKeyPress (Key key);
/// Executes event handlers for window close events.
/// @note This will be invoked **before** the window-close procedure begins.
void processOnClose();
/// Executes event handlers for window open events.
/// @note This will be invoked **after** the window-open procedure completes.
void processOnOpen();
/// Executes event handlers for mouse press events.
void processMousePress(MouseButton btn);
/// Executes event handlers for mouse release events.
void processMouseRelease(MouseButton btn);
/// Executes event handlers for window focus events.
void processFocusIn();
/// Executes event handlers for window unfocus events.
void processFocusOut();
void processMouseMove(Vector2 last_pos, Vector2 new_pos);
private:
};
}

139
main.cpp
View File

@@ -1,23 +1,124 @@
#include <iostream>
#include "include/rewindow/types/window.h"
int main() {
auto* window = new(RWindow);
window->init(RenderingAPI::OPENGL, "name",100,100,false);
window->setFlag(RWindowFlags::RESIZABLE, false);
while (true) {
window->pollEvents();
#include <rewindow/types/window.h>
#include <rewindow/types/display.h>
#include <rewindow/logger/logger.h>
if (window->keyDown(SCANCODE::A)) {
std::cout << "A" << std::endl;
std::cout << (int64_t) window->getEvent(SCANCODE::A).empty() << std::endl;
//aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Windows :/
#if _WIN32
#include <windows.h>
#endif
#include <GL/gl.h>
Vector2 mouse_pos;
// 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) {}
void OnMouseMove(const ReWindow::MouseMoveEvent& e) override {}
void OnKeyDown(const ReWindow::KeyDownEvent& e) override {}
void OnRefresh(float elapsed) override {
glClearColor(255, 0, 0, 255);
glClear(GL_COLOR_BUFFER_BIT);
glSwapBuffers();
auto pos = GetMouseCoordinates();
//std::cout << pos.x << ", " << pos.y << std::endl;
RWindow::OnRefresh(elapsed);
}
bool OnResizeRequest(const ReWindow::WindowResizeRequestEvent& e) override {
std::cout << "resized to " << e.Size.x << ", " << e.Size.y << std::endl;
return true;
}
};
int main() {
auto* window = new MyWindow("Test Window", 600, 480);
jlog::Debug(std::format("New window '{}' created. width={} height={}", window->getTitle(), window->getWidth(), window->getHeight()));
window->setRenderer(RenderingAPI::OPENGL);
jlog::Debug(std::format("Rendering API OPENGL set for window '{}'", window->getTitle()));
window->Open();
jlog::Debug(std::format("Opened window '{}'", window->getTitle()));
// TODO: Cannot set flags until after window is open
// Make this work somehow
jlog::Debug("TODO: Cannot set flags until after window is open");
window->setFullscreen(false);
window->setVsyncEnabled(true);
window->setResizable(true);
window->setCursorVisible(false);
/*
std::vector<ReWindow::Display> d = ReWindow::Display::getDisplaysFromWindowManager();
for (ReWindow::Display& display : d) {
auto w = display.getDefaultGraphicsMode().getWidth();
auto h = display.getDefaultGraphicsMode().getHeight();
auto r = display.getDefaultGraphicsMode().getRefreshRate();
auto aspect = (float)w/(float)h;
std::cout << "Default: ";
std::cout << std::format("Mode ({},{}) @ {}hz Ratio {}", w, h, r, aspect) << std::endl;
for (ReWindow::FullscreenGraphicsMode& fgm : display.getGraphicsModes()) {
w = fgm.getWidth();
h = fgm.getHeight();
r = fgm.getRefreshRate();
auto aspect = (float)w/(float)h;
std::cout << std::format("Mode ({},{}) @ {}hz Ratio {}", w, h, r, aspect) << std::endl;
}
if (window->mouseButtonDown(MOUSEBUTTONCODE::LEFT_CLICK))
std::cout << window->mouseButtonDown(MOUSEBUTTONCODE::LEFT_CLICK) << std::endl;
//std::cout << window->events.size() << std::endl;
//window->resize(800,600);
//std::cout << window->getPos()[1] << std::endl;
//auto* d = new(KeyDownEvent);
//d->key = SCANCODE::A;
//window->events.push_back(d);
}
}
*/
ReWindow::Logger::Debug(std::format("Window '{}' flags: IN_FOCUS={} FULLSCREEN={} RESIZEABLE={} VSYNC={} QUIT={}",
window->getTitle(),
window->getFlag(RWindowFlags::IN_FOCUS),
window->getFlag(RWindowFlags::FULLSCREEN),
window->getFlag(RWindowFlags::RESIZABLE),
window->getFlag(RWindowFlags::VSYNC),
window->getFlag(RWindowFlags::QUIT)));
window->OnKeyDownEvent += [&] (ReWindow::KeyDownEvent e) {
jlog::Debug(e.key.CharCode);
};
window->OnMouseButtonDownEvent += [&] (ReWindow::MouseButtonDownEvent e) {
jlog::Debug(e.Button.CharCode);
};
while (window->isAlive()) {
window->pollEvents();
window->refresh();
}
}
/*
//Windows :(
#ifdef _WIN32
#ifndef UNICODE
#define UNICODE
#endif
extern "C" {
int wmain(int argc, wchar_t* argv[]) {
return main();
}
}
#endif
*/

View File

@@ -0,0 +1 @@
Main:new("Install build dependencies", "apt-get install -yq libx11-6 libx11-dev libgl-dev")

View File

@@ -1,10 +0,0 @@
#include "../include/rewindow/types/event.h"
bool RWindowEvent::empty() {
if (timePoint == EmptyRWindowEvent.timePoint || this->timePoint == EmptyKeyDownEvent.timePoint || this->timePoint == EmptyMouseButtonDownEvent.timePoint)
return true;
return false;
}
std::chrono::high_resolution_clock::time_point RWindowEvent::timeStamp() {
return timePoint;
}

View File

@@ -1,208 +0,0 @@
#include <iostream>
#include "rewindow/types/window.h"
Window window;
XEvent xev;
Display* display = XOpenDisplay(nullptr);
int defaultScreen = DefaultScreen(display);
//Visual* visual = DefaultVisual(display,defaultScreen);
XVisualInfo* visual;
//int depth = DefaultDepth(display, defaultScreen);
XSetWindowAttributes xSetWindowAttributes;
XWindowAttributes windowAttributes;
Atom wmDeleteWindow;
XSizeHints hints;
GLXContext glContext;
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);
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 |
Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask |
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);
} else {exit(0);}
}
void RWindow::destroyWindow() {
XDestroySubwindows(display, window);
XAutoRepeatOn(XOpenDisplay(nullptr));
XDestroyWindow(display, window);
delete this;
}
bool RWindow::getFlag(RWindowFlags flag) {
if (flags[(int)flag])
return true;
return false;
}
void RWindow::setFlag(RWindowFlags flag, bool state) {
XGetWindowAttributes(display,window,&windowAttributes);
flags[(int) flag] = state;
//Once you've done this you cannot make it resizable again.
if (flag == RWindowFlags::RESIZABLE && !state) {
hints.flags = PMinSize | PMaxSize;
hints.min_width = hints.max_width = windowAttributes.width;
hints.min_height = hints.max_height = windowAttributes.height;
XSetWMNormalHints(display, window, &hints);
}
}
void RWindow::pollEvents() {
while(XPending(display)) {
XNextEvent(display, &xev);
if (xev.type == ClientMessage) {
if (xev.xclient.message_type == XInternAtom(display, "WM_PROTOCOLS", False) &&
static_cast<Atom>(xev.xclient.data.l[0]) == wmDeleteWindow) {
destroyWindow();
exit(0);
}
}
if (xev.type == FocusIn) {
XAutoRepeatOff(display);
setFlag(RWindowFlags::IN_FOCUS, true);
}
if (xev.type == FocusOut) {
XAutoRepeatOn(display);
setFlag(RWindowFlags::IN_FOCUS, false);
}
if (xev.type == KeyRelease) {
for (unsigned int i = 0; i < events.size(); i++) {
if (auto *e = dynamic_cast<KeyDownEvent *>(events[i])) {
if ((int) e->key == (int) xev.xkey.keycode) {
delete events[i];
events.erase(events.begin() + i);
}
}
}
}
if (xev.type == KeyPress) {
//On Windows you'll have to do this the long way.
//The keycodes won't be the same :shrug:
auto *kD = new(KeyDownEvent);
kD->key = (SCANCODE) xev.xkey.keycode;
events.push_back(kD);
}
if (xev.type == ButtonRelease) {
for (unsigned int i = 0; i < events.size(); i++) {
if (auto *e = dynamic_cast<MouseButtonDownEvent *>(events[i])) {
if ((int) e->button == (int) xev.xbutton.button) {
delete events[i];
events.erase(events.begin() + i);
}
}
}
}
if (xev.type == ButtonPress) {
std::cout << (int) xev.xbutton.button << std::endl;
auto *mBD = new(MouseButtonDownEvent);
mBD->button = (MOUSEBUTTONCODE) xev.xbutton.button;
events.push_back(mBD);
}
if (xev.type == Expose) {
}
}
}
//Might make the window go off the screen on some window managers.
void RWindow::setSize(int width, int height) {
if (!getFlag(RWindowFlags::RESIZABLE))
return;
XResizeWindow(display, window, width, height);
}
std::unique_ptr<int[]> RWindow::getSize() {
XGetWindowAttributes(display,window,&windowAttributes);
std::unique_ptr<int[]> size = std::make_unique<int[]>(2);
size[0] = windowAttributes.width;
size[1] = windowAttributes.height;
return size;
}
//I'm unsure why this doesn't work as you'd expect.
std::unique_ptr<int[]> RWindow::getPos() {
XGetWindowAttributes(display,window,&windowAttributes);
std::unique_ptr<int[]> pos = std::make_unique<int[]>(2);
pos[0] = windowAttributes.x;
pos[1] = windowAttributes.y;
return pos;
}
void RWindow::setPos(int x, int y) {
XMoveWindow(display, window, x, y);
}
bool RWindow::keyDown(SCANCODE scancode) {
for (auto & ev : events) {
if (auto *e = dynamic_cast<KeyDownEvent *>(ev)) {
if (e->key == scancode) { return true;}
}
}
return false;
}
KeyDownEvent RWindow::getEvent(SCANCODE scancode) {
for (auto & ev : events) {
if (auto *e = dynamic_cast<KeyDownEvent *>(ev)) {
if (e->key == scancode) { return *e;}
}
}
return EmptyKeyDownEvent;
}
bool RWindow::mouseButtonDown(MOUSEBUTTONCODE buttoncode) {
for (auto & ev : events) {
if (auto *e = dynamic_cast<MouseButtonDownEvent *>(ev)) {
if (e->button == buttoncode) { return true;}
}
}
return false;
}
MouseButtonDownEvent RWindow::getEvent(MOUSEBUTTONCODE buttoncode) {
for (auto & ev : events) {
if (auto *e = dynamic_cast<MouseButtonDownEvent *>(ev)) {
if (e->button == buttoncode) { return *e;}
}
}
return EmptyMouseButtonDownEvent;
}
void RWindow::glSwapBuffers() {
glXSwapBuffers(display,window);
}
void RWindow::setVsyncEnabled(bool b) {
PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalEXT");
glXSwapIntervalEXT(display, None, b);
}

7
src/logger/logger.cpp Normal file
View File

@@ -0,0 +1,7 @@
#include "rewindow/logger/logger.h"
namespace ReWindow::Logger {
using namespace jlog;
GenericLogger Fatal {"ReWindow::fatal", GlobalLogFile, Colors::Reds::Crimson, Colors::Gray, Colors::Gray, Colors::Reds::Crimson, Colors::White};
GenericLogger Debug {"ReWindow::debug", GlobalLogFile, Colors::Purples::Purple, Colors::Gray, Colors::Gray, Colors::Purples::Purple, Colors::White};
}

View File

@@ -0,0 +1,74 @@
#include <rewindow/types/display.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#include <stdexcept>
using namespace ReWindow;
std::vector<ReWindow::Display> ReWindow::Display::getDisplaysFromWindowManager() {
std::vector<ReWindow::Display> result;
_XDisplay* display = XOpenDisplay(nullptr);
if (!display)
throw std::runtime_error("There isn't an X11 root display????");
Window root_window = DefaultRootWindow(display);
XRRScreenResources* screen_resources = XRRGetScreenResources(display, root_window);
if (!screen_resources)
throw std::runtime_error("Failed to get screen resources.");
for (int i = 0; i < screen_resources->noutput; i++) {
RROutput output = screen_resources->outputs[i];
XRROutputInfo* output_info = XRRGetOutputInfo(display, screen_resources, output);
if (output_info->connection == RR_Connected) {
ReWindow::Display d;
XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(display, screen_resources, output_info->crtc);
if (!crtc_info)
throw std::runtime_error("Failed to get CRT info.");
u32 default_width = (u32) crtc_info->width;
u32 default_height = (u32) crtc_info->height;
short default_refresh_rate = 0;
for (int k = 0; k < screen_resources->nmode; k++) {
if (screen_resources->modes[k].id == crtc_info->mode) {
XRRModeInfo mode_info = screen_resources->modes[k];
double refresh_rate;
if (mode_info.hTotal > 0 && mode_info.vTotal > 0)
refresh_rate = mode_info.dotClock / (double)(mode_info.hTotal * mode_info.vTotal),
default_refresh_rate = (short)refresh_rate;
d.default_graphics_mode = {default_width, default_height, default_refresh_rate};
break;
}
}
for (int j = 0; j < output_info->nmode; j++) {
RRMode mode = output_info->modes[j];
for (int k = 0; k < screen_resources->nmode; k++) {
if (screen_resources->modes[k].id == mode) {
XRRModeInfo mode_info = screen_resources->modes[k];
// Calculate refresh rate from the mode's dot clock
double refresh_rate = 0.0;
if (mode_info.hTotal > 0 && mode_info.vTotal > 0)
refresh_rate = mode_info.dotClock / (double)(mode_info.hTotal * mode_info.vTotal);
d.graphics_modes.emplace_back((u32) mode_info.width,(u32) mode_info.height,(short) refresh_rate);
}
}
}
XRRFreeCrtcInfo(crtc_info);
result.push_back(d);
}
XRRFreeOutputInfo(output_info);
}
XRRFreeScreenResources(screen_resources);
XCloseDisplay(display);
return result;
}

View File

@@ -0,0 +1,418 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <GL/glx.h>
#include <cstdlib>
#include <cstring>
#include <rewindow/types/window.h>
#include <rewindow/types/cursors.h>
#include <J3ML/J3ML.hpp>
#include <rewindow/logger/logger.h>
// TODO: Move all "global" members to be instantiated class members of Window
// Doing this would break the intended "Platform-Specific" Encapsulation
// So should we do derived platform-specific subclasses?
// The intended goal of the ReWindow class is a one-stop object that handles window management on **ALL** platforms
Window window;
XEvent xev;
Display* display = XOpenDisplay(nullptr);
int defaultScreen = DefaultScreen(display);
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;
Cursor invisible_cursor = 0;
Vector2 render_area_position = {0, 0};
Vector2 position = {0, 0};
bool should_poll_x_for_mouse_pos = true;
using namespace ReWindow;
void RWindow::raise() const {
Logger::Debug(std::format("Raising window '{}'", this->title));
// Get the position of the renderable area relative to the rest of the window.
XGetWindowAttributes(display, window, &windowAttributes);
render_area_position = { (float) windowAttributes.x, (float) windowAttributes.y };
XRaiseWindow(display, window);
}
void RWindow::lower() const
{
Logger::Debug(std::format("Lowering window '{}'", this->title));
XLowerWindow(display, window);
}
void RWindow::destroyWindow() {
Logger::Debug(std::format("Destroying window '{}'", this->title));
XDestroySubwindows(display, window);
Logger::Debug(std::format("Destroyed window '{}'", this->title));
XDestroyWindow(display, window);
delete this;
}
void RWindow::refresh() {
auto begin_frame = std::chrono::high_resolution_clock::now();
OnRefresh(delta_time);
// Only call once and cache the result.
mouse_coords = GetAccurateMouseCoordinates();
/// TODO: Implement optional minimum epsilon to trigger a Mouse Update.
if (mouse_coords != last_mouse_coords) {
processMouseMove(last_mouse_coords, mouse_coords);
last_mouse_coords = mouse_coords;
}
auto end_frame = std::chrono::high_resolution_clock::now();
auto frame_time = end_frame - begin_frame;
unsigned long int frame_time_us = std::chrono::duration_cast<std::chrono::microseconds>(frame_time).count();
double frame_time_s = frame_time_us / (1000.f * 1000.f);
delta_time = frame_time_s;
refresh_rate = 1.f / delta_time;
refresh_rate_prev_5 = refresh_rate_prev_4;
refresh_rate_prev_4 = refresh_rate_prev_3;
refresh_rate_prev_3 = refresh_rate_prev_2;
refresh_rate_prev_2 = refresh_rate_prev_1;
refresh_rate_prev_1 = refresh_rate;
avg_refresh_rate = (refresh_rate_prev_1 + refresh_rate_prev_2 + refresh_rate_prev_3 + refresh_rate_prev_4 + refresh_rate_prev_5) / 5.f;
refresh_count++;
}
void RWindow::setCursorVisible(bool cursor_enable) {
cursor_visible = cursor_enable;
if (invisible_cursor == 0) {
Pixmap blank_pixmap = XCreatePixmap(display, window, 1, 1, 1);
XColor dummy; dummy.pixel = 0; dummy.red = 0; dummy.flags = 0;
invisible_cursor = XCreatePixmapCursor(display, blank_pixmap, blank_pixmap, &dummy, &dummy, 0, 0);
XFreePixmap(display, blank_pixmap);
}
if (!cursor_enable)
XDefineCursor(display, window, invisible_cursor);
if (cursor_enable)
XUndefineCursor(display, window);
}
void RWindow::setFlag(RWindowFlags flag, bool state) {
XGetWindowAttributes(display,window,&windowAttributes);
flags[(int) flag] = state;
//Once you've done this you cannot make it resizable again.
if (flag == RWindowFlags::RESIZABLE && !state) {
Logger::Debug("Once you've done this you cannot make it resizable again.");
hints.flags = PMinSize | PMaxSize;
hints.min_width = hints.max_width = windowAttributes.width;
hints.min_height = hints.max_height = windowAttributes.height;
XSetWMNormalHints(display, window, &hints);
}
Logger::Debug(std::format("Set flag '{}' to state '{}' for window '{}'", RWindowFlagToStr(flag), state, this->title));
}
void RWindow::pollEvents() {
while(XPending(display)) {
XNextEvent(display, &xev);
if (xev.type == ClientMessage)
Logger::Debug(std::format("Recieved event '{}'", "ClientMessage"));
if (xev.xclient.message_type == XInternAtom(display, "WM_PROTOCOLS", False) && static_cast<Atom>(xev.xclient.data.l[0]) == wmDeleteWindow) {
processOnClose();
destroyWindow();
system("xset r on");
exit(0);
}
if (xev.type == FocusIn) {
Logger::Debug(std::format("Recieved event '{}'", "FocusIn"));
XAutoRepeatOff(display);
setFlag(RWindowFlags::IN_FOCUS, true);
if (!cursor_visible)
XDefineCursor(display, window, invisible_cursor);
// Get the position of the renderable area relative to the rest of the window.
XGetWindowAttributes(display, window, &windowAttributes);
render_area_position = { (float) windowAttributes.x, (float) windowAttributes.y };
processFocusIn();
}
if (xev.type == FocusOut) {
Logger::Debug(std::format("Recieved event '{}'", "FocusOut"));
XAutoRepeatOn(display);
setFlag(RWindowFlags::IN_FOCUS, false);
if (!cursor_visible)
XUndefineCursor(display, window);
processFocusOut();
}
if (xev.type == KeyRelease) {
Logger::Debug(std::format("Recieved event '{}'", "KeyRelease"));
auto scancode = (X11Scancode) xev.xkey.keycode;
auto key = GetKeyFromX11Scancode(scancode);
processKeyRelease(key);
}
if (xev.type == KeyPress) {
Logger::Debug(std::format("Recieved event '{}'", "KeyPress"));
auto scancode = (X11Scancode) xev.xkey.keycode;
auto key = GetKeyFromX11Scancode(scancode);
processKeyPress(key);
}
if (xev.type == ButtonRelease) {
Logger::Debug(std::format("Recieved event '{}'", "ButtonRelease"));
MouseButton button = GetMouseButtonFromXButton(xev.xbutton.button);
processMouseRelease(button);
}
if (xev.type == ButtonPress) {
MouseButton button = GetMouseButtonFromXButton(xev.xbutton.button);
Logger::Debug(std::format("Window event: MouseButtonPress {}", button.CharCode));
processMousePress(button);
}
if (xev.type == Expose)
{
Logger::Debug(std::format("Recieved event '{}'", "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)
{
Logger::Debug(std::format("Recieved event '{}'", "MotionNotify"));
}
if (xev.type == ConfigureNotify) {
if (this->width != xev.xconfigurerequest.width || this->height != xev.xconfigurerequest.height) {
Logger::Debug(std::format("Recieved event '{}'", "ResizeRequest"));
this->width = xev.xconfigurerequest.width;
this->height = xev.xconfigurerequest.height;
auto eventData = WindowResizeRequestEvent();
eventData.Size = { (float) xev.xconfigurerequest.width, (float) xev.xconfigurerequest.height };
lastKnownWindowSize = eventData.Size;
OnResizeRequest(eventData);
OnResizeRequestEvent(eventData);
}
//Window Moved.
if (position.x != xev.xconfigurerequest.x || position.y != xev.xconfigurerequest.y)
position = { (float) xev.xconfigurerequest.x, (float) xev.xconfigurerequest.y };
}
}
previousKeyboard = currentKeyboard;
}
// Might make the window go off the screen on some window managers.
void RWindow::setSize(int newWidth, int newHeight) {
if (!getFlag(RWindowFlags::RESIZABLE)) return;
this->width = newWidth;
this->height = newHeight;
XResizeWindow(display, window, newWidth, newHeight);
XFlush(display);
Logger::Debug(std::format("Set size for window '{}'. width={} height={}", this->title, newWidth, newHeight));
}
Vector2 RWindow::GetAccurateMouseCoordinates() const {
Window root_return, child_return;
int root_x_ret, root_y_ret;
int win_x_ret, win_y_ret;
uint32_t mask_return;
// This seems to be relative to the top left corner of the renderable area.
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: normalize coordinates from displaySpace to windowSpace
// TODO: fire mouse movement event
Vector2 m_coords = { (float) win_x_ret, (float) win_y_ret };
return m_coords;
}
return Vector2::Zero;
}
// TODO: implement integer vector2/3 types
Vector2 RWindow::getSize() const {
return {(float) this->width, (float) this->height};
}
Vector2 RWindow::getLastKnownResize() const
{
return lastKnownWindowSize;
}
// TODO: implement integer vector2/3 types
Vector2 RWindow::getPos() const {
return position;
}
void RWindow::setPos(int x, int y) {
XMoveWindow(display, window, x, y);
position = { (float) x, (float) y };
}
void RWindow::setPos(const Vector2& pos) {
setPos(pos.x, pos.y);
}
void RWindow::glSwapBuffers() {
glXSwapBuffers(display,window);
}
bool RWindow::isResizable() const {
return getFlag(RWindowFlags::RESIZABLE);
}
void RWindow::fullscreen() {
Logger::Debug(std::format("Fullscreening window '{}'", this->title));
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);
Logger::Debug(std::format("Fullscreened window '{}'", this->title));
}
void RWindow::restoreFromFullscreen() {
Logger::Debug(std::format("Restoring window '{}' from fullscreen", this->title));
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);
Logger::Debug(std::format("Restored window '{}' from fullscreen", this->title));
}
void RWindow::setVsyncEnabled(bool b) {
PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalEXT");
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);
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);
// Get the position of the renderable area relative to the rest of the window.
XGetWindowAttributes(display, window, &windowAttributes);
render_area_position = { (float) windowAttributes.x, (float) windowAttributes.y };
open = true;
processOnOpen();
}
void RWindow::setTitle(const std::string &title) {
this->title = title;
XStoreName(display, window, title.c_str());
}
// TODO: Implement MouseButton map
bool RWindow::isMouseButtonDown(MouseButton button) const {
return false;
}
Vector2 RWindow::getPositionOfRenderableArea() const {
return render_area_position;
}
// TODO: Implement ControllerButton map

View File

@@ -0,0 +1,34 @@
#include <rewindow/types/display.h>
using namespace ReWindow;
FullscreenGraphicsMode::FullscreenGraphicsMode(u32 width, u32 height, short refresh_rate) {
this->width = width;
this->height = height;
this->refresh_rate = refresh_rate;
}
u32 FullscreenGraphicsMode::getWidth() const {
return width;
}
u32 FullscreenGraphicsMode::getHeight() const {
return height;
}
float FullscreenGraphicsMode::getRefreshRate() const {
return refresh_rate;
}
FullscreenGraphicsMode Display::getDefaultGraphicsMode() {
return default_graphics_mode;
}
std::vector<FullscreenGraphicsMode> Display::getGraphicsModes() {
return graphics_modes;
}
Display::Display(const FullscreenGraphicsMode& default_graphics_mode, const std::vector<FullscreenGraphicsMode>& graphics_modes) {
this->default_graphics_mode = default_graphics_mode;
this->graphics_modes = graphics_modes;
}

View File

@@ -0,0 +1,172 @@
#include <rewindow/types/window.h>
#include "rewindow/logger/logger.h"
std::string RWindowFlagToStr(RWindowFlags flag) {
switch (flag) {
case RWindowFlags::IN_FOCUS: return "IN_FOCUS";
case RWindowFlags::FULLSCREEN: return "FULLSCREEN";
case RWindowFlags::RESIZABLE: return "RESIZEABLE";
case RWindowFlags::VSYNC: return "VSYNC";
case RWindowFlags::QUIT: return "QUIT";
case RWindowFlags::MAX_FLAG: return "MAX_FLAG";
default:
return "unimplemented flag";
}
};
using namespace ReWindow;
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) {}
Vector2 RWindow::GetMouseCoordinates() const {
return mouse_coords;
}
bool RWindow::getFlag(RWindowFlags flag) const {
return flags[(int) flag];
}
bool RWindow::isAlive() const {
return true;
}
void RWindow::setResizable(bool resizable) {
this->resizable = resizable;
this->setFlag(RWindowFlags::RESIZABLE, resizable);
}
void RWindow::setFullscreen(bool fs) {
if (fs)
fullscreen();
else
restoreFromFullscreen();
}
void RWindow::processFocusIn()
{
RWindowEvent event {};
OnFocusGain(event);
OnFocusGainEvent(event);
}
void RWindow::processFocusOut()
{
RWindowEvent event {};
OnFocusLost(event);
OnFocusLostEvent(event);
}
void RWindow::processMousePress(MouseButton btn)
{
auto eventData = MouseButtonDownEvent(btn);
OnMouseButtonDownEvent(eventData);
OnMouseButtonDown(eventData);
}
void RWindow::processMouseMove(Vector2 last_pos, Vector2 new_pos)
{
auto eventData = MouseMoveEvent(new_pos);
OnMouseMove(eventData);
OnMouseMoveEvent(eventData);
}
void RWindow::processMouseRelease(MouseButton btn)
{
auto eventData = MouseButtonUpEvent(btn);
OnMouseButtonUpEvent(eventData);
OnMouseButtonUp(eventData);
}
void RWindow::processKeyRelease(Key key) {
currentKeyboard.PressedKeys[key] = false;
auto event = KeyUpEvent(key);
OnKeyUp(event);
OnKeyUpEvent(key);
}
std::string RWindow::getTitle() const {
return this->title;
}
/*
Vector2 RWindow::getSize() const
{
return {this->width, this->height};
}
*/
int RWindow::getWidth() const
{
return this->width;
}
int RWindow::getHeight() const
{
return this->height;
}
void RWindow::setSizeWithoutEvent(const Vector2& size) {
width = size.x;
height = size.y;
}
void RWindow::setLastKnownWindowSize(const Vector2& size) {
lastKnownWindowSize = size;
}
void RWindow::setRenderer(RenderingAPI api) {
renderer = api;
}
void RWindow::setSize(const Vector2& size) {
this->width = size.x;
this->height = size.y;
this->setSize(size.x, size.y);
}
bool RWindow::isKeyDown(Key key) const {
for (const auto& pair : currentKeyboard.PressedKeys)
if (pair.first == key && pair.second)
return true;
return false;
}
void RWindow::processKeyPress(Key key) {
currentKeyboard.PressedKeys[key] = true;
auto eventData = KeyDownEvent(key);
OnKeyDown(eventData);
OnKeyDownEvent(key);
}
void RWindow::processOnClose()
{
OnClosing();
OnClosingEvent();
}
void RWindow::processOnOpen()
{
OnOpen();
OnOpenEvent();
}
void RWindow::Close() {
/// TODO: Implement closing the window without destroying the handle.
processOnClose();
}

View File

@@ -0,0 +1,350 @@
#include <Windows.h>
#include <gl/GL.h>
#include <rewindow/types/window.h>
using namespace ReWindow;
bool fullscreenmode = false;
bool open = false;
HINSTANCE hInstance = GetModuleHandle(nullptr);
HWND hwnd;
HDC hdc;
HGLRC glContext;
void raise() { SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); }
void lower() { SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); }
void RWindow::setFlag(RWindowFlags flag, bool state) {
flags[(int) flag] = state;
if (flag == RWindowFlags::RESIZABLE && !state) {
RECT rect;
GetWindowRect(hwnd, &rect);
LONG style = GetWindowLong(hwnd, GWL_STYLE);
style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
SetWindowLong(hwnd, GWL_STYLE, style);
SetWindowPos(hwnd, nullptr, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
}
void RWindow::pollEvents() {
MSG msg;
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
void RWindow::setSize(int newWidth, int newHeight) {
if (!getFlag(RWindowFlags::RESIZABLE)) return;
this->width = newWidth;
this->height = newHeight;
SetWindowPos(hwnd, nullptr, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER);
}
Vector2 RWindow::getCursorPos() const {
POINT point;
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
return { (float)point.x, (float)point.y };
}
void RWindow::setCursorVisible(bool cursor_enable) {
cursor_visible = cursor_enable;
}
bool RWindow::getCursorVisible() {
return cursor_visible;
}
Vector2 RWindow::getSize() const {
RECT rect;
GetClientRect(hwnd, &rect);
return { (float)(rect.right - rect.left), (float)(rect.bottom - rect.top) };
}
void RWindow::setPos(int x, int y) {
SetWindowPos(hwnd, nullptr, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
void RWindow::setPos(const Vector2& pos) {
setPos(pos.x, pos.y);
}
void RWindow::fullscreen() {
// Implement fullscreen
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_OVERLAPPEDWINDOW);
SetWindowPos(hwnd, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
}
void RWindow::restoreFromFullscreen() {
// Implement restore from fullscreen
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW);
SetWindowPos(hwnd, nullptr, 0, 0, width, height, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
void RWindow::setVsyncEnabled(bool b) {
typedef BOOL(WINAPI* PFNWGLSWAPINTERVALEXTPROC)(int interval);
auto wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT");
if (wglSwapIntervalEXT)
wglSwapIntervalEXT(b ? 1 : 0);
}
bool RWindow::isFullscreen() const {
return fullscreenmode;
}
RWindow* eWindow = nullptr;
KeyboardState* pKeyboard = nullptr;
KeyboardState* cKeyboard = nullptr;
//Event loop.
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CLOSE: {
DestroyWindow(hwnd);
}
case WM_DESTROY: {
exit(0);
}
case WM_SIZE: {
eWindow->setSizeWithoutEvent({(float) LOWORD(lParam), (float) HIWORD(lParam)});
auto eventData = WindowResizeRequestEvent();
eventData.Size = {(float) eWindow->getWidth(), (float) eWindow->getHeight()};
eWindow->setLastKnownWindowSize({(float) eWindow->getWidth(), (float) eWindow->getHeight()});
eWindow->OnResizeRequest(eventData);
eWindow->OnResizeRequestEvent(eventData);
//Just to be absolutely sure the OpenGL viewport resizes along with the window.
glViewport(0, 0, eWindow->getWidth(), eWindow->getHeight());
break;
}
case WM_SETFOCUS: {
RWindowEvent event {};
eWindow->OnFocusGain(event);
eWindow->OnFocusGainEvent(event);
eWindow->setFlag(RWindowFlags::IN_FOCUS, true);
break;
}
case WM_KILLFOCUS: {
RWindowEvent event {};
eWindow->OnFocusLost(event);
eWindow->OnFocusLostEvent(event);
eWindow->setFlag(RWindowFlags::IN_FOCUS, false);
break;
}
case WM_SETCURSOR: {
if (LOWORD(lParam) == HTCLIENT && eWindow->getCursorVisible() == false)
SetCursor(nullptr);
break;
}
case WM_KEYDOWN: {
auto key = GetKeyFromWindowsScancode((WindowsScancode) wParam);
//Key repeat fix.
if (!pKeyboard->PressedKeys[key]) {
eWindow->OnKeyDownEvent(key);
eWindow->OnKeyDown(key);
eWindow->pressKey(key);
}
break;
}
case WM_KEYUP: {
auto key = GetKeyFromWindowsScancode((WindowsScancode) wParam);
eWindow->OnKeyUpEvent(key);
eWindow->OnKeyUp(key);
eWindow->liftKey(key);
break;
}
//Mouse Buttons.
case WM_MOUSEWHEEL: {
auto eventData = MouseButtonDownEvent();
int wheel_delta = GET_WHEEL_DELTA_WPARAM(wParam);
//If the wheel delta is positive it's MWheelUp, Negative is MWheelDown.
if (wheel_delta > 0)
eventData.Button = MouseButtons::MWheelUp,
eWindow->OnMouseButtonDownEvent(eventData),
eWindow->OnMouseButtonDown(eventData);
else
eventData.Button = MouseButtons::MWheelDown,
eWindow->OnMouseButtonDownEvent(eventData),
eWindow->OnMouseButtonDown(eventData);
break;
}
case WM_LBUTTONDOWN: {
auto eventData = MouseButtonDownEvent();
eventData.Button = MouseButtons::Left;
eWindow->OnMouseButtonDownEvent(eventData);
eWindow->OnMouseButtonDown(eventData);
break;
}
case WM_LBUTTONUP: {
auto eventData = MouseButtonUpEvent();
eventData.Button = MouseButtons::Left;
eWindow->OnMouseButtonUpEvent(eventData);
eWindow->OnMouseButtonUp(eventData);
break;
}
case WM_RBUTTONDOWN: {
auto eventData = MouseButtonDownEvent();
eventData.Button = MouseButtons::Right;
eWindow->OnMouseButtonDownEvent(eventData);
eWindow->OnMouseButtonDown(eventData);
break;
}
case WM_RBUTTONUP: {
auto eventData = MouseButtonUpEvent();
eventData.Button = MouseButtons::Right;
eWindow->OnMouseButtonUpEvent(eventData);
eWindow->OnMouseButtonUp(eventData);
break;
}
case WM_MBUTTONDOWN: {
auto eventData = MouseButtonDownEvent();
eventData.Button = MouseButtons::Middle;
eWindow->OnMouseButtonDownEvent(eventData);
eWindow->OnMouseButtonDown(eventData);
break;
}
case WM_MBUTTONUP: {
auto eventData = MouseButtonUpEvent();
eventData.Button = MouseButtons::Middle;
eWindow->OnMouseButtonUpEvent(eventData);
eWindow->OnMouseButtonUp(eventData);
break;
}
case WM_XBUTTONDOWN: {
WORD button = GET_XBUTTON_WPARAM(wParam);
auto eventData = MouseButtonDownEvent();
if (button == XBUTTON1)
eventData.Button = MouseButtons::Mouse4,
eWindow->OnMouseButtonDownEvent(eventData),
eWindow->OnMouseButtonDown(eventData);
if (button == XBUTTON2)
eventData.Button = MouseButtons::Mouse5,
eWindow->OnMouseButtonDownEvent(eventData),
eWindow->OnMouseButtonDown(eventData);
break;
}
case WM_XBUTTONUP: {
WORD button = GET_XBUTTON_WPARAM(wParam);
auto eventData = MouseButtonUpEvent();
if (button == XBUTTON1)
eventData.Button = MouseButtons::Mouse4,
eWindow->OnMouseButtonUpEvent(eventData),
eWindow->OnMouseButtonUp(eventData);
if (button == XBUTTON2)
eventData.Button = MouseButtons::Mouse5,
eWindow->OnMouseButtonUpEvent(eventData),
eWindow->OnMouseButtonUp(eventData);
break;
}
//This is the same as "Motion Notify" in the X Window System.
case WM_MOUSEMOVE:
break;
}
if (pKeyboard != nullptr && cKeyboard != nullptr)
pKeyboard = cKeyboard;
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void RWindow::setCursorStyle(CursorStyle style) const {}
void RWindow::Open() {
eWindow = this;
pKeyboard = &previousKeyboard;
cKeyboard = &currentKeyboard;
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = "RWindowClass";
RegisterClass(&wc);
hwnd = CreateWindowEx(
0,
"RWindowClass",
title.c_str(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, width, height,
nullptr,
nullptr,
hInstance,
nullptr
);
if (renderer == RenderingAPI::OPENGL) {
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
24,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24,
8,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
hdc = GetDC(hwnd);
int pixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, pixelFormat, &pfd);
glContext = wglCreateContext(hdc);
wglMakeCurrent(hdc, glContext);
}
ShowWindow(hwnd, SW_SHOW);
open = true;
}
void RWindow::glSwapBuffers() {
SwapBuffers(hdc);
}
void 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);
}

View File

@@ -0,0 +1,9 @@
#include <rewindow/types/gamepadbutton.h>
bool GamepadButton::operator==(const GamepadButton &rhs) const {
return this->GetMnemonicButtonCode() == rhs.GetMnemonicButtonCode();
}
void GamepadThumbstick::SetDeadzone(float minimum) const {
}

46
src/types/key.cpp Normal file
View File

@@ -0,0 +1,46 @@
#include <rewindow/types/key.h>
//#include <rewindow/logger.h>
//std::vector<Key> Key::keyboard = {};
std::vector<Key> Key::GetKeyboard() { return keyboard; }
Key::Key() {
keyboard.push_back(*this);
}
Key::Key(const char* charcode, X11Scancode scancode, WindowsScancode sc)
: CharCode(charcode), x11ScanCode(scancode), winScanCode(sc)
{
//TODO doing this is what crashes the program.
keyboard.push_back(*this);
}
bool Key::operator==(const Key &rhs) const {
//This is not a good workaround.
return (this->x11ScanCode == rhs.x11ScanCode);
}
bool Key::operator<(const Key &rhs) const {
return (this->CharCode < rhs.CharCode);
}
Key GetKeyFromX11Scancode(X11Scancode code) {
for (const auto& key : Key::GetKeyboard())
if (key.x11ScanCode == code)
return key;
std::cout << "Unavaliable Scancode: " + std::to_string((int)code) << std::endl;
return Keys::Space;
}
Key GetKeyFromWindowsScancode(WindowsScancode code) {
for (const auto& key : Key::GetKeyboard())
if (key.winScanCode == code)
return key;
std::cout << "Unavaliable Scancode: " + std::to_string((int) code) << std::endl;
return Keys::Space;
}

33
src/types/mousebutton.cpp Normal file
View File

@@ -0,0 +1,33 @@
#include <rewindow/types/mousebutton.h>
#include <string>
#include "rewindow/logger/logger.h"
MouseButton::MouseButton() {
}
MouseButton::MouseButton(const char* charcode, unsigned int index) {
this->CharCode = charcode;
this->ButtonIndex = index;
}
bool MouseButton::operator==(const MouseButton &mb) const {
return (mb.ButtonIndex == this->ButtonIndex);
}
MouseButton GetMouseButtonFromXButton(unsigned int button) {
switch(button) {
case 1: return MouseButtons::Left;
case 2: return MouseButtons::Middle;
case 3: return MouseButtons::Right;
case 4: return MouseButtons::MWheelUp;
case 5: return MouseButtons::MWheelDown;
//For *whatever* reason. These aren't in X.h
case 8: return MouseButtons::Mouse4;
case 9: return MouseButtons::Mouse5;
default: {
ReWindow::Logger::Fatal("Undefined XButtonCode: " + std::to_string((int) button));
return MouseButtons::Unimplemented;
}
}
}

View File

View File

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