Compare commits

..

223 Commits

Author SHA1 Message Date
74fc93c4e1 Merge pull request 'Make WindowProc a static member, so we can hide processEvent...() methods.' (#29) from protect-events into main
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m21s
Reviewed-on: #29
2025-07-13 19:12:16 -04:00
f75825eb28 Make WindowProc a static member, so we can hide processEvent...() methods.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m41s
2025-07-13 18:11:07 -05:00
99a5978448 Fixed window sizing issue on Windows.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m52s
2025-07-12 18:48:31 -04:00
3862fb602f WIndows fix bug in RestoreFromFullscreen
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m39s
2025-07-12 18:14:16 -04:00
13dfa1216d Linux Fullscreen Graphics Mode
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m47s
2025-07-12 17:21:30 -04:00
bc59e49402 SetCursorPosition Windows
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m36s
2025-07-12 17:08:37 -04:00
ac9512ef1d Cleanup
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m54s
2025-07-12 16:55:26 -04:00
87f862730b SetCursorFocused Windows
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m28s
2025-07-08 16:08:33 -04:00
bb776026ad SetCursorCenter Windows
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m50s
2025-06-29 19:44:33 -04:00
42deab60f4 XWindows SetCursorCenter & SetCursorFocused
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m50s
2025-06-15 16:38:04 -04:00
199642b1a9 Windows KeyRepeat
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m30s
2025-06-07 11:11:57 -04:00
c354b1deef std::pair
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m50s
2025-06-06 09:56:34 -04:00
c3c6a29dc6 XWindows KeyRepeat toggle
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m56s
2025-06-06 09:36:29 -04:00
f7d39b0174 Fix obscure ternary operator order, which somehow got missed for months.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m30s
2025-06-04 13:49:47 -05:00
f3cd2b6d82 Add return to VulkanWindow::GetGraphicsDriverVendor() to suppress warning.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m42s
This does need to be properly implemented, however.
2025-06-04 04:26:40 -04:00
ca459af9b1 Update OpenGLWindow.cpp
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m58s
Fix for our window not showing up in the window list on some floating window managers.
2025-05-29 11:47:34 -04:00
ffdafedb94 Fix OnClose not being called on Windows. Still doesn't work correctly on Linux (Are we handling the XEvent?)
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m35s
2025-05-22 17:25:38 -05:00
aebc6fcfd3 Fixed Windows MouseWheel Event being +120 or -120, we want +1 or -1
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m7s
2025-03-08 16:05:08 -05:00
0ba3618b3c Update OpenGLWindow.cpp
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m25s
Fixed a case where on some distros the OpenGL shared object is called something different.
2025-01-31 00:46:56 -05:00
778166c23f Cleanup
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m15s
2025-01-30 19:33:48 -05:00
8d4db443bd Get rid of the need for SetFlag
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m17s
2025-01-30 18:48:38 -05:00
0cfd66eb40 Fix Markdown error.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m52s
2025-01-30 12:50:30 -05:00
c18fca517f Merge remote-tracking branch 'origin/josh-patch-1'
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m23s
2025-01-30 12:48:37 -05:00
515d428168 RWindow::IsVisible Windoze
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m33s
2025-01-30 00:43:05 -05:00
a77a8a3754 RWindow::IsVisible
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m23s
2025-01-29 22:34:00 -05:00
3fd2a8ce14 Update windows/Window.cpp
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m22s
On windows everything will be in the same cpp because their event loop is bad.
2025-01-29 13:01:52 -05:00
ffeb4a99e0 Update README.md
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m22s
2025-01-29 06:56:32 -05:00
d6c4c0b0f5 Shafted by Billy G again.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m58s
2025-01-29 02:53:51 -05:00
83d23eb3f4 RWindow::MessageBox
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 3m55s
2025-01-29 01:41:21 -05:00
c0ee42b782 RWindow::Flash windows.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m27s
2025-01-28 18:40:46 -05:00
1fec28b373 RWindow::Flash
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m41s
2025-01-28 18:00:12 -05:00
8f8f3304ba Update Window.cpp
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m52s
Get rid of the use of System to turn key repeat back on

*It was necessary before because of design shortcomings that seem to have been fixed*
2025-01-28 17:35:14 -05:00
d657315bab SoftwareRendered bool
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m23s
2025-01-28 10:45:53 -05:00
47a9340eff Remove the need to link to opengl32.dll directly.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m17s
2025-01-27 17:08:51 -05:00
7593c5f2c7 Fix for windows.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m33s
2025-01-27 11:55:19 -05:00
85d84c2828 Dirty trick to not expose platform specific variables.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m2s
2025-01-27 11:40:26 -05:00
3d5fdbc9c6 Cleanup & incomplete Vulkan.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m31s
2025-01-26 22:47:41 -05:00
ff8fee6e90 Fix for Windows.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m19s
2025-01-26 20:08:03 -05:00
3c4777c525 Update Window.h
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m30s
2025-01-26 15:21:13 -05:00
Redacted
9707981cfd Update README.md
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m30s
2025-01-26 01:51:47 -05:00
Redacted
3b8763863a Update reci/scripts/builddeps.reci
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m26s
2025-01-26 01:49:00 -05:00
Redacted
bf7351ac8e Update .gitea/workflows/buildtest.yml
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
2025-01-26 01:48:41 -05:00
a627b22ecb Improve compatability.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m18s
Resolve functions we use for OpenGL at runtime so if your PC doesn't support that renderer you could still use a different one.
2025-01-26 01:37:17 -05:00
1062b471b2 Allow the user to specify the OpenGL version they want.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m23s
2025-01-26 00:34:56 -05:00
abff453347 Refactor to better support more rendering apis
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m39s
2025-01-26 00:17:48 -05:00
8472bf754c Remove J3ML.
J3ML was only *really* used for pair of int or pair of float. So it was kindof a waste to bring in all of J3ML just for that. Took it out.
2025-01-25 21:57:54 -05:00
e39881f2dc update RWindow::Open
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m0s
Create the OpenGL Context without the debug flag if the system supports it (big performance gain)
2025-01-18 13:06:15 -05:00
830dd954a2 Fix for Windows.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m52s
2025-01-15 22:58:20 -05:00
e764dcf5b8 Update to latest J3ML
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m34s
2025-01-10 19:54:16 -05:00
4b8479f1d3 Remove unused include
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m58s
2025-01-10 19:52:03 -05:00
f79164f89b Boilerplate clipboardservice namespace.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m50s
2025-01-09 01:12:22 -05:00
a2ef397bdb Merge remote-tracking branch 'origin/main'
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m57s
2025-01-07 18:03:27 -05:00
6fd30ff25b Fixed subtle error with MouseButtonDownEvent. 2025-01-07 18:03:21 -05:00
8d8e14ef40 Refactor InputService to separate header file.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m32s
2024-12-11 15:16:21 -06:00
ee408c2fe6 Merge remote-tracking branch 'origin/main'
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m44s
2024-12-11 11:03:47 -06:00
f50280824d Add inputservice.hpp 2024-12-11 11:03:34 -06:00
74d5f13c06 Temporary Input namespace which will become part of ReInput subproject later.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m54s
2024-12-11 01:36:56 -05:00
1950aee948 Further cleanup (Not stable), WIP RenderingAPI refactor, WIP windows fixes.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
2024-12-06 15:22:04 -05:00
2d9f7e08b0 Refactored window finalization logic.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m6s
2024-12-06 13:14:20 -05:00
561e806b5f Merge remote-tracking branch 'origin/main'
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m41s
2024-12-06 11:54:25 -05:00
fa807256af Actually Fixed IsKeyDown 2024-12-06 11:54:19 -05:00
b10a4d1d39 gamepad stuff
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m4s
2024-12-04 10:16:54 -05:00
a3adbb6266 Fix Mouse Button errors, implement MouseWheel events
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m42s
2024-12-03 21:24:50 -05:00
b75f44f1ee Fix IsMouseButtonDown infinite loop
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m39s
2024-12-03 19:39:58 -05:00
e4e860564c Fix RWindow::SetResizable on linux/X-server
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m38s
2024-12-03 19:19:51 -05:00
fb6825224f Fix RWindow::SetResizable on linux/X-server 2024-12-03 19:16:43 -05:00
6b9bf4c2cc Update window.cpp
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m0s
fix the types not being convertable on loonix
2024-12-01 17:36:56 -05:00
f25370cada Make it atleast start on Windows again.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m53s
TODO fix the mouse buttons and keyboard input. They currently segfault the program.
2024-12-01 22:31:08 -05:00
f826b2a268 Other Minor Edits
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 6m14s
2024-11-04 11:56:13 -05:00
5dfa0fe114 Additional Commentary
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m33s
2024-11-01 15:44:06 -04:00
216b7218e6 Try and fix conflicts
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m11s
2024-11-01 14:12:39 -04:00
dc466e695f Merge remote-tracking branch 'origin/main'
# Conflicts:
#	include/rewindow/types/window.h
#	src/platform/shared/window.cpp
2024-11-01 14:08:46 -04:00
a4322c4b21 Refactoring RWindow class to support usage in ReCaveGame 2024-11-01 14:01:58 -04:00
db63cc2272 Update window.cpp
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 3m25s
2024-10-14 21:37:44 -04:00
1d9424a243 Merge branch 'main' of https://git.redacted.cc/Redacted/ReWindow
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
2024-10-14 21:24:22 -04:00
2e0d84d559 getGraphicsDriverVendor 2024-10-14 21:24:20 -04:00
cc2cc6f7c1 Fix build error, migrate to new event delegation system.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 4m43s
2024-10-11 11:39:39 -04:00
fb6ed84b76 Update to newest J3ML
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m40s
2024-10-10 12:21:53 -04:00
Redacted
3085ad21a9 Update .gitea/workflows/buildtest.yml
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m28s
2024-10-04 23:32:02 -04:00
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
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
36 changed files with 3213 additions and 399 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 libxrandr-dev libvulkan-dev && 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,5 +1,5 @@
cmake_minimum_required(VERSION 3.20)
project(ReWindowLibrary
cmake_minimum_required(VERSION 3.18..3.27)
project(ReWindow
VERSION 1.0
LANGUAGES CXX
)
@@ -10,37 +10,73 @@ 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)
find_package(OpenGL REQUIRED)
include_directories({$OPENGL_INCLUDE_DIRS})
include(cmake/CPM.cmake)
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
)
#TODO dlopen these at runtime so if one isn't supported the program still works.
if (UNIX AND NOT APPLE)
include_directories(${Vulkan_INCLUDE_DIR})
endif()
if (WIN32)
include_directories(${VULKAN_SDK}/Include)
endif()
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/ReWindow/*.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/ReWindow/*.cpp")
endif()
include_directories("include")
add_library(ReWindowLibrary SHARED ${SOURCES})
# Why god???
set_target_properties(ReWindowLibrary PROPERTIES LINKER_LANGUAGE CXX)
if(UNIX AND NOT APPLE)
target_link_libraries(ReWindowLibrary PUBLIC X11 ${OPENGL_LIBRARIES})
add_executable(ReWindowLibraryDemo main.cpp)
target_link_libraries(ReWindowLibraryDemo PUBLIC ReWindowLibrary)
if(UNIX)
add_library(ReWindow SHARED ${SOURCES})
endif()
if(WIN32)
endif()
add_library(ReWindow STATIC ${SOURCES})
endif()
target_include_directories(ReWindow PUBLIC ${Event_SOURCE_DIR}/include)
# Why god???
set_target_properties(ReWindow PROPERTIES LINKER_LANGUAGE CXX)
if(UNIX AND NOT APPLE)
target_link_libraries(ReWindow PUBLIC X11 Event jlog)
target_link_libraries(ReWindow PUBLIC)
add_executable(ReWindowDemo main.cpp)
target_link_libraries(ReWindowDemo PUBLIC ReWindow)
endif()
if(WIN32)
target_compile_options(ReWindow PUBLIC /utf-8)
target_link_libraries(ReWindow PUBLIC Event jlog)
add_executable(ReWindowDemo main.cpp)
target_link_libraries(ReWindowDemo PUBLIC ReWindow)
endif()

View File

@@ -1,33 +1,48 @@
# ReWindow
[![License: Unlicense](https://img.shields.io/badge/license-Unlicense-blue.svg)](http://unlicense.org/)
A library which allows easily creating and managing a window and it's events across multiple platforms *primarily for games*.
## Run Demo
Install dependencies
```bash
dnf install cmake make gcc-g++ libX11 libX11-devel
```
Clone the repository
```bash
git clone https://git.redacted.cc/Redacted/ReWindow.git
```
Build
```bash
cd ReWindow && mkdir build && cd build && cmake .. && make
```
Run it
```bash
./ReWindowDemo
```
# ReWindow
[![License: Unlicense](https://img.shields.io/badge/license-Unlicense-blue.svg)](http://unlicense.org/)
A library which allows easily creating and managing a window and it's events across multiple platforms *primarily for games*.
## Features
- Window Creation - Create multiple windows at once. Windows can also create so-called `message-boxes`, which are technically windows too.
- Window Management - Change the state of the window, title, size, fullscreen mode, v-sync, and more.
- Window Events - Callback function hooks for reading user-input and window state events, such as exit, focus, etc.
- State of the Art C++20
- Supported Platforms: X11 on Linux, Windows
- Builds on ARM.
- One API supports all platforms.
- Supports OpenGL, Vulkan, Software Rendering(?)
- Public Domain.
- Lightweight AF.
- Painless integration with \<your favorite graphics API\>. (Ours is JGL!)
- Straightforward, well-documented source code and API.
- Packaged with InputService as a built-in, portable input API.
## Run Demo
Install dependencies
```bash
Fedora/RHEL: dnf install cmake make gcc-g++ libX11 libX11-devel mesa-libGL-devel vulkan-loader-devel
Ubuntu/Debian: apt-get install cmake make gcc g++ libx11-6 libx11-dev libgl-dev libvulkan-dev libxrandr-dev
```
Clone the repository
```bash
git clone https://git.redacted.cc/Redacted/ReWindow.git
```
Build
```bash
cd ReWindow && mkdir build && cd build && cmake .. && make
```
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,10 @@
#pragma once
/// X11 Clipboard API looked unhinged. So fuck it, use this system for now.
namespace ClipboardService
{
std::string GetClipboard(int historyIndex = 0);
void SetClipboard(const std::string& str, bool overwrites_last = false);
unsigned int GetClipboardHistorySize();
unsigned int GetClipboardHistoryMax();
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include <Event.h>
#include <ReWindow/types/WindowEvents.h>
namespace InputService {
using namespace ReWindow;
inline Event<KeyboardEvent> OnKeyboardEvent;
inline Event<KeyboardEvent> OnKeyEvent;
inline Event<KeyDownEvent> OnKeyDown;
inline Event<KeyUpEvent> OnKeyUp;
inline Event<MouseMoveEvent> OnMouseEvent;
inline Event<MouseButtonEvent> OnMouseButtonEvent;
inline Event<MouseMoveEvent> OnMouseMove;
inline Event<MouseButtonDownEvent> OnMouseDown;
inline Event<MouseButtonUpEvent> OnMouseUp;
inline Event<MouseWheelEvent> OnMouseWheel;
bool IsKeyDown(const Key& key);
bool IsMouseButtonDown(const MouseButton& button);
std::pair<int, int> GetMousePosition();
std::pair<int, int> GetWindowSize();
};

13
include/ReWindow/Logger.h Normal file
View File

@@ -0,0 +1,13 @@
#pragma once
#include <jlog/Logger.hpp>
namespace ReWindow::Logger {
using namespace jlog;
extern GenericLogger Info;
extern GenericLogger Fatal;
extern GenericLogger Error;
extern GenericLogger Warning;
extern GenericLogger Debug;
}

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,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,154 @@
//
// ~DAWSH
#pragma once
#include <vector>
#include <stdexcept>
#include <iostream>
#include <string>
#include <ReWindow/data/X11Scancodes.h>
#include <ReWindow/data/WindowsScancodes.h>
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() = default;
Key(const char* charcode, X11Scancode scancode, WindowsScancode wSc);
std::string Mnemonic;
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};
}
enum class KeyState {Pressed, Released};
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,46 @@
/// 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
#include <string>
class MouseButton {
public:
std::string Mnemonic;
unsigned int ButtonIndex;
MouseButton() = default;
explicit MouseButton(const std::string& charcode, unsigned int index);
bool operator == (const MouseButton& mb) const;
bool operator<(const MouseButton& rhs) const;
MouseButton(const MouseButton&) = default;
};
namespace MouseButtons
{
static const MouseButton Left ("L", 1);
static const MouseButton Right ("R", 2);
static const MouseButton Middle ("M", 3);
static const MouseButton Mouse4 ("4", 8);
static const MouseButton Mouse5 ("5", 9);
static const MouseButton Unimplemented ("?", 0);
/// NOTE: IsMouseButtonDown will not return correctly for the mouse-wheel-buttons, because the action is effectively instantaneous.
static const MouseButton MWheelUp ("U", 4);
/// NOTE: IsMouseButtonDown will not return correctly for the mouse-wheel-buttons, because the action is effectively instantaneous.
static const MouseButton MWheelDown ("D", 5);
}
MouseButton GetMouseButtonFromXButton(unsigned int button);

View File

@@ -0,0 +1,407 @@
#pragma once
#include <cstdint>
#include <vector>
#include <Event.h>
#include <map>
#include <thread>
#include <ReWindow/types/Key.h>
#include <ReWindow/types/Cursors.h>
#include <ReWindow/types/MouseButton.h>
#include <ReWindow/types/WindowEvents.h>
#include <queue>
#include <Windows.h>
namespace ReWindow {
struct KeyboardState { std::map<Key, bool> PressedKeys; };
class MouseState;
class RWindow;
class OpenGLWindow;
class VulkanWindow;
}
class ReWindow::MouseState {
public:
struct
{
bool LMB = false;
bool RMB = false;
bool MMB = false;
bool SideButton1 = false;
bool SideButton2 = false;
bool MWheelUp = false;
bool MWheelDown = false;
}
Buttons;
std::pair<int, int> Position;
int Wheel = 0;
public:
[[nodiscard]] bool IsDown(const MouseButton& btn) const;
void Set(const MouseButton& btn, bool state);
bool& operator[](const MouseButton& btn);
};
/// RWindow is a class implementation of a platform-independent window abstraction.
/// This library also provides abstractions for user-input devices, and their interaction with the window.
class ReWindow::RWindow {
protected:
class Platform;
Platform* platform;
inline static RWindow* extant;
int width = 640;
int height = 480;
bool open = false; // Is the underlying OS-Window-Handle actually open.
bool closing = false;
bool resizable = true;
bool fullscreen_mode = false;
bool focused = true;
bool vsync = false;
bool cursor_visible = true;
bool cursor_focused = false;
bool toggling_cursor_focus = false;
bool key_repeat = false;
float delta_time = 0.f;
float refresh_rate = 0.f;
unsigned long long refresh_count = 0;
std::string title = "Redacted Window";
std::vector<RWindowEvent> eventLog; // history of all logged window events.
std::queue<RWindowEvent> eventQueue; //
MouseState currentMouse; // purrent frame mouse state.
MouseState previousMouse; // previous frame mouse state
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;
/// Returns the most accurate and recent available mouse coordinates relative to the top left corner of the renderable area (not including the title bar).
/// @note Call this version at most **once** per-frame. It polls the X-Window server and therefore is quite slow.
/// @see getCursorPos();
[[nodiscard]] std::pair<int, int> GetAccurateCursorCoordinates() const;
protected:
void LogEvent(const RWindowEvent& e) { eventLog.push_back(e); }
//void EnqueueEvent(const RWindowEvent& e) { eventQueue.push(e);}
[[nodiscard]] RWindowEvent GetLastEvent() const { return eventLog.back(); }
/// Requests the operating system to make the window fullscreen. Saves the previous window size as well.
void Fullscreen();
/// Requests the operating system to take the window out of fullscreen mode. Previously saved window size is restored, if possible.
void RestoreFromFullscreen();
public:
KeyboardState currentKeyboard; // current frame keyboard state.
KeyboardState previousKeyboard; // previous frame keyboard state.
/// The default constructor does not set any members, and are left uninitialized.
RWindow();
/// Constructs a window by explicitly setting the title, width, height, and optionally; rendering API, fullscreen, resizable, and vsync.
/// @param wTitle The window title text.
/// @param wWidth
/// @param wHeight
/// @param wFullscreen
/// @param wResizable
/// @param wVsync
explicit RWindow(const std::string& wTitle, int wWidth = 640, int wHeight = 480,
bool wFullscreen = false, bool wResizable = true, bool wVsync = false);
/// The destructor deallocates and cleans up any memory used by the RWindow program.
/// @note If the window handle is not already destroyed, it will be done here.
virtual ~RWindow();
static RWindow* GetExtant() { return extant; };
/// Bindables are provided for hooking into window instances conveniently, without the need to derive and override for simple use cases.
Event<> OnOpenEvent;
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;
Event<MouseWheelEvent> OnMouseWheelEvent;
/// These methods can also be overridden in derived classes.
/// Called upon the window requesting to open.
virtual void OnOpen() {}
/// Called right before the window closes.
virtual void OnClosing() {}
/// Called when the window loses focus.
virtual void OnFocusLost(const RWindowEvent& e) {}
/// Called when the window gains focus.
virtual void OnFocusGain(const RWindowEvent& e) {}
/// Called when the window is 'refreshed', in other words, a render pass is completed.
virtual void OnRefresh(float elapsed) {}
/// Called when a resize request has succeeded.
virtual void OnResizeSuccess() {}
/// Called when a resize request is sent to the operating system.
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&) {}
virtual void OnMouseWheel(const MouseWheelEvent&) {}
[[nodiscard]] int GetMouseWheelPersistent() const { return currentMouse.Wheel; }
[[nodiscard]] bool IsOpen() const { return open; }
/// Returns whether the window is currently visible to the user.
// TODO On Linux, Some desktop environments don't always do this when switching workspaces.
[[nodiscard]] bool IsVisible() const;
[[nodiscard]] bool IsClosing() const { return closing; }
/// Returns whether the window currently has mouse and/or keyboard focus.
[[nodiscard]] bool IsFocused() const;
/// Returns whether the window is currently in Fullscreen.
// TODO: Support Fullscreen, FullscreenWindowed, and Windowed?
[[nodiscard]] bool IsFullscreen() const;
/// Returns whether the window can be resized.
[[nodiscard]] bool IsResizable() const;
/// Returns whether V-Sync is enabled.
[[nodiscard]] bool IsVsyncEnabled() const;
/// Returns whether the window is considered to be alive. Once dead, any logic loop should be terminated, and the cleanup procedure should run.
[[nodiscard]] bool IsAlive() const;
/// Returns whether the given key is currently being pressed.
[[nodiscard]] bool IsKeyDown(Key key) const;
/// Returns whether the given mouse button is currently being pressed.
[[nodiscard]] bool IsMouseButtonDown(const MouseButton& button) const;
[[nodiscard]] float GetDeltaTime() const;
/// Returns the approximate frames-per-second using delta time.
[[nodiscard]] float GetRefreshRate() const;
/// Returns the number of frames ran since the windows' creation.
[[nodiscard]] unsigned long long GetRefreshCount() const;
/// Cleans up and closes the window object.
void Close();
/// Closes the window immediately, potentially without allowing finalization to occur.
void ForceClose();
/** Display a small window with some text and an "OK" button.
* I tried un-defining the macro, Calling it in a lambda,
* Calling MessageBoxA, Putting the call to the MessageBox
* function in its own namespace and then calling that.
* It just wouldn't let me name it MessageBox - Redacted. */
/// @note Execution of the parent window is stopped while the message box is up.
void DialogOK(const std::string& title, const std::string& message);
/// Sets whether the window is fullscreen.
void SetFullscreen(bool fs);
/// Sets whether the window can be resized by the user.
/// @note Resize events will still be sent if fullscreen is toggled.
void DisableResizing();
/// Sets the title of this window.
void SetTitle(const std::string& title);
[[nodiscard]] std::string GetTitle() const;
/// Returns the horizontal length of this window, in pixels.
[[nodiscard]] int GetWidth() const;
/// Returns the vertical length of this window, in pixels.
[[nodiscard]] int GetHeight() const;
/// This is unfortunately here because of the poor design of windows. Maybe once interfaces are done this won't be required anymore.
void SetSizeWithoutEvent(const std::pair<int, int>& size);
/// Tells the underlying window manager to destroy this window and drop the handle.
/// The window, in theory, can not be re-opened after this.
void DestroyOSWindowHandle();
/// Reads events from the operating system, and processes them accordingly.
/// TODO: Move out of public API, consumers should call Refresh or ideally an update() call.
void PollEvents();
/// Updates internal window state, similar to ManagedRefresh, but without accounting for any timekeeping. This is left up to the user.
void Refresh();
/// Updates the window and handles timing internally.
void ManagedRefresh();
/// Requests the operating system to change the window size.
/// @param width
/// @param height
void SetSize(int width, int height);
/// Requests the operating system to change the window size.
/// @param size
void SetSize(const std::pair<int, int>& size);
/// Returns the position of the window's top-left corner relative to the display
[[nodiscard]] std::pair<int, int> GetPosition() const;
/// Returns the known size of the window, in {x,y} pixel measurement.
[[nodiscard]] std::pair<int, int> GetSize() const;
/// Requests the operating system to move the window to the specified coordinates on the display.
/// @param x The horizontal screen position to place the window at.
/// @param y The vertical screen position to place the window at.
void SetPosition(int x, int y);
/// Requests the operating system to move the window to the specified coordinates on the display.
/// @param pos A std::pair<int, int> representing the x,y coordinates of the desired window destination. Fractional values are ignored.
void SetPosition(const std::pair<int, int>& pos);
/// Pull the window to the top, such that it is displayed on top of everything else.
/// NOTE: The implementation is defined per-OS, and thus there is no guarantee of it always working.
void Raise();
/// Push the window Lower, such that it is effectively hidden behind other windows.
/// NOTE: The implementation is defined per-OS, and thus there is no guarantee of it always working.
void Lower();
// TODO verify functionality if the cursor is invisible.
void SetCursorStyle(CursorStyle style) const;
void SetCursorCustomIcon() const;
/// @returns Where the cursor was just before we teleported it to the center.
/// @note You should check if our window is in focus before doing this.
/// @note This is useful for 3D games.
std::pair<int, int> SetCursorCenter();
/// Set the position of the cursor relative to the top-left corner of the renderable area.
/// @returns False if the cursor could not be guaranteed to be teleported.
/// @note our window *must* be visible and in focus.
/// @note Moving the cursor outside our window is unsupported.
/// @note Doesn't update where the mouse is observed for this refresh.
[[nodiscard]] bool SetCursorPosition(const std::pair<int, int>& position);
[[nodiscard]] bool SetCursorPosition(int x, int y);
/// Tells the operating system to not allow the cursor to go off our window.
/// @note This is useful for 3D games.
void SetCursorFocused(bool state);
/// Hides the cursor when it's inside our window.
/// @note This is useful for 3D games.
void SetCursorVisible(bool cursor_enable);
/// @returns Whether the cursor is visible.
bool GetCursorVisible();
/// @returns Whether the cursor is focused (cannot go off of our window).
/// @note Delayed until the next time our window is in focus.
bool GetCursorFocused();
/// Returns an std::pair<int, int> representing mouse coordinates relative to the top-left corner of the window.
/// This result is cached from the operating-system each time poll events is called.
/// @see GetAccurateMouseCoordinates().
[[nodiscard]] std::pair<int, int> GetCursorPosition() const;
/// Returns the current time, represented as a high-resolution std::chrono alias.
static std::chrono::steady_clock::time_point GetTimestamp();
/// Computes elapsed time from a start-point and end-point.
float ComputeElapsedFrameTimeSeconds(std::chrono::steady_clock::time_point start, std::chrono::steady_clock::time_point end);
/// Updates internals to account for the latest calculated frame time.
void UpdateFrameTiming(float frame_time);
#ifdef WIN32
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif
protected:
/// These unfortunately *have* to be public because of the poor design of the windows event loop.
void processKeyRelease(Key key);
void processKeyPress(Key key);
/// @note This will be invoked **before** the window-close procedure begins.
void processOnClose();
/// @note This will be invoked **after** the window-open procedure completes.
void processOnOpen();
void processMousePress(const MouseButton& btn);
void processMouseRelease(const MouseButton& btn);
void processFocusIn();
void processFocusOut();
void processMouseMove(const std::pair<int, int>& last_pos, const std::pair<int, int>& new_pos);
void processMouseWheel(int scrolls);
/// Virtual functions which *must* be overridden based on the Renderer.
public:
virtual void SwapBuffers() = 0;
/// Sets whether vertical sync is enabled.
/// @note This is implemented per-OS, and as such, it simply requests the OS to do what we want. No guarantee about follow-through can be given.
virtual void SetVsyncEnabled(bool state) = 0;
/// Sets whether we're using key repeat.
void SetKeyRepeatEnabled(bool state);
/// @returns If key repeat is enabled.
[[nodiscard]] bool IsKeyRepeat() const { return key_repeat; };
/// Returns the name of the developer of the user's graphics driver, if it can be determined.
virtual std::string GetGraphicsDriverVendor() = 0;
/// This function instructs the operating system to create the actual window, and give it to us to control.
/// Calling this function, therefore, creates the real 'window' object on the operating system.
[[nodiscard]] virtual bool Open() = 0;
/// Bring attention to the user, On X11 this flashes the entry for this window in the window list.
/// @note If the window is already in focus when this is called nothing happens.
void Flash();
/// @returns True if we are definitely running on a software renderer.
/// @note For some APIs this isn't typically possible.
[[nodiscard]] virtual bool SoftwareRendered() { return false; }
};
// TODO Set flags in window constructor.
class ReWindow::OpenGLWindow : public RWindow {
protected:
uint8_t gl_major, gl_minor;
public:
void SwapBuffers() override;
void SetVsyncEnabled(bool state) override;
std::string GetGraphicsDriverVendor() override;
[[nodiscard]] bool Open() override;
[[nodiscard]] bool SoftwareRendered() override;
public:
OpenGLWindow(const std::string& title, int width, int height, uint8_t gl_major, uint8_t gl_minor);
};
class ReWindow::VulkanWindow : public RWindow {
public:
void SwapBuffers() override;
void SetVsyncEnabled(bool state) override;
std::string GetGraphicsDriverVendor() override;
[[nodiscard]] bool Open() override;
VulkanWindow(const std::string& title, int width, int height);
};

