Compare commits

..

39 Commits

Author SHA1 Message Date
Jonas 'Sortie' Termansen 08b581914d fixup! Add display server. 2023-06-13 23:34:13 +02:00
Jonas 'Sortie' Termansen 371f0dcd80 fixup! Add display server. 2023-06-13 23:12:10 +02:00
Jonas 'Sortie' Termansen 7afc8f50df fixup! Add display server. 2023-06-11 21:46:00 +02:00
Jonas 'Sortie' Termansen 485e932deb squash! Add display server.
Remove the obsolete dispd.
2023-06-11 17:07:28 +02:00
Jonas 'Sortie' Termansen 1903483c0c fixup! Switch trianglix(1) from dispd to dispmsg_issue(2). 2023-06-10 16:24:56 +02:00
Jonas 'Sortie' Termansen ce3b519991 fixup! Add display server. 2023-06-10 16:23:11 +02:00
Jonas 'Sortie' Termansen 6c6880ea31 Switch trianglix(1) from dispd to dispmsg_issue(2). 2023-06-10 15:33:58 +02:00
Juhani Krekelä b9d6423f76 fixup! Add display server. 2023-06-10 01:08:26 +03:00
Jonas 'Sortie' Termansen be23ab5b0e fixup! Add display server. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 894efe6956 Aurora procedural wallpaper. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 2c7c88e95c Work around pty deadlock. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen d17c0d76a3 Add cdrom mounting live environment. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen ce1144fcc3 Revert "Parallelize driver initialization."
This reverts commit 0fef08bbc4.
2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 4d71053443 Parallelize driver initialization. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen f21db9505b Speed up ata(4) 400 ns waits.
Waiting for any non-zero duration currently waits for at least one timer
cycle (10 ms), which is especially expensive during early boot.

The current workaround of simply reading the status 14 times seems really
suspicious although the osdev wiki documents it, but let's see how well it
works on real hardware, it's probably good enough.

