Archived
1
Fork 0
This repository has been archived on 2025-04-12. You can view files and clone it, but cannot push or open issues or pull requests.
prism/platforms/linux/main.cpp.in
2020-08-11 12:07:21 -04:00

349 lines
9.2 KiB
C++
Executable file

#include <@APP_INCLUDE@>
#include <engine.hpp>
#include "gfx_vulkan.hpp"
#include "platform.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <xcb/xcb.h>
#include <X11/Xutil.h>
#include <GL/gl.h>
#include <GL/glx.h>
@APP_CLASS@* app = nullptr;
GFX* interface = nullptr;
Display *dpy = nullptr;
int mouse_x = -1, mouse_y = -1;
bool mouse_down[2] = {false, false};
xcb_connection_t* connection = nullptr;
xcb_screen_t* screen = nullptr;
struct WindowConnection {
xcb_connection_t* connection;
xcb_window_t window;
};
std::vector<WindowConnection> window_connections;
xcb_intern_atom_reply_t *atom_wm_delete_window;
static std::map<InputButton, int> inputToKeyCode = { {
{InputButton::A, 38},
{InputButton::W, 25},
{InputButton::S, 39},
{InputButton::D, 40},
{InputButton::Q, 24}
}};
/*
* Platform functions"
*/
const char* platform::get_name() {
return "Linux";
}
static inline xcb_intern_atom_reply_t* intern_atom_helper(xcb_connection_t *conn, bool only_if_exists, const char *str)
{
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(conn, only_if_exists, strlen(str), str);
return xcb_intern_atom_reply(conn, cookie, NULL);
}
int platform::open_window(const std::string_view title, const int x, const int y, const int width, const int height, const WindowFlags flags) {
auto& win = window_connections.emplace_back();
win.connection = connection;
uint32_t mask;
uint32_t values[32];
xcb_void_cookie_t cookie;
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
values[0] = screen->black_pixel;
values[1] =
XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
XCB_EVENT_MASK_POINTER_MOTION |
XCB_EVENT_MASK_BUTTON_PRESS |
XCB_EVENT_MASK_BUTTON_RELEASE;
win.window = xcb_generate_id(connection);
cookie = xcb_create_window(win.connection,
XCB_COPY_FROM_PARENT, win.window, screen->root,
x, y, width, height,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
mask, values);
/* Magic code that will send notification when window is destroyed */
xcb_intern_atom_reply_t* reply = intern_atom_helper(connection, true, "WM_PROTOCOLS");
atom_wm_delete_window = intern_atom_helper(connection, false, "WM_DELETE_WINDOW");
xcb_change_property(connection, XCB_PROP_MODE_REPLACE,
win.window, (*reply).atom, 4, 32, 1,
&(*atom_wm_delete_window).atom);
xcb_change_property(connection, XCB_PROP_MODE_REPLACE,
win.window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
title.size(), title.data());
xcb_map_window(connection, win.window);
xcb_flush(connection);
engine->add_window((void*)&win, 0, width, height);
app->initialize_render();
return window_connections.size() - 1;
}
void platform::close_window(const int index) {
}
void platform::force_quit() {
}
float platform::get_window_dpi(const int index) {
return 1.0;
}
float platform::get_monitor_dpi() {
return 1.0;
}
platform::Rect platform::get_monitor_resolution() {
}
platform::Rect platform::get_monitor_work_area() {
}
std::tuple<int, int> platform::get_window_position(const int index) {
}
std::tuple<int, int> platform::get_window_size(const int index) {
}
std::tuple<int, int> platform::get_window_drawable_size(const int index) {
}
bool platform::is_window_focused(const int index) {
}
void platform::set_window_focused(const int index) {
}
void platform::set_window_position(const int index, const int x, const int y) {
}
void platform::set_window_size(const int index, const int w, const int h) {
}
void platform::set_window_title(const int index, const std::string_view title) {
xcb_change_property(connection, XCB_PROP_MODE_REPLACE,
window_connections[index].window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
title.size(), title.data());
}
bool platform::get_key_down(const InputButton key) {
int keycode = inputToKeyCode[key];
char keys[32];
XQueryKeymap(dpy, keys);
return keys[keycode/8]&(0x1<<(keycode%8));
}
int platform::get_keycode(const InputButton key) {
return inputToKeyCode[key];
}
std::tuple<int, int> platform::get_cursor_position() {
return {mouse_x, mouse_y};
}
std::tuple<int, int> platform::get_screen_cursor_position() {
return {mouse_x, mouse_y};
}
bool platform::get_mouse_button_down(const int button) {
return mouse_down[button];
}
std::tuple<float, float> platform::get_wheel_delta() {
}
std::tuple<float, float> platform::get_right_stick_position() {
}
std::tuple<float, float> platform::get_left_stick_position() {
}
void platform::capture_mouse(const bool capture) {
}
void platform::open_dialog(const bool existing, std::function<void(std::string)> returnFunction, bool openDirectory) {
}
void platform::save_dialog(std::function<void(std::string)> returnFunction) {
}
char* platform::translate_keycode(const unsigned int keycode) {
char* array = new char[2];
XKeyEvent event;
memset(&event, 0, sizeof(event));
event.type = 2;
event.display = dpy;
event.keycode = keycode;
int count = XLookupString(&event, array, 1, nullptr, 0);
array[1] = '\0';
return array;
}
int stdout_copy;
int stderr_copy;
void platform::mute_output() {
stdout_copy = dup(STDOUT_FILENO);
stderr_copy = dup(STDERR_FILENO);
freopen("/dev/null", "a", stdout);
freopen("/dev/null", "a", stderr);
}
void platform::unmute_output() {
dup2(stdout_copy, STDOUT_FILENO);
dup2(stderr_copy, STDERR_FILENO);
close(stdout_copy);
close(stderr_copy);
}
int main(int argc, char* argv[]) {
dpy = XOpenDisplay(nullptr);
const xcb_setup_t *setup;
xcb_screen_iterator_t iter;
int scr;
connection = xcb_connect(NULL, &scr);
setup = xcb_get_setup(connection);
iter = xcb_setup_roots_iterator(setup);
while (scr-- > 0)
xcb_screen_next(&iter);
screen = iter.data;
engine = new Engine(argc, argv);
app = new @APP_CLASS@();
engine->set_app(app);
GFXCreateInfo info = {};
interface = new GFXVulkan();
if(interface->initialize(info)) {
engine->set_gfx(interface);
} else {
return -1;
}
app_main(engine);
while(1) {
xcb_generic_event_t* event = nullptr;
while((event = xcb_poll_for_event (connection))) {
switch(event->response_type & 0x7f) {
case XCB_CLIENT_MESSAGE:
{
if ((*(xcb_client_message_event_t*)event).data.data32[0] ==
(*atom_wm_delete_window).atom) {
engine->quit();
}
}
break;
case XCB_MOTION_NOTIFY:
{
auto ev = (xcb_motion_notify_event_t *)event;
engine->process_mouse_move(ev->event_x, ev->event_y);
mouse_x = ev->event_x;
mouse_y = ev->event_y;
}
break;
case XCB_BUTTON_PRESS:
{
xcb_button_press_event_t *press = (xcb_button_press_event_t *)event;
int index = 0;
if(press->detail == 3)
index = 1;
engine->process_mouse(index, press->event_x, press->event_y);
mouse_down[index] = true;
mouse_x = press->event_x;
mouse_y = press->event_y;
}
break;
case XCB_BUTTON_RELEASE:
{
xcb_button_press_event_t *press = (xcb_button_press_event_t *)event;
int index = 0;
if(press->detail == 3)
index = 1;
engine->process_mouse_released(index);
mouse_down[index] = false;
}
break;
case XCB_CONFIGURE_NOTIFY:
{
const xcb_configure_notify_event_t *cfgEvent = (const xcb_configure_notify_event_t *)event;
engine->resize(0, cfgEvent->width, cfgEvent->height);
}
break;
case XCB_KEY_PRESS:
{
const xcb_key_release_event_t *keyEvent = (const xcb_key_release_event_t *)event;
engine->process_key(keyEvent->detail);
}
break;
case XCB_KEY_RELEASE:
{
const xcb_key_release_event_t *keyEvent = (const xcb_key_release_event_t *)event;
engine->process_key_up(keyEvent->detail);
}
break;
}
free(event);
}
if(engine->is_quitting())
break;
engine->update(1.0 / 60.0);
engine->begin_frame();
engine->render(0);
}
return 0;
}