View File

@@ -0,0 +1,97 @@
#pragma once
#include <chrono>
#include <ReWindow/types/Key.h>
#include <ReWindow/types/MouseButton.h>
namespace ReWindow {
using namespace std::chrono_literals;
using precision_clock = std::chrono::high_resolution_clock;
using precision_timestamp = precision_clock::time_point;
class TimestampedEvent {
public:
precision_timestamp Timestamp;
explicit TimestampedEvent(precision_timestamp timestamp) : Timestamp(timestamp) {}
TimestampedEvent() : Timestamp(precision_clock::now())
{ }
};
class RWindowEvent : public TimestampedEvent {
public:
RWindowEvent() : TimestampedEvent() { }
};
class InputDeviceEvent : public RWindowEvent {
public:
InputDeviceEvent() : RWindowEvent() { }
};
class KeyboardEvent : public InputDeviceEvent {
public:
Key key;
KeyState state;
KeyboardEvent(const Key& key, KeyState state) : InputDeviceEvent(), key(key), state(state) {}
};
class MouseEvent : public InputDeviceEvent {};
class GamepadEvent : public InputDeviceEvent {};
class MouseButtonEvent : public MouseEvent {
public:
MouseButton Button;
bool Pressed; // TODO: replace with MouseButtonState enum
MouseButtonEvent() = default;
MouseButtonEvent(const MouseButton& button, bool pressed) : MouseEvent(), Button(button), Pressed(pressed) {}
};
class MouseButtonDownEvent : public MouseButtonEvent {
public:
MouseButtonDownEvent() = default;
explicit MouseButtonDownEvent(const MouseButton& button) : MouseButtonEvent(button, true) {}
};
class MouseButtonUpEvent : public MouseButtonEvent {
public:
MouseButtonUpEvent() = default;
explicit MouseButtonUpEvent(const MouseButton& button) : MouseButtonEvent(button, false) {}
};
class MouseMoveEvent : public MouseEvent {
public:
std::pair<int, int> Position;
std::pair<int, int> Delta;
MouseMoveEvent(const std::pair<int, int> &pos) : MouseEvent(), Position(pos)
{}
MouseMoveEvent(int x, int y) : MouseEvent(), Position(std::pair<int, int>(x, y))
{}
};
class KeyDownEvent : public KeyboardEvent {
public:
explicit KeyDownEvent(const Key& key) : KeyboardEvent(key, KeyState::Pressed) {}
};
class KeyUpEvent : public KeyboardEvent {
public:
explicit KeyUpEvent(const Key& key) : KeyboardEvent(key, KeyState::Released) {}
};
class MouseWheelEvent : public MouseEvent
{
public:
int WheelMovement;
MouseWheelEvent() = default;
MouseWheelEvent(int wheel) : MouseEvent(), WheelMovement(wheel) {}
};
class WindowResizeRequestEvent : public MouseButtonEvent
{
public:
std::pair<int, int> Size;
};
}