Try to determine the initial selected drive to save one drive selection.
2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen a82e17b25e Decrease PS/2 timeouts. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 233b717d35 Add uptime(1) -pr options. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen e4cf1113f0 fixup! Add iso9660 filesystem implementation. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 936ddeaca3 fixup! Add iso9660 filesystem implementation. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 9578e30a93 Add iso9660 filesystem implementation. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 884be7059b Add kernel virtual address space usage debug information. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 7490e1049a Revert "Update to bison-3.8.2."
This reverts commit b82fae810b42c5426d21c4dc153b32f086dd7fde.
2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen ea5fe9d185 Update to bison-3.8.2. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen f200d5d1e9 Debug TCP socket state listing. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen cf17a12829 Add kernel heap allocation tracing debug facility. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen cc0f498034 Add m4, perl, and texinfo to the basic ports set. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 07d937c023 Trianglix 4. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 7278f17cfb Add tix-check(8). 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen a169f736ac Volatile release. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 3e9a06d7e1 Add tix-upgrade(8). 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen a6637ace20 fixup! Add display server. 2023-06-08 22:50:30 +02:00
Jonas 'Sortie' Termansen 631dd60568 Add display server. 2023-06-08 22:50:29 +02:00
Jonas 'Sortie' Termansen a3c2f7f0b4 Add pty(1). 2023-06-08 22:50:04 +02:00
Jonas 'Sortie' Termansen 329f110f33 Add signify port. 2023-06-08 22:50:04 +02:00
Jonas 'Sortie' Termansen 790a92304d Add irc(1).
Co-authored-by: Juhani Krekelä <juhani@krekelä.fi>
2023-06-08 22:50:04 +02:00
Jonas 'Sortie' Termansen edc622cb00 Add getaddrinfo(1). 2023-06-08 22:50:04 +02:00
Jonas 'Sortie' Termansen 107a17186b Add host(1). 2023-06-08 22:50:04 +02:00
Jonas 'Sortie' Termansen f7f0a218dc Enable stack smash protection by default. 2023-06-08 22:50:04 +02:00
Jonas 'Sortie' Termansen 2472a09e16 Enable undefined behavior sanitization by default. 2023-06-08 22:50:04 +02:00
16 changed files with 439 additions and 656 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, 2014, 2015, 2016, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
* Copyright (c) 2023 Juhani 'nortti' Krekelä.
*
* Permission to use, copy, modify, and distribute this software for any
@ -38,25 +38,25 @@
#include <termios.h>
#include <unistd.h>
static bool set_current_mode(const struct tiocgdisplay* display,
struct dispmsg_crtc_mode mode)
static uint64_t device;
static uint64_t connector;
static bool set_current_mode(struct dispmsg_crtc_mode mode)
{
struct dispmsg_set_crtc_mode msg;
msg.msgid = DISPMSG_SET_CRTC_MODE;
msg.device = display->device;
msg.connector = display->connector;
msg.device = 0;
msg.connector = 0;
msg.mode = mode;
return dispmsg_issue(&msg, sizeof(msg)) == 0;
}
static struct dispmsg_crtc_mode*
get_available_modes(const struct tiocgdisplay* display,
size_t* num_modes_ptr)
static struct dispmsg_crtc_mode* get_available_modes(size_t* num_modes_ptr)
{
struct dispmsg_get_crtc_modes msg;
msg.msgid = DISPMSG_GET_CRTC_MODES;
msg.device = display->device;
msg.connector = display->connector;
msg.device = 0;
msg.connector = 0;
size_t guess = 1;
while ( true )
{
@ -133,9 +133,7 @@ static bool mode_passes_filter(struct dispmsg_crtc_mode mode,
return true;
}
static void filter_modes(struct dispmsg_crtc_mode* modes,
size_t* num_modes_ptr,
struct filter* filter)
static void filter_modes(struct dispmsg_crtc_mode* modes, size_t* num_modes_ptr, struct filter* filter)
{
size_t in_num = *num_modes_ptr;
size_t out_num = 0;
@ -147,247 +145,6 @@ static void filter_modes(struct dispmsg_crtc_mode* modes,
*num_modes_ptr = out_num;
}
static bool get_mode(struct dispmsg_crtc_mode* modes,
size_t num_modes,
unsigned int xres,
unsigned int yres,
unsigned int bpp,
struct dispmsg_crtc_mode* mode)
{
bool found = false;
bool found_other = false;
size_t index;
size_t other_index = 0;
for ( size_t i = 0; i < num_modes; i++ )
{
if ( modes[i].view_xres == xres &&
modes[i].view_yres == yres &&
modes[i].fb_format == bpp )
{
index = i;
found = true;
break;
}
if ( modes[i].control & DISPMSG_CONTROL_OTHER_RESOLUTIONS )
{
found_other = true;
other_index = i;
}
}
if ( !found )
{
if ( found_other )
index = other_index;
else
// Not in the list of pre-set resolutions and setting a custom
// resolution is not supported.
return false;
}
*mode = modes[index];
if ( mode->control & DISPMSG_CONTROL_OTHER_RESOLUTIONS )
{
mode->fb_format = bpp;
mode->view_xres = xres;
mode->view_yres = yres;
mode->control &= ~DISPMSG_CONTROL_OTHER_RESOLUTIONS;
mode->control |= DISPMSG_CONTROL_VALID;
}
return true;
}
static bool select_mode(struct dispmsg_crtc_mode* modes,
size_t num_modes,
int mode_set_error,
struct dispmsg_crtc_mode* mode)
{
int num_modes_display_length = 1;
for ( size_t i = num_modes; 10 <= i; i /= 10 )
num_modes_display_length++;
size_t selection;
bool decided;
bool first_render;
struct wincurpos render_at;
selection = 0;
decided = false;
first_render = true;
memset(&render_at, 0, sizeof(render_at));
while ( !decided )
{
fflush(stdout);
struct winsize ws;
if ( tcgetwinsize(1, &ws) != 0 )
{
ws.ws_col = 80;
ws.ws_row = 25;
}
struct wincurpos wcp;
if ( tcgetwincurpos(1, &wcp) != 0 )
{
wcp.wcp_col = 1;
wcp.wcp_row = 1;
}
size_t off = 1; // The "Please select ..." line at the top.
if ( mode_set_error )
off++;
size_t entries_per_page = ws.ws_row - off;
size_t page = selection / entries_per_page;
size_t from = page * entries_per_page;
size_t how_many_available = num_modes - from;
size_t how_many = entries_per_page;
if ( how_many_available < how_many )
how_many = how_many_available;
size_t lines_on_screen = off + how_many;
if ( first_render )
{
while ( wcp.wcp_row &&
ws.ws_row - (wcp.wcp_row + 1) < lines_on_screen )
{
printf("\e[S");
printf("\e[%juH", 1 + (uintmax_t) wcp.wcp_row);
wcp.wcp_row--;
wcp.wcp_col = 1;
}
render_at = wcp;
first_render = false;
}
printf("\e[m");
printf("\e[%juH", 1 + (uintmax_t) render_at.wcp_row);
printf("\e[2K");
if ( mode_set_error )
printf("Error: Could not set desired mode: %s\n",
strerror(mode_set_error));
printf("Please select one of these video modes or press ESC to "
"abort.\n");
for ( size_t i = 0; i < how_many; i++ )
{
size_t index = from + i;
size_t screenline = off + index - from;
const char* color = index == selection ? "\e[31m" : "\e[m";
printf("\e[%zuH", 1 + render_at.wcp_row + screenline);
printf("%s", color);
printf("\e[2K");
printf(" [%-*zu] ", num_modes_display_length, index);
if ( modes[index].control & DISPMSG_CONTROL_VALID )
printf("%ux%ux%u",
modes[index].view_xres,
modes[index].view_yres,
modes[index].fb_format);
else if ( modes[index].control & DISPMSG_CONTROL_OTHER_RESOLUTIONS )
printf("(enter a custom resolution)");
else
printf("(unknown video device feature)");
printf("\e[m");
}
printf("\e[J");
fflush(stdout);
unsigned int oldtermmode;
if ( gettermmode(0, &oldtermmode) < 0 )
err(1, "gettermmode");
if ( settermmode(0, TERMMODE_KBKEY | TERMMODE_UNICODE |
TERMMODE_SIGNAL) < 0 )
err(1, "settermmode");
bool redraw = false;
while ( !redraw && !decided )
{
uint32_t codepoint;
ssize_t numbytes = read(0, &codepoint, sizeof(codepoint));
if ( numbytes < 0 )
err(1, "read");
int kbkey = KBKEY_DECODE(codepoint);
if ( kbkey )
{
switch ( kbkey )
{
case KBKEY_ESC:
if ( settermmode(0, oldtermmode) < 0 )
err(1, "settermmode");
printf("\n");
return false;
break;
case KBKEY_UP:
if ( selection )
selection--;
else
selection = num_modes -1;
redraw = true;
break;
case KBKEY_DOWN:
if ( selection + 1 == num_modes )
selection = 0;
else
selection++;
redraw = true;
break;
case KBKEY_ENTER:
if ( settermmode(0, oldtermmode) < 0 )
err(1, "settermmode");
fgetc(stdin);
printf("\n");
decided = true;
break;
}
}
else
{
if ( L'0' <= codepoint && codepoint <= '9' )
{
uint32_t requested = codepoint - '0';
if ( requested < num_modes )
{
selection = requested;
redraw = true;
}
}
}
}
if ( settermmode(0, oldtermmode) < 0 )
err(1, "settermmode");
}
*mode = modes[selection];
if ( mode->control & DISPMSG_CONTROL_OTHER_RESOLUTIONS )
{
uintmax_t req_bpp, req_width, req_height;
while ( true )
{
printf("Enter video mode [WIDTHxHEIGHTxBPP]: ");
fflush(stdout);
if ( scanf("%jux%jux%ju", &req_width, &req_height, &req_bpp) != 3 )
{
fgetc(stdin);
fflush(stdin);
continue;
}
fgetc(stdin);
break;
}
mode->fb_format = req_bpp;
mode->view_xres = req_width;
mode->view_yres = req_height;
mode->control &= ~DISPMSG_CONTROL_OTHER_RESOLUTIONS;
mode->control |= DISPMSG_CONTROL_VALID;
}
return true;
}
static size_t parse_size_t(const char* str)
{
char* endptr;
@ -497,6 +254,20 @@ int main(int argc, char* argv[])
}
}
unsigned int xres = 0;
unsigned int yres = 0;
unsigned int bpp = 0;
if ( 1 <= argc - optind )
{
if ( 1 < argc - optind )
errx(1, "Unexpected extra operand");
if ( sscanf(argv[optind], "%ux%ux%u", &xres, &yres, &bpp) != 3 )
errx(1, "Invalid video mode: %s", argv[optind]);
}
int tty_fd = open("/dev/tty", O_RDWR);
if ( tty_fd < 0 )
err(1, "/dev/tty");
struct tiocgdisplay display;
struct tiocgdisplays gdisplays;
memset(&gdisplays, 0, sizeof(gdisplays));
@ -507,67 +278,248 @@ int main(int argc, char* argv[])
fprintf(stderr, "No video devices are associated with this terminal.\n");
exit(13);
}
device = display.device;
connector = display.connector;
size_t num_modes = 0;
struct dispmsg_crtc_mode* modes = get_available_modes(&display, &num_modes);
struct dispmsg_crtc_mode* modes = get_available_modes(&num_modes);
if ( !modes )
err(1, "Unable to detect available video modes");
if ( !num_modes )
{
fprintf(stderr, "No video modes are currently available.\n");
fprintf(stderr, "Try make sure a device driver exists and is "
"activated.\n");
fprintf(stderr, "Try make sure a device driver exists and is activated.\n");
exit(11);
}
filter_modes(modes, &num_modes, &filter);
if ( !num_modes )
{
fprintf(stderr, "No video mode remains after filtering away unwanted "
"modes.\n");
fprintf(stderr, "Try make sure the desired device driver is loaded and "
"is configured correctly.\n");
fprintf(stderr, "No video mode remains after filtering away unwanted modes.\n");
fprintf(stderr, "Try make sure the desired device driver is loaded and is configured correctly.\n");
exit(12);
}
if ( 1 < argc - optind )
errx(1, "Unexpected extra operand");
else if ( argc - optind == 1 )
{
unsigned int xres, yres, bpp;
if ( sscanf(argv[optind], "%ux%ux%u", &xres, &yres, &bpp) != 3 )
errx(1, "Invalid video mode: %s", argv[optind]);
int num_modes_display_length = 1;
for ( size_t i = num_modes; 10 <= i; i /= 10 )
num_modes_display_length++;
struct dispmsg_crtc_mode mode;
if ( !get_mode(modes, num_modes, xres, yres, bpp, &mode) )
errx(1, "No such available resolution: %s", argv[optind]);
if ( !set_current_mode(&display, mode) )
err(1, "Failed to set video mode %jux%jux%ju",
(uintmax_t) mode.view_xres,
(uintmax_t) mode.view_yres,
(uintmax_t) mode.fb_format);
}
else
int mode_set_error = 0;
size_t selection;
bool decided;
bool first_render;
struct wincurpos render_at;
retry_pick_mode:
selection = 0;
decided = false;
first_render = true;
memset(&render_at, 0, sizeof(render_at));
if ( 1 <= argc - optind )
{
int mode_set_error = 0;
bool mode_set = false;
while ( !mode_set )
bool found_other = true;
size_t other_selection = 0;
for ( size_t i = 0; i < num_modes; i++ )
{
struct dispmsg_crtc_mode mode;
if ( !select_mode(modes, num_modes, mode_set_error, &mode) )
exit(10);
if ( !(mode_set = set_current_mode(&display, mode)) )
if ( modes[i].view_xres == xres &&
modes[i].view_yres == yres &&
modes[i].fb_format == bpp )
{
mode_set_error = errno;
warn("Failed to set video mode %jux%jux%ju",
(uintmax_t) mode.view_xres,
(uintmax_t) mode.view_yres,
(uintmax_t) mode.fb_format);
selection = i;
decided = true;
break;
}
if ( modes[i].control & DISPMSG_CONTROL_OTHER_RESOLUTIONS )
{
found_other = true;
other_selection = i;
}
}
if ( !decided )
{
if ( found_other )
selection = other_selection;
else
err(1, "No such available resolution: %s", argv[optind]);
}
}
while ( !decided )
{
fflush(stdout);
struct winsize ws;
if ( tcgetwinsize(1, &ws) != 0 )
{
ws.ws_col = 80;
ws.ws_row = 25;
}
struct wincurpos wcp;
if ( tcgetwincurpos(1, &wcp) != 0 )
{
wcp.wcp_col = 1;
wcp.wcp_row = 1;
}
size_t off = 1; // The "Please select ..." line at the top.
if ( mode_set_error )
off++;
size_t entries_per_page = ws.ws_row - off;
size_t page = selection / entries_per_page;
size_t from = page * entries_per_page;
size_t how_many_available = num_modes - from;
size_t how_many = entries_per_page;
if ( how_many_available < how_many )
how_many = how_many_available;
size_t lines_on_screen = off + how_many;
if ( first_render )
{
while ( wcp.wcp_row && ws.ws_row - (wcp.wcp_row + 1) < lines_on_screen )
{
printf("\e[S");
printf("\e[%juH", 1 + (uintmax_t) wcp.wcp_row);
wcp.wcp_row--;
wcp.wcp_col = 1;
}
render_at = wcp;
first_render = false;
}
printf("\e[m");
printf("\e[%juH", 1 + (uintmax_t) render_at.wcp_row);
printf("\e[2K");
if ( mode_set_error )
printf("Error: Could not set desired mode: %s\n", strerror(mode_set_error));
printf("Please select one of these video modes or press ESC to abort.\n");
for ( size_t i = 0; i < how_many; i++ )
{
size_t index = from + i;
size_t screenline = off + index - from;
const char* color = index == selection ? "\e[31m" : "\e[m";
printf("\e[%zuH", 1 + render_at.wcp_row + screenline);
printf("%s", color);
printf("\e[2K");
printf(" [%-*zu] ", num_modes_display_length, index);
if ( modes[i].control & DISPMSG_CONTROL_VALID )
printf("%ux%ux%u",
modes[i].view_xres,
modes[i].view_yres,
modes[i].fb_format);
else if ( modes[i].control & DISPMSG_CONTROL_OTHER_RESOLUTIONS )
printf("(enter a custom resolution)");
else
printf("(unknown video device feature)");
printf("\e[m");
}
printf("\e[J");
fflush(stdout);
unsigned int oldtermmode;
if ( gettermmode(0, &oldtermmode) < 0 )
err(1, "gettermmode");
if ( settermmode(0, TERMMODE_KBKEY | TERMMODE_UNICODE | TERMMODE_SIGNAL) < 0 )
err(1, "settermmode");
bool redraw = false;
while ( !redraw && !decided )
{
uint32_t codepoint;
ssize_t numbytes = read(0, &codepoint, sizeof(codepoint));
if ( numbytes < 0 )
err(1, "read");
int kbkey = KBKEY_DECODE(codepoint);
if ( kbkey )
{
switch ( kbkey )
{
case KBKEY_ESC:
if ( settermmode(0, oldtermmode) < 0 )
err(1, "settermmode");
printf("\n");
exit(10);
break;
case KBKEY_UP:
if ( selection )
selection--;
else
selection = num_modes -1;
redraw = true;
break;
case KBKEY_DOWN:
if ( selection + 1 == num_modes )
selection = 0;
else
selection++;
redraw = true;
break;
case KBKEY_ENTER:
if ( settermmode(0, oldtermmode) < 0 )
err(1, "settermmode");
fgetc(stdin);
printf("\n");
decided = true;
break;
}
}
else
{
if ( L'0' <= codepoint && codepoint <= '9' )
{
uint32_t requested = codepoint - '0';
if ( requested < num_modes )
{
selection = requested;
redraw = true;
}
}
}
}
if ( settermmode(0, oldtermmode) < 0 )
err(1, "settermmode");
}
struct dispmsg_crtc_mode mode = modes[selection];
if ( mode.control & DISPMSG_CONTROL_OTHER_RESOLUTIONS )
{
uintmax_t req_bpp = bpp;
uintmax_t req_width = xres;
uintmax_t req_height = yres;
while ( argc - optind < 1 )
{
printf("Enter video mode [WIDTHxHEIGHTxBPP]: ");
fflush(stdout);
if ( scanf("%jux%jux%ju", &req_width, &req_height, &req_bpp) != 3 )
{
fgetc(stdin);
fflush(stdin);
continue;
}
fgetc(stdin);
break;
}
mode.fb_format = req_bpp;
mode.view_xres = req_width;
mode.view_yres = req_height;
mode.control &= ~DISPMSG_CONTROL_OTHER_RESOLUTIONS;
mode.control |= DISPMSG_CONTROL_VALID;
}
if ( !set_current_mode(mode) )
{
mode_set_error = errno;
warn("Unable to set video mode %jux%jux%ju",
(uintmax_t) mode.view_xres,
(uintmax_t) mode.view_yres,
(uintmax_t) mode.fb_format);
goto retry_pick_mode;
}
return 0;

View File

@ -42,21 +42,18 @@ void connection_schedule_transmit(struct connection* connection,
size_t available = connection->outgoing_size - connection->outgoing_used;
if ( available < count )
{
// TODO: Overflow.
size_t required_size = connection->outgoing_used + count;
// TODO: Check allocation.
unsigned char* new_outgoing = malloc(required_size);
size_t first_available =
connection->outgoing_size - connection->outgoing_offset;
size_t first = connection->outgoing_used < first_available ?
connection->outgoing_used :
first_available;
unsigned char* new_outgoing = (unsigned char*) malloc(required_size);
size_t first_part_available = connection->outgoing_size - connection->outgoing_offset;
size_t first_part = connection->outgoing_used < first_part_available ?
connection->outgoing_used :
first_part_available;
if ( connection->outgoing )
{
memcpy(new_outgoing, connection->outgoing +
connection->outgoing_offset, first);
size_t second = connection->outgoing_used - first;
memcpy(new_outgoing + first, connection->outgoing, second);
connection->outgoing_offset, first_part);
size_t second_part = connection->outgoing_used - first_part;
memcpy(new_outgoing + first_part, connection->outgoing, second_part);
free(connection->outgoing);
}
connection->outgoing_offset = 0;
@ -64,14 +61,12 @@ void connection_schedule_transmit(struct connection* connection,
connection->outgoing = new_outgoing;
}
size_t used_offset =
(connection->outgoing_offset + connection->outgoing_used) %
connection->outgoing_size;
size_t first_available = connection->outgoing_size - used_offset;
size_t first = count < first_available ? count : first_available;
memcpy(connection->outgoing + used_offset, buffer, first);
size_t second = count - first;
memcpy(connection->outgoing, (const unsigned char*) buffer + first, second);
size_t used_offset = (connection->outgoing_offset + connection->outgoing_used) % connection->outgoing_size;
size_t first_part_available = connection->outgoing_size - used_offset;
size_t first_part = count < first_part_available ? count : first_part_available;
memcpy(connection->outgoing + used_offset, buffer, first_part);
size_t second_part = count - first_part;
memcpy(connection->outgoing, (const unsigned char*) buffer + first_part, second_part);
connection->outgoing_used += count;
}
@ -102,28 +97,25 @@ 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* auxiliary __attribute__((unused)), \
size_t auxiliary_size __attribute__((unused)), \
const struct server* server __attribute__((unused)))
void connection_handler_##message_name(struct connection* connection, \
struct display_##message_name* msg, \
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* auxiliary, \
size_t auxiliary_size, \
const struct server* server __attribute__((unused)))
void connection_handler_##message_name(struct connection* connection, \
struct display_##message_name* msg, \
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)
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)
{
@ -142,8 +134,7 @@ CONNECTION_MESSAGE_HANDLER_NO_AUX(shutdown)
CONNECTION_MESSAGE_HANDLER_NO_AUX(create_window)
{
struct window* window =
connection_find_window_raw(connection, msg->window_id);
struct window* window = connection_find_window_raw(connection, msg->window_id);
if ( !window )
return;
if ( window->created )
@ -274,8 +265,7 @@ short connection_interested_poll_events(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) )
{
ssize_t amount = read(connection->fd,
(unsigned char*) &connection->packet_header +
@ -285,13 +275,12 @@ void connection_can_read(struct connection* connection,
if ( amount < 0 && (errno == EAGAIN || errno == EWOULDBLOCK) )
return;
if ( amount < 0 || amount == 0 )
return; // TODO: No longer signal interest in reading + disconnect.
return; // TODO: No longer signal interest in reading and disconnect.
connection->packet_header_received += amount;
}
size_t packet_length = connection->packet_header.message_length;
// TODO: Check allocation and protect against too big buffers.
if ( !connection->packet )
connection->packet = (unsigned char*) malloc(packet_length);
@ -303,7 +292,7 @@ void connection_can_read(struct connection* connection,
if ( amount < 0 && (errno == EAGAIN || errno == EWOULDBLOCK) )
return;
if ( amount < 0 || amount == 0 )
return; // TODO: No longer signal interest in reading + disconnect.
return; // TODO: No longer signal interest in reading and disconnect.
connection->packet_received += amount;
}
@ -324,7 +313,7 @@ void connection_can_read(struct connection* connection,
connection->packet = NULL;
connection->packet_received = 0;
// TODO: Check if we can receive another packet, but only if we haven't
// TODO: Check if we can received another packet, but only if we haven't
// done so much work that the display server is starved.
}
@ -332,18 +321,14 @@ void connection_can_write(struct connection* connection)
{
while ( connection->outgoing_used )
{
size_t available =
connection->outgoing_size - connection->outgoing_offset;
size_t count = connection->outgoing_used < available ?
connection->outgoing_used : available;
unsigned char* buf = connection->outgoing + connection->outgoing_offset;
ssize_t amount = write(connection->fd, buf, count);
size_t available = connection->outgoing_size - connection->outgoing_offset;
size_t count = connection->outgoing_used < available ? connection->outgoing_used : available;
ssize_t amount = write(connection->fd, connection->outgoing + connection->outgoing_offset, count);
if ( amount < 0 && (errno == EAGAIN || errno == EWOULDBLOCK) )
return;
if ( amount < 0 || amount == 0 )
return; // TODO: No longer signal interest in writing + disconnect.
connection->outgoing_offset = (connection->outgoing_offset + amount) %
connection->outgoing_size;
return; // TODO: No longer signal interest in writing and disconnect.
connection->outgoing_offset = (connection->outgoing_offset + amount) % connection->outgoing_size;
connection->outgoing_used -= amount;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016, 2018, 2022, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015, 2016, 2018, 2022 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
@ -17,6 +17,7 @@
* Display server logic.
*/
#include <sys/display.h>
#include <sys/keycodes.h>
#include <sys/ps2mouse.h>
@ -123,8 +124,7 @@ void display_unlink_window(struct display* display, struct window* window)
assert_is_well_formed_display_list(display);
}
void display_unlink_window_removal(struct display* display,
struct window* window)
void display_unlink_window_removal(struct display* display, struct window* window)
{
assert_is_well_formed_display_list(display);
@ -145,8 +145,7 @@ void display_unlink_window_removal(struct display* display,
assert_is_well_formed_display_list(display);
}
void display_unmark_active_window(struct display* display,
struct window* window)
void display_unmark_active_window(struct display* display, struct window* window)
{
assert(display->active_window == window);
window->focus = false;
@ -174,8 +173,7 @@ void display_move_window_to_top(struct display* display, struct window* window)
display_link_window_at_top(display, window);
}
void display_change_active_window(struct display* display,
struct window* window)
void display_change_active_window(struct display* display, struct window* window)
{
if ( display->active_window == window )
{
@ -286,8 +284,7 @@ void display_composit(struct display* display, struct framebuffer fb)
uint32_t bg_color = make_color(0x89 * 2/3, 0xc7 * 2/3, 0xff * 2/3);
for ( size_t y = 0; y < damage_rect.height; y++ )
for ( size_t x = 0; x < damage_rect.width; x++ )
framebuffer_set_pixel(fb, damage_rect.left + x, damage_rect.top + y,
bg_color);
framebuffer_set_pixel(fb, damage_rect.left + x, damage_rect.top + y, bg_color);
#endif
framebuffer_copy_to_framebuffer(fb, display->wallpaper);
@ -306,8 +303,7 @@ void display_composit(struct display* display, struct framebuffer fb)
if ( window->left < 0 )
{
winfb_left = 0;
winfb = framebuffer_crop(winfb, -window->left, 0,
winfb.xres, winfb.yres);
winfb = framebuffer_crop(winfb, -window->left, 0, winfb.xres, winfb.yres);
}
else
winfb_left = window->left;
@ -315,8 +311,7 @@ void display_composit(struct display* display, struct framebuffer fb)
if ( window->top < 0 )
{
winfb_top = 0;
winfb = framebuffer_crop(winfb, 0, -window->top,
winfb.xres, winfb.yres);
winfb = framebuffer_crop(winfb, 0, -window->top, winfb.xres, winfb.yres);
}
else
winfb_top = window->top;
@ -325,19 +320,14 @@ void display_composit(struct display* display, struct framebuffer fb)
size_t winfb_height = winfb.yres;
#if 0
if ( winfb_left < damage_rect.left &&
winfb_width < damage_rect.left - winfb_left )
if ( winfb_left < damage_rect.left && winfb_width < damage_rect.left - winfb_left )
continue;
if ( winfb_left < damage_rect.left )
{
winfb_left = damage_rect.left;
winfb_width -= damage_rect.left - winfb_left;
}
winfb_left = damage_rect.left, winfb_width -= damage_rect.left - winfb_left;
#endif
struct framebuffer fb_dst =
framebuffer_crop(fb, winfb_left, winfb_top,
winfb_width, winfb_height);
framebuffer_crop(fb, winfb_left, winfb_top, winfb_width, winfb_height);
framebuffer_copy_to_framebuffer_blend(fb_dst, winfb);
}
@ -346,7 +336,6 @@ void display_composit(struct display* display, struct framebuffer fb)
switch ( display->mouse_state )
{
case MOUSE_STATE_NONE: break;
case MOUSE_STATE_BUTTON_PRESS: break;
case MOUSE_STATE_TITLE_MOVE: break;
case MOUSE_STATE_RESIZE_BOTTOM: cursor_text = ""; break;
case MOUSE_STATE_RESIZE_BOTTOM_LEFT: cursor_text = ""; break;
@ -367,14 +356,12 @@ void display_composit(struct display* display, struct framebuffer fb)
struct framebuffer arrow_render = arrow_framebuffer;
if ( pointer_x < 0 )
{
arrow_render = framebuffer_crop(arrow_render, -pointer_x, 0,
arrow_render.xres, arrow_render.yres);
arrow_render = framebuffer_crop(arrow_render, -pointer_x, 0, arrow_render.xres, arrow_render.yres);
pointer_x = 0;
}
if ( pointer_y < 0 )
{
arrow_render = framebuffer_crop(arrow_render, 0, -pointer_y,
arrow_render.xres, arrow_render.yres);
arrow_render = framebuffer_crop(arrow_render, 0, -pointer_y, arrow_render.xres, arrow_render.yres);
pointer_y = 0;
}
@ -391,13 +378,19 @@ void display_composit(struct display* display, struct framebuffer fb)
void display_render(struct display* display)
{
struct dispmsg_get_crtc_mode get_mode_msg = {0};
get_mode_msg.msgid = DISPMSG_GET_CRTC_MODE;
get_mode_msg.device = display->display.device;
get_mode_msg.connector = display->display.connector;
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;
struct dispmsg_crtc_mode mode;
{
struct dispmsg_get_crtc_mode msg;
memset(&msg, 0, sizeof(msg));
msg.msgid = DISPMSG_GET_CRTC_MODE;
msg.device = 0; // TODO: Multi-screen support!
msg.connector = 0; // TODO: Multi-screen support!
if ( dispmsg_issue(&msg, sizeof(msg)) != 0 )
err(1, "dispmsg_issue: dispmsg_get_crtc_mode");
mode = msg.mode;
}
if ( !(mode.control & DISPMSG_CONTROL_VALID) )
errx(1, "No valid video mode was set");
@ -432,13 +425,18 @@ void display_render(struct display* display)
display_composit(display, display->fb);
struct dispmsg_write_memory write_memory_msg = {0};
write_memory_msg.msgid = DISPMSG_WRITE_MEMORY;
write_memory_msg.device = display->display.device;
write_memory_msg.size = framebuffer_size;
write_memory_msg.src = (uint8_t*) display->fb.buffer;
if ( dispmsg_issue(&write_memory_msg, sizeof(write_memory_msg)) != 0 )
err(1, "dispmsg_issue: dispmsg_write_memory");
{
struct dispmsg_write_memory msg;
memset(&msg, 0, sizeof(msg));
msg.msgid = DISPMSG_WRITE_MEMORY;
msg.device = 0; // TODO: Multi-screen support!
msg.offset = 0; // TODO: mode.fb_location!
msg.size = framebuffer_size;
msg.src = (uint8_t*) display->fb.buffer;
if ( dispmsg_issue(&msg, sizeof(msg)) != 0 )
err(1, "dispmsg_issue: dispmsg_write_memory");
}
}
void display_keyboard_event(struct display* display, uint32_t codepoint)
@ -539,8 +537,7 @@ void display_keyboard_event(struct display* display, uint32_t codepoint)
{
// TODO: window->title can be null.
char* new_title;
if ( 0 <= asprintf(&new_title, "%s%s", window->title,
grab_inputbed_string) )
if ( 0 <= asprintf(&new_title, "%s%s", window->title, grab_inputbed_string) )
{
window->grab_input = true;
free(window->title);
@ -654,83 +651,34 @@ void display_mouse_event(struct display* display, uint8_t byte)
ssize_t window_pointer_x = display->pointer_x - window->left;
ssize_t window_pointer_y = display->pointer_y - window->top;
if ( display->active_window != window )
{
if ( bytes[0] & (MOUSE_BUTTON_LEFT | MOUSE_BUTTON_MIDDLE |
MOUSE_BUTTON_RIGHT) )
{
// TODO: Exit mouse from the current window.
display_set_active_window(display, window);
}
else
return;
}
size_t border_width = window_border_width(window);
size_t button_width = FONT_WIDTH * 2;
ssize_t buttons_x = window->width - border_width
- button_width * 3 + 1;
size_t tt_height = FONT_HEIGHT;
size_t tt_pos_y = (TITLE_HEIGHT - FONT_HEIGHT) / 2 + 2;
bool mouse_on_title = 0 <= window_pointer_x &&
window_pointer_x < (ssize_t) window->width &&
0 <= window_pointer_y &&
window_pointer_y <= (ssize_t) TITLE_HEIGHT;
for ( size_t n = 0; n < 3; n++ )
{
if ( (ssize_t) tt_pos_y <= window_pointer_y &&
window_pointer_y <= (ssize_t) (tt_height + tt_pos_y) &&
(ssize_t) (button_width * n) <= window_pointer_x - buttons_x &&
window_pointer_x - buttons_x < (ssize_t) (button_width * (n + 1)) )
{
if ( display->mouse_state == MOUSE_STATE_NONE &&
(bytes[0] & MOUSE_BUTTON_LEFT) )
{
display->mouse_state = MOUSE_STATE_BUTTON_PRESS;
window->button_states[n] = BUTTON_STATE_PRESSED;
window_render_frame(window);
}
else if ( display->mouse_state == MOUSE_STATE_BUTTON_PRESS &&
window->button_states[n] == BUTTON_STATE_PRESSED )
{
window->button_states[n] = BUTTON_STATE_NORMAL;
window_render_frame(window);
switch ( n )
{
case 0: /* TODO: Minimize. */ break;
case 1: window_toggle_maximized(window); break;
case 2: window_quit(window); break;
}
return;
}
else if ( display->mouse_state == MOUSE_STATE_NONE &&
window->button_states[n] != BUTTON_STATE_HOVER )
{
window->button_states[n] = BUTTON_STATE_HOVER;
window_render_frame(window);
}
}
else if ( window->button_states[n] != BUTTON_STATE_NORMAL )
{
window->button_states[n] = BUTTON_STATE_NORMAL;
display->mouse_state = MOUSE_STATE_NONE;
window_render_frame(window);
}
}
if ( bytes[0] & MOUSE_BUTTON_LEFT )
{
display_set_active_window(display, window);
if ( display->mouse_state == MOUSE_STATE_NONE )
{
// TODO: Stay in state until mouse release.
if ( display->key_lalt || mouse_on_title )
if ( display->key_lalt ||
(0 <= window_pointer_x &&
window_pointer_x < (ssize_t) window->width &&
0 <= window_pointer_y &&
window_pointer_y <= (ssize_t) TITLE_HEIGHT) )
{
if ( window_pointer_x < buttons_x || !mouse_on_title )
size_t border_width = window_border_width(window);
size_t button_width = FONT_WIDTH * 2;
ssize_t buttons_x = window->width - border_width
- button_width * 3 + 1;
ssize_t rel_x = window_pointer_x - buttons_x;
if ( 0 <= rel_x && rel_x < (ssize_t) button_width )
{
// TODO Minimize window.
}
else if ( 0 <= rel_x && rel_x < (ssize_t) button_width * 2 )
window_toggle_maximized(window);
else if ( 0 <= rel_x && rel_x < (ssize_t) button_width * 3 )
window_quit(window);
else
display->mouse_state = MOUSE_STATE_TITLE_MOVE;
}
else if ( window_pointer_x < 0 && window_pointer_y < 0 )
} else if ( window_pointer_x < 0 && window_pointer_y < 0 )
display->mouse_state = MOUSE_STATE_RESIZE_TOP_LEFT;
else if ( window_pointer_x < 0 &&
0 <= window_pointer_y &&
@ -761,19 +709,18 @@ void display_mouse_event(struct display* display, uint8_t byte)
if ( xm || ym )
{
bool floating = window->window_state == WINDOW_STATE_REGULAR;
bool on_edge =
display->pointer_x == 0 ||
display->pointer_y == 0 ||
display->pointer_x == (ssize_t) display->screen_width ||
display->pointer_y == (ssize_t) display->screen_height;
bool on_edge = display->pointer_x == 0
|| display->pointer_y == 0
|| display->pointer_x
== (ssize_t) display->screen_width
|| display->pointer_y
== (ssize_t) display->screen_height;
switch ( display->mouse_state )
{
case MOUSE_STATE_NONE: break;
case MOUSE_STATE_BUTTON_PRESS: break;
case MOUSE_STATE_TITLE_MOVE:
if ( clipped_edge )
{
// TODO: Clean these up.
// I'd declare those in function scope but I'm afraid of
// messing with the code too much.
ssize_t x = display->pointer_x;
@ -785,22 +732,22 @@ void display_mouse_event(struct display* display, uint8_t byte)
ssize_t corner_size = (sw < sh ? sw : sh) / 4;
if ( x < corner_size && y < corner_size )
window_tile_top_left(window);
else if ( sw - x < corner_size && y < corner_size )
else if (sw - x < corner_size && y < corner_size )
window_tile_top_right(window);
else if ( x < corner_size && sh - y < corner_size )
window_tile_bottom_left(window);
else if ( sw - x < corner_size && sh - y < corner_size )
else if (sw - x < corner_size && sh - y < corner_size )
window_tile_bottom_right(window);
else if ( x == 0 )
else if (x == 0)
window_tile_left(window);
else if ( x == sw )
else if (x == sw)
window_tile_right(window);
else if ( y == 0 )
else if (y == 0)
window_tile_top(window);
else if ( y == sh )
else if (y == sh)
window_tile_bottom(window);
}
else if ( floating || !on_edge )
else if (floating || !on_edge)
{
if ( !floating )
{
@ -852,8 +799,7 @@ void display_mouse_event(struct display* display, uint8_t byte)
}
}
void display_on_resolution_change(struct display* display, size_t width,
size_t height)
void display_on_resolution_change(struct display* display, size_t width, size_t height)
{
if ( display->screen_width == width && display->screen_height == height )
return;
@ -861,9 +807,7 @@ void display_on_resolution_change(struct display* display, size_t width,
display->screen_height = height;
display->pointer_x = width / 2;
display->pointer_y = height / 2;
for ( struct window* window = display->bottom_window;
window;
window = window->above_window )
for ( struct window* window = display->bottom_window; window; window = window->above_window )
window_on_display_resolution_change(window, display);
wallpaper(display->wallpaper);
}

View File

@ -1,5 +1,5 @@
.Dd June 11, 2023
.Dt DISPLAY 1
.Dt DISPLAY 8
.Os
.Sh NAME
.Nm display
@ -25,25 +25,6 @@ script in the background.
.Nm
exits when Control + Alt + Delete is pressed.
.Pp
The options are as follows:
.Bl -tag -width "12345678"
.It Fl m Ar mouse
Use
.Pa mouse
device instead of
.Pa /dev/mouse .
.It Fl t Ar tty
Use
.Pa tty
device instead of
.Pa /dev/tty .
.It Fl s Ar socket
Listen on
.Pa socket
instead of
.Pa /var/run/display .
.El
.Pp
The keyboard shortcuts are as follows:
.Bl -tag -width "Control + Alt + Delete"
.It Alt + F4
@ -112,7 +93,7 @@ Applications use
to connect to
.Nm
or
.Pa /var/run/display
.Pa /run/display
by default.
.El
.Sh FILES
@ -120,7 +101,7 @@ by default.
.It Pa ~/.displayrc , /etc/displayrc , /etc/default/displayrc
.Xr displayrc 5
script that spawns the user's preferred startup applications.
.It Pa /var/run/display
.It Pa /run/display
.Xr unix 4
socket where
.Nm

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016, 2017, 2022, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015, 2016, 2017, 2022 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
@ -45,23 +45,43 @@ static void ready(void)
unsetenv("READYFD");
}
int main(int argc, char* argv[])
static void compact_arguments(int* argc, char*** argv)
{
const char* mouse = "/dev/mouse";
const char* socket = "/var/run/display";
const char* tty = NULL;
int opt;
while ( (opt = getopt(argc, argv, "m:s:t:")) != -1 )
for ( int i = 0; i < *argc; i++ )
{
switch ( opt )
while ( i < *argc && !(*argv)[i] )
{
case 'm': mouse = optarg; break;
case 's': socket = optarg; break;
case 't': tty = optarg; break;
default: return 1;
for ( int n = i; n < *argc; n++ )
(*argv)[n] = (*argv)[n+1];
(*argc)--;
}
}
}
int main(int argc, char* argv[])
{
for ( int i = 1; i < argc; i++ )
{
const char* arg = argv[i];
if ( arg[0] != '-' || !arg[1] )
continue;
argv[i] = NULL;
if ( !strcmp(arg, "--") )
break;
if ( arg[1] != '-' )
{
char c;
while ( (c = *++arg) ) switch ( c )
{
default:
errx(1, "unknown option -- '%c'", c);
}
}
else
errx(1, "unknown option: %s", arg);
}
compact_arguments(&argc, &argv);
memcpy(arrow_buffer, arrow, sizeof(arrow));
@ -75,7 +95,7 @@ int main(int argc, char* argv[])
display_initialize(&display);
struct server server;
server_initialize(&server, &display, tty, mouse, socket);
server_initialize(&server, &display);
if ( setenv("DISPLAY_SOCKET", server.server_path, 1) < 0 )
err(1, "setenv");
@ -84,8 +104,8 @@ int main(int argc, char* argv[])
char* home_session = NULL;
char** session_argv = NULL;
if ( optind < argc )
session_argv = argv + optind;
if ( 1 < argc )
session_argv = argv + 1;
else
{
const char* home = getenv("HOME");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016, 2022, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015, 2016, 2022 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
@ -20,7 +20,6 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include <sys/display.h>
#include <sys/ps2mouse.h>
#include <stdbool.h>
@ -32,7 +31,6 @@
enum mouse_state
{
MOUSE_STATE_NONE,
MOUSE_STATE_BUTTON_PRESS,
MOUSE_STATE_TITLE_MOVE,
MOUSE_STATE_RESIZE_BOTTOM,
MOUSE_STATE_RESIZE_BOTTOM_LEFT,
@ -48,7 +46,6 @@ struct window;
struct display
{
struct tiocgdisplay display;
struct framebuffer fb;
struct framebuffer wallpaper;
size_t fb_size;
@ -77,23 +74,19 @@ void assert_is_well_formed_display_list(struct display* display);
void assert_is_well_formed_display(struct display* display);
void display_link_window_at_top(struct display* display, struct window* window);
void display_unlink_window(struct display* display, struct window* window);
void display_unlink_window_removal(struct display* display,
struct window* window);
void display_unmark_active_window(struct display* display,
struct window* window);
void display_unlink_window_removal(struct display* display, struct window* window);
void display_unmark_active_window(struct display* display, struct window* window);
void display_mark_active_window(struct display* display, struct window* window);
void display_update_active_window(struct display* display);
void display_move_window_to_top(struct display* display, struct window* window);
void display_change_active_window(struct display* display,
struct window* window);
void display_change_active_window(struct display* display, struct window* window);
void display_set_active_window(struct display* display, struct window* window);
void display_add_window(struct display* display, struct window* window);
void display_remove_window(struct display* display, struct window* window);
void display_composit(struct display* display, struct framebuffer fb);
void display_render(struct display* display);
void display_keyboard_event(struct display* display, uint32_t codepoint);
void display_on_resolution_change(struct display* display, size_t width,
size_t height);
void display_on_resolution_change(struct display* display, size_t width, size_t height);
void display_mouse_event(struct display* display, uint8_t byte);
#endif

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
* purpose with or without fee is hereby granted, provided that the above
@ -17,7 +17,6 @@
* Display server main loop.
*/
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/termmode.h>
#include <sys/un.h>
@ -44,7 +43,7 @@ static int open_local_server_socket(const char* path, int flags)
{
size_t path_length = strlen(path);
size_t addr_size = offsetof(struct sockaddr_un, sun_path) + path_length + 1;
struct sockaddr_un* sockaddr = malloc(addr_size);
struct sockaddr_un* sockaddr = (struct sockaddr_un*) malloc(addr_size);
if ( !sockaddr )
return -1;
sockaddr->sun_family = AF_LOCAL;
@ -60,8 +59,7 @@ static int open_local_server_socket(const char* path, int flags)
return fd;
}
void server_initialize(struct server* server, struct display* display,
const char* tty, const char* mouse, const char* socket)
void server_initialize(struct server* server, struct display* display)
{
memset(server, 0, sizeof(*server));
@ -70,27 +68,18 @@ void server_initialize(struct server* server, struct display* display,
load_font();
server->tty_fd = 0;
if ( tty || !isatty(server->tty_fd) )
if ( !isatty(server->tty_fd) )
{
tty = tty ? tty : "/dev/tty";
server->tty_fd = open(tty, O_RDONLY);
server->tty_fd = open("/dev/tty", O_RDONLY);
if ( server->tty_fd < 0 )
err(1, tty);
err(1, "/dev/tty");
}
// TODO: Support for multiple displays.
struct tiocgdisplays gdisplays = {0};
gdisplays.count = 1;
gdisplays.displays = &display->display;
if ( ioctl(server->tty_fd, TIOCGDISPLAYS, &gdisplays) < 0 ||
gdisplays.count == 0 )
errx(1, "%s: No video devices are associated with this terminal", tty);
server->mouse_fd = open(mouse, O_RDONLY | O_CLOEXEC);
server->mouse_fd = open("/dev/mouse", O_RDONLY | O_CLOEXEC);
if ( server->mouse_fd < 0 )
err(1, "%s", mouse);
err(1, "%s", "/dev/mouse");
server->server_path = socket;
server->server_path = "/run/display";
server->server_fd = open_local_server_socket(server->server_path,
SOCK_NONBLOCK | SOCK_CLOEXEC);
if ( server->server_fd < 0 )
@ -98,11 +87,11 @@ void server_initialize(struct server* server, struct display* display,
unsigned int termmode =
TERMMODE_KBKEY | TERMMODE_UNICODE | TERMMODE_NONBLOCK;
if ( settermmode(server->tty_fd, termmode) < 0 )
if ( settermmode(0, termmode) < 0 )
err(1, "settermmode");
server->pfds_count = server_pfds_count(server);
server->pfds =
server->pfds = (struct pollfd*)
reallocarray(NULL, sizeof(struct pollfd), server->pfds_count);
if ( !server->pfds )
err(1, "malloc");
@ -122,7 +111,7 @@ bool server_accept(struct server* server)
size_t new_length = server->connections_length * 2;
if ( !new_length )
new_length = 16;
struct connection** new_connections =
struct connection** new_connections = (struct connection**)
reallocarray(server->connections, new_length,
sizeof(struct connection*));
if ( !new_connections )
@ -136,7 +125,7 @@ bool server_accept(struct server* server)
}
size_t new_pfds_count = server_pfds_count(server) + 1;
struct pollfd* new_pfds =
struct pollfd* new_pfds = (struct pollfd*)
reallocarray(server->pfds, sizeof(struct pollfd), new_pfds_count);
if ( !new_pfds )
{
@ -147,7 +136,8 @@ bool server_accept(struct server* server)
server->pfds = new_pfds;
server->pfds_count = new_pfds_count;
struct connection* connection = malloc(sizeof(struct connection));
struct connection* connection = (struct connection*)
malloc(sizeof(struct connection));
if ( !connection )
{
warn("dropped connection: %s: malloc", server->server_path);

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
* purpose with or without fee is hereby granted, provided that the above
@ -41,8 +41,7 @@ struct server
size_t pfds_count;
};
void server_initialize(struct server* server, struct display* display,
const char* tty, const char* mouse, const char* socket);
void server_initialize(struct server* server, struct display* display);
bool server_accept(struct server* server);
size_t server_pfds_count(const struct server* server);
void server_poll(struct server* server);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016, 2017, 2022, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015, 2016, 2017, 2022 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
@ -56,8 +56,6 @@ void window_render_frame(struct window* window)
: make_color_a(180, 180, 255, 128);
uint32_t title_color = has_focus ? make_color_a(16, 16, 16, 240)
: make_color_a(32, 32, 32, 200);
uint32_t button_hover_glass = make_color_a(220, 220, 255, 255);
uint32_t button_press_glass = make_color_a(180, 180, 255, 255);
size_t start_x = 0;
size_t start_y = 0;
@ -127,21 +125,6 @@ void window_render_frame(struct window* window)
for (size_t y = 0; y < button_height; y++)
framebuffer_set_pixel(buttons_fb, button_width * 2 + x, y, 0xFF8080FF);
#endif
for ( size_t n = 0; n < 3; n++ )
{
uint32_t color = glass_color;
switch ( window->button_states[n] )
{
case BUTTON_STATE_NORMAL: continue;
case BUTTON_STATE_HOVER: color = button_hover_glass; break;
case BUTTON_STATE_PRESSED: color = button_press_glass; break;
}
size_t bx = button_width * n;
size_t by = 0;
for ( size_t y = 0; y < tt_height; y++ )
for ( size_t x = 0; x < button_width; x++ )
framebuffer_set_pixel(buttons_fb, bx + x, by + y, color);
}
for ( size_t i = 0; i < button_size; i++ )
{
size_t bx = button_width * 0 + (button_width - button_size) / 2;
@ -208,8 +191,7 @@ void window_render_frame(struct window* window)
tt_width = buttons_x - border_width;
tt_width = 0 < tt_width ? tt_width : 0;
}
render_text(framebuffer_crop(window->buffer, tt_pos_x, tt_pos_y,
tt_width, tt_height), tt, tt_color);
render_text(framebuffer_crop(window->buffer, tt_pos_x, tt_pos_y, tt_width, tt_height), tt, tt_color);
}
void window_move(struct window* window, size_t left, size_t top)
@ -233,8 +215,7 @@ void window_client_resize(struct window* window,
window->buffer.xres = window->width;
window->buffer.yres = window->height;
window->buffer.pitch = window->width;
// TODO: Check malloc.
window->buffer.buffer =
window->buffer.buffer = (uint32_t*)
malloc(sizeof(uint32_t) * window->width * window->height);
for ( size_t y = 0; y < window->height; y++ )
for ( size_t x = 0; x < window->width; x++ )
@ -326,10 +307,9 @@ void window_destroy(struct window* window)
window->created = false;
}
void window_on_display_resolution_change(struct window* window,
struct display* display)
void window_on_display_resolution_change(struct window* window, struct display* display)
{
// TODO: Move window back inside screen.
// TODO: Potentially move window back inside screen?
if ( window->window_state == WINDOW_STATE_MAXIMIZED )
{
// TODO: Change size of maximized window.
@ -337,8 +317,7 @@ void window_on_display_resolution_change(struct window* window,
}
}
void window_tile(struct window* window, enum window_state state, size_t left,
size_t top, size_t width, size_t height)
void window_tile(struct window* window, enum window_state state, size_t left, size_t top, size_t width, size_t height)
{
if ( window->window_state == state )
return;
@ -358,13 +337,12 @@ void window_tile(struct window* window, enum window_state state, size_t left,
window->width = width;
window->height = height;
// TODO: Share logic with window_client_resize.
window->buffer.xres = window->width;
window->buffer.yres = window->height;
window->buffer.pitch = window->width;
// TODO: Check malloc.
window->buffer.buffer =
calloc(1, sizeof(uint32_t) * window->width * window->height);
window->buffer.buffer = (uint32_t*)
malloc(sizeof(uint32_t) * window->width * window->height);
memset(window->buffer.buffer, 0, sizeof(uint32_t) * window->width * window->height);
window->window_state = state;
@ -385,8 +363,7 @@ void window_restore(struct window* window)
return;
window->top = window->saved_top;
window->left = window->saved_left;
window_client_resize(window, window->saved_width - 2 * BORDER_WIDTH,
window->saved_height - TITLE_HEIGHT - BORDER_WIDTH);
window_client_resize(window, window->saved_width - 2 * BORDER_WIDTH, window->saved_height - TITLE_HEIGHT - BORDER_WIDTH);
window_notify_client_resize(window);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016, 2018, 2022, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015, 2016, 2018, 2022 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
@ -35,13 +35,6 @@ static const size_t BORDER_WIDTH = 8;
static const size_t TITLE_HEIGHT = 28;
static const size_t RESIZE_GRACE = 16;
enum button_state
{
BUTTON_STATE_NORMAL,
BUTTON_STATE_HOVER,
BUTTON_STATE_PRESSED,
};
enum window_state
{
WINDOW_STATE_REGULAR,
@ -75,7 +68,6 @@ struct window
size_t saved_height;
uint32_t window_id;
enum window_state window_state;
enum button_state button_states[3];
bool created;
bool show;
bool focus;
@ -86,20 +78,16 @@ struct framebuffer window_client_buffer(struct window* window);
void window_render_frame(struct window* window);
void window_move(struct window* window, size_t left, size_t top);
void window_resize(struct window* window, size_t width, size_t height);
void window_client_resize(struct window* window, size_t client_width,
size_t client_height);
void window_initialize(struct window* window, struct connection* connection,
struct display* display, uint32_t window_id);
void window_client_resize(struct window* window, size_t client_width, size_t client_height);
void window_initialize(struct window* window, struct connection* connection, struct display* display, uint32_t window_id);
void window_quit(struct window* window);
void window_destroy(struct window* window);
void window_drag_resize(struct window* window, int ld, int td, int wd, int hd);
void window_on_display_resolution_change(struct window* window,
struct display* display);
void window_on_display_resolution_change(struct window* window, struct display* display);
void window_maximize(struct window* window);
void window_restore(struct window* window);
void window_toggle_maximized(struct window* window);
void window_tile(struct window* window, enum window_state state, size_t left,
size_t top, size_t width, size_t height);
void window_tile(struct window* window, enum window_state state, size_t left, size_t top, size_t width, size_t height);
void window_tile_leftward(struct window* window);
void window_tile_rightward(struct window* window);
void window_tile_up(struct window* window);
@ -113,6 +101,7 @@ void window_tile_bottom(struct window* window);
void window_tile_bottom_left(struct window* window);
void window_tile_bottom_right(struct window* window);
void window_notify_client_resize(struct window* window);
size_t window_border_width(const struct window* window);
#endif

View File

@ -16,7 +16,7 @@ libdisplay.o \
all: $(LIBRARY)
.PHONY: all install clean
.PHONY: all install uninstall clean
install: all
mkdir -p $(DESTDIR)$(LIBDIR)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016, 2017, 2023 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
@ -100,7 +100,7 @@ struct display_connection* display_connect_default(void)
{
return display_connect(getenv("DISPLAY_SOCKET") ?
getenv("DISPLAY_SOCKET") :
"/var/run/display");
"/run/display");
}
void display_disconnect(struct display_connection* connection)

View File

@ -38,8 +38,8 @@
#include <unistd.h>
#include <display.h>
#include <nyan.h>
#include "nyan.h"
#include "pixel.h"
uint32_t WINDOW_ID = 0;

View File

@ -9,7 +9,6 @@ CFLAGS?=$(OPTLEVEL)
CFLAGS:=$(CFLAGS) -Wall -Wextra
PROGRAM=terminal
MANPAGES1 = terminal.1
OBJS=\
terminal.o \
@ -23,8 +22,6 @@ all: $(PROGRAM)
install: all
mkdir -p $(DESTDIR)$(BINDIR)
install $(PROGRAM) $(DESTDIR)$(BINDIR)
mkdir -p $(DESTDIR)$(MANDIR)/man1
install $(MANPAGES1) $(DESTDIR)$(MANDIR)/man1
$(PROGRAM): $(OBJS)
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) $(OBJS) -o $@ $(LIBS)

View File

@ -1,44 +0,0 @@
.Dd June 17, 2023
.Dt TERMINAL 1
.Os
.Sh NAME
.Nm terminal
.Nd graphical terminal emulator
.Sh SYNOPSIS
.Nm
.Op Ar command ...
.Sh DESCRIPTION
.Nm
is a graphical terminal emulator for the
.Xr display 1
desktop environment.
.Nm
has essentially the same features as the
.Xr kernel 7
console.
.Pp
The
.Ar command
is executed inside a
.Xr pts 4
psuedoterminal.
A login shell can be requested with a leading hyphen
.Sq - .
If no command was specified, the user's shell per
.Xr passwd 5
is run as a login shell with
.Xr sh 1
as a fallback.
.Sh ENVIRONMENT
.Bl -tag -width "TERM"
.It TERM Ns = Ns Sy sortix
The terminal type.
.El
.Sh EXIT STATUS
.Nm
will exit 0 on success and non-zero otherwise.
.Sh SEE ALSO
.Xr display 1 ,
.Xr sh 1 ,
.Xr pts 4 ,
.Xr tty 4