fixup! Add display server.

This commit is contained in:
Juhani Krekelä 2023-05-15 23:04:05 +03:00
parent be23ab5b0e
commit b9d6423f76
10 changed files with 182 additions and 46 deletions

View File

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

View File

@ -20,6 +20,7 @@
#include <sys/stat.h>
#include <display.h>
#include <err.h>
#include <errno.h>
#include <error.h>
@ -34,6 +35,20 @@
#include <unistd.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[])
{
bool list = false;
@ -103,8 +118,29 @@ int main(int argc, char* argv[])
err(1, "read: %s", kblayout_path);
close(kblayout_fd);
if ( tcsetblob(tty_fd, "kblayout", kblayout, kblayout_size) < 0 )
err(1, "tcsetblob: kblayout: %s:", kblayout_path);
if ( getenv("DISPLAY_SOCKET") )
{
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);

View File

@ -1,5 +1,6 @@
/*
* 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
* purpose with or without fee is hereby granted, provided that the above
@ -28,6 +29,7 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include "connection.h"
@ -97,14 +99,23 @@ struct window* connection_find_window(struct connection* connection,
#define CONNECTION_MESSAGE_HANDLER_NO_AUX(message_name) \
void connection_handler_##message_name(struct connection* connection, \
struct display_##message_name* msg, \
void* auxilerary __attribute__((unused)), \
size_t auxilerary_size __attribute__((unused)))
void* auxiliary __attribute__((unused)), \
size_t auxiliary_size __attribute__((unused)), \
const struct server* server __attribute__((unused)))
#define CONNECTION_MESSAGE_HANDLER(message_name) \
void connection_handler_##message_name(struct connection* connection, \
struct display_##message_name* msg, \
unsigned char* auxilerary, \
size_t auxilerary_size)
unsigned char* auxiliary, \
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)
{
@ -157,9 +168,9 @@ CONNECTION_MESSAGE_HANDLER(render_window)
src.xres = msg->width;
src.yres = msg->height;
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;
struct framebuffer dst =
@ -175,9 +186,9 @@ CONNECTION_MESSAGE_HANDLER(title_window)
if ( !window )
return;
const char* title = (char*) auxilerary;
const char* title = (char*) auxiliary;
free(window->title);
window->title = strndup(title, auxilerary_size);
window->title = strndup(title, auxiliary_size);
window_render_frame(window);
}
@ -198,10 +209,27 @@ CONNECTION_MESSAGE_HANDLER_NO_AUX(hide_window)
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,
void* msg,
void* auxilerary,
size_t auxilerary_size);
void* auxiliary,
size_t auxiliary_size,
const struct server* server);
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(hide_window),
REGISTER_CONNECTION_MESSAGE_HANDLER(shutdown),
REGISTER_CONNECTION_MESSAGE_HANDLER(chkblayout),
};
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);
}
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) )
{
@ -272,10 +302,10 @@ void connection_can_read(struct connection* connection)
{
struct connection_message_handler_registration* handler =
&connection_message_handlers[packet_id];
unsigned char* auxilerary = connection->packet + handler->message_size;
size_t auxilerary_size = packet_length - handler->message_size;
unsigned char* auxiliary = connection->packet + handler->message_size;
size_t auxiliary_size = packet_length - handler->message_size;
handler->handler(connection, connection->packet,
auxilerary, auxilerary_size);
auxiliary, auxiliary_size, server);
}
connection->packet_header_received = 0;

View File

@ -25,6 +25,7 @@
#include <display-protocol.h>
#include "server.h"
#include "window.h"
struct display;
@ -58,7 +59,8 @@ struct window* connection_find_window_raw(struct connection* connection,
struct window* connection_find_window(struct connection* connection,
uint32_t window_id);
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_destroy(struct connection* connection);

View File

@ -68,7 +68,7 @@ void server_initialize(struct server* server, struct display* display)
load_font();
server->tty_fd = 0;
if ( !isatty(0) )
if ( !isatty(server->tty_fd) )
{
server->tty_fd = open("/dev/tty", O_RDONLY);
if ( server->tty_fd < 0 )
@ -245,7 +245,7 @@ void server_poll(struct server* server)
if ( pfd->revents & POLLOUT )
connection_can_write(connection);
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.

View File

@ -1,5 +1,6 @@
/*
* 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
* purpose with or without fee is hereby granted, provided that the above
@ -84,6 +85,13 @@ struct display_shutdown
uint32_t code;
};
#define DISPLAY_CHKBLAYOUT 8
struct display_chkblayout
{
uint32_t id;
/* keyboard layout data bytes follow */
};
#define EVENT_DISCONNECT 0
struct event_disconnect
{
@ -110,4 +118,11 @@ struct event_keyboard
uint32_t codepoint;
};
#define EVENT_ACK 4
struct event_ack
{
uint32_t id;
int error;
};
#endif