View File

@@ -1,50 +0,0 @@
#pragma once
#include <cstdint>
#include <vector>
#include <memory>
#include "event.h"
#if __linux__
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/gl.h>
#include <GL/glx.h>
#endif
enum class RWindowFlags: uint8_t {
IN_FOCUS = 0,
FULLSCREEN = 1,
RESIZABLE = 2,
VSYNC = 3
};
enum class RenderingAPI: uint8_t {
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) {}
};

View File

@@ -1,27 +1,78 @@
#include <iostream>
#include "include/rewindow/types/window.h"
int main() {
auto* window = new(RWindow);
window->init(RenderingAPI::OPENGL, "name",1152,864, false);
window->setFlag(RWindowFlags::RESIZABLE, false);
int i;
while (true) {
if (i <= 10)
window->pollEvents();
window->glSwapBuffers();
i++;
std::cout << i << std::endl;
if (window->keyDown(SCANCODE::A)) {
std::cout << "A" << std::endl;
std::cout << (int64_t) window->getEvent(SCANCODE::A).empty() << 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);
#include <ReWindow/types/Window.h>
#include <ReWindow/Logger.h>
using namespace ReWindow;
std::ostream& operator<<(std::ostream& os, const std::pair<int, int>& v) {
return os << "{" << v.first << ", " << v.second << "}";
}
class MyWindow : public OpenGLWindow {
public:
MyWindow(const std::string& title, int w, int h) : OpenGLWindow(title, w, h, 2, 1) {}
void OnMouseMove(const MouseMoveEvent& e) override {}
void OnKeyDown(const KeyDownEvent& e) override {
if (e.key == Keys::F11)
SetFullscreen(!IsFullscreen());
}
bool OnResizeRequest(const WindowResizeRequestEvent& e) override { return true; }
void OnMouseButtonDown(const MouseButtonDownEvent& e) override { RWindow::OnMouseButtonDown(e); }
void OnMouseButtonUp(const MouseButtonUpEvent& e) override { RWindow::OnMouseButtonUp(e); }
void OnRefresh(float elapsed) override {
if (IsMouseButtonDown(MouseButtons::Left))
std::cout << "Left Mouse Button" << std::endl;
if (IsMouseButtonDown(MouseButtons::Right))
std::cout << "Right Mouse Button" << std::endl;
if (IsMouseButtonDown(MouseButtons::Middle))
std::cout << "Middle Mouse Button" << std::endl;
if (IsMouseButtonDown(MouseButtons::Mouse4))
std::cout << "Mouse4 Mouse Button" << std::endl;
if (IsMouseButtonDown(MouseButtons::Mouse5))
std::cout << "Mouse5 Mouse Button" << std::endl;
SwapBuffers();
}
};
int main() {
auto* window = new MyWindow("Test Window", 600, 480);
Logger::Debug(std::format("New window '{}' created. width={} height={}", window->GetTitle(), window->GetWidth(), window->GetHeight()));
if (window->Open())
Logger::Debug(std::format("Opened window '{}'", window->GetTitle()));
Logger::Debug("TODO: Cannot set flags until after window is open");
window->SetVsyncEnabled(true);
window->DisableResizing();
window->SetKeyRepeatEnabled(false);
Logger::Debug(std::format
(
"Window '{}' flags: IN_FOCUS={} FULLSCREEN={} RESIZEABLE={} VSYNC={} KEY_REPEAT={} QUIT={}",
window->GetTitle(), window->IsFocused(), window->IsFullscreen(), window->IsResizable(),
window->IsVsyncEnabled(), window->IsKeyRepeat(), window->IsClosing())
);
window->OnKeyDownEvent += [&] (KeyDownEvent e) { jlog::Debug(e.key.Mnemonic); };
window->OnMouseButtonDownEvent += [&] (MouseButtonDownEvent e) { jlog::Debug(e.Button.Mnemonic + std::to_string(e.Button.ButtonIndex)); };
window->OnMouseWheelEvent += [&, window] (MouseWheelEvent e) { std::cout << window->GetMouseWheelPersistent() << std::endl; };
while (!window->IsClosing()) {
window->ManagedRefresh();
if (window->IsFocused())
window->SetCursorCenter();
}
delete window;
}

View File

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

View File

@@ -0,0 +1,28 @@
#include <string>
#include <vector>
#include "ReWindow/ClipboardService.h"
std::vector<std::string> clipboard_history;
std::string clipboard;
namespace ClipboardService {
std::string GetClipboard(int historyIndex) {
if (historyIndex > 0) {
return clipboard_history[historyIndex - 1];
}
return clipboard;
}
void SetClipboard(const std::string& str, bool overwrites_last) {
if (!overwrites_last) {
clipboard_history.push_back(clipboard);
}
clipboard = str;
}
}

View File

@@ -0,0 +1,17 @@
#include "ReWindow/InputService.h"
#include "ReWindow/types/Window.h"
namespace InputService
{
bool IsKeyDown(const Key &key) {
return RWindow::GetExtant()->IsKeyDown(key);
}
bool IsMouseButtonDown(const MouseButton &button) {
return RWindow::GetExtant()->IsMouseButtonDown(button);
}
std::pair<int, int> GetMousePosition() {
return RWindow::GetExtant()->GetCursorPosition();
}
std::pair<int, int> GetWindowSize() {
return RWindow::GetExtant()->GetSize();
}
}

11
src/ReWindow/Logger.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include "ReWindow/Logger.h"
namespace ReWindow::Logger {
using namespace jlog;
using namespace Colors;
GenericLogger Info {"ReWindow", GlobalLogFile, Gray, Gray, Gray, Gray};
GenericLogger Fatal {"ReWindow::Fatal", GlobalLogFile, Reds::Crimson, Gray, Gray, Reds::Crimson, White};
GenericLogger Debug {"ReWindow::Debug", GlobalLogFile, Purples::Purple, Gray, Gray, Purples::Purple, White};
GenericLogger Error {"ReWindow::Error", GlobalLogFile, Red, Gray, Gray, Gray};
}

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"
bool vsync = false;
Window window;
XEvent xev;
Display* display = XOpenDisplay(nullptr);
int defaultScreen = DefaultScreen(display);
XVisualInfo* visual;
XSetWindowAttributes xSetWindowAttributes;
XWindowAttributes windowAttributes;
Atom wmDeleteWindow;
XSizeHints hints;
GLXContext glContext;
PFNGLXSWAPINTERVALEXTPROC _glXSwapIntervalEXT = nullptr; //It causes issues if it's named just "glXSwapIntervalEXT".
void RWindow::init(RenderingAPI api, const char* title, int width, int height, bool sync) {
if (api == RenderingAPI::OPENGL) {
xSetWindowAttributes.border_pixel = BlackPixel(display, defaultScreen);
xSetWindowAttributes.background_pixel = BlackPixel(display, defaultScreen);
xSetWindowAttributes.override_redirect = True;
xSetWindowAttributes.event_mask = ExposureMask;
GLint glAttributes[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None};
visual = glXChooseVisual(display, defaultScreen, glAttributes);
glContext = glXCreateContext(display, visual, nullptr, GL_TRUE);
vsync = sync;
xSetWindowAttributes.colormap = XCreateColormap(display, RootWindow(display, defaultScreen), visual->visual,
AllocNone);
window = XCreateWindow(display, RootWindow(display, defaultScreen), 0, 0, width, height, 0, visual->depth,
InputOutput, visual->visual, CWBackPixel | CWColormap | CWBorderPixel | NoEventMask,
&xSetWindowAttributes);
XSelectInput(display, window,
ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
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);
setVsyncEnabled(vsync);
} 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) {
vsync = b;
_glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalEXT");
_glXSwapIntervalEXT(display, window, vsync);
}

View File

@@ -0,0 +1,235 @@
#include <ReWindow/types/Window.h>
#include <ReWindow/Logger.h>
#include <GL/glx.h>
#include <dlfcn.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
using namespace ReWindow;
class ReWindow::RWindow::Platform {
public:
Window window;
XEvent xev;
Display* display;
int defaultScreen;
XVisualInfo* visual;
XSetWindowAttributes xSetWindowAttributes;
XWindowAttributes windowAttributes;
Atom wmDeleteWindow;
Atom windowTypeAtom;
Atom windowTypeUtilityAtom;
XSizeHints hints;
Cursor invisible_cursor = 0;
XWMHints* wm_hints = nullptr;
GLXContext gl_context;
};
void* glx_lib = nullptr;
void* opengl_lib = nullptr;
namespace OpenGL {
bool constructor_success = false;
typedef const GLubyte *(*glGetString_t)(GLenum name);
glGetString_t glGetString = nullptr;
typedef Bool (*glXMakeCurrent_t)(Display *dpy, GLXDrawable drawable, GLXContext ctx);
glXMakeCurrent_t glXMakeCurrent = nullptr;
typedef void *(*glXGetProcAddressARB_t)(const GLubyte *procname);
glXGetProcAddressARB_t glXGetProcAddressARB = nullptr;
typedef void (*glXSwapBuffers_t)(Display *dpy, GLXDrawable drawable);
glXSwapBuffers_t glXSwapBuffers = nullptr;
typedef GLXContext (*glXCreateContext_t)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
glXCreateContext_t glXCreateContext = nullptr;
typedef GLXFBConfig *(*glXChooseFBConfig_t)(Display *dpy, int screen, const int *attribList, int *nItems);
glXChooseFBConfig_t glXChooseFBConfig = nullptr;
typedef XVisualInfo *(*glXGetVisualFromFBConfig_t)(Display *dpy, GLXFBConfig config);
glXGetVisualFromFBConfig_t glXGetVisualFromFBConfig = nullptr;
typedef XVisualInfo *(*glXChooseVisual_t)(Display *dpy, int screen, const int *attribList);
glXChooseVisual_t glXChooseVisual = nullptr;
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
}
// Used to determine if we should force our window to start as floating on tiling window managers.
[[nodiscard]] bool TilingWindowManager() {
const char* xdg_env = std::getenv("XDG_CURRENT_DESKTOP");
const char* session_env = std::getenv("DESKTOP_SESSION");
std::string xdg_current_desktop = xdg_env ? xdg_env : "";
std::string desktop_session = session_env ? session_env : "";
if (xdg_current_desktop == "i3" || desktop_session == "i3")
return true;
return false;
// TODO check for dwm & sway.
}
void OpenGLWindow::SwapBuffers() {
OpenGL::glXSwapBuffers(platform->display,platform->window);
}
void OpenGLWindow::SetVsyncEnabled(bool state) {
auto glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) OpenGL::glXGetProcAddressARB((const GLubyte *) "glXSwapIntervalEXT");
glXSwapIntervalEXT(platform->display, platform->window, state);
}
std::string OpenGLWindow::GetGraphicsDriverVendor() {
return std::string((const char*) OpenGL::glGetString(GL_VENDOR));
}
bool OpenGLWindow::Open() {
bool tiling = TilingWindowManager();
if (!OpenGL::constructor_success)
return false;
platform->display = XOpenDisplay(nullptr);
platform->defaultScreen = DefaultScreen(platform->display);
platform->xSetWindowAttributes.border_pixel = BlackPixel(platform->display, platform->defaultScreen);
platform->xSetWindowAttributes.background_pixel = BlackPixel(platform->display, platform->defaultScreen);
platform->xSetWindowAttributes.event_mask = ExposureMask;
if (tiling)
platform->xSetWindowAttributes.override_redirect = True;
auto glXCreateContextAttribsARB = (OpenGL::glXCreateContextAttribsARBProc) OpenGL::glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB");
XVisualInfo* vi = nullptr;
// Fallback to the old way if you somehow don't have this.
if (!glXCreateContextAttribsARB) {
GLint glAttributes[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None};
platform->visual = OpenGL::glXChooseVisual(platform->display, platform->defaultScreen, glAttributes);
platform->gl_context = OpenGL::glXCreateContext(platform->display, platform->visual, nullptr, GL_TRUE);
platform->window = XCreateWindow(platform->display, RootWindow(platform->display, platform->defaultScreen), 0, 0, width, height, 0, platform->visual->depth,
InputOutput, platform->visual->visual, CWBackPixel | CWColormap | CWBorderPixel | NoEventMask, &platform->xSetWindowAttributes);
Logger::Debug("Created OpenGL Context with glXCreateContext.");
if (!platform->window)
return false;
}
else {
static int visual_attributes[]
{
GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8,
GLX_DOUBLEBUFFER, True, None
};
int fb_count;
GLXFBConfig* fb_configurations = OpenGL::glXChooseFBConfig(platform->display, platform->defaultScreen, visual_attributes, &fb_count);
if (!fb_configurations || fb_count == 0)
return false;
GLXFBConfig best_fbc = fb_configurations[0];
vi = OpenGL::glXGetVisualFromFBConfig(platform->display, best_fbc);
if (!vi)
return false;
platform->xSetWindowAttributes.colormap = XCreateColormap(platform->display, RootWindow(platform->display, vi->screen), vi->visual, AllocNone);
platform->window = XCreateWindow(platform->display, RootWindow(platform->display, vi->screen), 0, 0, width, height, 0, vi->depth, InputOutput,
vi->visual, CWBackPixel | CWColormap | CWBorderPixel, &platform->xSetWindowAttributes);
int context_attributes[] { GLX_CONTEXT_MAJOR_VERSION_ARB, gl_major, GLX_CONTEXT_MINOR_VERSION_ARB, gl_minor, None };
platform->gl_context = glXCreateContextAttribsARB(platform->display, best_fbc, nullptr, True, context_attributes);
XFree(fb_configurations);
Logger::Debug("Created OpenGL Context with glXCreateContextAttribsARB");
}
if (!platform->gl_context)
return false;
if (!OpenGL::glXMakeCurrent(platform->display, platform->window, platform->gl_context))
return false;
if (vi)
XFree(vi);
XSelectInput(platform->display, platform->window, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
PointerMotionHintMask | FocusChangeMask | StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask | VisibilityChangeMask | CWColormap );
XMapWindow(platform->display, platform->window);
XStoreName(platform->display, platform->window, title.c_str());
if (tiling) {
platform->windowTypeAtom = XInternAtom(platform->display, "_NET_WM_WINDOW_TYPE", False);
platform->windowTypeUtilityAtom = XInternAtom(platform->display, "_NET_WM_WINDOW_TYPE_UTILITY", False);
XChangeProperty(platform->display, platform->window, platform->windowTypeAtom, XA_ATOM, 32, PropModeReplace,
(unsigned char *) &platform->windowTypeUtilityAtom, 1);
}
platform->wmDeleteWindow = XInternAtom(platform->display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(platform->display, platform->window, &platform->wmDeleteWindow, 1);
XGetWindowAttributes(platform->display, platform->window, &platform->windowAttributes);
open = true;
processOnOpen();
return true;
}
OpenGLWindow::OpenGLWindow(const std::string& title, int width, int height, uint8_t gl_major, uint8_t gl_minor)
: gl_major(gl_major), gl_minor(gl_minor), RWindow(title, width, height) {
// Try this first.
glx_lib = dlopen("libGLX.so", RTLD_NOLOAD);
opengl_lib = dlopen("libOpenGL.so", RTLD_NOLOAD);
if (!glx_lib)
glx_lib = dlopen("libGLX.so", RTLD_LAZY);
if (!glx_lib)
glx_lib = dlopen("libGLX.so.0", RTLD_LAZY);
if (!opengl_lib)
opengl_lib = dlopen("libGL.so", RTLD_LAZY);
if (!opengl_lib)
opengl_lib = dlopen("libOpenGL.so", RTLD_LAZY);
if (!opengl_lib)
opengl_lib = dlopen("libOpenGL.so.0", RTLD_LAZY);
if (!opengl_lib)
opengl_lib = dlopen("libOpenGL.so.0.0.0", RTLD_LAZY);
if (!opengl_lib)
Logger::Error("libOpenGL.so couldn't be found in your LD_LIBRARY_PATH."),
OpenGL::constructor_success = false;
if (!glx_lib)
Logger::Error("libGLX.so couldn't be found in your LD_LIBRARY_PATH."),
OpenGL::constructor_success = false;
OpenGL::glGetString = (OpenGL::glGetString_t) dlsym(opengl_lib, "glGetString");
OpenGL::glXMakeCurrent = (OpenGL::glXMakeCurrent_t) dlsym(glx_lib, "glXMakeCurrent");
OpenGL::glXGetProcAddressARB = (OpenGL::glXGetProcAddressARB_t) dlsym(glx_lib, "glXGetProcAddressARB");
OpenGL::glXSwapBuffers = (OpenGL::glXSwapBuffers_t) dlsym(glx_lib, "glXSwapBuffers");
OpenGL::glXCreateContext = (OpenGL::glXCreateContext_t) dlsym(glx_lib, "glXCreateContext");
OpenGL::glXChooseFBConfig = (OpenGL::glXChooseFBConfig_t) dlsym(glx_lib, "glXChooseFBConfig");
OpenGL::glXGetVisualFromFBConfig = (OpenGL::glXGetVisualFromFBConfig_t) dlsym(glx_lib, "glXGetVisualFromFBConfig");
OpenGL::glXChooseVisual = (OpenGL::glXChooseVisual_t) dlsym(glx_lib, "glXChooseVisual");
OpenGL::constructor_success = true;
}
bool OpenGLWindow::SoftwareRendered() {
std::string renderer((const char*) OpenGL::glGetString(GL_RENDERER));
if (renderer.find("llvmpipe"))
return true;
if (renderer.find("softpipe"))
return true;
return false;
}

View File

@@ -0,0 +1,255 @@
#include <ReWindow/types/Window.h>
#include <ReWindow/Logger.h>
#include <dlfcn.h>
#include <set>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_xlib.h>
using namespace ReWindow;
class ReWindow::RWindow::Platform {
public:
Window window;
XEvent xev;
Display* display;
int defaultScreen;
XVisualInfo* visual;
XSetWindowAttributes xSetWindowAttributes;
XWindowAttributes windowAttributes;
Atom wmDeleteWindow;
Atom windowTypeAtom;
Atom windowTypeUtilityAtom;
XSizeHints hints;
Cursor invisible_cursor = 0;
XWMHints* wm_hints = nullptr;
};
namespace Vulkan {
bool constructor_success = false;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = nullptr;
PFN_vkCreateInstance vkCreateInstance = nullptr;
PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = nullptr;
PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = nullptr;
PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = nullptr;
PFN_vkGetDeviceQueue vkGetDeviceQueue = nullptr;
PFN_vkCreateDevice vkCreateDevice = nullptr;
PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR = nullptr;
PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = nullptr;
}
void* vulkan_lib = nullptr;
VkInstance vulkan_context = nullptr;
VkApplicationInfo vulkan_application_info{};
VkSurfaceKHR vulkan_surface = nullptr;
VkDevice vulkan_logical_device = nullptr;
VkQueue vulkan_graphics_queue = nullptr;
VkQueue vulkan_present_queue = nullptr;
// Necessary because some functions aren't available until you have a context (Vulkan is weird).
void LoadVulkanInstancedFunctions(VkInstance vulkan_ctx) {
Vulkan::vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties) Vulkan::vkGetInstanceProcAddr(vulkan_ctx, "vkGetPhysicalDeviceProperties");
Vulkan::vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices) Vulkan::vkGetInstanceProcAddr(vulkan_ctx, "vkEnumeratePhysicalDevices");
Vulkan::vkGetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties) Vulkan::vkGetInstanceProcAddr(vulkan_ctx, "vkGetPhysicalDeviceQueueFamilyProperties");
Vulkan::vkGetDeviceQueue = (PFN_vkGetDeviceQueue) Vulkan::vkGetInstanceProcAddr(vulkan_ctx, "vkGetDeviceQueue");
Vulkan::vkCreateDevice = (PFN_vkCreateDevice) Vulkan::vkGetInstanceProcAddr(vulkan_ctx, "vkCreateDevice");
Vulkan::vkCreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR) Vulkan::vkGetInstanceProcAddr(vulkan_ctx, "vkCreateXlibSurfaceKHR");
Vulkan::vkGetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) Vulkan::vkGetInstanceProcAddr(vulkan_ctx, "vkGetPhysicalDeviceSurfaceSupportKHR");
}
bool VulkanWindow::Open() {
if (!Vulkan::constructor_success)
return false;
platform->display = XOpenDisplay(nullptr);
platform->defaultScreen = DefaultScreen(platform->display);
platform->xSetWindowAttributes.border_pixel = BlackPixel(platform->display, platform->defaultScreen);
platform->xSetWindowAttributes.background_pixel = BlackPixel(platform->display, platform->defaultScreen);
platform->xSetWindowAttributes.override_redirect = True;
platform->xSetWindowAttributes.event_mask = ExposureMask;
vulkan_application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
vulkan_application_info.pApplicationName = title.c_str();
vulkan_application_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
vulkan_application_info.pEngineName = "";
vulkan_application_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
vulkan_application_info.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
create_info.pApplicationInfo = &vulkan_application_info;
const char* extensions[] = { "VK_KHR_surface", "VK_KHR_xlib_surface" };
create_info.enabledExtensionCount = 2;
create_info.ppEnabledExtensionNames = extensions;
if (Vulkan::vkCreateInstance(&create_info, nullptr, &vulkan_context) != VK_SUCCESS) {
Logger::Error("Couldn't create Vulkan instance.");
return false;
}
LoadVulkanInstancedFunctions(vulkan_context);
XVisualInfo visual_info_t{};
visual_info_t.screen = platform->defaultScreen;
int visual_count;
XVisualInfo* vi = XGetVisualInfo(platform->display, VisualScreenMask, &visual_info_t, &visual_count);
if (!vi)
return false;
Colormap colormap = XCreateColormap(platform->display, RootWindow(platform->display, vi->screen), vi->visual, AllocNone);
platform->xSetWindowAttributes.colormap = colormap;
platform->window = XCreateWindow(platform->display, RootWindow(platform->display, vi->screen),
0, 0, width, height, 0, vi->depth, InputOutput,
vi->visual, CWBackPixel | CWColormap | CWBorderPixel, &platform->xSetWindowAttributes);
if (!platform->window) {
Logger::Error("Failed to create X11 window for Vulkan.");
return false;
}
XFree(vi);
VkXlibSurfaceCreateInfoKHR surface_create_info{};
surface_create_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
surface_create_info.dpy = platform->display;
surface_create_info.window = platform-> window;
if (Vulkan::vkCreateXlibSurfaceKHR(vulkan_context, &surface_create_info, nullptr, &vulkan_surface) != VK_SUCCESS) {
Logger::Error("Failed to create Vulkan X11 surface.");
return false;
}
unsigned int device_count = 0;
Vulkan::vkEnumeratePhysicalDevices(vulkan_context, &device_count, nullptr);
if (device_count == 0) {
Logger::Error("Opening the window as Vulkan but there isn't a Vulkan compatible graphics card?");
return false;
}
std::vector<VkPhysicalDevice> vulkan_devices(device_count);
Vulkan::vkEnumeratePhysicalDevices(vulkan_context, &device_count, vulkan_devices.data());
VkPhysicalDevice selected_device = VK_NULL_HANDLE;
int graphics_family = -1;
int present_family = -1;
for (const auto& d : vulkan_devices) {
unsigned int queue_family_count = 0;
Vulkan::vkGetPhysicalDeviceQueueFamilyProperties(d, &queue_family_count, nullptr);
std::vector<VkQueueFamilyProperties> queue_families(queue_family_count);
Vulkan::vkGetPhysicalDeviceQueueFamilyProperties(d, &queue_family_count, queue_families.data());
bool has_graphics = false;
bool has_present = false;
for (unsigned int i = 0; i < queue_family_count; i++) {
if (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { has_graphics = true; graphics_family = i; }
VkBool32 present_support = false;
Vulkan::vkGetPhysicalDeviceSurfaceSupportKHR(d, i, vulkan_surface, &present_support);
if (present_support) { has_present = true; present_family = i; }
if (has_graphics && has_present) { selected_device = d; break; }
}
if (selected_device != VK_NULL_HANDLE)
break;
}
if (selected_device == VK_NULL_HANDLE) {
Logger::Error("There isn't a Vulkan device which supports rendering & presenting?");
return false;
}
VkPhysicalDeviceProperties device_properties;
Vulkan::vkGetPhysicalDeviceProperties(selected_device, &device_properties);
Logger::Debug("Vulkan continuing with selected device: " + std::string(device_properties.deviceName));
float queue_prio = 1.0f;
std::vector<VkDeviceQueueCreateInfo> queue_create_info;
std::set<unsigned int> unique_queue_families = { (unsigned int) graphics_family, (unsigned int) present_family};
for (unsigned int qf : unique_queue_families) {
VkDeviceQueueCreateInfo vdqci{};
vdqci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
vdqci.queueFamilyIndex = qf;
vdqci.queueCount = 1;
vdqci.pQueuePriorities = &queue_prio;
queue_create_info.push_back(vdqci);
}
// TODO allow the user to specify this.
VkPhysicalDeviceFeatures enabled_features{};
VkDeviceCreateInfo device_create_info{};
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_create_info.queueCreateInfoCount = queue_create_info.size();
device_create_info.pQueueCreateInfos = queue_create_info.data();
device_create_info.pEnabledFeatures = &enabled_features;
// TODO allow the user to specify this.
std::vector<const char*> device_ext = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
device_create_info.enabledExtensionCount = device_ext.size();
device_create_info.ppEnabledExtensionNames = device_ext.data();
if (Vulkan::vkCreateDevice(selected_device, &device_create_info, nullptr, &vulkan_logical_device) != VK_SUCCESS) {
Logger::Error("Couldn't create the Vulkan logical device.");
return false;
}
Vulkan::vkGetDeviceQueue(vulkan_logical_device, graphics_family, 0, &vulkan_graphics_queue);
Vulkan::vkGetDeviceQueue(vulkan_logical_device, present_family, 0, &vulkan_present_queue);
XSelectInput(platform->display, platform->window, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
PointerMotionHintMask | FocusChangeMask | StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask | VisibilityChangeMask | CWColormap );
XMapWindow(platform->display, platform->window);
XStoreName(platform->display, platform->window, title.c_str());
platform->windowTypeAtom = XInternAtom(platform->display, "_NET_WM_WINDOW_TYPE", False);
platform->windowTypeUtilityAtom = XInternAtom(platform->display, "_NET_WM_WINDOW_TYPE_UTILITY", False);
XChangeProperty(platform->display, platform->window, platform->windowTypeAtom, XA_ATOM, 32, PropModeReplace, (unsigned char*) &platform->windowTypeUtilityAtom, 1);
platform->wmDeleteWindow = XInternAtom(platform->display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(platform->display, platform->window, &platform->wmDeleteWindow, 1);
XGetWindowAttributes(platform->display, platform->window, &platform->windowAttributes);
open = true;
processOnOpen();
return true;
}
void VulkanWindow::SwapBuffers() {
}
void VulkanWindow::SetVsyncEnabled(bool state) {
}
std::string VulkanWindow::GetGraphicsDriverVendor() {
return "Unknown OpenGL";// TODO: Implement properly!
}
VulkanWindow::VulkanWindow(const std::string& title, int width, int height) : RWindow(title, width, height) {
vulkan_lib = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL);
if (!vulkan_lib)
vulkan_lib = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL);
if (!vulkan_lib)
Logger::Debug("libvulkan.so couldn't be found in your LD_LIBRARY_PATH."),
Vulkan::constructor_success = false;
Vulkan::vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) dlsym(vulkan_lib,"vkGetInstanceProcAddr");
Vulkan::vkCreateInstance = (PFN_vkCreateInstance) Vulkan::vkGetInstanceProcAddr(NULL, "vkCreateInstance");
Vulkan::constructor_success = true;
}

