Compare commits
4 Commits
be23ab5b0e
...
1903483c0c
Author | SHA1 | Date |
---|---|---|
Jonas 'Sortie' Termansen | 1903483c0c | |
Jonas 'Sortie' Termansen | ce3b519991 | |
Jonas 'Sortie' Termansen | 6c6880ea31 | |
Juhani Krekelä | b9d6423f76 |
|
@ -11,7 +11,7 @@ CFLAGS += -Wall -Wextra
|
||||||
BINARIES = chkblayout
|
BINARIES = chkblayout
|
||||||
MANPAGES1 = chkblayout.1
|
MANPAGES1 = chkblayout.1
|
||||||
|
|
||||||
LIBS =
|
LIBS = -ldisplay
|
||||||
|
|
||||||
all: $(BINARIES)
|
all: $(BINARIES)
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <display.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <error.h>
|
#include <error.h>
|
||||||
|
@ -34,6 +35,20 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
|
#define CHKBLAYOUT_ID 0
|
||||||
|
|
||||||
|
static bool chkblayout_ack_received = false;
|
||||||
|
static int chkblayout_error;
|
||||||
|
|
||||||
|
static void on_ack(void* ctx, uint32_t id, int error)
|
||||||
|
{
|
||||||
|
(void) ctx;
|
||||||
|
if ( id != CHKBLAYOUT_ID )
|
||||||
|
return;
|
||||||
|
chkblayout_error = error;
|
||||||
|
chkblayout_ack_received = true;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
bool list = false;
|
bool list = false;
|
||||||
|
@ -103,8 +118,29 @@ int main(int argc, char* argv[])
|
||||||
err(1, "read: %s", kblayout_path);
|
err(1, "read: %s", kblayout_path);
|
||||||
close(kblayout_fd);
|
close(kblayout_fd);
|
||||||
|
|
||||||
if ( tcsetblob(tty_fd, "kblayout", kblayout, kblayout_size) < 0 )
|
if ( getenv("DISPLAY_SOCKET") )
|
||||||
err(1, "tcsetblob: kblayout: %s:", kblayout_path);
|
{
|
||||||
|
struct display_connection* connection = display_connect_default();
|
||||||
|
if ( !connection )
|
||||||
|
err(1, "Could not connect to display server");
|
||||||
|
|
||||||
|
display_chkblayout(connection, CHKBLAYOUT_ID, kblayout, kblayout_size);
|
||||||
|
|
||||||
|
struct display_event_handlers handlers = {0};
|
||||||
|
handlers.ack_handler = on_ack;
|
||||||
|
while ( !chkblayout_ack_received )
|
||||||
|
display_wait_event(connection, &handlers);
|
||||||
|
|
||||||
|
if ( chkblayout_error )
|
||||||
|
{
|
||||||
|
errno = chkblayout_error;
|
||||||
|
err(1, "tcsetblob: kblayout: %s", kblayout_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
display_disconnect(connection);
|
||||||
|
}
|
||||||
|
else if ( tcsetblob(tty_fd, "kblayout", kblayout, kblayout_size) < 0 )
|
||||||
|
err(1, "tcsetblob: kblayout: %s", kblayout_path);
|
||||||
|
|
||||||
free(kblayout);
|
free(kblayout);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2015, 2016, 2023 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2014, 2015, 2016, 2023 Jonas 'Sortie' Termansen.
|
||||||
|
* Copyright (c) 2023 Juhani 'nortti' Krekelä.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -28,6 +29,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
@ -97,14 +99,23 @@ struct window* connection_find_window(struct connection* connection,
|
||||||
#define CONNECTION_MESSAGE_HANDLER_NO_AUX(message_name) \
|
#define CONNECTION_MESSAGE_HANDLER_NO_AUX(message_name) \
|
||||||
void connection_handler_##message_name(struct connection* connection, \
|
void connection_handler_##message_name(struct connection* connection, \
|
||||||
struct display_##message_name* msg, \
|
struct display_##message_name* msg, \
|
||||||
void* auxilerary __attribute__((unused)), \
|
void* auxiliary __attribute__((unused)), \
|
||||||
size_t auxilerary_size __attribute__((unused)))
|
size_t auxiliary_size __attribute__((unused)), \
|
||||||
|
const struct server* server __attribute__((unused)))
|
||||||
|
|
||||||
#define CONNECTION_MESSAGE_HANDLER(message_name) \
|
#define CONNECTION_MESSAGE_HANDLER(message_name) \
|
||||||
void connection_handler_##message_name(struct connection* connection, \
|
void connection_handler_##message_name(struct connection* connection, \
|
||||||
struct display_##message_name* msg, \
|
struct display_##message_name* msg, \
|
||||||
unsigned char* auxilerary, \
|
unsigned char* auxiliary, \
|
||||||
size_t auxilerary_size)
|
size_t auxiliary_size, \
|
||||||
|
const struct server* server __attribute__((unused)))
|
||||||
|
|
||||||
|
#define CONNECTION_MESSAGE_HANDLER_SERVER(message_name) \
|
||||||
|
void connection_handler_##message_name(struct connection* connection, \
|
||||||
|
struct display_##message_name* msg, \
|
||||||
|
unsigned char* auxiliary, \
|
||||||
|
size_t auxiliary_size, \
|
||||||
|
const struct server* server)
|
||||||
|
|
||||||
CONNECTION_MESSAGE_HANDLER_NO_AUX(shutdown)
|
CONNECTION_MESSAGE_HANDLER_NO_AUX(shutdown)
|
||||||
{
|
{
|
||||||
|
@ -157,9 +168,9 @@ CONNECTION_MESSAGE_HANDLER(render_window)
|
||||||
src.xres = msg->width;
|
src.xres = msg->width;
|
||||||
src.yres = msg->height;
|
src.yres = msg->height;
|
||||||
src.pitch = msg->width;
|
src.pitch = msg->width;
|
||||||
src.buffer = (uint32_t*) auxilerary;
|
src.buffer = (uint32_t*) auxiliary;
|
||||||
|
|
||||||
if ( auxilerary_size < sizeof(uint32_t) * src.xres * src.yres )
|
if ( auxiliary_size < sizeof(uint32_t) * src.xres * src.yres )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct framebuffer dst =
|
struct framebuffer dst =
|
||||||
|
@ -175,9 +186,9 @@ CONNECTION_MESSAGE_HANDLER(title_window)
|
||||||
if ( !window )
|
if ( !window )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const char* title = (char*) auxilerary;
|
const char* title = (char*) auxiliary;
|
||||||
free(window->title);
|
free(window->title);
|
||||||
window->title = strndup(title, auxilerary_size);
|
window->title = strndup(title, auxiliary_size);
|
||||||
|
|
||||||
window_render_frame(window);
|
window_render_frame(window);
|
||||||
}
|
}
|
||||||
|
@ -198,10 +209,27 @@ CONNECTION_MESSAGE_HANDLER_NO_AUX(hide_window)
|
||||||
window->show = false;
|
window->show = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CONNECTION_MESSAGE_HANDLER_SERVER(chkblayout)
|
||||||
|
{
|
||||||
|
struct event_ack event;
|
||||||
|
event.id = msg->id;
|
||||||
|
event.error = 0;
|
||||||
|
if ( tcsetblob(server->tty_fd, "kblayout", auxiliary, auxiliary_size) < 0 )
|
||||||
|
event.error = errno;
|
||||||
|
|
||||||
|
struct display_packet_header header;
|
||||||
|
header.message_id = EVENT_ACK;
|
||||||
|
header.message_length = sizeof(event);
|
||||||
|
|
||||||
|
connection_schedule_transmit(connection, &header, sizeof(header));
|
||||||
|
connection_schedule_transmit(connection, &event, sizeof(event));
|
||||||
|
}
|
||||||
|
|
||||||
typedef void (*connection_message_handler)(struct connection* connection,
|
typedef void (*connection_message_handler)(struct connection* connection,
|
||||||
void* msg,
|
void* msg,
|
||||||
void* auxilerary,
|
void* auxiliary,
|
||||||
size_t auxilerary_size);
|
size_t auxiliary_size,
|
||||||
|
const struct server* server);
|
||||||
|
|
||||||
struct connection_message_handler_registration
|
struct connection_message_handler_registration
|
||||||
{
|
{
|
||||||
|
@ -223,6 +251,7 @@ struct connection_message_handler_registration connection_message_handlers[] =
|
||||||
REGISTER_CONNECTION_MESSAGE_HANDLER(show_window),
|
REGISTER_CONNECTION_MESSAGE_HANDLER(show_window),
|
||||||
REGISTER_CONNECTION_MESSAGE_HANDLER(hide_window),
|
REGISTER_CONNECTION_MESSAGE_HANDLER(hide_window),
|
||||||
REGISTER_CONNECTION_MESSAGE_HANDLER(shutdown),
|
REGISTER_CONNECTION_MESSAGE_HANDLER(shutdown),
|
||||||
|
REGISTER_CONNECTION_MESSAGE_HANDLER(chkblayout),
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t num_connection_message_handlers = sizeof(connection_message_handlers) /
|
size_t num_connection_message_handlers = sizeof(connection_message_handlers) /
|
||||||
|
@ -233,7 +262,8 @@ short connection_interested_poll_events(struct connection* connection)
|
||||||
return POLLIN | (connection->outgoing_used ? POLLOUT : 0);
|
return POLLIN | (connection->outgoing_used ? POLLOUT : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void connection_can_read(struct connection* connection)
|
void connection_can_read(struct connection* connection,
|
||||||
|
const struct server* server)
|
||||||
{
|
{
|
||||||
while ( connection->packet_header_received < sizeof(connection->packet_header) )
|
while ( connection->packet_header_received < sizeof(connection->packet_header) )
|
||||||
{
|
{
|
||||||
|
@ -272,10 +302,10 @@ void connection_can_read(struct connection* connection)
|
||||||
{
|
{
|
||||||
struct connection_message_handler_registration* handler =
|
struct connection_message_handler_registration* handler =
|
||||||
&connection_message_handlers[packet_id];
|
&connection_message_handlers[packet_id];
|
||||||
unsigned char* auxilerary = connection->packet + handler->message_size;
|
unsigned char* auxiliary = connection->packet + handler->message_size;
|
||||||
size_t auxilerary_size = packet_length - handler->message_size;
|
size_t auxiliary_size = packet_length - handler->message_size;
|
||||||
handler->handler(connection, connection->packet,
|
handler->handler(connection, connection->packet,
|
||||||
auxilerary, auxilerary_size);
|
auxiliary, auxiliary_size, server);
|
||||||
}
|
}
|
||||||
|
|
||||||
connection->packet_header_received = 0;
|
connection->packet_header_received = 0;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <display-protocol.h>
|
#include <display-protocol.h>
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
struct display;
|
struct display;
|
||||||
|
@ -58,7 +59,8 @@ struct window* connection_find_window_raw(struct connection* connection,
|
||||||
struct window* connection_find_window(struct connection* connection,
|
struct window* connection_find_window(struct connection* connection,
|
||||||
uint32_t window_id);
|
uint32_t window_id);
|
||||||
short connection_interested_poll_events(struct connection* connection);
|
short connection_interested_poll_events(struct connection* connection);
|
||||||
void connection_can_read(struct connection* connection);
|
void connection_can_read(struct connection* connection,
|
||||||
|
const struct server* server);
|
||||||
void connection_can_write(struct connection* connection);
|
void connection_can_write(struct connection* connection);
|
||||||
void connection_destroy(struct connection* connection);
|
void connection_destroy(struct connection* connection);
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ void server_initialize(struct server* server, struct display* display)
|
||||||
load_font();
|
load_font();
|
||||||
|
|
||||||
server->tty_fd = 0;
|
server->tty_fd = 0;
|
||||||
if ( !isatty(0) )
|
if ( !isatty(server->tty_fd) )
|
||||||
{
|
{
|
||||||
server->tty_fd = open("/dev/tty", O_RDONLY);
|
server->tty_fd = open("/dev/tty", O_RDONLY);
|
||||||
if ( server->tty_fd < 0 )
|
if ( server->tty_fd < 0 )
|
||||||
|
@ -245,7 +245,7 @@ void server_poll(struct server* server)
|
||||||
if ( pfd->revents & POLLOUT )
|
if ( pfd->revents & POLLOUT )
|
||||||
connection_can_write(connection);
|
connection_can_write(connection);
|
||||||
if ( pfd->revents & POLLIN )
|
if ( pfd->revents & POLLIN )
|
||||||
connection_can_read(connection);
|
connection_can_read(connection, server);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compact the array down here so the pfds match the connections above.
|
// Compact the array down here so the pfds match the connections above.
|
||||||
|
|
|
@ -15,7 +15,7 @@ BINARIES:=\
|
||||||
asteroids \
|
asteroids \
|
||||||
aquatinspitz \
|
aquatinspitz \
|
||||||
|
|
||||||
LIBS:=-ldispd -ldisplay
|
LIBS:=-ldisplay
|
||||||
|
|
||||||
all: $(BINARIES)
|
all: $(BINARIES)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2014, 2015, 2016, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -22,6 +22,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <error.h>
|
#include <error.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
@ -34,12 +35,15 @@
|
||||||
#include <timespec.h>
|
#include <timespec.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <dispd.h>
|
#include <display.h>
|
||||||
|
|
||||||
// Utility global variables every game will need.
|
// Utility global variables every game will need.
|
||||||
|
uint32_t window_id = 0;
|
||||||
|
static size_t framesize;
|
||||||
|
static uint32_t* fb;
|
||||||
static bool game_running = true;
|
static bool game_running = true;
|
||||||
static size_t game_width = 1280;
|
static size_t game_width = 800;
|
||||||
static size_t game_height = 720;
|
static size_t game_height = 512;
|
||||||
#define MAX_KEY_NUMBER 512
|
#define MAX_KEY_NUMBER 512
|
||||||
static bool keys_down[MAX_KEY_NUMBER];
|
static bool keys_down[MAX_KEY_NUMBER];
|
||||||
static bool keys_pending[MAX_KEY_NUMBER];
|
static bool keys_pending[MAX_KEY_NUMBER];
|
||||||
|
@ -200,20 +204,16 @@ void update(float deltatime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the game into the framebuffer.
|
// Render the game into the framebuffer.
|
||||||
void render(struct dispd_window* window)
|
void render(struct display_connection* connection)
|
||||||
{
|
{
|
||||||
struct dispd_framebuffer* window_fb = dispd_begin_render(window);
|
size_t old_framesize = framesize;
|
||||||
if ( !window_fb )
|
|
||||||
{
|
|
||||||
error(0, 0, "unable to begin rendering dispd window");
|
|
||||||
game_running = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t* fb = (uint32_t*) dispd_get_framebuffer_data(window_fb);
|
size_t xres = game_width;
|
||||||
size_t xres = dispd_get_framebuffer_width(window_fb);
|
size_t yres = game_height;
|
||||||
size_t yres = dispd_get_framebuffer_height(window_fb);
|
size_t pitch = xres;
|
||||||
size_t pitch = dispd_get_framebuffer_pitch(window_fb) / sizeof(uint32_t);
|
framesize = xres * yres * sizeof(uint32_t);
|
||||||
|
if ( old_framesize != framesize && !(fb = realloc(fb, framesize)) )
|
||||||
|
err(1, "malloc");
|
||||||
|
|
||||||
// Render a colorful background.
|
// Render a colorful background.
|
||||||
for ( size_t y = 0; y < yres; y++ )
|
for ( size_t y = 0; y < yres; y++ )
|
||||||
|
@ -273,7 +273,9 @@ void render(struct dispd_window* window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispd_finish_render(window_fb);
|
display_render_window(connection, window_id, 0, 0,
|
||||||
|
game_width, game_height, fb);
|
||||||
|
display_show_window(connection, window_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ... to here. No need to edit stuff below.
|
// ... to here. No need to edit stuff below.
|
||||||
|
@ -310,50 +312,68 @@ bool pop_is_key_just_down(int abskbkey)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read input from the keyboard.
|
// When the connection to the display server has disconnected.
|
||||||
void input(void)
|
void on_disconnect(void* ctx)
|
||||||
{
|
{
|
||||||
// Read the keyboard input from the user.
|
(void) ctx;
|
||||||
unsigned termmode = TERMMODE_KBKEY | TERMMODE_SIGNAL | TERMMODE_NONBLOCK;
|
exit(0);
|
||||||
if ( settermmode(0, termmode) )
|
}
|
||||||
error(1, errno, "settermmode");
|
|
||||||
uint32_t codepoint;
|
// When the window is asked to quit.
|
||||||
ssize_t numbytes;
|
void on_quit(void* ctx, uint32_t window_id)
|
||||||
while ( 0 < (numbytes = read(0, &codepoint, sizeof(codepoint))) )
|
{
|
||||||
{
|
(void) ctx;
|
||||||
int kbkey = KBKEY_DECODE(codepoint);
|
(void) window_id;
|
||||||
if( !kbkey )
|
exit(0);
|
||||||
continue;
|
}
|
||||||
int abskbkey = (kbkey < 0) ? -kbkey : kbkey;
|
|
||||||
if ( MAX_KEY_NUMBER <= (size_t) abskbkey )
|
// When the window has been resized.
|
||||||
continue;
|
void on_resize(void* ctx, uint32_t window_id, uint32_t width, uint32_t height)
|
||||||
bool is_key_down_event = 0 < kbkey;
|
{
|
||||||
if ( !keys_down[abskbkey] && is_key_down_event )
|
(void) ctx;
|
||||||
keys_pending[abskbkey] = true;
|
if ( window_id != window_id )
|
||||||
keys_down[abskbkey] = is_key_down_event;
|
return;
|
||||||
}
|
game_width = width;
|
||||||
|
game_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When a key has been pressed.
|
||||||
|
void on_keyboard(void* ctx, uint32_t window_id, uint32_t codepoint)
|
||||||
|
{
|
||||||
|
(void) ctx;
|
||||||
|
if ( window_id != window_id )
|
||||||
|
return;
|
||||||
|
int kbkey = KBKEY_DECODE(codepoint);
|
||||||
|
if ( !kbkey )
|
||||||
|
return;
|
||||||
|
int abskbkey = (kbkey < 0) ? -kbkey : kbkey;
|
||||||
|
if ( MAX_KEY_NUMBER <= (size_t) abskbkey )
|
||||||
|
return;
|
||||||
|
bool is_key_down_event = 0 < kbkey;
|
||||||
|
if ( !keys_down[abskbkey] && is_key_down_event )
|
||||||
|
keys_pending[abskbkey] = true;
|
||||||
|
keys_down[abskbkey] = is_key_down_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the game until no longer needed.
|
// Run the game until no longer needed.
|
||||||
void mainloop(struct dispd_window* window)
|
void mainloop(struct display_connection* connection)
|
||||||
{
|
{
|
||||||
struct dispd_framebuffer* window_fb = dispd_begin_render(window);
|
struct display_event_handlers handlers = {0};
|
||||||
if ( window_fb )
|
handlers.disconnect_handler = on_disconnect;
|
||||||
{
|
handlers.quit_handler = on_quit;
|
||||||
game_width = dispd_get_framebuffer_width(window_fb);
|
handlers.resize_handler = on_resize;
|
||||||
game_height = dispd_get_framebuffer_height(window_fb);
|
handlers.keyboard_handler = on_keyboard;
|
||||||
dispd_finish_render(window_fb);
|
|
||||||
}
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
struct timespec last_frame_time;
|
struct timespec last_frame_time;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &last_frame_time);
|
clock_gettime(CLOCK_MONOTONIC, &last_frame_time);
|
||||||
|
|
||||||
render(window);
|
render(connection);
|
||||||
|
|
||||||
while ( game_running )
|
while ( game_running )
|
||||||
{
|
{
|
||||||
|
|
||||||
struct timespec current_frame_time;
|
struct timespec current_frame_time;
|
||||||
clock_gettime(CLOCK_MONOTONIC, ¤t_frame_time);
|
clock_gettime(CLOCK_MONOTONIC, ¤t_frame_time);
|
||||||
|
|
||||||
|
@ -361,71 +381,31 @@ void mainloop(struct dispd_window* window)
|
||||||
timespec_sub(current_frame_time, last_frame_time);
|
timespec_sub(current_frame_time, last_frame_time);
|
||||||
float deltatime = deltatime_ts.tv_sec + deltatime_ts.tv_nsec / 1E9f;
|
float deltatime = deltatime_ts.tv_sec + deltatime_ts.tv_nsec / 1E9f;
|
||||||
|
|
||||||
input();
|
while ( display_poll_event(connection, &handlers) == 0 );
|
||||||
|
|
||||||
update(deltatime);
|
update(deltatime);
|
||||||
render(window);
|
render(connection);
|
||||||
|
|
||||||
last_frame_time = current_frame_time;
|
last_frame_time = current_frame_time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the terminal state when the process terminates.
|
|
||||||
static struct termios saved_tio;
|
|
||||||
|
|
||||||
static void restore_terminal_on_exit(void)
|
|
||||||
{
|
|
||||||
tcsetattr(0, TCSAFLUSH, &saved_tio);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void restore_terminal_on_signal(int signum)
|
|
||||||
{
|
|
||||||
if ( signum == SIGTSTP )
|
|
||||||
{
|
|
||||||
struct termios tio;
|
|
||||||
tcgetattr(0, &tio);
|
|
||||||
tcsetattr(0, TCSAFLUSH, &saved_tio);
|
|
||||||
raise(SIGSTOP);
|
|
||||||
tcgetattr(0, &saved_tio);
|
|
||||||
tcsetattr(0, TCSAFLUSH, &tio);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tcsetattr(0, TCSAFLUSH, &saved_tio);
|
|
||||||
raise(signum);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a display context, run the game, and then cleanly exit.
|
// Create a display context, run the game, and then cleanly exit.
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
if ( !isatty(0) )
|
struct display_connection* connection = display_connect_default();
|
||||||
error(1, errno, "standard input");
|
if ( !connection && errno == ECONNREFUSED )
|
||||||
if ( tcgetattr(0, &saved_tio) < 0 )
|
display_spawn(argc, argv);
|
||||||
error(1, errno, "tcsetattr: standard input");
|
if ( !connection )
|
||||||
if ( atexit(restore_terminal_on_exit) != 0 )
|
error(1, errno, "Could not connect to display server");
|
||||||
error(1, errno, "atexit");
|
|
||||||
struct sigaction sa;
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
|
||||||
sa.sa_handler = restore_terminal_on_signal;
|
|
||||||
sigaction(SIGTSTP, &sa, NULL);
|
|
||||||
sa.sa_flags = SA_RESETHAND;
|
|
||||||
sigaction(SIGINT, &sa, NULL);
|
|
||||||
sigaction(SIGQUIT, &sa, NULL);
|
|
||||||
sigaction(SIGTERM, &sa, NULL);
|
|
||||||
|
|
||||||
if ( !dispd_initialize(&argc, &argv) )
|
display_create_window(connection, window_id);
|
||||||
error(1, 0, "couldn't initialize dispd library");
|
display_resize_window(connection, window_id, game_width, game_height);
|
||||||
struct dispd_session* session = dispd_attach_default_session();
|
display_title_window(connection, window_id, "Aquatinspitz");
|
||||||
if ( !session )
|
|
||||||
error(1, 0, "couldn't attach to dispd default session");
|
|
||||||
if ( !dispd_session_setup_game_rgba(session) )
|
|
||||||
error(1, 0, "couldn't setup dispd rgba session");
|
|
||||||
struct dispd_window* window = dispd_create_window_game_rgba(session);
|
|
||||||
if ( !window )
|
|
||||||
error(1, 0, "couldn't create dispd rgba window");
|
|
||||||
|
|
||||||
mainloop(window);
|
mainloop(connection);
|
||||||
|
|
||||||
dispd_destroy_window(window);
|
display_disconnect(connection);
|
||||||
dispd_detach_session(session);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <sys/termmode.h>
|
#include <sys/termmode.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <error.h>
|
#include <error.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -1179,6 +1180,8 @@ void RunFrame(struct display_connection* connection)
|
||||||
{
|
{
|
||||||
free(buf);
|
free(buf);
|
||||||
buf = (uint32_t*) malloc(framesize);
|
buf = (uint32_t*) malloc(framesize);
|
||||||
|
if ( !buf )
|
||||||
|
err(1, "malloc");
|
||||||
}
|
}
|
||||||
|
|
||||||
GameLogic();
|
GameLogic();
|
||||||
|
@ -1199,7 +1202,8 @@ void RunFrame(struct display_connection* connection)
|
||||||
last_frame_sec = now.tv_sec;
|
last_frame_sec = now.tv_sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
display_render_window(connection, WINDOW_ID, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, buf);
|
display_render_window(connection, WINDOW_ID, 0, 0,
|
||||||
|
WINDOW_WIDTH, WINDOW_HEIGHT, buf);
|
||||||
display_show_window(connection, WINDOW_ID);
|
display_show_window(connection, WINDOW_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||||
|
* Copyright (c) 2023 Juhani 'nortti' Krekelä.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -84,6 +85,13 @@ struct display_shutdown
|
||||||
uint32_t code;
|
uint32_t code;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DISPLAY_CHKBLAYOUT 8
|
||||||
|
struct display_chkblayout
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
/* keyboard layout data bytes follow */
|
||||||
|
};
|
||||||
|
|
||||||
#define EVENT_DISCONNECT 0
|
#define EVENT_DISCONNECT 0
|
||||||
struct event_disconnect
|
struct event_disconnect
|
||||||
{
|
{
|
||||||
|
@ -110,4 +118,11 @@ struct event_keyboard
|
||||||
uint32_t codepoint;
|
uint32_t codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define EVENT_ACK 4
|
||||||
|
struct event_ack
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
int error;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2015, 2016, 2017 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2014, 2015, 2016, 2017 Jonas 'Sortie' Termansen.
|
||||||
|
* Copyright (c) 2023 Juhani 'nortti' Krekelä.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -46,8 +47,8 @@ void display_destroy_window(struct display_connection* connection,
|
||||||
uint32_t window_id);
|
uint32_t window_id);
|
||||||
void display_resize_window(struct display_connection* connection,
|
void display_resize_window(struct display_connection* connection,
|
||||||
uint32_t window_id,
|
uint32_t window_id,
|
||||||
uint32_t width, uint32_t
|
uint32_t width,
|
||||||
height);
|
uint32_t height);
|
||||||
void display_render_window(struct display_connection* connection,
|
void display_render_window(struct display_connection* connection,
|
||||||
uint32_t window_id,
|
uint32_t window_id,
|
||||||
uint32_t left,
|
uint32_t left,
|
||||||
|
@ -56,18 +57,24 @@ void display_render_window(struct display_connection* connection,
|
||||||
uint32_t height,
|
uint32_t height,
|
||||||
uint32_t* data);
|
uint32_t* data);
|
||||||
void display_title_window(struct display_connection* connection,
|
void display_title_window(struct display_connection* connection,
|
||||||
uint32_t window_id,
|
uint32_t window_id,
|
||||||
const char* title);
|
const char* title);
|
||||||
void display_show_window(struct display_connection* connection,
|
void display_show_window(struct display_connection* connection,
|
||||||
uint32_t window_id);
|
uint32_t window_id);
|
||||||
void display_hide_window(struct display_connection* connection,
|
void display_hide_window(struct display_connection* connection,
|
||||||
uint32_t window_id);
|
uint32_t window_id);
|
||||||
|
|
||||||
|
void display_chkblayout(struct display_connection* connection,
|
||||||
|
uint32_t id,
|
||||||
|
void* data,
|
||||||
|
uint32_t kblayout_bytes);
|
||||||
|
|
||||||
typedef void (*display_event_disconnect_handler_t)(void*);
|
typedef void (*display_event_disconnect_handler_t)(void*);
|
||||||
typedef void (*display_event_quit_handler_t)(void*, uint32_t);
|
typedef void (*display_event_quit_handler_t)(void*, uint32_t);
|
||||||
typedef void (*display_event_resize_handler_t)(void*, uint32_t, uint32_t,
|
typedef void (*display_event_resize_handler_t)(void*, uint32_t, uint32_t,
|
||||||
uint32_t);
|
uint32_t);
|
||||||
typedef void (*display_event_keyboard_handler_t)(void*, uint32_t, uint32_t);
|
typedef void (*display_event_keyboard_handler_t)(void*, uint32_t, uint32_t);
|
||||||
|
typedef void (*display_event_ack_handler_t)(void*, uint32_t, int);
|
||||||
|
|
||||||
struct display_event_handlers
|
struct display_event_handlers
|
||||||
{
|
{
|
||||||
|
@ -76,6 +83,7 @@ struct display_event_handlers
|
||||||
display_event_quit_handler_t quit_handler;
|
display_event_quit_handler_t quit_handler;
|
||||||
display_event_resize_handler_t resize_handler;
|
display_event_resize_handler_t resize_handler;
|
||||||
display_event_keyboard_handler_t keyboard_handler;
|
display_event_keyboard_handler_t keyboard_handler;
|
||||||
|
display_event_ack_handler_t ack_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
int display_poll_event(struct display_connection* connection,
|
int display_poll_event(struct display_connection* connection,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2015, 2016, 2017 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2014, 2015, 2016, 2017 Jonas 'Sortie' Termansen.
|
||||||
|
* Copyright (c) 2023 Juhani 'nortti' Krekelä.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -90,7 +91,8 @@ struct display_connection* display_connect(const char* socket_path)
|
||||||
if ( (connection->fd = open_local_client_socket(socket_path, 0)) < 0 )
|
if ( (connection->fd = open_local_client_socket(socket_path, 0)) < 0 )
|
||||||
return free(connection), (struct display_connection*) NULL;
|
return free(connection), (struct display_connection*) NULL;
|
||||||
size_t send_buffer_size = 2 * 1024 * 1024;
|
size_t send_buffer_size = 2 * 1024 * 1024;
|
||||||
setsockopt(connection->fd, SOL_SOCKET, SO_SNDBUF, &send_buffer_size, sizeof(send_buffer_size));
|
setsockopt(connection->fd, SOL_SOCKET, SO_SNDBUF, &send_buffer_size,
|
||||||
|
sizeof(send_buffer_size));
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,20 +115,25 @@ int display_connection_fd(struct display_connection* connection)
|
||||||
return connection->fd;
|
return connection->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_message(struct display_connection* connection, uint32_t message_id,
|
static void send_message(struct display_connection* connection,
|
||||||
const void* message, size_t message_size,
|
uint32_t message_id,
|
||||||
const void* auxilerary, size_t auxilerary_size)
|
const void* message,
|
||||||
|
size_t message_size,
|
||||||
|
const void* auxiliary,
|
||||||
|
size_t auxiliary_size)
|
||||||
{
|
{
|
||||||
struct display_packet_header header;
|
struct display_packet_header header;
|
||||||
header.message_id = message_id;
|
header.message_id = message_id;
|
||||||
header.message_length = message_size + auxilerary_size;
|
header.message_length = message_size + auxiliary_size;
|
||||||
writeall(connection->fd, &header, sizeof(header));
|
writeall(connection->fd, &header, sizeof(header));
|
||||||
writeall(connection->fd, message, message_size);
|
writeall(connection->fd, message, message_size);
|
||||||
writeall(connection->fd, auxilerary, auxilerary_size);
|
writeall(connection->fd, auxiliary, auxiliary_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_message_no_aux(struct display_connection* connection, uint32_t message_id,
|
static void send_message_no_aux(struct display_connection* connection,
|
||||||
const void* message, size_t message_size)
|
uint32_t message_id,
|
||||||
|
const void* message,
|
||||||
|
size_t message_size)
|
||||||
{
|
{
|
||||||
send_message(connection, message_id, message, message_size, 0, 0);
|
send_message(connection, message_id, message, message_size, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -138,21 +145,26 @@ void display_shutdown(struct display_connection* connection, uint32_t code)
|
||||||
send_message_no_aux(connection, DISPLAY_SHUTDOWN, &msg, sizeof(msg));
|
send_message_no_aux(connection, DISPLAY_SHUTDOWN, &msg, sizeof(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_create_window(struct display_connection* connection, uint32_t window_id)
|
void display_create_window(struct display_connection* connection,
|
||||||
|
uint32_t window_id)
|
||||||
{
|
{
|
||||||
struct display_create_window msg;
|
struct display_create_window msg;
|
||||||
msg.window_id = window_id;
|
msg.window_id = window_id;
|
||||||
send_message_no_aux(connection, DISPLAY_CREATE_WINDOW, &msg, sizeof(msg));
|
send_message_no_aux(connection, DISPLAY_CREATE_WINDOW, &msg, sizeof(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_destroy_window(struct display_connection* connection, uint32_t window_id)
|
void display_destroy_window(struct display_connection* connection,
|
||||||
|
uint32_t window_id)
|
||||||
{
|
{
|
||||||
struct display_destroy_window msg;
|
struct display_destroy_window msg;
|
||||||
msg.window_id = window_id;
|
msg.window_id = window_id;
|
||||||
send_message_no_aux(connection, DISPLAY_DESTROY_WINDOW, &msg, sizeof(msg));
|
send_message_no_aux(connection, DISPLAY_DESTROY_WINDOW, &msg, sizeof(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_resize_window(struct display_connection* connection, uint32_t window_id, uint32_t width, uint32_t height)
|
void display_resize_window(struct display_connection* connection,
|
||||||
|
uint32_t window_id,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t height)
|
||||||
{
|
{
|
||||||
struct display_resize_window msg;
|
struct display_resize_window msg;
|
||||||
msg.window_id = window_id;
|
msg.window_id = window_id;
|
||||||
|
@ -161,7 +173,13 @@ void display_resize_window(struct display_connection* connection, uint32_t windo
|
||||||
send_message_no_aux(connection, DISPLAY_RESIZE_WINDOW, &msg, sizeof(msg));
|
send_message_no_aux(connection, DISPLAY_RESIZE_WINDOW, &msg, sizeof(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_render_window(struct display_connection* connection, uint32_t window_id, uint32_t left, uint32_t top, uint32_t width, uint32_t height, uint32_t* data)
|
void display_render_window(struct display_connection* connection,
|
||||||
|
uint32_t window_id,
|
||||||
|
uint32_t left,
|
||||||
|
uint32_t top,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t height,
|
||||||
|
uint32_t* data)
|
||||||
{
|
{
|
||||||
struct display_render_window msg;
|
struct display_render_window msg;
|
||||||
msg.window_id = window_id;
|
msg.window_id = window_id;
|
||||||
|
@ -173,27 +191,42 @@ void display_render_window(struct display_connection* connection, uint32_t windo
|
||||||
data, sizeof(uint32_t) * width * height);
|
data, sizeof(uint32_t) * width * height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_title_window(struct display_connection* connection, uint32_t window_id, const char* title)
|
void display_title_window(struct display_connection* connection,
|
||||||
|
uint32_t window_id,
|
||||||
|
const char* title)
|
||||||
{
|
{
|
||||||
struct display_title_window msg;
|
struct display_title_window msg;
|
||||||
msg.window_id = window_id;
|
msg.window_id = window_id;
|
||||||
send_message(connection, DISPLAY_TITLE_WINDOW, &msg, sizeof(msg), title, strlen(title));
|
send_message(connection, DISPLAY_TITLE_WINDOW, &msg, sizeof(msg), title, strlen(title));
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_show_window(struct display_connection* connection, uint32_t window_id)
|
void display_show_window(struct display_connection* connection,
|
||||||
|
uint32_t window_id)
|
||||||
{
|
{
|
||||||
struct display_show_window msg;
|
struct display_show_window msg;
|
||||||
msg.window_id = window_id;
|
msg.window_id = window_id;
|
||||||
send_message_no_aux(connection, DISPLAY_SHOW_WINDOW, &msg, sizeof(msg));
|
send_message_no_aux(connection, DISPLAY_SHOW_WINDOW, &msg, sizeof(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_hide_window(struct display_connection* connection, uint32_t window_id)
|
void display_hide_window(struct display_connection* connection,
|
||||||
|
uint32_t window_id)
|
||||||
{
|
{
|
||||||
struct display_hide_window msg;
|
struct display_hide_window msg;
|
||||||
msg.window_id = window_id;
|
msg.window_id = window_id;
|
||||||
send_message_no_aux(connection, DISPLAY_HIDE_WINDOW, &msg, sizeof(msg));
|
send_message_no_aux(connection, DISPLAY_HIDE_WINDOW, &msg, sizeof(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void display_chkblayout(struct display_connection* connection,
|
||||||
|
uint32_t id,
|
||||||
|
void* data,
|
||||||
|
uint32_t kblayout_bytes)
|
||||||
|
{
|
||||||
|
struct display_chkblayout msg;
|
||||||
|
msg.id = id;
|
||||||
|
send_message(connection, DISPLAY_CHKBLAYOUT, &msg, sizeof(msg),
|
||||||
|
data, kblayout_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
static bool display_read_event(struct display_connection* connection)
|
static bool display_read_event(struct display_connection* connection)
|
||||||
{
|
{
|
||||||
while ( connection->header_bytes < sizeof(connection->header) )
|
while ( connection->header_bytes < sizeof(connection->header) )
|
||||||
|
@ -236,7 +269,8 @@ static bool display_read_event(struct display_connection* connection)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int display_dispatch_event(struct display_connection* connection, struct display_event_handlers* handlers)
|
static int display_dispatch_event(struct display_connection* connection,
|
||||||
|
struct display_event_handlers* handlers)
|
||||||
{
|
{
|
||||||
if ( connection->header_bytes == sizeof(connection->header) &&
|
if ( connection->header_bytes == sizeof(connection->header) &&
|
||||||
connection->payload &&
|
connection->payload &&
|
||||||
|
@ -281,6 +315,14 @@ static int display_dispatch_event(struct display_connection* connection, struct
|
||||||
handlers->keyboard_handler(handlers->context, event->window_id, event->codepoint);
|
handlers->keyboard_handler(handlers->context, event->window_id, event->codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( connection->header.message_id == EVENT_ACK &&
|
||||||
|
connection->header.message_length >= sizeof(struct event_ack) )
|
||||||
|
{
|
||||||
|
struct event_ack* event = (struct event_ack*) connection->payload;
|
||||||
|
if ( handlers->ack_handler )
|
||||||
|
handlers->ack_handler(handlers->context, event->id, event->error);
|
||||||
|
}
|
||||||
|
|
||||||
connection->header_bytes = 0;
|
connection->header_bytes = 0;
|
||||||
free(connection->payload), connection->payload = NULL;
|
free(connection->payload), connection->payload = NULL;
|
||||||
connection->payload_bytes = 0;
|
connection->payload_bytes = 0;
|
||||||
|
@ -300,7 +342,8 @@ static int display_event_read_hangup(struct display_event_handlers* handlers)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int display_poll_event(struct display_connection* connection, struct display_event_handlers* handlers)
|
int display_poll_event(struct display_connection* connection,
|
||||||
|
struct display_event_handlers* handlers)
|
||||||
{
|
{
|
||||||
fcntl(connection->fd, F_SETFL, fcntl(connection->fd, F_GETFL) | O_NONBLOCK);
|
fcntl(connection->fd, F_SETFL, fcntl(connection->fd, F_GETFL) | O_NONBLOCK);
|
||||||
bool read_success = display_read_event(connection);
|
bool read_success = display_read_event(connection);
|
||||||
|
@ -310,7 +353,8 @@ int display_poll_event(struct display_connection* connection, struct display_eve
|
||||||
return display_dispatch_event(connection, handlers);
|
return display_dispatch_event(connection, handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
int display_wait_event(struct display_connection* connection, struct display_event_handlers* handlers)
|
int display_wait_event(struct display_connection* connection,
|
||||||
|
struct display_event_handlers* handlers)
|
||||||
{
|
{
|
||||||
if ( !display_read_event(connection) )
|
if ( !display_read_event(connection) )
|
||||||
return display_event_read_hangup(handlers);
|
return display_event_read_hangup(handlers);
|
||||||
|
|
|
@ -568,8 +568,8 @@ int main(void)
|
||||||
conf.release_sig_url);
|
conf.release_sig_url);
|
||||||
install_configurationf("upgrade.conf", "a", "src = yes\n");
|
install_configurationf("upgrade.conf", "a", "src = yes\n");
|
||||||
|
|
||||||
// TODO: GUI support.
|
bool kblayout_setable = 0 <= tcgetblob(0, "kblayout", NULL, 0) ||
|
||||||
bool kblayout_setable = 0 <= tcgetblob(0, "kblayout", NULL, 0);
|
getenv("DISPLAY_SOCKET");
|
||||||
while ( kblayout_setable )
|
while ( kblayout_setable )
|
||||||
{
|
{
|
||||||
// TODO: Detect the name of the current keyboard layout.
|
// TODO: Detect the name of the current keyboard layout.
|
||||||
|
|
|
@ -466,7 +466,8 @@ int main(void)
|
||||||
prompt(input, sizeof(input), "ready", "Ready?", ready);
|
prompt(input, sizeof(input), "ready", "Ready?", ready);
|
||||||
text("\n");
|
text("\n");
|
||||||
|
|
||||||
bool kblayout_setable = 0 <= tcgetblob(0, "kblayout", NULL, 0);
|
bool kblayout_setable = 0 <= tcgetblob(0, "kblayout", NULL, 0) ||
|
||||||
|
getenv("DISPLAY_SOCKET");
|
||||||
while ( kblayout_setable )
|
while ( kblayout_setable )
|
||||||
{
|
{
|
||||||
// TODO: Detect the name of the current keyboard layout.
|
// TODO: Detect the name of the current keyboard layout.
|
||||||
|
|
|
@ -11,8 +11,6 @@ CXXFLAGS:=$(CXXFLAGS) -std=gnu++11 -Wall -Wextra -fno-exceptions -fno-rtti -fche
|
||||||
|
|
||||||
BINARY:=trianglix
|
BINARY:=trianglix
|
||||||
|
|
||||||
LIBS:=-ldispd
|
|
||||||
|
|
||||||
all: $(BINARY)
|
all: $(BINARY)
|
||||||
|
|
||||||
.PHONY: all install clean
|
.PHONY: all install clean
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2014, 2015, 2016, 2018 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2014, 2015, 2016, 2018, 2013 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <dispd.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <error.h>
|
#include <error.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -892,13 +892,6 @@ public:
|
||||||
buffer(buffer), pitch(pitch), xres(xres), yres(yres) { }
|
buffer(buffer), pitch(pitch), xres(xres), yres(yres) { }
|
||||||
FrameBufferInfo(const FrameBufferInfo& o) :
|
FrameBufferInfo(const FrameBufferInfo& o) :
|
||||||
buffer(o.buffer), pitch(o.pitch), xres(o.xres), yres(o.yres) { }
|
buffer(o.buffer), pitch(o.pitch), xres(o.xres), yres(o.yres) { }
|
||||||
FrameBufferInfo(struct dispd_framebuffer* fb)
|
|
||||||
{
|
|
||||||
buffer = dispd_get_framebuffer_data(fb);
|
|
||||||
pitch = dispd_get_framebuffer_pitch(fb);
|
|
||||||
xres = dispd_get_framebuffer_width(fb);
|
|
||||||
yres = dispd_get_framebuffer_height(fb);
|
|
||||||
}
|
|
||||||
~FrameBufferInfo() { }
|
~FrameBufferInfo() { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1433,14 +1426,45 @@ static void Render(FrameBufferInfo fb, struct Desktop* desktop)
|
||||||
RenderBackground(fb, desktop);
|
RenderBackground(fb, desktop);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Render(struct dispd_window* window, struct RenderInfo* info)
|
static bool Render(struct RenderInfo* info)
|
||||||
{
|
{
|
||||||
struct dispd_framebuffer* fb = dispd_begin_render(window);
|
struct dispmsg_get_crtc_mode get_mode_msg;
|
||||||
if ( !fb )
|
memset(&get_mode_msg, 0, sizeof(get_mode_msg));
|
||||||
return false;
|
get_mode_msg.msgid = DISPMSG_GET_CRTC_MODE;
|
||||||
FrameBufferInfo fbinfo(fb);
|
get_mode_msg.device = 0; // TODO: Multi-screen support!
|
||||||
|
get_mode_msg.connector = 0; // TODO: Multi-screen support!
|
||||||
|
if ( dispmsg_issue(&get_mode_msg, sizeof(get_mode_msg)) != 0 )
|
||||||
|
err(1, "dispmsg_issue: dispmsg_get_crtc_mode");
|
||||||
|
struct dispmsg_crtc_mode mode = get_mode_msg.mode;
|
||||||
|
|
||||||
|
if ( !(mode.control & DISPMSG_CONTROL_VALID) )
|
||||||
|
errx(1, "No valid video mode was set");
|
||||||
|
if ( mode.control & DISPMSG_CONTROL_VGA )
|
||||||
|
errx(1, "A VGA text mode was set");
|
||||||
|
if ( mode.fb_format != 32 )
|
||||||
|
errx(1, "A 32-bit video mode wasn't set");
|
||||||
|
|
||||||
|
size_t pitch = 4 * mode.view_xres;
|
||||||
|
size_t framebuffer_size = pitch * mode.view_yres;
|
||||||
|
uint8_t* framebuffer = (uint8_t*) malloc(framebuffer_size);
|
||||||
|
if ( !framebuffer )
|
||||||
|
err(1, "malloc");
|
||||||
|
|
||||||
|
FrameBufferInfo fbinfo(framebuffer, pitch, mode.view_xres, mode.view_yres);
|
||||||
Render(fbinfo, &info->desktop);
|
Render(fbinfo, &info->desktop);
|
||||||
dispd_finish_render(fb);
|
|
||||||
|
struct dispmsg_write_memory write_memory_msg;
|
||||||
|
memset(&write_memory_msg, 0, sizeof(write_memory_msg));
|
||||||
|
write_memory_msg.msgid = DISPMSG_WRITE_MEMORY;
|
||||||
|
write_memory_msg.device = get_mode_msg.device;
|
||||||
|
write_memory_msg.offset = get_mode_msg.connector;
|
||||||
|
write_memory_msg.size = framebuffer_size;
|
||||||
|
write_memory_msg.src = framebuffer;
|
||||||
|
if ( dispmsg_issue(&write_memory_msg, sizeof(write_memory_msg)) != 0 )
|
||||||
|
err(1, "dispmsg_issue: dispmsg_write_memory");
|
||||||
|
|
||||||
|
free(framebuffer);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1834,7 +1858,7 @@ static void HandleEvents(int kbfd, struct Desktop* desktop)
|
||||||
desktop->text_angle += text_speed * delta;
|
desktop->text_angle += text_speed * delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int MainLoop(int argc, char* argv[], int kbfd, struct dispd_window* window)
|
static int MainLoop(int argc, char* argv[], int kbfd)
|
||||||
{
|
{
|
||||||
(void) argc;
|
(void) argc;
|
||||||
(void) argv;
|
(void) argv;
|
||||||
|
@ -1843,7 +1867,7 @@ static int MainLoop(int argc, char* argv[], int kbfd, struct dispd_window* windo
|
||||||
for ( info.frame = 0; true; info.frame++ )
|
for ( info.frame = 0; true; info.frame++ )
|
||||||
{
|
{
|
||||||
HandleEvents(kbfd, &info.desktop);
|
HandleEvents(kbfd, &info.desktop);
|
||||||
if ( !Render(window, &info) )
|
if ( !Render(&info) )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1892,27 +1916,13 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
memcpy(font + 128 * 16, rune_font, sizeof(rune_font));
|
memcpy(font + 128 * 16, rune_font, sizeof(rune_font));
|
||||||
|
|
||||||
if ( !dispd_initialize(&argc, &argv) )
|
|
||||||
error(1, 0, "couldn't initialize dispd library");
|
|
||||||
struct dispd_session* session = dispd_attach_default_session();
|
|
||||||
if ( !session )
|
|
||||||
error(1, 0, "couldn't attach to dispd default session");
|
|
||||||
if ( !dispd_session_setup_game_rgba(session) )
|
|
||||||
error(1, 0, "couldn't setup dispd rgba session");
|
|
||||||
struct dispd_window* window = dispd_create_window_game_rgba(session);
|
|
||||||
if ( !window )
|
|
||||||
error(1, 0, "couldn't create dispd rgba window");
|
|
||||||
|
|
||||||
int kbfd = CreateKeyboardConnection();
|
int kbfd = CreateKeyboardConnection();
|
||||||
if ( kbfd < 0 )
|
if ( kbfd < 0 )
|
||||||
error(1, 0, "couldn't create keyboard connection");
|
error(1, 0, "couldn't create keyboard connection");
|
||||||
|
|
||||||
int ret = MainLoop(argc, argv, kbfd, window);
|
int ret = MainLoop(argc, argv, kbfd);
|
||||||
|
|
||||||
close(kbfd);
|
close(kbfd);
|
||||||
|
|
||||||
dispd_destroy_window(window);
|
|
||||||
dispd_detach_session(session);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue