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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,17 @@ void connection_schedule_transmit(struct connection* connection,
|
||||||
connection->outgoing_used += count;
|
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,
|
void connection_initialize(struct connection* connection,
|
||||||
struct display* display,
|
struct display* display,
|
||||||
int fd)
|
int fd)
|
||||||
|
@ -235,18 +246,10 @@ CONNECTION_MESSAGE_HANDLER_NO_AUX(hide_window)
|
||||||
|
|
||||||
CONNECTION_MESSAGE_HANDLER_SERVER(chkblayout)
|
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 )
|
if ( tcsetblob(server->tty_fd, "kblayout", auxiliary, auxiliary_size) < 0 )
|
||||||
event.error = errno;
|
connection_schedule_ack_event(connection, msg->id, errno);
|
||||||
|
else
|
||||||
struct display_packet_header header;
|
connection_schedule_ack_event(connection, msg->id, 0);
|
||||||
header.id = EVENT_ACK;
|
|
||||||
header.size = sizeof(event);
|
|
||||||
|
|
||||||
connection_schedule_transmit(connection, &header, sizeof(header));
|
|
||||||
connection_schedule_transmit(connection, &event, sizeof(event));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CONNECTION_MESSAGE_HANDLER_NO_AUX(request_displays)
|
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)
|
CONNECTION_MESSAGE_HANDLER_NO_AUX_SERVER(request_display_modes)
|
||||||
{
|
{
|
||||||
struct event_display_modes success;
|
struct event_display_modes event;
|
||||||
success.id = msg->id;
|
event.id = msg->id;
|
||||||
success.modes_count = 0;
|
event.modes_count = 0;
|
||||||
struct event_ack failure;
|
|
||||||
failure.id = msg->id;
|
|
||||||
failure.error = 0;
|
|
||||||
|
|
||||||
struct dispmsg_crtc_mode* modes = NULL;
|
struct dispmsg_crtc_mode* modes = NULL;
|
||||||
// TODO: Multimonitor support.
|
// TODO: Multimonitor support.
|
||||||
if ( msg->display_id != 0 )
|
if ( msg->display_id != 0 )
|
||||||
failure.error = EINVAL;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
size_t modes_count = 0;
|
connection_schedule_ack_event(connection, msg->id, EINVAL);
|
||||||
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));
|
|
||||||
return;
|
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;
|
struct display_packet_header header;
|
||||||
header.id = EVENT_DISPLAY_MODES;
|
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, &header, sizeof(header));
|
||||||
connection_schedule_transmit(connection, &success, sizeof(success));
|
connection_schedule_transmit(connection, &event, sizeof(event));
|
||||||
connection_schedule_transmit(connection, modes, modes_size);
|
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,
|
static bool set_current_mode(const struct tiocgdisplay* display,
|
||||||
struct dispmsg_crtc_mode mode)
|
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)
|
CONNECTION_MESSAGE_HANDLER_NO_AUX_SERVER(set_display_mode)
|
||||||
{
|
{
|
||||||
struct event_ack event;
|
|
||||||
event.id = msg->id;
|
|
||||||
event.error = 0;
|
|
||||||
// TODO: Multimonitor support.
|
// TODO: Multimonitor support.
|
||||||
if ( msg->display_id != 0 )
|
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) )
|
else if ( !set_current_mode(&server->display->display, msg->mode) )
|
||||||
event.error = errno;
|
connection_schedule_ack_event(connection, msg->id, errno);
|
||||||
|
else
|
||||||
struct display_packet_header header;
|
connection_schedule_ack_event(connection, msg->id, 0);
|
||||||
header.id = EVENT_ACK;
|
|
||||||
header.size = 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,
|
||||||
|
@ -403,6 +429,7 @@ struct connection_message_handler_registration connection_message_handlers[] =
|
||||||
REGISTER_CONNECTION_MESSAGE_HANDLER(chkblayout),
|
REGISTER_CONNECTION_MESSAGE_HANDLER(chkblayout),
|
||||||
REGISTER_CONNECTION_MESSAGE_HANDLER(request_displays),
|
REGISTER_CONNECTION_MESSAGE_HANDLER(request_displays),
|
||||||
REGISTER_CONNECTION_MESSAGE_HANDLER(request_display_modes),
|
REGISTER_CONNECTION_MESSAGE_HANDLER(request_display_modes),
|
||||||
|
REGISTER_CONNECTION_MESSAGE_HANDLER(request_display_mode),
|
||||||
REGISTER_CONNECTION_MESSAGE_HANDLER(set_display_mode),
|
REGISTER_CONNECTION_MESSAGE_HANDLER(set_display_mode),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,14 @@ struct display_request_display_modes
|
||||||
uint32_t display_id;
|
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
|
struct display_set_display_mode
|
||||||
{
|
{
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
@ -163,4 +170,11 @@ struct event_display_modes
|
||||||
/* modes_count * sizeof(struct dispmsg_crtc_mode) video mode bytes follow */
|
/* 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
|
#endif
|
||||||
|
|
|
@ -71,6 +71,9 @@ void display_request_displays(struct display_connection* connection,
|
||||||
void display_request_display_modes(struct display_connection* connection,
|
void display_request_display_modes(struct display_connection* connection,
|
||||||
uint32_t id,
|
uint32_t id,
|
||||||
uint32_t display_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,
|
void display_set_display_mode(struct display_connection* connection,
|
||||||
uint32_t id,
|
uint32_t id,
|
||||||
uint32_t display_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_displays_handler_t)(void*, uint32_t, uint32_t);
|
||||||
typedef void (*display_event_display_modes_handler_t)(void*, uint32_t, uint32_t,
|
typedef void (*display_event_display_modes_handler_t)(void*, uint32_t, uint32_t,
|
||||||
void*, size_t);
|
void*, size_t);
|
||||||
|
typedef void (*display_event_display_mode_handler_t)(void*, uint32_t,
|
||||||
|
struct dispmsg_crtc_mode);
|
||||||
|
|
||||||
struct display_event_handlers
|
struct display_event_handlers
|
||||||
{
|
{
|
||||||
|
@ -96,6 +101,7 @@ struct display_event_handlers
|
||||||
display_event_ack_handler_t ack_handler;
|
display_event_ack_handler_t ack_handler;
|
||||||
display_event_displays_handler_t displays_handler;
|
display_event_displays_handler_t displays_handler;
|
||||||
display_event_display_modes_handler_t display_modes_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,
|
int display_poll_event(struct display_connection* connection,
|
||||||
|
|
|
@ -249,6 +249,17 @@ void display_request_display_modes(struct display_connection* connection,
|
||||||
sizeof(msg));
|
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,
|
void display_set_display_mode(struct display_connection* connection,
|
||||||
uint32_t id,
|
uint32_t id,
|
||||||
uint32_t display_id,
|
uint32_t display_id,
|
||||||
|
@ -381,6 +392,15 @@ static int display_dispatch_event(struct display_connection* connection,
|
||||||
aux, aux_size);
|
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;
|
connection->header_got = 0;
|
||||||
free(connection->payload);
|
free(connection->payload);
|
||||||
connection->payload = NULL;
|
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
|
* 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
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <display.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -40,6 +42,16 @@
|
||||||
#include "execute.h"
|
#include "execute.h"
|
||||||
#include "interactive.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)
|
void shlvl(void)
|
||||||
{
|
{
|
||||||
long shlvl = 0;
|
long shlvl = 0;
|
||||||
|
@ -265,8 +277,70 @@ bool missing_program(const char* program)
|
||||||
return true;
|
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)
|
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 tiocgdisplay display;
|
||||||
struct tiocgdisplays gdisplays;
|
struct tiocgdisplays gdisplays;
|
||||||
memset(&gdisplays, 0, sizeof(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
|
* 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
|
||||||
|
|
Loading…
Reference in New Issue