View File

@@ -0,0 +1,532 @@
#include <cstring>
#include <ReWindow/types/Window.h>
#include <ReWindow/types/Cursors.h>
#include <ReWindow/Logger.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
class ReWindow::RWindow::Platform {
public:
Window window;
XEvent xev;
Display* display;
int defaultScreen;
XVisualInfo* visual;
XSetWindowAttributes xSetWindowAttributes;
XWindowAttributes windowAttributes;
Atom wmDeleteWindow;
Atom windowTypeAtom;
Atom windowTypeUtilityAtom;
XSizeHints hints;
Cursor invisible_cursor = 0;
XWMHints* wm_hints = nullptr;
bool window_visible = true;
std::pair<int, int> position = { 0, 0 };
std::pair<int, int> size_before_fullscreen {0, 0};
};
using namespace ReWindow;
void RWindow::SetSize(const std::pair<int, int>& size) {
this->SetSize(size.first, size.second);
}
bool RWindow::SetCursorPosition(const std::pair<int, int>& position) {
if (!IsFocused())
return false;
if (!IsVisible())
return false;
if (position.first > GetWidth() || position.first < 0)
return false;
if (position.second > GetHeight() || position.second < 0)
return false;
// TODO XWarpPointer has no way to verify it actually happened.
XWarpPointer(platform->display, None, platform->window, 0, 0, 0, 0, position.first, position.second);
return true;
}
void RWindow::SetKeyRepeatEnabled(bool state) {
key_repeat = state;
if (state)
return (void) XAutoRepeatOn(platform->display);
XAutoRepeatOff(platform->display);
}
void RWindow::Flash() {
if (IsFocused())
return;
if (platform->wm_hints == nullptr)
platform->wm_hints = XAllocWMHints();
platform->wm_hints->flags = XUrgencyHint;
XSetWMHints(platform->display, platform->window, platform->wm_hints);
}
RWindow::RWindow() {
platform = new Platform();
extant = this;
}
void RWindow::SetCursorFocused(bool state) {
toggling_cursor_focus = state;
if (!state && cursor_focused) {
XUngrabPointer(platform->display, CurrentTime);
cursor_focused = state;
return;
}
}
std::pair<int, int> RWindow::SetCursorCenter() {
auto current_pos = GetAccurateCursorCoordinates();
XWarpPointer(platform->display, None, platform->window, 0, 0, 0, 0, width / 2, height / 2);
return current_pos;
}
RWindow::RWindow(const std::string& wTitle, int wWidth, int wHeight, bool wFullscreen, bool wResizable, bool wVsync)
: title(wTitle), width(wWidth), height(wHeight), fullscreen_mode(wFullscreen), resizable(wResizable), vsync(wVsync)
{ platform = new Platform(); extant = this; }
void RWindow::Raise() {
Logger::Debug(std::format("Raising window '{}'", this->title));
// Get the position of the renderable area relative to the rest of the window.
XGetWindowAttributes(platform->display, platform->window, &platform->windowAttributes);
XRaiseWindow(platform->display, platform->window);
}
void RWindow::DialogOK(const std::string& window_title, const std::string& message) {
int padding = 10;
XFontStruct* font = XLoadQueryFont(platform->display, "6x13");
int text_width = XTextWidth(font, message.c_str(), message.size());
int button_text_width = XTextWidth(font, "OK", 2);
std::pair<int, int> button_size = {80, 30};
std::pair<int, int> dimensions = { std::max(text_width + 2 * padding, button_size.first + 2 * padding), 82};
std::pair<int, int> text_pos = {(dimensions.first - text_width) / 2, padding + font->ascent};
std::pair<int, int> button_pos = { (dimensions.first - button_size.first) / 2, text_pos.second + font->ascent + padding };
Window window = XCreateSimpleWindow(platform->display, RootWindow(platform->display, platform->defaultScreen),
100, 100, dimensions.first, dimensions.second, 1,
BlackPixel(platform->display, platform->defaultScreen),
WhitePixel(platform->display, platform->defaultScreen));
XStoreName(platform->display, window, window_title.c_str());
XSelectInput(platform->display, window, ExposureMask | ButtonPressMask | StructureNotifyMask);
// No resizing.
XSizeHints hints;
hints.flags = PMinSize | PMaxSize;
hints.min_width = hints.max_width = dimensions.first;
hints.min_height = hints.max_height = dimensions.second;
XSetWMNormalHints(platform->display, window, &hints);
Atom wm_delete_window = XInternAtom(platform->display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(platform->display, window, &wm_delete_window, 1);
XMapWindow(platform->display, window);
GC gc = XCreateGC(platform->display, window, 0, nullptr);
XSetForeground(platform->display, gc, BlackPixel(platform->display, platform->defaultScreen));
XEvent event;
while (true) {
XNextEvent(platform->display, &event);
if (event.type == Expose) {
XDrawString(platform->display, window, gc, text_pos.first, text_pos.second, message.c_str(), message.size());
XDrawString(platform->display, window, gc, button_pos.first + (button_size.first - button_text_width) / 2, button_pos.second + 20, "OK", 2);
XDrawRectangle(platform->display, window, gc, button_pos.first, button_pos.second, button_size.first, button_size.second);
}
else if (event.type == ClientMessage) {
if (event.xclient.message_type == XInternAtom(platform->display, "WM_PROTOCOLS", False) &&
static_cast<Atom>(event.xclient.data.l[0]) == wm_delete_window)
break;
}
else if (event.type == ButtonPress) {
if (event.xbutton.x >= button_pos.first && event.xbutton.x <= button_pos.first + button_size.first
&& event.xbutton.y >= button_pos.second && event.xbutton.y <= button_pos.second + button_size.second)
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
XFreeFont(platform->display, font);
XFreeGC(platform->display, gc);
XDestroyWindow(platform->display, window);
}
void RWindow::Lower()
{
Logger::Debug(std::format("Lowering window '{}'", this->title));
XLowerWindow(platform->display, platform->window);
}
void RWindow::DestroyOSWindowHandle() {
// Turn key repeat back on.
XAutoRepeatOn(platform->display);
XFlush(platform->display);
Logger::Debug(std::format("Destroying sub-windows for window '{}'", this->title));
XDestroySubwindows(platform->display, platform->window);
Logger::Debug(std::format("Destroyed window '{}'", this->title));
XDestroyWindow(platform->display, platform->window);
XCloseDisplay(platform->display);
delete platform;
}
void RWindow::SetCursorVisible(bool cursor_enable) {
cursor_visible = cursor_enable;
if (platform->invisible_cursor == 0) {
Pixmap blank_pixmap = XCreatePixmap(platform->display, platform->window, 1, 1, 1);
XColor dummy; dummy.pixel = 0; dummy.red = 0; dummy.flags = 0;
platform->invisible_cursor = XCreatePixmapCursor(platform->display, blank_pixmap, blank_pixmap, &dummy, &dummy, 0, 0);
XFreePixmap(platform->display, blank_pixmap);
}
if (!cursor_enable)
XDefineCursor(platform->display, platform->window, platform->invisible_cursor);
if (cursor_enable)
XUndefineCursor(platform->display, platform->window);
}
void RWindow::DisableResizing() {
XGetWindowAttributes(platform->display, platform->window, &platform->windowAttributes);
platform->hints.flags = PMinSize | PMaxSize;
platform->hints.min_width = platform->hints.max_width = platform->windowAttributes.width;
platform->hints.min_height = platform->hints.max_height = platform->windowAttributes.height;
XSetWMNormalHints(platform->display, platform->window, &platform->hints);
this->resizable = false;
}
void RWindow::PollEvents() {
while(XPending(platform->display)) {
XNextEvent(platform->display, &platform->xev);
if (platform->xev.type == ClientMessage)
Logger::Info(std::format("Event '{}'", "ClientMessage"));
if (platform->xev.xclient.message_type == XInternAtom(platform->display, "WM_PROTOCOLS", False) &&
static_cast<Atom>(platform->xev.xclient.data.l[0]) == platform->wmDeleteWindow) {
Close();
}
if (platform->xev.type == FocusIn) {
Logger::Debug(std::format("Event'{}'", "FocusIn"));
if (!key_repeat)
XAutoRepeatOff(platform->display);
else
XAutoRepeatOn(platform->display);
XFlush(platform->display);
if (cursor_focused) {
cursor_focused = false;
SetCursorFocused(true);
}
if (platform->wm_hints) {
platform->wm_hints->flags &= ~XUrgencyHint;
XSetWMHints(platform->display, platform->window, platform->wm_hints);
XFree(platform->wm_hints);
}
if (!cursor_visible)
XDefineCursor(platform->display, platform->window, platform->invisible_cursor);
// Get the position of the renderable area relative to the rest of the window.
XGetWindowAttributes(platform->display, platform->window, &platform->windowAttributes);
processFocusIn();
focused = true;
}
if (platform->xev.type == UnmapNotify) {
if (cursor_focused) {
SetCursorFocused(false);
cursor_focused = true;
}
}
if (platform->xev.type == FocusOut) {
Logger::Debug(std::format("Event '{}'", "FocusOut"));
XAutoRepeatOn(platform->display);
XFlush(platform->display);
if (cursor_focused) {
SetCursorFocused(false);
cursor_focused = true;
}
if (!cursor_visible)
XUndefineCursor(platform->display, platform->window);
processFocusOut();
focused = false;
}
if (platform->xev.type == KeyRelease) {
Logger::Debug(std::format("Event '{}'", "KeyRelease"));
auto scancode = (X11Scancode) platform->xev.xkey.keycode;
auto key = GetKeyFromX11Scancode(scancode);
processKeyRelease(key);
}
if (platform->xev.type == KeyPress) {
Logger::Debug(std::format("Event '{}'", "KeyPress"));
auto scancode = (X11Scancode) platform->xev.xkey.keycode;
auto key = GetKeyFromX11Scancode(scancode);
processKeyPress(key);
}
if (platform->xev.type == ButtonRelease) {
// Mouse Wheel fires both the ButtonPress and ButtonRelease instantaneously.
// Therefore, we handle it as a specific MouseWheel event rather than a MouseButton event,
// and only call on ButtonPress, otherwise it will appear to duplicate the mouse wheel scroll.
if (platform->xev.xbutton.button != 4 && platform->xev.xbutton.button != 5) {
MouseButton button = GetMouseButtonFromXButton(platform->xev.xbutton.button);
Logger::Debug(std::format("Event '{}'", "ButtonRelease"));
processMouseRelease(button);
}
}
if (platform->xev.type == ButtonPress) {
// Mouse Wheel fires both the ButtonPress and ButtonRelease instantaneously.
// Therefore, we handle it as a specific MouseWheel event rather than a MouseButton event,
// and only call on ButtonPress, otherwise it will appear to duplicate the mouse wheel scroll.
if (platform->xev.xbutton.button == 4) {
processMouseWheel(-1);
} else if (platform->xev.xbutton.button == 5) {
processMouseWheel(1);
} else {
MouseButton button = GetMouseButtonFromXButton(platform->xev.xbutton.button);
Logger::Debug(std::format("Event: MouseButtonPress {}", button.Mnemonic));
processMousePress(button);
}
}
if (platform->xev.type == Expose) {
Logger::Debug(std::format("Event '{}'", "Expose"));
}
if (platform->xev.type == MotionNotify) {
if (toggling_cursor_focus) {
XWindowAttributes attrs;
XGetWindowAttributes(platform->display, platform->window, &attrs);
if (attrs.map_state == IsViewable) {
int result = XGrabPointer
(
platform->display, platform->window, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync, platform->window, None, CurrentTime
);
if (result == GrabSuccess) {
toggling_cursor_focus = false;
cursor_focused = true;
}
}
}
}
if (platform->xev.type == ConfigureNotify) {
if (this->width != platform->xev.xconfigurerequest.width ||
this->height != platform->xev.xconfigurerequest.height) {
Logger::Debug(std::format("Event '{}'", "ResizeRequest"));
this->width = platform->xev.xconfigurerequest.width;
this->height = platform->xev.xconfigurerequest.height;
auto eventData = WindowResizeRequestEvent();
eventData.Size = {platform->xev.xconfigurerequest.width, platform->xev.xconfigurerequest.height};
OnResizeRequest(eventData);
OnResizeRequestEvent(eventData);
}
//Window Moved.
if (platform->position.first != platform->xev.xconfigurerequest.x || platform->position.second != platform->xev.xconfigurerequest.y)
platform->position = { platform->xev.xconfigurerequest.x, platform->xev.xconfigurerequest.y };
}
if (platform->xev.type == VisibilityNotify) {
if (platform->xev.xvisibility.state == VisibilityFullyObscured)
platform->window_visible = false;
else if (platform->xev.xvisibility.state == VisibilityUnobscured ||
platform->xev.xvisibility.state == VisibilityPartiallyObscured)
platform->window_visible = true;
}
}
previousKeyboard = currentKeyboard;
previousMouse.Buttons = currentMouse.Buttons;
}
// Might make the window go off the screen on some window managers.
void RWindow::SetSize(int newWidth, int newHeight) {
if (!resizable)
return;
this->width = newWidth;
this->height = newHeight;
XResizeWindow(platform->display, platform->window, newWidth, newHeight);
XFlush(platform->display);
Logger::Info(std::format("Set size for '{}' to {} x {}", this->title, newWidth, newHeight));
}
std::pair<int, int> RWindow::GetAccurateCursorCoordinates() 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(platform->display, platform->window, &root_return, &child_return, &root_x_ret, &root_y_ret, &win_x_ret, &win_y_ret, &mask_return);
if (mouseAvailable) {
// TODO: normalize coordinates from platform->displaySpace to windowSpace
// TODO: fire mouse movement event
std::pair<int, int> m_coords = { win_x_ret, win_y_ret };
return m_coords;
}
return {};
}
bool RWindow::IsVisible() const {
return platform->window_visible;
}
// TODO: implement integer std::pair<int, int>/3 types
std::pair<int, int> RWindow::GetPosition() const {
return platform->position;
}
std::pair<int, int> RWindow::GetSize() const { return { this->width, this->height }; }
void RWindow::SetPosition(int x, int y) {
XMoveWindow(platform->display, platform->window, x, y);
platform->position = {x, y};
}
void RWindow::SetPosition(const std::pair<int, int>& pos) {
SetPosition(pos.first, pos.second);
}
void RWindow::Fullscreen() {
platform->size_before_fullscreen = GetSize();
if (!this->resizable) {
XSizeHints hints;
hints.flags = PMinSize | PMaxSize;
hints.min_width = 0;
hints.min_height = 0;
hints.max_width = 100000;
hints.max_height = 100000;
XSetWMNormalHints(platform->display, platform->window, &hints);
XFlush(platform->display);
}
Atom wm_state = XInternAtom(platform->display, "_NET_WM_STATE", False);
Atom wm_fullscreen = XInternAtom(platform->display, "_NET_WM_STATE_FULLSCREEN", False);
if (!wm_state || !wm_fullscreen) {
Logger::Error("We don't have the required atom for fullscreen graphics mode?");
return;
}
XEvent xev{};
xev.type = ClientMessage;
xev.xclient.window = platform->window;
xev.xclient.message_type = wm_state;
xev.xclient.format = 32;
xev.xclient.data.l[0] = 1;
xev.xclient.data.l[1] = wm_fullscreen;
xev.xclient.data.l[2] = 0;
xev.xclient.data.l[3] = 1;
xev.xclient.data.l[4] = 0;
XSendEvent(platform->display,
DefaultRootWindow(platform->display),
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&xev);
XFlush(platform->display);
fullscreen_mode = true;
Logger::Debug(std::format("Fullscreened '{}'", this->title));
}
void RWindow::RestoreFromFullscreen() {
Atom wm_state = XInternAtom(platform->display, "_NET_WM_STATE", False);
Atom fullscreen = XInternAtom(platform->display, "_NET_WM_STATE_FULLSCREEN", False);
if (!wm_state || !fullscreen) {
Logger::Error("We don't have the required atom for fullscreen graphics mode?");
return;
}
XEvent xev{};
xev.type = ClientMessage;
xev.xclient.window = platform->window;
xev.xclient.message_type = wm_state;
xev.xclient.format = 32;
xev.xclient.data.l[0] = 0;
xev.xclient.data.l[1] = fullscreen;
xev.xclient.data.l[2] = 0;
xev.xclient.data.l[3] = 1;
xev.xclient.data.l[4] = 0;
XSendEvent(
platform->display,
DefaultRootWindow(platform->display),
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&xev
);
if (!this->resizable) {
XSizeHints hints;
hints.flags = PMinSize | PMaxSize;
hints.min_width = hints.max_width = platform->size_before_fullscreen.first;
hints.min_height = hints.max_height = platform->size_before_fullscreen.second;
XSetWMNormalHints(platform->display, platform->window, &hints);
this->width = platform->size_before_fullscreen.first;
this->height = platform->size_before_fullscreen.second;
}
XFlush(platform->display);
fullscreen_mode = false;
Logger::Debug(std::format("Restored '{}' from Fullscreen", this->title));
}
void RWindow::SetCursorStyle(CursorStyle style) const {
auto x11_cursor_resolved_enum = (unsigned int) style.X11Cursor;
Cursor c = XCreateFontCursor(platform->display, x11_cursor_resolved_enum);
XDefineCursor(platform->display, platform->window, c);
}
void RWindow::SetTitle(const std::string& title) {
this->title = title;
XStoreName(platform->display, platform->window, title.c_str());
}

View File

@@ -0,0 +1,252 @@
#include <ReWindow/types/Window.h>
#include <ReWindow/InputService.h>
#include <ReWindow/Logger.h>
using namespace ReWindow;
RWindow::~RWindow() {
if (open)
DestroyOSWindowHandle();
}
std::pair<int, int> RWindow::GetCursorPosition() const {
return currentMouse.Position;
}
bool RWindow::IsAlive() const {
return (!closing) && open;
}
void RWindow::SetFullscreen(bool fs) {
if (fs)
Fullscreen();
else
RestoreFromFullscreen();
}
#pragma region Event Processors Implementation
void RWindow::processFocusIn() {
RWindowEvent event {};
OnFocusGain(event);
OnFocusGainEvent(event);
LogEvent(event);
}
void RWindow::processFocusOut() {
RWindowEvent event {};
OnFocusLost(event);
OnFocusLostEvent(event);
LogEvent(event);
}
void RWindow::processMousePress(const MouseButton& btn) {
currentMouse.Set(btn, true);
auto event = MouseButtonDownEvent(btn);
OnMouseButtonDown(event);
OnMouseButtonDownEvent(event);
InputService::OnMouseButtonEvent(MouseButtonEvent(btn, true));
InputService::OnMouseDown(event);
LogEvent(event);
}
void RWindow::processMouseMove(const std::pair<int, int>& last_pos, const std::pair<int, int>& new_pos) {
currentMouse.Position = new_pos;
auto event = MouseMoveEvent(new_pos);
OnMouseMove(event);
OnMouseMoveEvent(event);
InputService::OnMouseMove(event);
LogEvent(event);
}
void RWindow::processMouseRelease(const MouseButton& btn) {
currentMouse.Set(btn, false);
auto event = MouseButtonUpEvent(btn);
OnMouseButtonUp(event);
OnMouseButtonUpEvent(event);
InputService::OnMouseButtonEvent(MouseButtonEvent(btn, false));
InputService::OnMouseUp(event);
LogEvent(event);
}
void RWindow::processKeyRelease(Key key) {
currentKeyboard.PressedKeys[key] = false;
auto event = KeyUpEvent(key);
OnKeyUp(event);
OnKeyUpEvent(event);
InputService::OnKeyboardEvent(KeyboardEvent(key, KeyState::Released));
InputService::OnKeyEvent(KeyboardEvent(key, KeyState::Released));
InputService::OnKeyUp(event);
LogEvent(event);
}
void RWindow::processKeyPress(Key key) {
currentKeyboard.PressedKeys[key] = true;
auto event = KeyDownEvent(key);
OnKeyDown(event);
OnKeyDownEvent(event);
InputService::OnKeyDown(event);
InputService::OnKeyboardEvent(KeyboardEvent(key, KeyState::Pressed));
InputService::OnKeyEvent(KeyboardEvent(key, KeyState::Pressed));
LogEvent(event);
}
void RWindow::processOnClose() {
auto event = RWindowEvent();
OnClosing();
OnClosingEvent();
LogEvent(event);
}
void RWindow::processOnOpen() {
auto event = RWindowEvent();
OnOpen();
OnOpenEvent();
LogEvent(event);
}
#pragma endregion
std::string RWindow::GetTitle() const { return this->title; }
int RWindow::GetWidth() const { return this->width; }
int RWindow::GetHeight() const { return this->height; }
bool RWindow::IsResizable() const { return resizable; }
bool RWindow::IsFullscreen() const { return fullscreen_mode; }
bool RWindow::IsFocused() const { return focused; }
bool RWindow::IsVsyncEnabled() const { return vsync; }
float RWindow::GetDeltaTime() const { return delta_time; }
float RWindow::GetRefreshRate() const { return refresh_rate; }
bool RWindow::SetCursorPosition(const int x, const int y) { return SetCursorPosition({x, y}); }
unsigned long long RWindow::GetRefreshCount() const { return refresh_count; }
void RWindow::SetSizeWithoutEvent(const std::pair<int, int>& size) {
width = size.first;
height = size.second;
}
bool RWindow::IsKeyDown(Key key) const {
if (currentKeyboard.PressedKeys.contains(key))
return currentKeyboard.PressedKeys.at(key);
return false; // NOTE: Key may not be mapped!!
}
bool RWindow::IsMouseButtonDown(const MouseButton& button) const {
// TODO: Implement MouseButton map
return currentMouse.IsDown(button);
}
void RWindow::ManagedRefresh() {
auto begin = GetTimestamp();
Refresh();
auto end = GetTimestamp();
float dt = ComputeElapsedFrameTimeSeconds(begin, end);
UpdateFrameTiming(dt);
}
void RWindow::Refresh() {
PollEvents();
OnRefresh(delta_time);
// Only call once and cache the result.
currentMouse.Position = GetAccurateCursorCoordinates();
if (currentMouse.Position != previousMouse.Position) {
processMouseMove(previousMouse.Position, currentMouse.Position);
previousMouse.Position = currentMouse.Position;
}
}
bool RWindow::GetCursorFocused() {
return cursor_focused;
}
float RWindow::ComputeElapsedFrameTimeSeconds(std::chrono::steady_clock::time_point start, std::chrono::steady_clock::time_point end) {
auto frame_time = end - start;
unsigned long int frame_time_us = std::chrono::duration_cast<std::chrono::microseconds>(frame_time).count();
float frame_time_s = frame_time_us / (1000.f * 1000.f);
return frame_time_s;
}
std::chrono::steady_clock::time_point RWindow::GetTimestamp() {
return std::chrono::steady_clock::now();
}
void RWindow::UpdateFrameTiming(float frame_time) {
delta_time = frame_time;
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::processMouseWheel(int scrolls) {
currentMouse.Wheel += scrolls;
auto ev = MouseWheelEvent(scrolls);
OnMouseWheel(ev);
OnMouseWheelEvent(ev);
previousMouse.Wheel = currentMouse.Wheel;
}
void RWindow::Close() {
closing = true;
processOnClose();
}
void RWindow::ForceClose() {
Close();
DestroyOSWindowHandle();
}
bool MouseState::IsDown(const MouseButton& btn) const {
if (btn == MouseButtons::Left) return Buttons.LMB;
if (btn == MouseButtons::Right) return Buttons.RMB;
if (btn == MouseButtons::Middle) return Buttons.MMB;
if (btn == MouseButtons::Mouse4) return Buttons.SideButton1;
if (btn == MouseButtons::Mouse5) return Buttons.SideButton2;
//if (btn == MouseButtons::MWheelUp) return Buttons.MWheelUp;
//if (btn == MouseButtons::MWheelDown) return Buttons.MWheelDown;
return false; // Unknown button?
}
void MouseState::Set(const MouseButton& btn, bool state) {
if (btn == MouseButtons::Left) Buttons.LMB = state;
if (btn == MouseButtons::Right) Buttons.RMB = state;
if (btn == MouseButtons::Middle) Buttons.MMB = state;
if (btn == MouseButtons::Mouse4) Buttons.SideButton1 = state;
if (btn == MouseButtons::Mouse5) Buttons.SideButton2 = state;
//if (btn == MouseButtons::MWheelUp) Buttons.MWheelUp = state;
//if (btn == MouseButtons::MWheelDown) Buttons.MWheelDown = state;
}
bool &MouseState::operator [](const MouseButton& btn) {
if (btn == MouseButtons::Left) return Buttons.LMB;
if (btn == MouseButtons::Right) return Buttons.RMB;
if (btn == MouseButtons::Middle) return Buttons.MMB;
if (btn == MouseButtons::Mouse4) return Buttons.SideButton1;
if (btn == MouseButtons::Mouse5) return Buttons.SideButton2;
//if (btn == MouseButtons::MWheelUp) return Buttons.MWheelUp;
//if (btn == MouseButtons::MWheelDown) return Buttons.MWheelDown;
throw std::invalid_argument("Attempted to handle unmapped mouse button.");
}

View File

@@ -0,0 +1,511 @@
#include <Windows.h>
#include <gl/GL.h>
#include <ReWindow/types/Window.h>
#include <ReWindow/Logger.h>
class ReWindow::RWindow::Platform {
public:
HINSTANCE hInstance;
HWND hwnd;
HDC hdc;
std::pair<int, int> window_size_before_fullscreen;
std::pair<int, int> window_position_before_fullscreen;
};
using namespace ReWindow;
// TODO get rid of this.
bool local_focused = true;
bool local_toggling_cursor_focused = false;
void RWindow::SetSize(int newWidth, int newHeight) {
if (!resizable)
return;
this->width = newWidth;
this->height = newHeight;
DWORD style = GetWindowLong(platform->hwnd, GWL_STYLE);
DWORD exStyle = GetWindowLong(platform->hwnd, GWL_EXSTYLE);
RECT rect = { 0, 0, newWidth, newHeight };
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
int totalWidth = rect.right - rect.left;
int totalHeight = rect.bottom - rect.top;
SetWindowPos(platform->hwnd, nullptr, 0, 0, totalWidth, totalHeight,
SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
}
void RWindow::SetCursorFocused(bool state) {
local_toggling_cursor_focused = state;
if (state)
cursor_focused = true;
else if (!state && cursor_focused) {
ClipCursor(nullptr);
cursor_focused = false;
local_toggling_cursor_focused = false;
}
}
bool RWindow::SetCursorPosition(const std::pair<int, int>& position) {
if (!IsFocused())
return false;
if (!IsVisible())
return false;
if (position.first < 0 || position.first > GetWidth())
return false;
if (position.second < 0 || position.second > GetHeight())
return false;
POINT screen_pos = { position.first, position.second };
if (!ClientToScreen(platform->hwnd, &screen_pos))
return false;
if (!SetCursorPos(screen_pos.x, screen_pos.y))
return false;
return true;
}
std::pair<int, int> RWindow::SetCursorCenter() {
auto current_cursor_pos = GetAccurateCursorCoordinates();
RECT client_rect;
GetClientRect(platform->hwnd, &client_rect);
POINT center((client_rect.right - client_rect.left) / 2, (client_rect.bottom - client_rect.top) / 2 );
ClientToScreen(platform->hwnd, &center);
SetCursorPos(center.x, center.y);
return current_cursor_pos;
}
void RWindow::PollEvents() {
MSG msg;
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
TranslateMessage(&msg),
DispatchMessage(&msg);
focused = local_focused;
}
LRESULT CALLBACK RWindow::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
auto* window = reinterpret_cast<RWindow*>( GetWindowLongPtr(hwnd, GWLP_USERDATA) );
switch (uMsg) {
case WM_CLOSE: {
window->processOnClose();
DestroyWindow(hwnd);
}
case WM_DESTROY: {
exit(0);
}
case WM_SIZE: {
window->SetSizeWithoutEvent({ LOWORD(lParam), HIWORD(lParam) });
auto eventData = WindowResizeRequestEvent();
eventData.Size = { window->GetWidth(), window->GetHeight() };
// TODO: Implement eWindow->processOnResize()
window->OnResizeRequest(eventData);
window->OnResizeRequestEvent(eventData);
break;
}
case WM_SETFOCUS: {
window->processFocusIn();
local_focused = true;
if (window->GetCursorFocused())
local_toggling_cursor_focused = true;
// Cancels window flashing.
// TODO check if we're flashing before this.
static FLASHWINFO flash_inter {sizeof(FLASHWINFO), hwnd, FLASHW_STOP, 0, 0};
FlashWindowEx(&flash_inter);
break;
}
case WM_KILLFOCUS: {
window->processFocusOut();
if (window->GetCursorFocused()) {
ClipCursor(nullptr);
local_toggling_cursor_focused = true;
}
local_focused = false;
}
case WM_SETCURSOR: {
if (LOWORD(lParam) == HTCLIENT && window->GetCursorVisible() == false)
SetCursor(nullptr);
break;
}
case WM_KEYDOWN: {
auto key = GetKeyFromWindowsScancode((WindowsScancode) wParam);
if (window->IsKeyRepeat())
window->processKeyPress(key);
else if ((lParam & 1 << 30) == 0)
window->processKeyPress(key);
break;
}
case WM_KEYUP: {
auto key = GetKeyFromWindowsScancode((WindowsScancode) wParam);
window->processKeyRelease(key);
break;
}
// Mouse Buttons.
case WM_MOUSEWHEEL: {
int wheel_delta = GET_WHEEL_DELTA_WPARAM(wParam);
// Clamp to normalized range [+1 or -1].
// TODO: Test this and make sure sign is the same on both platforms for each direction.
wheel_delta = (wheel_delta > 0) ? 1 : -1;
// TODO: Determine sign of wheel_delta for each direction, (and on linux too), and document this.
window->processMouseWheel(wheel_delta);
break;
}
case WM_LBUTTONDOWN: {
window->processMousePress(MouseButtons::Left);
break;
}
case WM_LBUTTONUP: {
window->processMouseRelease(MouseButtons::Left);
break;
}
case WM_RBUTTONDOWN: {
window->processMousePress(MouseButtons::Right);
break;
}
case WM_RBUTTONUP: {
window->processMouseRelease(MouseButtons::Right);
break;
}
case WM_MBUTTONDOWN: {
window->processMousePress(MouseButtons::Middle);
break;
}
case WM_MBUTTONUP: {
window->processMouseRelease(MouseButtons::Middle);
break;
}
case WM_XBUTTONDOWN: {
WORD button = GET_XBUTTON_WPARAM(wParam);
if (button == XBUTTON1)
window->processMousePress(MouseButtons::Mouse4);
if (button == XBUTTON2)
window->processMousePress(MouseButtons::Mouse5);
break;
}
case WM_XBUTTONUP: {
WORD button = GET_XBUTTON_WPARAM(wParam);
if (button == XBUTTON1)
window->processMouseRelease(MouseButtons::Mouse4);
if (button == XBUTTON2)
window->processMouseRelease(MouseButtons::Mouse5);
break;
}
//This is the same as "Motion Notify" in the X Window System.
case WM_MOUSEMOVE: {
if (local_toggling_cursor_focused) {
RECT rect;
if (GetClientRect(hwnd, &rect)) {
POINT top_left = { rect.left, rect.top };
POINT bottom_right = { rect.right, rect.bottom };
MapWindowPoints(hwnd, nullptr, &top_left, 1);
MapWindowPoints(hwnd, nullptr, &bottom_right, 1);
RECT clip_rect = { top_left.x, top_left.y, bottom_right.x, bottom_right.y };
if (ClipCursor(&clip_rect))
local_toggling_cursor_focused = false;
}
}
}
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
bool fullscreenmode = false;
bool open = false;
void RWindow::Raise() { SetWindowPos(platform->hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); }
void RWindow::Lower() { SetWindowPos(platform->hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); }
//TODO somehow check if our window is entirely obscured by other windows.
bool RWindow::IsVisible() const {
if (!IsWindow(platform->hwnd))
return false;
if (IsIconic(platform->hwnd))
return false;
return true;
}
void RWindow::Flash() {
if (!focused) {
FLASHWINFO fi;
fi.cbSize = sizeof(FLASHWINFO);
fi.hwnd = platform->hwnd;
fi.dwFlags = FLASHW_ALL;
fi.uCount = 0;
fi.dwTimeout = 0;
FlashWindowEx(&fi);
}
}
void RWindow::DestroyOSWindowHandle() {
DestroyWindow(platform->hwnd);
}
void RWindow::DisableResizing() {
RECT rect;
GetWindowRect(platform->hwnd, &rect);
LONG style = GetWindowLong(platform->hwnd, GWL_STYLE);
style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
SetWindowLong(platform->hwnd, GWL_STYLE, style);
SetWindowPos(platform->hwnd, nullptr, rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER);
this->resizable = false;
}
std::pair<int, int> RWindow::GetAccurateCursorCoordinates() const {
POINT point;
GetCursorPos(&point);
ScreenToClient(platform->hwnd, &point);
return { point.x, point.y };
}
void RWindow::SetCursorVisible(bool cursor_enable) {
cursor_visible = cursor_enable;
}
bool RWindow::GetCursorVisible() {
return cursor_visible;
}
void RWindow::SetKeyRepeatEnabled(bool state) {
key_repeat = state;
}
std::pair<int, int> RWindow::GetSize() const {
RECT rect;
GetClientRect(platform->hwnd, &rect);
return { (rect.right - rect.left), (rect.bottom - rect.top) };
}
std::pair<int, int> RWindow::GetPosition() const {
RECT rect;
if (GetWindowRect(platform->hwnd, &rect))
return { rect.left, rect.top };
return { -1, -1 };
}
void RWindow::SetPosition(int x, int y) {
SetWindowPos(platform->hwnd, nullptr, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
void RWindow::SetPosition(const std::pair<int, int>& pos) {
SetPosition(pos.first, pos.second);
}
void RWindow::Fullscreen() {
platform->window_position_before_fullscreen = GetPosition();
platform->window_size_before_fullscreen = GetSize();
platform->window_position_before_fullscreen = this->GetPosition();
SetWindowLong(platform->hwnd, GWL_STYLE, GetWindowLong(platform->hwnd, GWL_STYLE) & ~WS_OVERLAPPEDWINDOW);
SetWindowPos(platform->hwnd, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
fullscreen_mode = true;
}
void RWindow::RestoreFromFullscreen() {
SetWindowLong(platform->hwnd, GWL_STYLE, GetWindowLong(platform->hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW);
RECT rect = {0, 0, platform->window_size_before_fullscreen.first, platform->window_size_before_fullscreen.second };
AdjustWindowRectEx(&rect, GetWindowLong(platform->hwnd, GWL_STYLE), FALSE, GetWindowLong(platform->hwnd, GWL_EXSTYLE));
int window_width = rect.right - rect.left;
int window_height = rect.bottom - rect.top;
SetWindowPos(
platform->hwnd,
nullptr,
platform->window_position_before_fullscreen.first,
platform->window_position_before_fullscreen.second,
window_width,
window_height,
SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER
);
DisableResizing();
this->width = platform->window_position_before_fullscreen.first;
this->height = platform->window_position_before_fullscreen.second;
fullscreen_mode = false;
}
void RWindow::SetCursorStyle(CursorStyle style) const {}
RWindow::RWindow() {
extant = this;
platform = new Platform();
}
RWindow::RWindow(const std::string& wTitle, int wWidth, int wHeight,
bool wFullscreen, bool wResizable, bool wVsync) :
title(wTitle), width(wWidth), height(wHeight), fullscreen_mode(wFullscreen), resizable(wResizable),
vsync(wVsync) {
extant = this;
platform = new Platform();
}
void RWindow::DialogOK(const std::string& title, const std::string& message_box_text) {
MessageBox(nullptr, message_box_text.c_str(), title.c_str(), MB_OK);
}
HGLRC glContext;
HMODULE gl_lib = nullptr;
bool constructor_success = true;
namespace OpenGL {
typedef const GLubyte* (APIENTRY *GLGETSTRINGPROC)(GLenum name);
GLGETSTRINGPROC glGetString = nullptr;
typedef BOOL (WINAPI *WGLMAKECURRENTPROC)(HDC hdc, HGLRC hglrc);
WGLMAKECURRENTPROC wglMakeCurrent = nullptr;
typedef FARPROC (WINAPI *WGLGETPROCADDRPROC)(LPCSTR lpszProc);
WGLGETPROCADDRPROC wglGetProcAddress = nullptr;
typedef HGLRC (WINAPI *WGLCREATECONTEXTPROC)(HDC hdc);
WGLCREATECONTEXTPROC wglCreateContext = nullptr;
}
bool OpenGLWindow::Open() {
if (!constructor_success)
return false;
platform->hInstance = GetModuleHandle(nullptr);
WNDCLASS wc = { };
wc.lpfnWndProc = RWindow::WindowProc;
wc.hInstance = platform->hInstance;
wc.lpszClassName = "RWindowClass";
RegisterClass(&wc);
RECT rect = { 0, 0, width, height };
AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, 0);
int win_width = rect.right - rect.left;
int win_height = rect.bottom - rect.top;
platform->hwnd = CreateWindowEx(
0,
"RWindowClass",
title.c_str(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, win_width, win_height,
nullptr,
nullptr,
platform->hInstance,
nullptr
);
SetWindowLongPtr(platform->hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
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
};
platform->hdc = GetDC(platform->hwnd);
int pixelFormat = ChoosePixelFormat(platform->hdc, &pfd);
SetPixelFormat(platform->hdc, pixelFormat, &pfd);
glContext = OpenGL::wglCreateContext(platform->hdc);
OpenGL::wglMakeCurrent(platform->hdc, glContext);
ShowWindow(platform->hwnd, SW_SHOW);
open = true;
return true;
}
std::string OpenGLWindow::GetGraphicsDriverVendor() {
return std::string(reinterpret_cast<const char*>(OpenGL::glGetString(GL_VENDOR)));
}
void OpenGLWindow::SwapBuffers() {
::SwapBuffers(platform->hdc);
}
void OpenGLWindow::SetVsyncEnabled(bool b) {
typedef BOOL(WINAPI* PFNWGLSWAPINTERVALEXTPROC)(int interval);
auto wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) OpenGL::wglGetProcAddress("wglSwapIntervalEXT");
if (wglSwapIntervalEXT)
wglSwapIntervalEXT(b ? 1 : 0);
}
bool OpenGLWindow::SoftwareRendered() {
std::string renderer(reinterpret_cast<const char*>(OpenGL::glGetString(GL_RENDERER)));
if (renderer.find("llvmpipe"))
return true;
if (renderer.find("softpipe"))
return true;
if (renderer.find("GDI Generic"))
return true;
if (GetGraphicsDriverVendor().find("Mesa"))
return true;
return false;
}
OpenGLWindow::OpenGLWindow(const std::string& title, int width, int height, uint8_t gl_major, uint8_t gl_minor)
: gl_major(gl_major), gl_minor(gl_minor), RWindow(title, width, height) {
gl_lib = LoadLibrary("opengl32.dll");
if (!gl_lib)
Logger::Error("opengl32.dll couldn't be found. If you have it, you can try putting it in the same directory as the executable."),
constructor_success = false;
OpenGL::glGetString = (OpenGL::GLGETSTRINGPROC) GetProcAddress(gl_lib, "glGetString");
OpenGL::wglMakeCurrent = (OpenGL::WGLMAKECURRENTPROC) GetProcAddress(gl_lib, "wglMakeCurrent");
OpenGL::wglGetProcAddress = (OpenGL::WGLGETPROCADDRPROC) GetProcAddress(gl_lib, "wglGetProcAddress");
OpenGL::wglCreateContext = (OpenGL::WGLCREATECONTEXTPROC) GetProcAddress(gl_lib, "wglCreateContext");
}

View File

@@ -0,0 +1,7 @@
#include <ReWindow/types/WindowEvents.h>
namespace ReWindow
{
}

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

@@ -0,0 +1,41 @@
#include <ReWindow/types/Key.h>
//std::vector<Key> Key::keyboard = {};
std::vector<Key> Key::GetKeyboard() { return keyboard; }
Key::Key(const char* charcode, X11Scancode scancode, WindowsScancode sc)
: Mnemonic(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->Mnemonic < rhs.Mnemonic);
}
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;
}

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

@@ -0,0 +1,35 @@
#include <ReWindow/types/MouseButton.h>
#include <string>
#include <ReWindow/Logger.h>
MouseButton::MouseButton(const std::string& charcode, unsigned int index) {
this->Mnemonic = charcode;
this->ButtonIndex = index;
}
bool MouseButton::operator==(const MouseButton &mb) const {
return (mb.ButtonIndex == this->ButtonIndex);
}
bool MouseButton::operator<(const MouseButton &rhs) const {
return (this->ButtonIndex < rhs.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"