fixup! Add display server.
This commit is contained in:
parent
63260a916e
commit
6d08070639
|
@ -706,5 +706,8 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
if ( use_display )
|
||||
display_disconnect(connection);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,17 @@ void connection_schedule_transmit(struct connection* connection,
|
|||
connection->outgoing_used += count;
|
||||
}
|
||||
|
||||
void connection_schedule_ack_event(struct connection* connection,
|
||||
uint32_t id,
|
||||
int32_t error)
|
||||
{
|
||||
struct event_ack event = { .id = id, .error = error };
|
||||
struct display_packet_header header = { .id = EVENT_ACK,
|
||||
.size = sizeof(event) };
|
||||
connection_schedule_transmit(connection, &header, sizeof(header));
|
||||
connection_schedule_transmit(connection, &event, sizeof(event));
|
||||
}
|
||||
|
||||
void connection_initialize(struct connection* connection,
|
||||
struct display* display,
|
||||
int fd)
|
||||
|
@ -235,18 +246,10 @@ CONNECTION_MESSAGE_HANDLER_NO_AUX(hide_window)
|
|||
|
||||
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.id = EVENT_ACK;
|
||||
header.size = sizeof(event);
|
||||
|
||||
connection_schedule_transmit(connection, &header, sizeof(header));
|
||||
connection_schedule_transmit(connection, &event, sizeof(event));
|
||||
connection_schedule_ack_event(connection, msg->id, errno);
|
||||
else
|
||||
connection_schedule_ack_event(connection, msg->id, 0);
|
||||
}
|
||||
|
||||
CONNECTION_MESSAGE_HANDLER_NO_AUX(request_displays)
|
||||
|
@ -297,53 +300,84 @@ get_available_modes(const struct tiocgdisplay* display,
|
|||
|
||||
CONNECTION_MESSAGE_HANDLER_NO_AUX_SERVER(request_display_modes)
|
||||
{
|
||||
struct event_display_modes success;
|
||||
success.id = msg->id;
|
||||
success.modes_count = 0;
|
||||
struct event_ack failure;
|
||||
failure.id = msg->id;
|
||||
failure.error = 0;
|
||||
struct event_display_modes event;
|
||||
event.id = msg->id;
|
||||
event.modes_count = 0;
|
||||
|
||||
struct dispmsg_crtc_mode* modes = NULL;
|
||||
// TODO: Multimonitor support.
|
||||
if ( msg->display_id != 0 )
|
||||
failure.error = EINVAL;
|
||||
else
|
||||
{
|
||||
size_t modes_count = 0;
|
||||
modes = get_available_modes(&server->display->display, &modes_count);
|
||||
if ( !modes )
|
||||
failure.error = errno;
|
||||
else if ( (uint32_t) modes_count != modes_count )
|
||||
{
|
||||
failure.error = EOVERFLOW;
|
||||
free(modes);
|
||||
}
|
||||
success.modes_count = modes_count;
|
||||
}
|
||||
|
||||
if ( failure.error )
|
||||
{
|
||||
struct display_packet_header header;
|
||||
header.id = EVENT_ACK;
|
||||
header.size = sizeof(failure);
|
||||
|
||||
connection_schedule_transmit(connection, &header, sizeof(header));
|
||||
connection_schedule_transmit(connection, &failure, sizeof(failure));
|
||||
connection_schedule_ack_event(connection, msg->id, EINVAL);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t modes_count;
|
||||
modes = get_available_modes(&server->display->display, &modes_count);
|
||||
if ( !modes )
|
||||
{
|
||||
connection_schedule_ack_event(connection, msg->id, errno);
|
||||
return;
|
||||
}
|
||||
else if ( (uint32_t) modes_count != modes_count )
|
||||
{
|
||||
free(modes);
|
||||
connection_schedule_ack_event(connection, msg->id, EOVERFLOW);
|
||||
return;
|
||||
}
|
||||
event.modes_count = modes_count;
|
||||
}
|
||||
|
||||
size_t modes_size = success.modes_count * sizeof(struct dispmsg_crtc_mode);
|
||||
size_t modes_size = event.modes_count * sizeof(struct dispmsg_crtc_mode);
|
||||
|
||||
struct display_packet_header header;
|
||||
header.id = EVENT_DISPLAY_MODES;
|
||||
header.size = sizeof(success) + modes_size;
|
||||
header.size = sizeof(event) + modes_size;
|
||||
|
||||
connection_schedule_transmit(connection, &header, sizeof(header));
|
||||
connection_schedule_transmit(connection, &success, sizeof(success));
|
||||
connection_schedule_transmit(connection, &event, sizeof(event));
|
||||
connection_schedule_transmit(connection, modes, modes_size);
|
||||
}
|
||||
|
||||
static bool get_current_mode(const struct tiocgdisplay* display,
|
||||
struct dispmsg_crtc_mode* mode)
|
||||
{
|
||||
struct dispmsg_set_crtc_mode msg;
|
||||
msg.msgid = DISPMSG_GET_CRTC_MODE;
|
||||
msg.device = display->device;
|
||||
msg.connector = display->connector;
|
||||
if ( dispmsg_issue(&msg, sizeof(msg)) )
|
||||
return false;
|
||||
*mode = msg.mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
CONNECTION_MESSAGE_HANDLER_NO_AUX_SERVER(request_display_mode)
|
||||
{
|
||||
struct event_display_mode event;
|
||||
event.id = msg->id;
|
||||
|
||||
// TODO: Multimonitor support.
|
||||
if ( msg->display_id != 0 )
|
||||
{
|
||||
connection_schedule_ack_event(connection, msg->id, EINVAL);
|
||||
return;
|
||||
}
|
||||
else if ( !get_current_mode(&server->display->display, &event.mode) )
|
||||
{
|
||||
connection_schedule_ack_event(connection, msg->id, EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
struct display_packet_header header;
|
||||
header.id = EVENT_DISPLAY_MODE;
|
||||
header.size = sizeof(event);
|
||||
|
||||
connection_schedule_transmit(connection, &header, sizeof(header));
|
||||
connection_schedule_transmit(connection, &event, sizeof(event));
|
||||
}
|
||||
|
||||
static bool set_current_mode(const struct tiocgdisplay* display,
|
||||
struct dispmsg_crtc_mode mode)
|
||||
{
|
||||
|
@ -357,21 +391,13 @@ static bool set_current_mode(const struct tiocgdisplay* display,
|
|||
|
||||
CONNECTION_MESSAGE_HANDLER_NO_AUX_SERVER(set_display_mode)
|
||||
{
|
||||
struct event_ack event;
|
||||
event.id = msg->id;
|
||||
event.error = 0;
|
||||
// TODO: Multimonitor support.
|
||||
if ( msg->display_id != 0 )
|
||||
event.error = EINVAL;
|
||||
connection_schedule_ack_event(connection, msg->id, EINVAL);
|
||||
else if ( !set_current_mode(&server->display->display, msg->mode) )
|
||||
event.error = errno;
|
||||
|
||||
struct display_packet_header header;
|
||||
header.id = EVENT_ACK;
|
||||
header.size = sizeof(event);
|
||||
|
||||
connection_schedule_transmit(connection, &header, sizeof(header));
|
||||
connection_schedule_transmit(connection, &event, sizeof(event));
|
||||
connection_schedule_ack_event(connection, msg->id, errno);
|
||||
else
|
||||
connection_schedule_ack_event(connection, msg->id, 0);
|
||||
}
|
||||
|
||||
typedef void (*connection_message_handler)(struct connection* connection,
|
||||
|
@ -403,6 +429,7 @@ struct connection_message_handler_registration connection_message_handlers[] =
|
|||
REGISTER_CONNECTION_MESSAGE_HANDLER(chkblayout),
|
||||
REGISTER_CONNECTION_MESSAGE_HANDLER(request_displays),
|
||||
REGISTER_CONNECTION_MESSAGE_HANDLER(request_display_modes),
|
||||
REGISTER_CONNECTION_MESSAGE_HANDLER(request_display_mode),
|
||||
REGISTER_CONNECTION_MESSAGE_HANDLER(set_display_mode),
|
||||
};
|
||||
|
||||
|
|
|
@ -107,7 +107,14 @@ struct display_request_display_modes
|
|||
uint32_t display_id;
|
||||
};
|
||||
|
||||
#define DISPLAY_SET_DISPLAY_MODE 11
|
||||
#define DISPLAY_REQUEST_DISPLAY_MODE 11
|
||||
struct display_request_display_mode
|
||||
{
|
||||
uint32_t id;
|
||||
uint32_t display_id;
|
||||
};
|
||||
|
||||
#define DISPLAY_SET_DISPLAY_MODE 12
|
||||
struct display_set_display_mode
|
||||
{
|
||||
uint32_t id;
|
||||
|
@ -163,4 +170,11 @@ struct event_display_modes
|
|||
/* modes_count * sizeof(struct dispmsg_crtc_mode) video mode bytes follow */
|
||||
};
|
||||
|
||||
#define EVENT_DISPLAY_MODE 7
|
||||
struct event_display_mode
|
||||
{
|
||||
uint32_t id;
|
||||
struct dispmsg_crtc_mode mode;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -71,6 +71,9 @@ void display_request_displays(struct display_connection* connection,
|
|||
void display_request_display_modes(struct display_connection* connection,
|
||||
uint32_t id,
|
||||
uint32_t display_id);
|
||||
void display_request_display_mode(struct display_connection* connection,
|
||||
uint32_t id,
|
||||
uint32_t display_id);
|
||||
void display_set_display_mode(struct display_connection* connection,
|
||||
uint32_t id,
|
||||
uint32_t display_id,
|
||||
|
@ -85,6 +88,8 @@ typedef void (*display_event_ack_handler_t)(void*, uint32_t, int32_t);
|
|||
typedef void (*display_event_displays_handler_t)(void*, uint32_t, uint32_t);
|
||||
typedef void (*display_event_display_modes_handler_t)(void*, uint32_t, uint32_t,
|
||||
void*, size_t);
|
||||
typedef void (*display_event_display_mode_handler_t)(void*, uint32_t,
|
||||
struct dispmsg_crtc_mode);
|
||||
|
||||
struct display_event_handlers
|
||||
{
|
||||
|
@ -96,6 +101,7 @@ struct display_event_handlers
|
|||
display_event_ack_handler_t ack_handler;
|
||||
display_event_displays_handler_t displays_handler;
|
||||
display_event_display_modes_handler_t display_modes_handler;
|
||||
display_event_display_mode_handler_t display_mode_handler;
|
||||
};
|
||||
|
||||
int display_poll_event(struct display_connection* connection,
|
||||
|
|
|
@ -249,6 +249,17 @@ void display_request_display_modes(struct display_connection* connection,
|
|||
sizeof(msg));
|
||||
}
|
||||
|
||||
void display_request_display_mode(struct display_connection* connection,
|
||||
uint32_t id,
|
||||
uint32_t display_id)
|
||||
{
|
||||
struct display_request_display_mode msg;
|
||||
msg.id = id;
|
||||
msg.display_id = display_id;
|
||||
send_message_no_aux(connection, DISPLAY_REQUEST_DISPLAY_MODE, &msg,
|
||||
sizeof(msg));
|
||||
}
|
||||
|
||||
void display_set_display_mode(struct display_connection* connection,
|
||||
uint32_t id,
|
||||
uint32_t display_id,
|
||||
|
@ -381,6 +392,15 @@ static int display_dispatch_event(struct display_connection* connection,
|
|||
aux, aux_size);
|
||||
}
|
||||
|
||||
if ( connection->header.id == EVENT_DISPLAY_MODE &&
|
||||
connection->header.size == sizeof(struct event_display_mode) )
|
||||
{
|
||||
struct event_display_mode* event = payload;
|
||||
if ( handlers->display_mode_handler )
|
||||
handlers->display_mode_handler(handlers->context, event->id,
|
||||
event->mode);
|
||||
}
|
||||
|
||||
connection->header_got = 0;
|
||||
free(connection->payload);
|
||||
connection->payload = NULL;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2016, 2017 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2015, 2016, 2017, 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
|
||||
|
@ -23,6 +24,7 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <display.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
@ -40,6 +42,16 @@
|
|||
#include "execute.h"
|
||||
#include "interactive.h"
|
||||
|
||||
#define REQUEST_DISPLAYS_ID 0
|
||||
#define REQUEST_DISPLAY_MODE_ID 1
|
||||
|
||||
static uint32_t displays_count;
|
||||
static bool displays_count_received;
|
||||
|
||||
static struct dispmsg_crtc_mode display_mode;
|
||||
static int request_display_mode_error;
|
||||
static bool display_mode_received;
|
||||
|
||||
void shlvl(void)
|
||||
{
|
||||
long shlvl = 0;
|
||||
|
@ -265,8 +277,70 @@ bool missing_program(const char* program)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void on_displays(void* ctx, uint32_t id, uint32_t displays)
|
||||
{
|
||||
(void) ctx;
|
||||
if ( id != REQUEST_DISPLAYS_ID )
|
||||
return;
|
||||
displays_count = displays;
|
||||
displays_count_received = true;
|
||||
}
|
||||
|
||||
static void on_display_mode(void* ctx, uint32_t id,
|
||||
struct dispmsg_crtc_mode mode)
|
||||
{
|
||||
(void) ctx;
|
||||
if ( id != REQUEST_DISPLAY_MODE_ID )
|
||||
return;
|
||||
display_mode = mode;
|
||||
request_display_mode_error = 0;
|
||||
display_mode_received = true;
|
||||
}
|
||||
|
||||
static void on_ack(void* ctx, uint32_t id, int32_t error)
|
||||
{
|
||||
(void) ctx;
|
||||
if ( id != REQUEST_DISPLAY_MODE_ID )
|
||||
return;
|
||||
if ( error )
|
||||
{
|
||||
request_display_mode_error = error;
|
||||
display_mode_received = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool get_video_mode(struct dispmsg_crtc_mode* mode)
|
||||
{
|
||||
if ( getenv("DISPLAY_SOCKET") )
|
||||
{
|
||||
struct display_connection* connection = display_connect_default();
|
||||
if ( !connection )
|
||||
return false;
|
||||
struct display_event_handlers handlers = {0};
|
||||
handlers.displays_handler = on_displays;
|
||||
handlers.display_mode_handler = on_display_mode;
|
||||
handlers.ack_handler = on_ack;
|
||||
display_request_displays(connection, REQUEST_DISPLAYS_ID);
|
||||
displays_count_received = false;
|
||||
while ( !displays_count_received )
|
||||
display_wait_event(connection, &handlers);
|
||||
if ( displays_count < 1 )
|
||||
{
|
||||
display_disconnect(connection);
|
||||
return false;
|
||||
}
|
||||
// TODO: Multimonitor support.
|
||||
display_request_display_mode(connection, REQUEST_DISPLAY_MODE_ID, 0);
|
||||
display_mode_received = false;
|
||||
while ( !display_mode_received )
|
||||
display_wait_event(connection, &handlers);
|
||||
display_disconnect(connection);
|
||||
if ( request_display_mode_error )
|
||||
return false;
|
||||
*mode = display_mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct tiocgdisplay display;
|
||||
struct tiocgdisplays gdisplays;
|
||||
memset(&gdisplays, 0, sizeof(gdisplays));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2015, 2016, 2023 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
|
Loading…
Reference in New Issue