View File

@ -1,5 +1,6 @@
/*
* 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
* 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);
void display_resize_window(struct display_connection* connection,
uint32_t window_id,
uint32_t width, uint32_t
height);
uint32_t width,
uint32_t height);
void display_render_window(struct display_connection* connection,
uint32_t window_id,
uint32_t left,
@ -56,18 +57,24 @@ void display_render_window(struct display_connection* connection,
uint32_t height,
uint32_t* data);
void display_title_window(struct display_connection* connection,
uint32_t window_id,
const char* title);
uint32_t window_id,
const char* title);
void display_show_window(struct display_connection* connection,
uint32_t window_id);
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_quit_handler_t)(void*, uint32_t);
typedef void (*display_event_resize_handler_t)(void*, uint32_t, 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
{
@ -76,6 +83,7 @@ struct display_event_handlers
display_event_quit_handler_t quit_handler;
display_event_resize_handler_t resize_handler;
display_event_keyboard_handler_t keyboard_handler;
display_event_ack_handler_t ack_handler;
};
int display_poll_event(struct display_connection* connection,

View File

@ -1,5 +1,6 @@
/*
* 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
* 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 )
return free(connection), (struct display_connection*) NULL;
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;
}
@ -113,20 +115,25 @@ int display_connection_fd(struct display_connection* connection)
return connection->fd;
}
static void send_message(struct display_connection* connection, uint32_t message_id,
const void* message, size_t message_size,
const void* auxilerary, size_t auxilerary_size)
static void send_message(struct display_connection* connection,
uint32_t message_id,
const void* message,
size_t message_size,
const void* auxiliary,
size_t auxiliary_size)
{
struct display_packet_header header;
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, 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,
const void* message, size_t message_size)
static void send_message_no_aux(struct display_connection* connection,
uint32_t message_id,
const void* message,
size_t message_size)
{
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));
}
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;
msg.window_id = window_id;
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;
msg.window_id = window_id;
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;
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));
}
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;
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);
}
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;
msg.window_id = window_id;
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;
msg.window_id = window_id;
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;
msg.window_id = window_id;
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)
{
while ( connection->header_bytes < sizeof(connection->header) )
@ -236,7 +269,8 @@ static bool display_read_event(struct display_connection* connection)
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) &&
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);
}
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;
free(connection->payload), connection->payload = NULL;
connection->payload_bytes = 0;
@ -300,7 +342,8 @@ static int display_event_read_hangup(struct display_event_handlers* handlers)
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);
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);
}
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) )
return display_event_read_hangup(handlers);

View File

@ -568,8 +568,8 @@ int main(void)
conf.release_sig_url);
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 )
{
// TODO: Detect the name of the current keyboard layout.

View File

@ -466,7 +466,8 @@ int main(void)
prompt(input, sizeof(input), "ready", "Ready?", ready);
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 )
{
// TODO: Detect the name of the current keyboard layout.