Compare commits

..

No commits in common. "1903483c0cfb43338859f6c2c8ff84a25d567e10" and "be23ab5b0edb5bf23a7167b0109ee555dd6d2be4" have entirely different histories.

15 changed files with 182 additions and 310 deletions

View File

@ -11,7 +11,7 @@ CFLAGS += -Wall -Wextra
BINARIES = chkblayout BINARIES = chkblayout
MANPAGES1 = chkblayout.1 MANPAGES1 = chkblayout.1
LIBS = -ldisplay LIBS =
all: $(BINARIES) all: $(BINARIES)

View File

@ -20,7 +20,6 @@
#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>
@ -35,20 +34,6 @@
#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;
@ -118,29 +103,8 @@ 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 ( getenv("DISPLAY_SOCKET") ) if ( tcsetblob(tty_fd, "kblayout", kblayout, kblayout_size) < 0 )
{ 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);

View File

@ -1,6 +1,5 @@
/* /*
* 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
@ -29,7 +28,6 @@
#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"
@ -99,23 +97,14 @@ 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* auxiliary __attribute__((unused)), \ void* auxilerary __attribute__((unused)), \
size_t auxiliary_size __attribute__((unused)), \ size_t auxilerary_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* auxiliary, \ unsigned char* auxilerary, \
size_t auxiliary_size, \ size_t auxilerary_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)
{ {
@ -168,9 +157,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*) auxiliary; src.buffer = (uint32_t*) auxilerary;
if ( auxiliary_size < sizeof(uint32_t) * src.xres * src.yres ) if ( auxilerary_size < sizeof(uint32_t) * src.xres * src.yres )
return; return;
struct framebuffer dst = struct framebuffer dst =
@ -186,9 +175,9 @@ CONNECTION_MESSAGE_HANDLER(title_window)
if ( !window ) if ( !window )
return; return;
const char* title = (char*) auxiliary; const char* title = (char*) auxilerary;
free(window->title); free(window->title);
window->title = strndup(title, auxiliary_size); window->title = strndup(title, auxilerary_size);
window_render_frame(window); window_render_frame(window);
} }
@ -209,27 +198,10 @@ 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* auxiliary, void* auxilerary,
size_t auxiliary_size, size_t auxilerary_size);
const struct server* server);
struct connection_message_handler_registration struct connection_message_handler_registration
{ {
@ -251,7 +223,6 @@ 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) /
@ -262,8 +233,7 @@ 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) )
{ {
@ -302,10 +272,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* auxiliary = connection->packet + handler->message_size; unsigned char* auxilerary = connection->packet + handler->message_size;
size_t auxiliary_size = packet_length - handler->message_size; size_t auxilerary_size = packet_length - handler->message_size;
handler->handler(connection, connection->packet, handler->handler(connection, connection->packet,
auxiliary, auxiliary_size, server); auxilerary, auxilerary_size);
} }
connection->packet_header_received = 0; connection->packet_header_received = 0;

View File

@ -25,7 +25,6 @@
#include <display-protocol.h> #include <display-protocol.h>
#include "server.h"
#include "window.h" #include "window.h"
struct display; struct display;
@ -59,8 +58,7 @@ 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);

View File

@ -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(server->tty_fd) ) if ( !isatty(0) )
{ {
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, server); connection_can_read(connection);
} }
// Compact the array down here so the pfds match the connections above. // Compact the array down here so the pfds match the connections above.

View File

@ -15,7 +15,7 @@ BINARIES:=\
asteroids \ asteroids \
aquatinspitz \ aquatinspitz \
LIBS:=-ldisplay LIBS:=-ldispd -ldisplay
all: $(BINARIES) all: $(BINARIES)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2015, 2016, 2023 Jonas 'Sortie' Termansen. * Copyright (c) 2014, 2015, 2016 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,7 +22,6 @@
#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>
@ -35,15 +34,12 @@
#include <timespec.h> #include <timespec.h>
#include <unistd.h> #include <unistd.h>
#include <display.h> #include <dispd.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 = 800; static size_t game_width = 1280;
static size_t game_height = 512; static size_t game_height = 720;
#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];
@ -204,16 +200,20 @@ void update(float deltatime)
} }
// Render the game into the framebuffer. // Render the game into the framebuffer.
void render(struct display_connection* connection) void render(struct dispd_window* window)
{ {
size_t old_framesize = framesize; struct dispd_framebuffer* window_fb = dispd_begin_render(window);
if ( !window_fb )
{
error(0, 0, "unable to begin rendering dispd window");
game_running = false;
return;
}
size_t xres = game_width; uint32_t* fb = (uint32_t*) dispd_get_framebuffer_data(window_fb);
size_t yres = game_height; size_t xres = dispd_get_framebuffer_width(window_fb);
size_t pitch = xres; size_t yres = dispd_get_framebuffer_height(window_fb);
framesize = xres * yres * sizeof(uint32_t); size_t pitch = dispd_get_framebuffer_pitch(window_fb) / 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,9 +273,7 @@ void render(struct display_connection* connection)
} }
} }
display_render_window(connection, window_id, 0, 0, dispd_finish_render(window_fb);
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.
@ -312,68 +310,50 @@ bool pop_is_key_just_down(int abskbkey)
return true; return true;
} }
// When the connection to the display server has disconnected. // Read input from the keyboard.
void on_disconnect(void* ctx) void input(void)
{ {
(void) ctx; // Read the keyboard input from the user.
exit(0); unsigned termmode = TERMMODE_KBKEY | TERMMODE_SIGNAL | TERMMODE_NONBLOCK;
} if ( settermmode(0, termmode) )
error(1, errno, "settermmode");
// When the window is asked to quit. uint32_t codepoint;
void on_quit(void* ctx, uint32_t window_id) ssize_t numbytes;
{ while ( 0 < (numbytes = read(0, &codepoint, sizeof(codepoint))) )
(void) ctx; {
(void) window_id; int kbkey = KBKEY_DECODE(codepoint);
exit(0); if( !kbkey )
} continue;
int abskbkey = (kbkey < 0) ? -kbkey : kbkey;
// When the window has been resized. if ( MAX_KEY_NUMBER <= (size_t) abskbkey )
void on_resize(void* ctx, uint32_t window_id, uint32_t width, uint32_t height) continue;
{ bool is_key_down_event = 0 < kbkey;
(void) ctx; if ( !keys_down[abskbkey] && is_key_down_event )
if ( window_id != window_id ) keys_pending[abskbkey] = true;
return; keys_down[abskbkey] = is_key_down_event;
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 display_connection* connection) void mainloop(struct dispd_window* window)
{ {
struct display_event_handlers handlers = {0}; struct dispd_framebuffer* window_fb = dispd_begin_render(window);
handlers.disconnect_handler = on_disconnect; if ( window_fb )
handlers.quit_handler = on_quit; {
handlers.resize_handler = on_resize; game_width = dispd_get_framebuffer_width(window_fb);
handlers.keyboard_handler = on_keyboard; game_height = dispd_get_framebuffer_height(window_fb);
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(connection); render(window);
while ( game_running ) while ( game_running )
{ {
struct timespec current_frame_time; struct timespec current_frame_time;
clock_gettime(CLOCK_MONOTONIC, &current_frame_time); clock_gettime(CLOCK_MONOTONIC, &current_frame_time);
@ -381,31 +361,71 @@ void mainloop(struct display_connection* connection)
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;
while ( display_poll_event(connection, &handlers) == 0 ); input();
update(deltatime); update(deltatime);
render(connection); render(window);
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[])
{ {
struct display_connection* connection = display_connect_default(); if ( !isatty(0) )
if ( !connection && errno == ECONNREFUSED ) error(1, errno, "standard input");
display_spawn(argc, argv); if ( tcgetattr(0, &saved_tio) < 0 )
if ( !connection ) error(1, errno, "tcsetattr: standard input");
error(1, errno, "Could not connect to display server"); if ( atexit(restore_terminal_on_exit) != 0 )
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);
display_create_window(connection, window_id); if ( !dispd_initialize(&argc, &argv) )
display_resize_window(connection, window_id, game_width, game_height); error(1, 0, "couldn't initialize dispd library");
display_title_window(connection, window_id, "Aquatinspitz"); 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");
mainloop(connection); mainloop(window);
display_disconnect(connection); dispd_destroy_window(window);
dispd_detach_session(session);
return 0; return 0;
} }

View File

@ -21,7 +21,6 @@
#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>
@ -1180,8 +1179,6 @@ 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();
@ -1202,8 +1199,7 @@ 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, display_render_window(connection, WINDOW_ID, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, buf);
WINDOW_WIDTH, WINDOW_HEIGHT, buf);
display_show_window(connection, WINDOW_ID); display_show_window(connection, WINDOW_ID);
} }

View File

@ -1,6 +1,5 @@
/* /*
* 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
@ -85,13 +84,6 @@ 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
{ {
@ -118,11 +110,4 @@ struct event_keyboard
uint32_t codepoint; uint32_t codepoint;
}; };
#define EVENT_ACK 4
struct event_ack
{
uint32_t id;
int error;
};
#endif #endif

View File

@ -1,6 +1,5 @@
/* /*
* 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
@ -47,8 +46,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 width, uint32_t
uint32_t height); 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,
@ -57,24 +56,18 @@ 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
{ {
@ -83,7 +76,6 @@ 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,

View File

@ -1,6 +1,5 @@
/* /*
* 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
@ -91,8 +90,7 @@ 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, setsockopt(connection->fd, SOL_SOCKET, SO_SNDBUF, &send_buffer_size, sizeof(send_buffer_size));
sizeof(send_buffer_size));
return connection; return connection;
} }
@ -115,25 +113,20 @@ int display_connection_fd(struct display_connection* connection)
return connection->fd; return connection->fd;
} }
static void send_message(struct display_connection* connection, static void send_message(struct display_connection* connection, uint32_t message_id,
uint32_t message_id, const void* message, size_t message_size,
const void* message, const void* auxilerary, size_t auxilerary_size)
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 + auxiliary_size; header.message_length = message_size + auxilerary_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, auxiliary, auxiliary_size); writeall(connection->fd, auxilerary, auxilerary_size);
} }
static void send_message_no_aux(struct display_connection* connection, static void send_message_no_aux(struct display_connection* connection, uint32_t message_id,
uint32_t message_id, const void* message, size_t message_size)
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);
} }
@ -145,26 +138,21 @@ 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, void display_create_window(struct display_connection* connection, uint32_t window_id)
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, void display_destroy_window(struct display_connection* connection, uint32_t window_id)
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, void display_resize_window(struct display_connection* connection, uint32_t window_id, uint32_t width, uint32_t height)
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;
@ -173,13 +161,7 @@ void display_resize_window(struct display_connection* connection,
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, 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)
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;
@ -191,42 +173,27 @@ void display_render_window(struct display_connection* connection,
data, sizeof(uint32_t) * width * height); data, sizeof(uint32_t) * width * height);
} }
void display_title_window(struct display_connection* connection, void display_title_window(struct display_connection* connection, uint32_t window_id, const char* title)
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, void display_show_window(struct display_connection* connection, uint32_t window_id)
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, void display_hide_window(struct display_connection* connection, uint32_t window_id)
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) )
@ -269,8 +236,7 @@ static bool display_read_event(struct display_connection* connection)
return true; return true;
} }
static int display_dispatch_event(struct display_connection* connection, static int display_dispatch_event(struct display_connection* connection, struct display_event_handlers* handlers)
struct display_event_handlers* handlers)
{ {
if ( connection->header_bytes == sizeof(connection->header) && if ( connection->header_bytes == sizeof(connection->header) &&
connection->payload && connection->payload &&
@ -315,14 +281,6 @@ static int display_dispatch_event(struct display_connection* connection,
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;
@ -342,8 +300,7 @@ static int display_event_read_hangup(struct display_event_handlers* handlers)
return -1; return -1;
} }
int display_poll_event(struct display_connection* connection, int display_poll_event(struct display_connection* connection, struct display_event_handlers* handlers)
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);
@ -353,8 +310,7 @@ int display_poll_event(struct display_connection* connection,
return display_dispatch_event(connection, handlers); return display_dispatch_event(connection, handlers);
} }
int display_wait_event(struct display_connection* connection, int display_wait_event(struct display_connection* connection, struct display_event_handlers* handlers)
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);

View File

@ -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");
bool kblayout_setable = 0 <= tcgetblob(0, "kblayout", NULL, 0) || // TODO: GUI support.
getenv("DISPLAY_SOCKET"); bool kblayout_setable = 0 <= tcgetblob(0, "kblayout", NULL, 0);
while ( kblayout_setable ) while ( kblayout_setable )
{ {
// TODO: Detect the name of the current keyboard layout. // TODO: Detect the name of the current keyboard layout.

View File

@ -466,8 +466,7 @@ 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.

View File

@ -11,6 +11,8 @@ 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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013, 2014, 2015, 2016, 2018, 2013 Jonas 'Sortie' Termansen. * Copyright (c) 2013, 2014, 2015, 2016, 2018 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 <err.h> #include <dispd.h>
#include <errno.h> #include <errno.h>
#include <error.h> #include <error.h>
#include <fcntl.h> #include <fcntl.h>
@ -892,6 +892,13 @@ 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:
@ -1426,45 +1433,14 @@ static void Render(FrameBufferInfo fb, struct Desktop* desktop)
RenderBackground(fb, desktop); RenderBackground(fb, desktop);
} }
static bool Render(struct RenderInfo* info) static bool Render(struct dispd_window* window, struct RenderInfo* info)
{ {
struct dispmsg_get_crtc_mode get_mode_msg; struct dispd_framebuffer* fb = dispd_begin_render(window);
memset(&get_mode_msg, 0, sizeof(get_mode_msg)); if ( !fb )
get_mode_msg.msgid = DISPMSG_GET_CRTC_MODE; return false;
get_mode_msg.device = 0; // TODO: Multi-screen support! FrameBufferInfo fbinfo(fb);
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;
} }
@ -1858,7 +1834,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) static int MainLoop(int argc, char* argv[], int kbfd, struct dispd_window* window)
{ {
(void) argc; (void) argc;
(void) argv; (void) argv;
@ -1867,7 +1843,7 @@ static int MainLoop(int argc, char* argv[], int kbfd)
for ( info.frame = 0; true; info.frame++ ) for ( info.frame = 0; true; info.frame++ )
{ {
HandleEvents(kbfd, &info.desktop); HandleEvents(kbfd, &info.desktop);
if ( !Render(&info) ) if ( !Render(window, &info) )
return 1; return 1;
} }
return 0; return 0;
@ -1916,13 +1892,27 @@ 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); int ret = MainLoop(argc, argv, kbfd, window);
close(kbfd); close(kbfd);
dispd_destroy_window(window);
dispd_detach_session(session);
return ret; return ret;
} }