Add display server.
This commit is contained in:
parent
348e89d5be
commit
80054fe389
61 changed files with 6851 additions and 123 deletions
5
Makefile
5
Makefile
|
@ -7,12 +7,15 @@ MODULES=\
|
||||||
libc \
|
libc \
|
||||||
libm \
|
libm \
|
||||||
dispd \
|
dispd \
|
||||||
|
libdisplay \
|
||||||
libmount \
|
libmount \
|
||||||
|
libui \
|
||||||
bench \
|
bench \
|
||||||
carray \
|
carray \
|
||||||
checksum \
|
checksum \
|
||||||
dhclient \
|
dhclient \
|
||||||
disked \
|
disked \
|
||||||
|
display \
|
||||||
dnsconfig \
|
dnsconfig \
|
||||||
editor \
|
editor \
|
||||||
ext \
|
ext \
|
||||||
|
@ -26,12 +29,14 @@ kblayout \
|
||||||
kblayout-compiler \
|
kblayout-compiler \
|
||||||
login \
|
login \
|
||||||
mkinitrd \
|
mkinitrd \
|
||||||
|
nyan \
|
||||||
ping \
|
ping \
|
||||||
regress \
|
regress \
|
||||||
rw \
|
rw \
|
||||||
sf \
|
sf \
|
||||||
sh \
|
sh \
|
||||||
sysinstall \
|
sysinstall \
|
||||||
|
terminal \
|
||||||
tix \
|
tix \
|
||||||
trianglix \
|
trianglix \
|
||||||
update-initrd \
|
update-initrd \
|
||||||
|
|
|
@ -198,6 +198,7 @@ fi
|
||||||
set enable_src=true
|
set enable_src=true
|
||||||
set enable_network_drivers=
|
set enable_network_drivers=
|
||||||
set enable_dhclient=true
|
set enable_dhclient=true
|
||||||
|
set enable_gui=true
|
||||||
set enable_ntpd=false
|
set enable_ntpd=false
|
||||||
set enable_sshd=false
|
set enable_sshd=false
|
||||||
|
|
||||||
|
@ -214,6 +215,7 @@ export no_random_seed
|
||||||
export enable_src
|
export enable_src
|
||||||
export enable_network_drivers
|
export enable_network_drivers
|
||||||
export enable_dhclient
|
export enable_dhclient
|
||||||
|
export enable_gui
|
||||||
export enable_ntpd
|
export enable_ntpd
|
||||||
export enable_sshd
|
export enable_sshd
|
||||||
EOF
|
EOF
|
||||||
|
@ -402,10 +404,11 @@ menuentry() {
|
||||||
echo
|
echo
|
||||||
printf "menuentry \"Sortix (%s)\" {\n" "$1"
|
printf "menuentry \"Sortix (%s)\" {\n" "$1"
|
||||||
if [ -n "$2" ]; then
|
if [ -n "$2" ]; then
|
||||||
|
printf " if \$enable_gui; then\n"
|
||||||
|
printf " load_sortix %s-gui\n" "$2"
|
||||||
|
printf " else\n"
|
||||||
printf " load_sortix %s\n" "$2"
|
printf " load_sortix %s\n" "$2"
|
||||||
#printf " load_sortix '"
|
printf " fi\n"
|
||||||
#printf '%s' "$2" | sed "s,','\\'',g"
|
|
||||||
#printf "'\n"
|
|
||||||
else
|
else
|
||||||
printf " load_sortix\n"
|
printf " load_sortix\n"
|
||||||
fi
|
fi
|
||||||
|
@ -418,7 +421,7 @@ menu_title="\$base_menu_title"
|
||||||
hook_menu_pre
|
hook_menu_pre
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
menuentry "\$title_single_user" '-- /sbin/init'
|
menuentry "\$title_single_user" '-- /sbin/init --target=single-user'
|
||||||
menuentry "\$title_sysinstall" '-- /sbin/init --target=sysinstall'
|
menuentry "\$title_sysinstall" '-- /sbin/init --target=sysinstall'
|
||||||
menuentry "\$title_sysupgrade" '-- /sbin/init --target=sysupgrade'
|
menuentry "\$title_sysupgrade" '-- /sbin/init --target=sysupgrade'
|
||||||
|
|
||||||
|
@ -446,6 +449,18 @@ menu_title="\$base_menu_title - Advanced Options"
|
||||||
|
|
||||||
hook_advanced_menu_pre
|
hook_advanced_menu_pre
|
||||||
|
|
||||||
|
if "\$enable_gui"; then
|
||||||
|
menuentry "Disable GUI" {
|
||||||
|
enable_gui=false
|
||||||
|
configfile /boot/grub/advanced.cfg
|
||||||
|
}
|
||||||
|
else
|
||||||
|
menuentry "Enable GUI" {
|
||||||
|
enable_gui=true
|
||||||
|
configfile /boot/grub/advanced.cfg
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
if "\$enable_src"; then
|
if "\$enable_src"; then
|
||||||
menuentry "Disable loading source code" {
|
menuentry "Disable loading source code" {
|
||||||
enable_src=false
|
enable_src=false
|
||||||
|
|
|
@ -151,6 +151,7 @@ EOF
|
||||||
tix-iso-bootconfig \
|
tix-iso-bootconfig \
|
||||||
--random-seed \
|
--random-seed \
|
||||||
--timeout=0 \
|
--timeout=0 \
|
||||||
|
--disable-gui \
|
||||||
--liveconfig=liveconfig \
|
--liveconfig=liveconfig \
|
||||||
bootconfig
|
bootconfig
|
||||||
mkdir -p bootconfig/boot/grub
|
mkdir -p bootconfig/boot/grub
|
||||||
|
|
3
display/.gitignore
vendored
Normal file
3
display/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
display
|
||||||
|
*.o
|
||||||
|
*.inc
|
45
display/Makefile
Normal file
45
display/Makefile
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
SOFTWARE_MEANT_FOR_SORTIX=1
|
||||||
|
include ../build-aux/platform.mak
|
||||||
|
include ../build-aux/compiler.mak
|
||||||
|
include ../build-aux/dirs.mak
|
||||||
|
|
||||||
|
OPTLEVEL?=-g -O2
|
||||||
|
CFLAGS?=$(OPTLEVEL)
|
||||||
|
|
||||||
|
CFLAGS:=$(CFLAGS) -Wall -Wextra
|
||||||
|
|
||||||
|
PROGRAM=display
|
||||||
|
|
||||||
|
OBJS=\
|
||||||
|
connection.o \
|
||||||
|
display-code.o \
|
||||||
|
display.o \
|
||||||
|
server.o \
|
||||||
|
window.o \
|
||||||
|
|
||||||
|
LIBS:=-lui
|
||||||
|
|
||||||
|
all: $(PROGRAM)
|
||||||
|
|
||||||
|
.PHONY: all install clean
|
||||||
|
|
||||||
|
install: all
|
||||||
|
mkdir -p $(DESTDIR)$(BINDIR)
|
||||||
|
install $(PROGRAM) $(DESTDIR)$(BINDIR)
|
||||||
|
mkdir -p $(DESTDIR)$(SYSCONFDIR)/default
|
||||||
|
printf '#!sh\nexec terminal\n' > $(DESTDIR)$(SYSCONFDIR)/default/displayrc
|
||||||
|
chmod +x $(DESTDIR)$(SYSCONFDIR)/default/displayrc
|
||||||
|
|
||||||
|
$(PROGRAM): $(OBJS)
|
||||||
|
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) $(OBJS) -o $@ $(LIBS)
|
||||||
|
|
||||||
|
display.o: arrow.inc
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
%.inc: %.rgb
|
||||||
|
carray -cs -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(PROGRAM) *.o *.inc
|
BIN
display/arrow.rgb
Normal file
BIN
display/arrow.rgb
Normal file
Binary file not shown.
318
display/connection.c
Normal file
318
display/connection.c
Normal file
|
@ -0,0 +1,318 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* connection.c
|
||||||
|
* Display protocol implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/termmode.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "connection.h"
|
||||||
|
|
||||||
|
void connection_schedule_transmit(struct connection* connection,
|
||||||
|
const void* buffer,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
assert(connection);
|
||||||
|
size_t available = connection->outgoing_size - connection->outgoing_used;
|
||||||
|
if ( available < count )
|
||||||
|
{
|
||||||
|
size_t required_size = connection->outgoing_used + count;
|
||||||
|
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_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;
|
||||||
|
connection->outgoing_size = required_size;
|
||||||
|
connection->outgoing = new_outgoing;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connection_initialize(struct connection* connection,
|
||||||
|
struct display* display,
|
||||||
|
int fd)
|
||||||
|
{
|
||||||
|
memset(connection, 0, sizeof(*connection));
|
||||||
|
connection->display = display;
|
||||||
|
connection->fd = fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct window* connection_find_window_raw(struct connection* connection,
|
||||||
|
uint32_t window_id)
|
||||||
|
{
|
||||||
|
if ( MAX_WINDOWS_PER_CONNECTION <= window_id )
|
||||||
|
return NULL;
|
||||||
|
return &connection->windows[window_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct window* connection_find_window(struct connection* connection,
|
||||||
|
uint32_t window_id)
|
||||||
|
{
|
||||||
|
struct window* result = connection_find_window_raw(connection, window_id);
|
||||||
|
if ( !result->created )
|
||||||
|
return NULL;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#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)))
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
||||||
|
CONNECTION_MESSAGE_HANDLER_NO_AUX(shutdown)
|
||||||
|
{
|
||||||
|
(void) connection;
|
||||||
|
if ( msg->code == 0 )
|
||||||
|
exit(0);
|
||||||
|
else if ( msg->code == 1 )
|
||||||
|
exit(1);
|
||||||
|
else if ( msg->code == 2 )
|
||||||
|
exit(2);
|
||||||
|
else
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CONNECTION_MESSAGE_HANDLER_NO_AUX(create_window)
|
||||||
|
{
|
||||||
|
struct window* window = connection_find_window_raw(connection, msg->window_id);
|
||||||
|
if ( !window )
|
||||||
|
return;
|
||||||
|
if ( window->created )
|
||||||
|
return;
|
||||||
|
window_initialize(window, connection, connection->display, msg->window_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
CONNECTION_MESSAGE_HANDLER_NO_AUX(destroy_window)
|
||||||
|
{
|
||||||
|
struct window* window = connection_find_window(connection, msg->window_id);
|
||||||
|
if ( !window )
|
||||||
|
return;
|
||||||
|
window_destroy(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
CONNECTION_MESSAGE_HANDLER_NO_AUX(resize_window)
|
||||||
|
{
|
||||||
|
struct window* window = connection_find_window(connection, msg->window_id);
|
||||||
|
if ( !window )
|
||||||
|
return;
|
||||||
|
window_client_resize(window, msg->width, msg->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
CONNECTION_MESSAGE_HANDLER(render_window)
|
||||||
|
{
|
||||||
|
struct window* window = connection_find_window(connection, msg->window_id);
|
||||||
|
if ( !window )
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct framebuffer src;
|
||||||
|
src.xres = msg->width;
|
||||||
|
src.yres = msg->height;
|
||||||
|
src.pitch = msg->width;
|
||||||
|
src.buffer = (uint32_t*) auxilerary;
|
||||||
|
|
||||||
|
if ( auxilerary_size < sizeof(uint32_t) * src.xres * src.yres )
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct framebuffer dst =
|
||||||
|
framebuffer_crop(window_client_buffer(window),
|
||||||
|
msg->left, msg->top, msg->width, msg->height);
|
||||||
|
|
||||||
|
framebuffer_copy_to_framebuffer(dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
CONNECTION_MESSAGE_HANDLER(title_window)
|
||||||
|
{
|
||||||
|
struct window* window = connection_find_window(connection, msg->window_id);
|
||||||
|
if ( !window )
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char* title = (char*) auxilerary;
|
||||||
|
free(window->title);
|
||||||
|
window->title = strndup(title, auxilerary_size);
|
||||||
|
|
||||||
|
window_render_frame(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
CONNECTION_MESSAGE_HANDLER_NO_AUX(show_window)
|
||||||
|
{
|
||||||
|
struct window* window = connection_find_window(connection, msg->window_id);
|
||||||
|
if ( !window )
|
||||||
|
return;
|
||||||
|
window->show = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CONNECTION_MESSAGE_HANDLER_NO_AUX(hide_window)
|
||||||
|
{
|
||||||
|
struct window* window = connection_find_window(connection, msg->window_id);
|
||||||
|
if ( !window )
|
||||||
|
return;
|
||||||
|
window->show = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*connection_message_handler)(struct connection* connection,
|
||||||
|
void* msg,
|
||||||
|
void* auxilerary,
|
||||||
|
size_t auxilerary_size);
|
||||||
|
|
||||||
|
struct connection_message_handler_registration
|
||||||
|
{
|
||||||
|
connection_message_handler handler;
|
||||||
|
size_t message_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define REGISTER_CONNECTION_MESSAGE_HANDLER(message_name) \
|
||||||
|
{ (connection_message_handler) connection_handler_##message_name, \
|
||||||
|
sizeof(struct display_##message_name) }
|
||||||
|
|
||||||
|
struct connection_message_handler_registration connection_message_handlers[] =
|
||||||
|
{
|
||||||
|
REGISTER_CONNECTION_MESSAGE_HANDLER(create_window),
|
||||||
|
REGISTER_CONNECTION_MESSAGE_HANDLER(destroy_window),
|
||||||
|
REGISTER_CONNECTION_MESSAGE_HANDLER(resize_window),
|
||||||
|
REGISTER_CONNECTION_MESSAGE_HANDLER(render_window),
|
||||||
|
REGISTER_CONNECTION_MESSAGE_HANDLER(title_window),
|
||||||
|
REGISTER_CONNECTION_MESSAGE_HANDLER(show_window),
|
||||||
|
REGISTER_CONNECTION_MESSAGE_HANDLER(hide_window),
|
||||||
|
REGISTER_CONNECTION_MESSAGE_HANDLER(shutdown),
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t num_connection_message_handlers = sizeof(connection_message_handlers) /
|
||||||
|
sizeof(connection_message_handlers[0]);
|
||||||
|
|
||||||
|
short connection_interested_poll_events(struct connection* connection)
|
||||||
|
{
|
||||||
|
return POLLIN | (connection->outgoing_used ? POLLOUT : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void connection_can_read(struct connection* connection)
|
||||||
|
{
|
||||||
|
while ( connection->packet_header_received < sizeof(connection->packet_header) )
|
||||||
|
{
|
||||||
|
ssize_t amount = read(connection->fd,
|
||||||
|
(unsigned char*) &connection->packet_header +
|
||||||
|
connection->packet_header_received,
|
||||||
|
sizeof(connection->packet_header) -
|
||||||
|
connection->packet_header_received);
|
||||||
|
if ( amount < 0 && (errno == EAGAIN || errno == EWOULDBLOCK) )
|
||||||
|
return;
|
||||||
|
if ( amount < 0 || amount == 0 )
|
||||||
|
return; // TODO: No longer signal interest in reading and disconnect.
|
||||||
|
connection->packet_header_received += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t packet_length = connection->packet_header.message_length;
|
||||||
|
|
||||||
|
if ( !connection->packet )
|
||||||
|
connection->packet = (unsigned char*) malloc(packet_length);
|
||||||
|
|
||||||
|
while ( connection->packet_received < packet_length )
|
||||||
|
{
|
||||||
|
ssize_t amount = read(connection->fd,
|
||||||
|
connection->packet + connection->packet_received,
|
||||||
|
packet_length - connection->packet_received);
|
||||||
|
if ( amount < 0 && (errno == EAGAIN || errno == EWOULDBLOCK) )
|
||||||
|
return;
|
||||||
|
if ( amount < 0 || amount == 0 )
|
||||||
|
return; // TODO: No longer signal interest in reading and disconnect.
|
||||||
|
connection->packet_received += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t packet_id = connection->packet_header.message_id;
|
||||||
|
|
||||||
|
if ( packet_id < num_connection_message_handlers )
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
handler->handler(connection, connection->packet,
|
||||||
|
auxilerary, auxilerary_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
connection->packet_header_received = 0;
|
||||||
|
free(connection->packet);
|
||||||
|
connection->packet = NULL;
|
||||||
|
connection->packet_received = 0;
|
||||||
|
|
||||||
|
// TODO: Check if we can received another packet, but only if we haven't
|
||||||
|
// done so much work that the display server is starved.
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
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 and disconnect.
|
||||||
|
connection->outgoing_offset = (connection->outgoing_offset + amount) % connection->outgoing_size;
|
||||||
|
connection->outgoing_used -= amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(connection->outgoing);
|
||||||
|
connection->outgoing = NULL;
|
||||||
|
connection->outgoing_used = 0;
|
||||||
|
connection->outgoing_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connection_destroy(struct connection* connection)
|
||||||
|
{
|
||||||
|
for ( size_t i = 0; i < MAX_WINDOWS_PER_CONNECTION; i++ )
|
||||||
|
{
|
||||||
|
if ( !connection->windows[i].created )
|
||||||
|
continue;
|
||||||
|
window_destroy(&connection->windows[i]);
|
||||||
|
}
|
||||||
|
close(connection->fd);
|
||||||
|
}
|
65
display/connection.h
Normal file
65
display/connection.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* connection.h
|
||||||
|
* Display protocol implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONNECTION_H
|
||||||
|
#define CONNECTION_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <display-protocol.h>
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
struct display;
|
||||||
|
struct window;
|
||||||
|
|
||||||
|
#define MAX_WINDOWS_PER_CONNECTION 256
|
||||||
|
|
||||||
|
struct connection
|
||||||
|
{
|
||||||
|
struct display* display;
|
||||||
|
struct window windows[MAX_WINDOWS_PER_CONNECTION];
|
||||||
|
struct display_packet_header packet_header;
|
||||||
|
size_t packet_header_received;
|
||||||
|
unsigned char* packet;
|
||||||
|
size_t packet_received;
|
||||||
|
unsigned char* outgoing;
|
||||||
|
size_t outgoing_offset;
|
||||||
|
size_t outgoing_used;
|
||||||
|
size_t outgoing_size;
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
void connection_schedule_transmit(struct connection* connection,
|
||||||
|
const void* buffer,
|
||||||
|
size_t count);
|
||||||
|
void connection_initialize(struct connection* connection,
|
||||||
|
struct display* display,
|
||||||
|
int fd);
|
||||||
|
struct window* connection_find_window_raw(struct connection* connection,
|
||||||
|
uint32_t window_id);
|
||||||
|
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_write(struct connection* connection);
|
||||||
|
void connection_destroy(struct connection* connection);
|
||||||
|
|
||||||
|
#endif
|
39
display/damage-rect.c
Normal file
39
display/damage-rect.c
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* damage-rect.c
|
||||||
|
* Damage rectangles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "damage-rect.h"
|
||||||
|
|
||||||
|
struct damage_rect damage_rect_add(struct damage_rect a, struct damage_rect b)
|
||||||
|
{
|
||||||
|
if ( !a.width || !a.height )
|
||||||
|
return b;
|
||||||
|
if ( !b.width || !b.height )
|
||||||
|
return a;
|
||||||
|
if ( a.left < b.left )
|
||||||
|
b.width += b.left - a.left, b.left = a.left;
|
||||||
|
if ( b.width < a.width )
|
||||||
|
b.width = a.width;
|
||||||
|
if ( a.top < b.top )
|
||||||
|
b.height += b.top - a.top, b.top = a.top;
|
||||||
|
if ( b.height < a.height )
|
||||||
|
b.height = a.height;
|
||||||
|
return b;
|
||||||
|
}
|
35
display/damage-rect.h
Normal file
35
display/damage-rect.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* damage-rect.h
|
||||||
|
* Damage rectangles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DAMAGE_RECT_H
|
||||||
|
#define DAMAGE_RECT_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct damage_rect
|
||||||
|
{
|
||||||
|
size_t left;
|
||||||
|
size_t top;
|
||||||
|
size_t width;
|
||||||
|
size_t height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct damage_rect damage_rect_add(struct damage_rect a, struct damage_rect b);
|
||||||
|
|
||||||
|
#endif
|
680
display/display-code.c
Normal file
680
display/display-code.c
Normal file
|
@ -0,0 +1,680 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* display-code.c
|
||||||
|
* Display server logic.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/display.h>
|
||||||
|
#include <sys/keycodes.h>
|
||||||
|
#include <sys/ps2mouse.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <display-protocol.h>
|
||||||
|
|
||||||
|
#include "connection.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "pixel.h"
|
||||||
|
#include "vgafont.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
extern struct framebuffer arrow_framebuffer;
|
||||||
|
|
||||||
|
void display_initialize(struct display* display)
|
||||||
|
{
|
||||||
|
memset(display, 0, sizeof(*display));
|
||||||
|
}
|
||||||
|
|
||||||
|
void assert_is_well_formed_display_list(struct display* display)
|
||||||
|
{
|
||||||
|
struct window* last_window = NULL;
|
||||||
|
struct window* iterator = display->bottom_window;
|
||||||
|
while ( iterator )
|
||||||
|
{
|
||||||
|
assert(iterator->below_window == last_window);
|
||||||
|
last_window = iterator;
|
||||||
|
iterator = iterator->above_window;
|
||||||
|
}
|
||||||
|
assert(last_window == display->top_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assert_is_well_formed_display(struct display* display)
|
||||||
|
{
|
||||||
|
assert_is_well_formed_display_list(display);
|
||||||
|
|
||||||
|
bool found_active_window = display->active_window == NULL;
|
||||||
|
bool found_tab_candidate = display->tab_candidate == NULL;
|
||||||
|
struct window* iterator = display->bottom_window;
|
||||||
|
while ( iterator )
|
||||||
|
{
|
||||||
|
if ( iterator == display->active_window )
|
||||||
|
found_active_window = true;
|
||||||
|
if ( iterator == display->tab_candidate )
|
||||||
|
found_tab_candidate = true;
|
||||||
|
iterator = iterator->above_window;
|
||||||
|
}
|
||||||
|
assert(found_active_window);
|
||||||
|
assert(found_tab_candidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_link_window_at_top(struct display* display, struct window* window)
|
||||||
|
{
|
||||||
|
assert_is_well_formed_display_list(display);
|
||||||
|
|
||||||
|
assert(!window->above_window);
|
||||||
|
assert(!window->below_window);
|
||||||
|
assert(display->top_window != window);
|
||||||
|
assert(display->bottom_window != window);
|
||||||
|
|
||||||
|
if ( (window->below_window = display->top_window) )
|
||||||
|
window->below_window->above_window = window;
|
||||||
|
window->above_window = NULL;
|
||||||
|
|
||||||
|
display->top_window = window;
|
||||||
|
if ( !display->bottom_window )
|
||||||
|
display->bottom_window = window;
|
||||||
|
|
||||||
|
assert_is_well_formed_display_list(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_unlink_window(struct display* display, struct window* window)
|
||||||
|
{
|
||||||
|
assert_is_well_formed_display_list(display);
|
||||||
|
|
||||||
|
assert(window->below_window || display->bottom_window == window);
|
||||||
|
assert(window->above_window || display->top_window == window);
|
||||||
|
|
||||||
|
if ( window->below_window )
|
||||||
|
window->below_window->above_window = window->above_window;
|
||||||
|
else
|
||||||
|
display->bottom_window = window->above_window;
|
||||||
|
if ( window->above_window )
|
||||||
|
window->above_window->below_window = window->below_window;
|
||||||
|
else
|
||||||
|
display->top_window = window->below_window;
|
||||||
|
|
||||||
|
assert(display->bottom_window != window);
|
||||||
|
assert(display->top_window != window);
|
||||||
|
|
||||||
|
window->above_window = NULL;
|
||||||
|
window->below_window = NULL;
|
||||||
|
|
||||||
|
assert_is_well_formed_display_list(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_unlink_window_removal(struct display* display, struct window* window)
|
||||||
|
{
|
||||||
|
assert_is_well_formed_display_list(display);
|
||||||
|
|
||||||
|
if ( display->tab_candidate == window )
|
||||||
|
if ( !(display->tab_candidate = window->below_window) )
|
||||||
|
if ( (display->tab_candidate = display->top_window) == window )
|
||||||
|
display->tab_candidate = NULL;
|
||||||
|
|
||||||
|
if ( display->active_window == window )
|
||||||
|
display->active_window = NULL;
|
||||||
|
|
||||||
|
window->focus = false;
|
||||||
|
|
||||||
|
assert_is_well_formed_display_list(display);
|
||||||
|
|
||||||
|
display_unlink_window(display, window);
|
||||||
|
|
||||||
|
assert_is_well_formed_display_list(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_unmark_active_window(struct display* display, struct window* window)
|
||||||
|
{
|
||||||
|
assert(display->active_window == window);
|
||||||
|
window->focus = false;
|
||||||
|
display->active_window = NULL;
|
||||||
|
window_render_frame(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_mark_active_window(struct display* display, struct window* window)
|
||||||
|
{
|
||||||
|
assert(!display->active_window);
|
||||||
|
window->focus = true;
|
||||||
|
display->active_window = window;
|
||||||
|
window_render_frame(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_update_active_window(struct display* display)
|
||||||
|
{
|
||||||
|
if ( !display->active_window && display->top_window )
|
||||||
|
display_mark_active_window(display, display->top_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_move_window_to_top(struct display* display, struct window* window)
|
||||||
|
{
|
||||||
|
display_unlink_window(display, window);
|
||||||
|
display_link_window_at_top(display, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_change_active_window(struct display* display, struct window* window)
|
||||||
|
{
|
||||||
|
if ( display->active_window == window )
|
||||||
|
{
|
||||||
|
display_move_window_to_top(display, window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_unmark_active_window(display, display->active_window);
|
||||||
|
display_mark_active_window(display, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_set_active_window(struct display* display, struct window* window)
|
||||||
|
{
|
||||||
|
display_change_active_window(display, window);
|
||||||
|
display_move_window_to_top(display, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_add_window(struct display* display, struct window* window)
|
||||||
|
{
|
||||||
|
display_link_window_at_top(display, window);
|
||||||
|
display_update_active_window(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_remove_window(struct display* display, struct window* window)
|
||||||
|
{
|
||||||
|
display_unlink_window_removal(display, window);
|
||||||
|
display_update_active_window(display);
|
||||||
|
|
||||||
|
assert(display->top_window != window);
|
||||||
|
assert(display->bottom_window != window);
|
||||||
|
struct window* last_window = NULL;
|
||||||
|
struct window* iterator = display->bottom_window;
|
||||||
|
while ( iterator )
|
||||||
|
{
|
||||||
|
assert(iterator != window);
|
||||||
|
assert(iterator->below_window == last_window);
|
||||||
|
last_window = iterator;
|
||||||
|
iterator = iterator->above_window;
|
||||||
|
}
|
||||||
|
assert(last_window == display->top_window);
|
||||||
|
|
||||||
|
assert(!display->top_window || display->active_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_composit(struct display* display, struct framebuffer fb)
|
||||||
|
{
|
||||||
|
struct damage_rect damage_rect = display->damage_rect;
|
||||||
|
damage_rect.left = 0;
|
||||||
|
damage_rect.top = 0;
|
||||||
|
damage_rect.width = fb.xres;
|
||||||
|
damage_rect.height = fb.yres;
|
||||||
|
if ( !damage_rect.width || !damage_rect.height )
|
||||||
|
return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
for ( struct window* window = display->bottom_window;
|
||||||
|
window;
|
||||||
|
window = window->above_window )
|
||||||
|
{
|
||||||
|
if ( !window->show )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
size_t winfb_left;
|
||||||
|
size_t winfb_top;
|
||||||
|
struct framebuffer winfb = window->buffer;
|
||||||
|
|
||||||
|
if ( window->left < 0 )
|
||||||
|
{
|
||||||
|
winfb_left = 0;
|
||||||
|
winfb = framebuffer_crop(winfb, -window->left, 0, winfb.xres, winfb.yres);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
winfb_left = window->left;
|
||||||
|
|
||||||
|
if ( window->top < 0 )
|
||||||
|
{
|
||||||
|
winfb_top = 0;
|
||||||
|
winfb = framebuffer_crop(winfb, 0, -window->top, winfb.xres, winfb.yres);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
winfb_top = window->top;
|
||||||
|
|
||||||
|
size_t winfb_width = winfb.xres;
|
||||||
|
size_t winfb_height = winfb.yres;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct framebuffer fb_dst =
|
||||||
|
framebuffer_crop(fb, winfb_left, winfb_top, winfb_width, winfb_height);
|
||||||
|
|
||||||
|
framebuffer_copy_to_framebuffer_blend(fb_dst, winfb);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* cursor_text = NULL;
|
||||||
|
switch ( display->mouse_state )
|
||||||
|
{
|
||||||
|
case MOUSE_STATE_NONE: break;
|
||||||
|
case MOUSE_STATE_TITLE_MOVE: break;
|
||||||
|
case MOUSE_STATE_RESIZE_BOTTOM: cursor_text = "↓"; break;
|
||||||
|
case MOUSE_STATE_RESIZE_BOTTOM_LEFT: cursor_text = "└"; break;
|
||||||
|
case MOUSE_STATE_RESIZE_BOTTOM_RIGHT: cursor_text = "┘"; break;
|
||||||
|
case MOUSE_STATE_RESIZE_LEFT: cursor_text = "←"; break;
|
||||||
|
case MOUSE_STATE_RESIZE_RIGHT: cursor_text = "→"; break;
|
||||||
|
case MOUSE_STATE_RESIZE_TOP: cursor_text = "↑"; break;
|
||||||
|
case MOUSE_STATE_RESIZE_TOP_LEFT: cursor_text = "┌"; break;
|
||||||
|
case MOUSE_STATE_RESIZE_TOP_RIGHT: cursor_text = "┐"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pointer_hwidth = arrow_framebuffer.xres / 2;
|
||||||
|
int pointer_hheight = arrow_framebuffer.yres / 2;
|
||||||
|
|
||||||
|
int pointer_x = display->pointer_x - (cursor_text ? 0 : pointer_hwidth);
|
||||||
|
int pointer_y = display->pointer_y - (cursor_text ? 0 : pointer_hheight);
|
||||||
|
|
||||||
|
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);
|
||||||
|
pointer_x = 0;
|
||||||
|
}
|
||||||
|
if ( pointer_y < 0 )
|
||||||
|
{
|
||||||
|
arrow_render = framebuffer_crop(arrow_render, 0, -pointer_y, arrow_render.xres, arrow_render.yres);
|
||||||
|
pointer_y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct framebuffer fb_dst =
|
||||||
|
framebuffer_crop(fb, pointer_x, pointer_y, fb.xres, fb.yres);
|
||||||
|
|
||||||
|
if ( cursor_text != NULL )
|
||||||
|
render_text(fb_dst, cursor_text, make_color(0, 0, 0));
|
||||||
|
else
|
||||||
|
framebuffer_copy_to_framebuffer_blend(fb_dst, arrow_render);
|
||||||
|
|
||||||
|
memset(&damage_rect, 0, sizeof(damage_rect));
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_render(struct display* display)
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
if ( mode.control & DISPMSG_CONTROL_VGA )
|
||||||
|
errx(1, "A VGA text mode was set");
|
||||||
|
if ( mode.fb_format != 32 )
|
||||||
|
errx(1, "A 32-bit video mode wasn't set");
|
||||||
|
|
||||||
|
struct framebuffer fb;
|
||||||
|
fb.xres = mode.view_xres;
|
||||||
|
fb.yres = mode.view_yres;
|
||||||
|
fb.pitch = mode.view_xres;
|
||||||
|
size_t framebuffer_length = fb.xres * fb.yres;
|
||||||
|
fb.buffer = (uint32_t*) malloc(sizeof(uint32_t) * framebuffer_length);
|
||||||
|
size_t framebuffer_size = framebuffer_length * sizeof(fb.buffer[0]);
|
||||||
|
|
||||||
|
display_on_resolution_change(display, mode.view_xres, mode.view_yres);
|
||||||
|
|
||||||
|
display_composit(display, fb);
|
||||||
|
|
||||||
|
{
|
||||||
|
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*) fb.buffer;
|
||||||
|
|
||||||
|
if ( dispmsg_issue(&msg, sizeof(msg)) != 0 )
|
||||||
|
err(1, "dispmsg_issue: dispmsg_write_memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This could be recycled if the resolution did not change.
|
||||||
|
free(fb.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_keyboard_event(struct display* display, uint32_t codepoint)
|
||||||
|
{
|
||||||
|
struct window* window = display->active_window;
|
||||||
|
|
||||||
|
int kbkey = KBKEY_DECODE(codepoint);
|
||||||
|
int abskbkey = kbkey < 0 ? -kbkey : kbkey;
|
||||||
|
|
||||||
|
if ( kbkey && (!window || !window->grab_input) )
|
||||||
|
{
|
||||||
|
switch ( abskbkey )
|
||||||
|
{
|
||||||
|
case KBKEY_LCTRL: display->key_lctrl = kbkey > 0; break;
|
||||||
|
case KBKEY_LALT: display->key_lalt = kbkey > 0; break;
|
||||||
|
case KBKEY_LSUPER: display->key_lsuper = kbkey > 0; break;
|
||||||
|
case KBKEY_RSUPER: display->key_rsuper = kbkey > 0; break;
|
||||||
|
}
|
||||||
|
if ( display->key_lctrl && display->key_lalt && kbkey == KBKEY_DELETE )
|
||||||
|
exit(0);
|
||||||
|
if ( display->key_lctrl && display->key_lalt && kbkey == KBKEY_T )
|
||||||
|
{
|
||||||
|
if ( !fork() )
|
||||||
|
{
|
||||||
|
execlp("terminal", "terminal", (char*) NULL);
|
||||||
|
_exit(127);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ( display->key_lctrl && display->key_lalt && kbkey == -KBKEY_T )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( kbkey && window && !window->grab_input )
|
||||||
|
{
|
||||||
|
// TODO: Ctrl+Q when termninal has a way of handling it or not.
|
||||||
|
if ( (display->key_lalt && kbkey == KBKEY_F4) /* ||
|
||||||
|
(display->key_lctrl && kbkey == KBKEY_Q)*/ )
|
||||||
|
{
|
||||||
|
struct event_keyboard event;
|
||||||
|
event.window_id = display->active_window->window_id;
|
||||||
|
|
||||||
|
struct display_packet_header header;
|
||||||
|
header.message_id = EVENT_QUIT;
|
||||||
|
header.message_length = sizeof(event);
|
||||||
|
|
||||||
|
assert(window->connection);
|
||||||
|
|
||||||
|
connection_schedule_transmit(window->connection, &header, sizeof(header));
|
||||||
|
connection_schedule_transmit(window->connection, &event, sizeof(event));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( display->key_lalt && kbkey == KBKEY_F10 )
|
||||||
|
{
|
||||||
|
window_toggle_maximized(display->active_window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( display->key_lalt && kbkey == KBKEY_TAB )
|
||||||
|
{
|
||||||
|
if ( !display->tab_candidate )
|
||||||
|
display->tab_candidate = display->active_window;
|
||||||
|
struct window* old_candidate = display->tab_candidate;
|
||||||
|
if ( !(display->tab_candidate = old_candidate->below_window) )
|
||||||
|
display->tab_candidate = display->top_window;
|
||||||
|
window_render_frame(old_candidate);
|
||||||
|
window_render_frame(display->tab_candidate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( kbkey == -KBKEY_LALT && display->tab_candidate )
|
||||||
|
{
|
||||||
|
if ( display->tab_candidate != display->active_window )
|
||||||
|
display_set_active_window(display, display->tab_candidate);
|
||||||
|
display->tab_candidate = NULL;
|
||||||
|
window = display->active_window;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( display->key_lsuper || display->key_lsuper )
|
||||||
|
{
|
||||||
|
struct window* window = display->active_window;
|
||||||
|
if ( kbkey == KBKEY_LEFT )
|
||||||
|
{
|
||||||
|
window_tile_leftward(window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( kbkey == KBKEY_RIGHT )
|
||||||
|
{
|
||||||
|
window_tile_rightward(window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( kbkey == KBKEY_UP )
|
||||||
|
{
|
||||||
|
window_tile_up(window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( kbkey == KBKEY_DOWN )
|
||||||
|
{
|
||||||
|
window_tile_down(window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* grab_inputbed_string = " - Input Grabbed";
|
||||||
|
if ( kbkey == KBKEY_F11 && window && !window->grab_input )
|
||||||
|
{
|
||||||
|
// TODO: window->title can be null.
|
||||||
|
char* new_title;
|
||||||
|
if ( 0 <= asprintf(&new_title, "%s%s", window->title, grab_inputbed_string) )
|
||||||
|
{
|
||||||
|
window->grab_input = true;
|
||||||
|
free(window->title);
|
||||||
|
window->title = new_title;
|
||||||
|
window_render_frame(window);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( kbkey == KBKEY_F12 && window && window->grab_input )
|
||||||
|
{
|
||||||
|
// TODO: Only remove from title if there.
|
||||||
|
size_t grab_inputbed_string_len = strlen(grab_inputbed_string);
|
||||||
|
window->title[strlen(window->title) - grab_inputbed_string_len] = '\0';
|
||||||
|
window->grab_input = false;
|
||||||
|
window_render_frame(window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !window )
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct event_keyboard event;
|
||||||
|
event.window_id = display->active_window->window_id;
|
||||||
|
event.codepoint = codepoint;
|
||||||
|
|
||||||
|
struct display_packet_header header;
|
||||||
|
header.message_id = EVENT_KEYBOARD;
|
||||||
|
header.message_length = sizeof(event);
|
||||||
|
|
||||||
|
assert(window->connection);
|
||||||
|
|
||||||
|
connection_schedule_transmit(window->connection, &header, sizeof(header));
|
||||||
|
connection_schedule_transmit(window->connection, &event, sizeof(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_mouse_event(struct display* display, uint8_t byte)
|
||||||
|
{
|
||||||
|
if ( display->mouse_byte_count == 0 && !(byte & MOUSE_ALWAYS_1) )
|
||||||
|
return;
|
||||||
|
if ( display->mouse_byte_count < MOUSE_PACKET_SIZE )
|
||||||
|
display->mouse_bytes[display->mouse_byte_count++] = byte;
|
||||||
|
if ( display->mouse_byte_count < MOUSE_PACKET_SIZE )
|
||||||
|
return;
|
||||||
|
display->mouse_byte_count = 0;
|
||||||
|
uint8_t* bytes = display->mouse_bytes;
|
||||||
|
|
||||||
|
int xm = MOUSE_X(bytes);
|
||||||
|
int ym = MOUSE_Y(bytes);
|
||||||
|
|
||||||
|
int old_pointer_x = display->pointer_x;
|
||||||
|
int old_pointer_y = display->pointer_y;
|
||||||
|
|
||||||
|
if ( xm*xm + ym*ym >= 2*2 )
|
||||||
|
{
|
||||||
|
xm *= 2;
|
||||||
|
ym *= 2;
|
||||||
|
}
|
||||||
|
else if ( xm*xm + ym*ym >= 5*5 )
|
||||||
|
{
|
||||||
|
xm *= 3;
|
||||||
|
ym *= 3;
|
||||||
|
}
|
||||||
|
display->pointer_x += xm;
|
||||||
|
display->pointer_y += ym;
|
||||||
|
|
||||||
|
if ( display->pointer_x < 0 )
|
||||||
|
display->pointer_x = 0;
|
||||||
|
if ( display->pointer_y < 0 )
|
||||||
|
display->pointer_y = 0;
|
||||||
|
if ( display->screen_width <= (size_t) display->pointer_x )
|
||||||
|
display->pointer_x = display->screen_width;
|
||||||
|
if ( display->screen_height <= (size_t) display->pointer_y )
|
||||||
|
display->pointer_y = display->screen_height;
|
||||||
|
xm = display->pointer_x - old_pointer_x;
|
||||||
|
ym = display->pointer_y - old_pointer_y;
|
||||||
|
|
||||||
|
struct window* window;
|
||||||
|
for ( window = display->top_window; window; window = window->below_window )
|
||||||
|
{
|
||||||
|
if ( display->mouse_state != MOUSE_STATE_NONE )
|
||||||
|
break;
|
||||||
|
int grace = RESIZE_GRACE;
|
||||||
|
if ( window->window_state == WINDOW_STATE_MAXIMIZED )
|
||||||
|
grace = 0;
|
||||||
|
if ( old_pointer_x < window->left - grace )
|
||||||
|
continue;
|
||||||
|
if ( old_pointer_y < window->top - grace )
|
||||||
|
continue;
|
||||||
|
if ( old_pointer_x > window->left + (ssize_t) window->width + grace )
|
||||||
|
continue;
|
||||||
|
if ( old_pointer_y > window->top + (ssize_t) window->height + grace)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( !window )
|
||||||
|
return;
|
||||||
|
|
||||||
|
ssize_t window_pointer_x = display->pointer_x - window->left;
|
||||||
|
ssize_t window_pointer_y = display->pointer_y - window->top;
|
||||||
|
|
||||||
|
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 ||
|
||||||
|
(0 <= window_pointer_x &&
|
||||||
|
window_pointer_x < (ssize_t) window->width &&
|
||||||
|
0 <= window_pointer_y &&
|
||||||
|
window_pointer_y <= (ssize_t) TITLE_HEIGHT) )
|
||||||
|
display->mouse_state = MOUSE_STATE_TITLE_MOVE;
|
||||||
|
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 &&
|
||||||
|
window_pointer_y < (ssize_t) window->height )
|
||||||
|
display->mouse_state = MOUSE_STATE_RESIZE_LEFT;
|
||||||
|
else if ( window_pointer_x < 0 &&
|
||||||
|
(ssize_t) window->height <= window_pointer_y )
|
||||||
|
display->mouse_state = MOUSE_STATE_RESIZE_BOTTOM_LEFT;
|
||||||
|
else if ( 0 <= window_pointer_x &&
|
||||||
|
window_pointer_x < (ssize_t) window->width &&
|
||||||
|
window_pointer_y < 0 )
|
||||||
|
display->mouse_state = MOUSE_STATE_RESIZE_TOP;
|
||||||
|
else if ( 0 <= window_pointer_x &&
|
||||||
|
window_pointer_x < (ssize_t) window->width &&
|
||||||
|
(ssize_t) window->height < window_pointer_y )
|
||||||
|
display->mouse_state = MOUSE_STATE_RESIZE_BOTTOM;
|
||||||
|
else if ( (ssize_t) window->width <= window_pointer_x &&
|
||||||
|
window_pointer_y < 0 )
|
||||||
|
display->mouse_state = MOUSE_STATE_RESIZE_TOP_RIGHT;
|
||||||
|
else if ( (ssize_t) window->width < window_pointer_x &&
|
||||||
|
0 <= window_pointer_y &&
|
||||||
|
window_pointer_y < (ssize_t) window->height )
|
||||||
|
display->mouse_state = MOUSE_STATE_RESIZE_RIGHT;
|
||||||
|
else if ( (ssize_t) window->width <= window_pointer_x &&
|
||||||
|
(ssize_t) window->height <= window_pointer_y )
|
||||||
|
display->mouse_state = MOUSE_STATE_RESIZE_BOTTOM_RIGHT;
|
||||||
|
}
|
||||||
|
if ( xm || ym )
|
||||||
|
{
|
||||||
|
switch ( display->mouse_state )
|
||||||
|
{
|
||||||
|
case MOUSE_STATE_NONE: break;
|
||||||
|
case MOUSE_STATE_TITLE_MOVE:
|
||||||
|
if ( window->window_state != WINDOW_STATE_REGULAR )
|
||||||
|
window_restore(window);
|
||||||
|
window_move(window, window->left + xm, window->top + ym);
|
||||||
|
break;
|
||||||
|
case MOUSE_STATE_RESIZE_TOP_LEFT:
|
||||||
|
window_drag_resize(window, xm, ym, -xm, -ym);
|
||||||
|
break;
|
||||||
|
case MOUSE_STATE_RESIZE_LEFT:
|
||||||
|
window_drag_resize(window, xm, 0, -xm, 0);
|
||||||
|
break;
|
||||||
|
case MOUSE_STATE_RESIZE_BOTTOM_LEFT:
|
||||||
|
window_drag_resize(window, xm, 0, -xm, ym);
|
||||||
|
break;
|
||||||
|
case MOUSE_STATE_RESIZE_TOP:
|
||||||
|
window_drag_resize(window, 0, ym, 0, -ym);
|
||||||
|
break;
|
||||||
|
case MOUSE_STATE_RESIZE_BOTTOM:
|
||||||
|
window_drag_resize(window, 0, 0, 0, ym);
|
||||||
|
break;
|
||||||
|
case MOUSE_STATE_RESIZE_TOP_RIGHT:
|
||||||
|
window_drag_resize(window, 0, ym, xm, -ym);
|
||||||
|
break;
|
||||||
|
case MOUSE_STATE_RESIZE_RIGHT:
|
||||||
|
window_drag_resize(window, 0, 0, xm, 0);
|
||||||
|
break;
|
||||||
|
case MOUSE_STATE_RESIZE_BOTTOM_RIGHT:
|
||||||
|
window_drag_resize(window, 0, 0, xm, ym);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Leave mouse state if the top window closes.
|
||||||
|
// TODO: Leave mouse state if the top window is switched.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
display->mouse_state = MOUSE_STATE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_on_resolution_change(struct display* display, size_t width, size_t height)
|
||||||
|
{
|
||||||
|
if ( display->screen_width == width && display->screen_height == height )
|
||||||
|
return;
|
||||||
|
display->screen_width = 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 )
|
||||||
|
window_on_display_resolution_change(window, display);
|
||||||
|
}
|
143
display/display.c
Normal file
143
display/display.c
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* display.c
|
||||||
|
* Display server.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "arrow.inc"
|
||||||
|
|
||||||
|
#include "display.h"
|
||||||
|
#include "framebuffer.h"
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
uint32_t arrow_buffer[48 * 48];
|
||||||
|
struct framebuffer arrow_framebuffer = { 48, arrow_buffer, 48, 48 };
|
||||||
|
|
||||||
|
static void ready(void)
|
||||||
|
{
|
||||||
|
const char* readyfd_env = getenv("READYFD");
|
||||||
|
if ( !readyfd_env )
|
||||||
|
return;
|
||||||
|
int readyfd = atoi(readyfd_env);
|
||||||
|
char c = '\n';
|
||||||
|
write(readyfd, &c, 1);
|
||||||
|
close(readyfd);
|
||||||
|
unsetenv("READYFD");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compact_arguments(int* argc, char*** argv)
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < *argc; i++ )
|
||||||
|
{
|
||||||
|
while ( i < *argc && !(*argv)[i] )
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
|
||||||
|
if ( getpgid(0) != getpid() )
|
||||||
|
errx(1, "This program must be run in its own process group");
|
||||||
|
|
||||||
|
struct display display;
|
||||||
|
display_initialize(&display);
|
||||||
|
|
||||||
|
struct server server;
|
||||||
|
server_initialize(&server, &display);
|
||||||
|
|
||||||
|
if ( setenv("DISPLAY_SOCKET", server.server_path, 1) < 0 )
|
||||||
|
err(1, "setenv");
|
||||||
|
|
||||||
|
ready();
|
||||||
|
|
||||||
|
char* home_session = NULL;
|
||||||
|
char** session_argv = NULL;
|
||||||
|
if ( 1 < argc )
|
||||||
|
session_argv = argv + 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char* home = getenv("HOME");
|
||||||
|
if ( home && asprintf(&home_session, "%s/.displayrc", home) < 0 )
|
||||||
|
err(1, "malloc");
|
||||||
|
const char* session_path = NULL;
|
||||||
|
if ( !access(home_session, F_OK) )
|
||||||
|
session_path = home_session;
|
||||||
|
else if ( !access("/etc/displayrc", F_OK) )
|
||||||
|
session_path = "/etc/displayrc";
|
||||||
|
else if ( !access("/etc/default/displayrc", F_OK) )
|
||||||
|
session_path = "/etc/default/displayrc";
|
||||||
|
if ( session_path )
|
||||||
|
session_argv = (char**) (const char*[]) {session_path, NULL};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( session_argv )
|
||||||
|
{
|
||||||
|
pid_t pid = fork();
|
||||||
|
if ( pid < 0 )
|
||||||
|
warn("fork");
|
||||||
|
else if ( pid == 0 )
|
||||||
|
{
|
||||||
|
execvp(session_argv[0], session_argv);
|
||||||
|
warn("%s", session_argv[0]);
|
||||||
|
_exit(127);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(home_session);
|
||||||
|
|
||||||
|
server_mainloop(&server);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
88
display/display.h
Normal file
88
display/display.h
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* display.h
|
||||||
|
* Display server.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DISPLAY_H
|
||||||
|
#define DISPLAY_H
|
||||||
|
|
||||||
|
#include <sys/ps2mouse.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "damage-rect.h"
|
||||||
|
#include "framebuffer.h"
|
||||||
|
|
||||||
|
enum mouse_state
|
||||||
|
{
|
||||||
|
MOUSE_STATE_NONE,
|
||||||
|
MOUSE_STATE_TITLE_MOVE,
|
||||||
|
MOUSE_STATE_RESIZE_BOTTOM,
|
||||||
|
MOUSE_STATE_RESIZE_BOTTOM_LEFT,
|
||||||
|
MOUSE_STATE_RESIZE_BOTTOM_RIGHT,
|
||||||
|
MOUSE_STATE_RESIZE_LEFT,
|
||||||
|
MOUSE_STATE_RESIZE_RIGHT,
|
||||||
|
MOUSE_STATE_RESIZE_TOP,
|
||||||
|
MOUSE_STATE_RESIZE_TOP_LEFT,
|
||||||
|
MOUSE_STATE_RESIZE_TOP_RIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct window;
|
||||||
|
|
||||||
|
struct display
|
||||||
|
{
|
||||||
|
struct damage_rect damage_rect;
|
||||||
|
struct window* top_window;
|
||||||
|
struct window* bottom_window;
|
||||||
|
struct window* active_window;
|
||||||
|
struct window* tab_candidate;
|
||||||
|
size_t screen_width;
|
||||||
|
size_t screen_height;
|
||||||
|
size_t num_tabs;
|
||||||
|
bool key_lctrl;
|
||||||
|
bool key_lalt;
|
||||||
|
bool key_lsuper;
|
||||||
|
bool key_rsuper;
|
||||||
|
int pointer_x;
|
||||||
|
int pointer_y;
|
||||||
|
enum mouse_state mouse_state;
|
||||||
|
size_t mouse_byte_count;
|
||||||
|
uint8_t mouse_bytes[MOUSE_PACKET_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
void display_initialize(struct display* display);
|
||||||
|
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_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_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_mouse_event(struct display* display, uint8_t byte);
|
||||||
|
|
||||||
|
#endif
|
272
display/server.c
Normal file
272
display/server.c
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* server.c
|
||||||
|
* Display server main loop.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/termmode.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <display-protocol.h>
|
||||||
|
|
||||||
|
#include "connection.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "server.h"
|
||||||
|
#include "vgafont.h"
|
||||||
|
|
||||||
|
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 = (struct sockaddr_un*) malloc(addr_size);
|
||||||
|
if ( !sockaddr )
|
||||||
|
return -1;
|
||||||
|
sockaddr->sun_family = AF_LOCAL;
|
||||||
|
strcpy(sockaddr->sun_path, path);
|
||||||
|
int fd = socket(AF_LOCAL, SOCK_STREAM | flags, 0);
|
||||||
|
if ( fd < 0 )
|
||||||
|
return free(sockaddr), -1;
|
||||||
|
if ( bind(fd, (const struct sockaddr*) sockaddr, addr_size) < 0 )
|
||||||
|
return close(fd), free(sockaddr), -1;
|
||||||
|
if ( listen(fd, SOMAXCONN) < 0 )
|
||||||
|
return close(fd), free(sockaddr), -1;
|
||||||
|
free(sockaddr);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void server_initialize(struct server* server, struct display* display)
|
||||||
|
{
|
||||||
|
memset(server, 0, sizeof(*server));
|
||||||
|
|
||||||
|
server->display = display;
|
||||||
|
|
||||||
|
load_font();
|
||||||
|
|
||||||
|
server->tty_fd = 0;
|
||||||
|
if ( !isatty(0) )
|
||||||
|
{
|
||||||
|
server->tty_fd = open("/dev/tty", O_RDONLY);
|
||||||
|
if ( server->tty_fd < 0 )
|
||||||
|
err(1, "/dev/tty");
|
||||||
|
}
|
||||||
|
|
||||||
|
server->mouse_fd = open("/dev/mouse", O_RDONLY | O_CLOEXEC);
|
||||||
|
if ( server->mouse_fd < 0 )
|
||||||
|
err(1, "%s", "/dev/mouse");
|
||||||
|
|
||||||
|
server->server_path = "/run/display";
|
||||||
|
server->server_fd = open_local_server_socket(server->server_path,
|
||||||
|
SOCK_NONBLOCK | SOCK_CLOEXEC);
|
||||||
|
if ( server->server_fd < 0 )
|
||||||
|
err(1, "open_local_server_socket: %s", server->server_path);
|
||||||
|
|
||||||
|
unsigned int termmode =
|
||||||
|
TERMMODE_KBKEY | TERMMODE_UNICODE | TERMMODE_NONBLOCK;
|
||||||
|
if ( settermmode(0, termmode) < 0 )
|
||||||
|
err(1, "settermmode");
|
||||||
|
|
||||||
|
server->pfds_count = server_pfds_count(server);
|
||||||
|
server->pfds = (struct pollfd*)
|
||||||
|
reallocarray(NULL, sizeof(struct pollfd), server->pfds_count);
|
||||||
|
if ( !server->pfds )
|
||||||
|
err(1, "malloc");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool server_accept(struct server* server)
|
||||||
|
{
|
||||||
|
int client_fd = accept4(server->server_fd, NULL, NULL, SOCK_NONBLOCK);
|
||||||
|
if ( client_fd < 0 )
|
||||||
|
{
|
||||||
|
warn("accept: %s", server->server_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( server->connections_used == server->connections_length )
|
||||||
|
{
|
||||||
|
size_t new_length = server->connections_length * 2;
|
||||||
|
if ( !new_length )
|
||||||
|
new_length = 16;
|
||||||
|
struct connection** new_connections = (struct connection**)
|
||||||
|
reallocarray(server->connections, new_length,
|
||||||
|
sizeof(struct connection*));
|
||||||
|
if ( !new_connections )
|
||||||
|
{
|
||||||
|
warn("dropped connection: %s: malloc", server->server_path);
|
||||||
|
close(client_fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
server->connections = new_connections;
|
||||||
|
server->connections_length = new_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t new_pfds_count = server_pfds_count(server) + 1;
|
||||||
|
struct pollfd* new_pfds = (struct pollfd*)
|
||||||
|
reallocarray(server->pfds, sizeof(struct pollfd), new_pfds_count);
|
||||||
|
if ( !new_pfds )
|
||||||
|
{
|
||||||
|
warn("dropped connection: %s: malloc", server->server_path);
|
||||||
|
close(client_fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
server->pfds = new_pfds;
|
||||||
|
server->pfds_count = new_pfds_count;
|
||||||
|
|
||||||
|
struct connection* connection = (struct connection*)
|
||||||
|
malloc(sizeof(struct connection));
|
||||||
|
if ( !connection )
|
||||||
|
{
|
||||||
|
warn("dropped connection: %s: malloc", server->server_path);
|
||||||
|
close(client_fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
server->connections[server->connections_used++] = connection;
|
||||||
|
connection_initialize(connection, server->display, client_fd);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t server_pfds_count(const struct server* server)
|
||||||
|
{
|
||||||
|
return 3 + server->connections_used;
|
||||||
|
}
|
||||||
|
|
||||||
|
void server_poll(struct server* server)
|
||||||
|
{
|
||||||
|
int code;
|
||||||
|
while ( 0 < waitpid(-1, &code, WNOHANG) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pollfd* pfds = server->pfds;
|
||||||
|
|
||||||
|
pfds[0].fd = server->server_fd;
|
||||||
|
pfds[0].events = POLLIN;
|
||||||
|
pfds[0].revents = 0;
|
||||||
|
pfds[1].fd = server->tty_fd;
|
||||||
|
pfds[1].events = POLLIN;
|
||||||
|
pfds[1].revents = 0;
|
||||||
|
pfds[2].fd = server->mouse_fd;
|
||||||
|
pfds[2].events = POLLIN;
|
||||||
|
pfds[2].revents = 0;
|
||||||
|
size_t cpfd_off = 3;
|
||||||
|
|
||||||
|
size_t connections_polled = server->connections_used;
|
||||||
|
for ( size_t i = 0; i < connections_polled; i++ )
|
||||||
|
{
|
||||||
|
struct pollfd* pfd = &pfds[cpfd_off + i];
|
||||||
|
struct connection* connection = server->connections[i];
|
||||||
|
pfd->fd = connection->fd;
|
||||||
|
pfd->events = connection_interested_poll_events(connection);
|
||||||
|
pfd->revents = 0;
|
||||||
|
}
|
||||||
|
size_t pfds_used = cpfd_off + connections_polled;
|
||||||
|
|
||||||
|
int num_events = ppoll(pfds, pfds_used, NULL, NULL);
|
||||||
|
if ( num_events < 0 )
|
||||||
|
err(1, "poll");
|
||||||
|
|
||||||
|
if ( pfds[0].revents )
|
||||||
|
{
|
||||||
|
// TODO: Handle if this can actually happen.
|
||||||
|
assert(!(pfds[0].revents & POLLERR));
|
||||||
|
assert(!(pfds[0].revents & POLLHUP));
|
||||||
|
assert(!(pfds[0].revents & POLLNVAL));
|
||||||
|
|
||||||
|
server_accept(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pfds[1].revents )
|
||||||
|
{
|
||||||
|
// TODO: Handle if this can actually happen.
|
||||||
|
assert(!(pfds[1].revents & POLLERR));
|
||||||
|
assert(!(pfds[1].revents & POLLHUP));
|
||||||
|
assert(!(pfds[1].revents & POLLNVAL));
|
||||||
|
|
||||||
|
uint32_t codepoint;
|
||||||
|
ssize_t size = sizeof(codepoint);
|
||||||
|
while ( read(server->tty_fd, &codepoint, size) == size )
|
||||||
|
display_keyboard_event(server->display, codepoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pfds[2].revents )
|
||||||
|
{
|
||||||
|
// TODO: Handle if this can actually happen.
|
||||||
|
assert(!(pfds[2].revents & POLLERR));
|
||||||
|
assert(!(pfds[2].revents & POLLHUP));
|
||||||
|
assert(!(pfds[2].revents & POLLNVAL));
|
||||||
|
|
||||||
|
unsigned char events[64];
|
||||||
|
ssize_t amount = read(server->mouse_fd, events, sizeof(events));
|
||||||
|
for ( ssize_t i = 0; i < amount; i++ )
|
||||||
|
display_mouse_event(server->display, events[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool any_disconnect = false;
|
||||||
|
for ( size_t i = 0; i < connections_polled; i++ )
|
||||||
|
{
|
||||||
|
struct pollfd* pfd = &pfds[cpfd_off + i];
|
||||||
|
if ( !pfd->revents )
|
||||||
|
continue;
|
||||||
|
struct connection* connection = server->connections[i];
|
||||||
|
if ( pfd->revents & (POLLERR | POLLHUP | POLLNVAL) &&
|
||||||
|
!(pfd->revents & POLLIN) )
|
||||||
|
{
|
||||||
|
connection_destroy(connection);
|
||||||
|
free(connection);
|
||||||
|
server->connections[i] = NULL;
|
||||||
|
any_disconnect = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( pfd->revents & POLLOUT )
|
||||||
|
connection_can_write(connection);
|
||||||
|
if ( pfd->revents & POLLIN )
|
||||||
|
connection_can_read(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compact the array down here so the pfds match the connections above.
|
||||||
|
if ( any_disconnect )
|
||||||
|
{
|
||||||
|
size_t new_used = 0;
|
||||||
|
for ( size_t i = 0; i < server->connections_used; i++ )
|
||||||
|
{
|
||||||
|
if ( server->connections[i] )
|
||||||
|
server->connections[new_used++] = server->connections[i];
|
||||||
|
}
|
||||||
|
server->connections_used = new_used;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void server_mainloop(struct server* server)
|
||||||
|
{
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
// TODO: Only do this if a redraw is actually needed.
|
||||||
|
display_render(server->display);
|
||||||
|
server_poll(server);
|
||||||
|
}
|
||||||
|
}
|
50
display/server.h
Normal file
50
display/server.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* connection.h
|
||||||
|
* Display server main loop.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERVER_H
|
||||||
|
#define SERVER_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct connection;
|
||||||
|
struct display;
|
||||||
|
struct pollfd;
|
||||||
|
|
||||||
|
struct server
|
||||||
|
{
|
||||||
|
struct display* display;
|
||||||
|
const char* server_path;
|
||||||
|
int server_fd;
|
||||||
|
int tty_fd;
|
||||||
|
int mouse_fd;
|
||||||
|
struct connection** connections;
|
||||||
|
size_t connections_used;
|
||||||
|
size_t connections_length;
|
||||||
|
struct pollfd* pfds;
|
||||||
|
size_t pfds_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
void server_mainloop(struct server* server);
|
||||||
|
|
||||||
|
#endif
|
482
display/window.c
Normal file
482
display/window.c
Normal file
|
@ -0,0 +1,482 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* window.c
|
||||||
|
* Window abstraction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <display-protocol.h>
|
||||||
|
|
||||||
|
#include "connection.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "framebuffer.h"
|
||||||
|
#include "pixel.h"
|
||||||
|
#include "vgafont.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
struct framebuffer window_client_buffer(struct window* window)
|
||||||
|
{
|
||||||
|
if ( window->window_state != WINDOW_STATE_REGULAR )
|
||||||
|
return framebuffer_crop(window->buffer, 0, TITLE_HEIGHT,
|
||||||
|
window->width, window->height - TITLE_HEIGHT);
|
||||||
|
return framebuffer_crop(window->buffer, BORDER_WIDTH, TITLE_HEIGHT,
|
||||||
|
window->width - 2 * BORDER_WIDTH,
|
||||||
|
window->height - TITLE_HEIGHT - BORDER_WIDTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_render_frame(struct window* window)
|
||||||
|
{
|
||||||
|
if ( !window->width || !window->height )
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool has_focus = window->display->tab_candidate ?
|
||||||
|
window->display->tab_candidate == window :
|
||||||
|
window->display->active_window == window;
|
||||||
|
|
||||||
|
uint32_t glass_color = has_focus ? make_color_a(200, 200, 255, 192)
|
||||||
|
: 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);
|
||||||
|
|
||||||
|
size_t start_x = 0;
|
||||||
|
size_t start_y = 0;
|
||||||
|
size_t end_x = window->width - 1;
|
||||||
|
size_t end_y = window->height - 1;
|
||||||
|
|
||||||
|
bool maximized = window->window_state != WINDOW_STATE_REGULAR;
|
||||||
|
|
||||||
|
int b0 = 0;
|
||||||
|
int b1 = 1;
|
||||||
|
int b2 = 2;
|
||||||
|
int b3 = BORDER_WIDTH;
|
||||||
|
int t0 = TITLE_HEIGHT;
|
||||||
|
|
||||||
|
for ( size_t y = start_y; y <= end_y; y++ )
|
||||||
|
{
|
||||||
|
for ( size_t x = start_x; x <= end_x; x++ )
|
||||||
|
{
|
||||||
|
uint32_t color;
|
||||||
|
if ( maximized && y <= start_y + t0 )
|
||||||
|
color = glass_color;
|
||||||
|
else if ( maximized )
|
||||||
|
continue;
|
||||||
|
else if ( x == start_x + b0 || x == end_x - b0 ||
|
||||||
|
y == start_y + b0 || y == end_y - b0 )
|
||||||
|
color = make_color_a(0, 0, 0, 32);
|
||||||
|
else if ( x == start_x + b1 || x == end_x - b1 ||
|
||||||
|
y == start_y + b1 || y == end_y - b1 )
|
||||||
|
color = make_color_a(0, 0, 0, 64);
|
||||||
|
else if ( x == start_x + b2 || x == end_x - b2 ||
|
||||||
|
y == start_y + b2 ||+ y == end_y - b2 )
|
||||||
|
color = make_color(240, 240, 250);
|
||||||
|
else if ( x < start_x + (b3-1) || x > end_x - (b3-1) ||
|
||||||
|
y < start_y + (t0-1) || y > end_y - (b3-1) )
|
||||||
|
color = glass_color;
|
||||||
|
else if ( x == start_x + (b3-1) || x == end_x - (b3-1) ||
|
||||||
|
y == start_y + (t0-1) || y == end_y - (b3-1) )
|
||||||
|
color = make_color(64, 64, 64);
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
framebuffer_set_pixel(window->buffer, x, y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* tt = window->title ? window->title : "";
|
||||||
|
size_t tt_max_width = window->width - 2 * BORDER_WIDTH;
|
||||||
|
size_t tt_desired_width = render_text_width(tt);
|
||||||
|
size_t tt_width = tt_desired_width < tt_max_width ? tt_desired_width : tt_max_width;
|
||||||
|
size_t tt_height = FONT_HEIGHT;
|
||||||
|
size_t tt_pos_x = BORDER_WIDTH + (tt_max_width - tt_width) / 2;
|
||||||
|
size_t tt_pos_y = (TITLE_HEIGHT - FONT_HEIGHT) / 2 + 2;
|
||||||
|
uint32_t tt_color = title_color;
|
||||||
|
render_text(framebuffer_crop(window->buffer, tt_pos_x, tt_pos_y, tt_width, tt_height), tt, tt_color);
|
||||||
|
|
||||||
|
size_t border_width = maximized ? BORDER_WIDTH / 2 : BORDER_WIDTH;
|
||||||
|
size_t button_size = FONT_WIDTH - 1;
|
||||||
|
size_t button_spacing = FONT_WIDTH;
|
||||||
|
struct framebuffer buttons_fb =
|
||||||
|
framebuffer_crop(window->buffer,
|
||||||
|
window->width - border_width - (FONT_HEIGHT - button_size) / 2 - 5 * button_spacing,
|
||||||
|
tt_pos_y, tt_width, tt_height);
|
||||||
|
size_t buttons_top = (FONT_HEIGHT - button_size) / 2;
|
||||||
|
for ( size_t i = 0; i < button_size; i++ )
|
||||||
|
{
|
||||||
|
framebuffer_set_pixel(buttons_fb, 0 * button_spacing + i,
|
||||||
|
buttons_top + button_size - 1, tt_color);
|
||||||
|
framebuffer_set_pixel(buttons_fb, 0 * button_spacing + i,
|
||||||
|
buttons_top + button_size - 2, tt_color);
|
||||||
|
}
|
||||||
|
for ( size_t i = 0; i < button_size; i++ )
|
||||||
|
{
|
||||||
|
framebuffer_set_pixel(buttons_fb, 2 * button_spacing + i,
|
||||||
|
buttons_top, tt_color);
|
||||||
|
framebuffer_set_pixel(buttons_fb, 2 * button_spacing + i,
|
||||||
|
buttons_top + button_size - 1 , tt_color);
|
||||||
|
framebuffer_set_pixel(buttons_fb, 2 * button_spacing,
|
||||||
|
buttons_top + i, tt_color);
|
||||||
|
framebuffer_set_pixel(buttons_fb, 2 * button_spacing + button_size - 1,
|
||||||
|
buttons_top + i, tt_color);
|
||||||
|
|
||||||
|
framebuffer_set_pixel(buttons_fb, 2 * button_spacing + i,
|
||||||
|
buttons_top + 1, tt_color);
|
||||||
|
framebuffer_set_pixel(buttons_fb, 2 * button_spacing + i,
|
||||||
|
buttons_top + button_size - 2 , tt_color);
|
||||||
|
framebuffer_set_pixel(buttons_fb, 2 * button_spacing + 1,
|
||||||
|
buttons_top + i, tt_color);
|
||||||
|
framebuffer_set_pixel(buttons_fb, 2 * button_spacing + button_size - 2,
|
||||||
|
buttons_top + i, tt_color);
|
||||||
|
}
|
||||||
|
for ( size_t i = 0; i < button_size; i++ )
|
||||||
|
{
|
||||||
|
framebuffer_set_pixel(buttons_fb, 4 * button_spacing + i,
|
||||||
|
buttons_top + i, tt_color);
|
||||||
|
framebuffer_set_pixel(buttons_fb, 4 * button_spacing + i,
|
||||||
|
buttons_top + button_size - 1 - i, tt_color);
|
||||||
|
|
||||||
|
framebuffer_set_pixel(buttons_fb, 4 * button_spacing + i + 1,
|
||||||
|
buttons_top + i, tt_color);
|
||||||
|
framebuffer_set_pixel(buttons_fb, 4 * button_spacing + i + 1,
|
||||||
|
buttons_top + button_size - 1 - i, tt_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_move(struct window* window, size_t left, size_t top)
|
||||||
|
{
|
||||||
|
window->left = left;
|
||||||
|
window->top = top;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_client_resize(struct window* window,
|
||||||
|
size_t client_width,
|
||||||
|
size_t client_height)
|
||||||
|
{
|
||||||
|
if ( window->window_state != WINDOW_STATE_MINIMIZED )
|
||||||
|
window->window_state = WINDOW_STATE_REGULAR;
|
||||||
|
|
||||||
|
free(window->buffer.buffer);
|
||||||
|
|
||||||
|
window->width = client_width + BORDER_WIDTH + BORDER_WIDTH;
|
||||||
|
window->height = client_height + TITLE_HEIGHT + BORDER_WIDTH;
|
||||||
|
|
||||||
|
window->buffer.xres = window->width;
|
||||||
|
window->buffer.yres = window->height;
|
||||||
|
window->buffer.pitch = window->width;
|
||||||
|
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_render_frame(window);
|
||||||
|
window_notify_client_resize(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_resize(struct window* window, size_t width, size_t height)
|
||||||
|
{
|
||||||
|
if ( width < BORDER_WIDTH + BORDER_WIDTH )
|
||||||
|
width = BORDER_WIDTH + BORDER_WIDTH;
|
||||||
|
if ( height < TITLE_HEIGHT + BORDER_WIDTH )
|
||||||
|
height = TITLE_HEIGHT + BORDER_WIDTH;
|
||||||
|
// TODO: Keep proper track of this for each state.
|
||||||
|
size_t client_width = width - (BORDER_WIDTH + BORDER_WIDTH);
|
||||||
|
size_t client_height = height - (TITLE_HEIGHT + BORDER_WIDTH);
|
||||||
|
window_client_resize(window, client_width, client_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_drag_resize(struct window* window, int ld, int td, int wd, int hd)
|
||||||
|
{
|
||||||
|
// TODO: Keep proper track of this for each state.
|
||||||
|
size_t client_width = window->width - (BORDER_WIDTH + BORDER_WIDTH);
|
||||||
|
size_t client_height = window->height - (TITLE_HEIGHT + BORDER_WIDTH);
|
||||||
|
if ( ld || td )
|
||||||
|
window_move(window, window->left + ld, window->top + td);
|
||||||
|
if ( wd || hd )
|
||||||
|
{
|
||||||
|
ssize_t new_width = (ssize_t) client_width + wd;
|
||||||
|
ssize_t new_height = (ssize_t) client_height + hd;
|
||||||
|
if ( new_width < 1 )
|
||||||
|
new_width = 1;
|
||||||
|
if ( new_height < 1 )
|
||||||
|
new_height = 1;
|
||||||
|
window_client_resize(window, new_width, new_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t next_window_position = 25;
|
||||||
|
|
||||||
|
void window_initialize(struct window* window,
|
||||||
|
struct connection* connection,
|
||||||
|
struct display* display,
|
||||||
|
uint32_t window_id)
|
||||||
|
{
|
||||||
|
memset(window, 0, sizeof(*window));
|
||||||
|
window->created = true;
|
||||||
|
window->connection = connection;
|
||||||
|
window->display = display;
|
||||||
|
window->title = NULL;
|
||||||
|
window->window_id = window_id;
|
||||||
|
display_add_window(window->display, window);
|
||||||
|
window->top = next_window_position;
|
||||||
|
window->left = next_window_position;
|
||||||
|
size_t max_position = display->screen_width < display->screen_height ?
|
||||||
|
display->screen_width : display->screen_height;
|
||||||
|
max_position = (max_position * 6) / 10;
|
||||||
|
next_window_position += 30;
|
||||||
|
next_window_position %= max_position;
|
||||||
|
window_client_resize(window, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_destroy(struct window* window)
|
||||||
|
{
|
||||||
|
display_remove_window(window->display, window);
|
||||||
|
free(window->buffer.buffer);
|
||||||
|
free(window->title);
|
||||||
|
memset(window, 0, sizeof(*window));
|
||||||
|
window->created = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_on_display_resolution_change(struct window* window, struct display* display)
|
||||||
|
{
|
||||||
|
// TODO: Potentially move window back inside screen?
|
||||||
|
if ( window->window_state == WINDOW_STATE_MAXIMIZED )
|
||||||
|
{
|
||||||
|
// TODO: Change size of maximized window.
|
||||||
|
(void) display;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if ( window->window_state == WINDOW_STATE_REGULAR )
|
||||||
|
{
|
||||||
|
window->saved_left = window->left;
|
||||||
|
window->saved_top = window->top;
|
||||||
|
window->saved_width = window->width;
|
||||||
|
window->saved_height = window->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(window->buffer.buffer);
|
||||||
|
|
||||||
|
window->left = left;
|
||||||
|
window->top = top;
|
||||||
|
window->width = width;
|
||||||
|
window->height = height;
|
||||||
|
|
||||||
|
window->buffer.xres = window->width;
|
||||||
|
window->buffer.yres = window->height;
|
||||||
|
window->buffer.pitch = window->width;
|
||||||
|
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;
|
||||||
|
|
||||||
|
window_render_frame(window);
|
||||||
|
window_notify_client_resize(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_maximize(struct window* window)
|
||||||
|
{
|
||||||
|
window_tile(window, WINDOW_STATE_MAXIMIZED,
|
||||||
|
0, 0,
|
||||||
|
window->display->screen_width, window->display->screen_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_restore(struct window* window)
|
||||||
|
{
|
||||||
|
if ( window->window_state == WINDOW_STATE_REGULAR )
|
||||||
|
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_notify_client_resize(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_toggle_maximized(struct window* window)
|
||||||
|
{
|
||||||
|
if ( window->window_state == WINDOW_STATE_MAXIMIZED )
|
||||||
|
window_restore(window);
|
||||||
|
else
|
||||||
|
window_maximize(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_leftward(struct window* window)
|
||||||
|
{
|
||||||
|
switch ( window->window_state )
|
||||||
|
{
|
||||||
|
case WINDOW_STATE_REGULAR: window_tile_left(window); break;
|
||||||
|
case WINDOW_STATE_MAXIMIZED: window_tile_left(window); break;
|
||||||
|
case WINDOW_STATE_MINIMIZED: window_tile_right(window); break;
|
||||||
|
case WINDOW_STATE_TILE_LEFT: break;
|
||||||
|
case WINDOW_STATE_TILE_RIGHT: window_restore(window); break;
|
||||||
|
case WINDOW_STATE_TILE_TOP: window_tile_top_left(window); break;
|
||||||
|
case WINDOW_STATE_TILE_TOP_LEFT: break;
|
||||||
|
case WINDOW_STATE_TILE_TOP_RIGHT: window_tile_top(window); break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM: window_tile_bottom_left(window); break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM_LEFT: break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM_RIGHT: window_tile_bottom(window); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_rightward(struct window* window)
|
||||||
|
{
|
||||||
|
switch ( window->window_state )
|
||||||
|
{
|
||||||
|
case WINDOW_STATE_REGULAR: window_tile_right(window); break;
|
||||||
|
case WINDOW_STATE_MAXIMIZED: window_tile_right(window); break;
|
||||||
|
case WINDOW_STATE_MINIMIZED: window_tile_right(window); break;
|
||||||
|
case WINDOW_STATE_TILE_LEFT: window_restore(window); break;
|
||||||
|
case WINDOW_STATE_TILE_RIGHT: break;
|
||||||
|
case WINDOW_STATE_TILE_TOP: window_tile_top_right(window); break;
|
||||||
|
case WINDOW_STATE_TILE_TOP_LEFT: window_tile_top(window); break;
|
||||||
|
case WINDOW_STATE_TILE_TOP_RIGHT: break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM: window_tile_bottom_right(window); break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM_LEFT: window_tile_bottom(window); break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM_RIGHT: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_up(struct window* window)
|
||||||
|
{
|
||||||
|
switch ( window->window_state )
|
||||||
|
{
|
||||||
|
case WINDOW_STATE_REGULAR: window_tile_top(window); break;
|
||||||
|
case WINDOW_STATE_MAXIMIZED: window_restore(window); break;
|
||||||
|
case WINDOW_STATE_MINIMIZED: window_tile_top(window); break;
|
||||||
|
case WINDOW_STATE_TILE_LEFT: window_tile_top_left(window); break;
|
||||||
|
case WINDOW_STATE_TILE_RIGHT: window_tile_top_right(window); break;
|
||||||
|
case WINDOW_STATE_TILE_TOP: window_maximize(window); break;
|
||||||
|
case WINDOW_STATE_TILE_TOP_LEFT: break;
|
||||||
|
case WINDOW_STATE_TILE_TOP_RIGHT: break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM: window_restore(window); break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM_LEFT: window_tile_left(window); break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM_RIGHT: window_tile_right(window); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_down(struct window* window)
|
||||||
|
{
|
||||||
|
switch ( window->window_state )
|
||||||
|
{
|
||||||
|
case WINDOW_STATE_REGULAR: window_tile_bottom(window); break;
|
||||||
|
case WINDOW_STATE_MAXIMIZED: window_tile_top(window); break;
|
||||||
|
case WINDOW_STATE_MINIMIZED: window_tile_bottom(window); break;
|
||||||
|
case WINDOW_STATE_TILE_LEFT: window_tile_bottom_left(window); break;
|
||||||
|
case WINDOW_STATE_TILE_RIGHT: window_tile_bottom_right(window); break;
|
||||||
|
case WINDOW_STATE_TILE_TOP: window_restore(window); break;
|
||||||
|
case WINDOW_STATE_TILE_TOP_LEFT: window_tile_left(window); break;
|
||||||
|
case WINDOW_STATE_TILE_TOP_RIGHT: window_tile_right(window); break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM: break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM_LEFT: break;
|
||||||
|
case WINDOW_STATE_TILE_BOTTOM_RIGHT: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_left(struct window* window)
|
||||||
|
{
|
||||||
|
window_tile(window, WINDOW_STATE_TILE_LEFT,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
window->display->screen_width / 2,
|
||||||
|
window->display->screen_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_right(struct window* window)
|
||||||
|
{
|
||||||
|
window_tile(window, WINDOW_STATE_TILE_RIGHT,
|
||||||
|
(window->display->screen_width + 1) / 2,
|
||||||
|
0,
|
||||||
|
(window->display->screen_width + 1) / 2,
|
||||||
|
window->display->screen_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_top(struct window* window)
|
||||||
|
{
|
||||||
|
window_tile(window, WINDOW_STATE_TILE_TOP,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
window->display->screen_width,
|
||||||
|
window->display->screen_height / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_top_left(struct window* window)
|
||||||
|
{
|
||||||
|
window_tile(window, WINDOW_STATE_TILE_TOP_LEFT,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
window->display->screen_width / 2,
|
||||||
|
window->display->screen_height / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_top_right(struct window* window)
|
||||||
|
{
|
||||||
|
window_tile(window, WINDOW_STATE_TILE_TOP_RIGHT,
|
||||||
|
(window->display->screen_width + 1) / 2,
|
||||||
|
0,
|
||||||
|
(window->display->screen_width + 1) / 2,
|
||||||
|
window->display->screen_height / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_bottom(struct window* window)
|
||||||
|
{
|
||||||
|
window_tile(window, WINDOW_STATE_TILE_BOTTOM,
|
||||||
|
0,
|
||||||
|
(window->display->screen_height + 1) / 2,
|
||||||
|
window->display->screen_width,
|
||||||
|
(window->display->screen_height + 1) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_bottom_left(struct window* window)
|
||||||
|
{
|
||||||
|
window_tile(window, WINDOW_STATE_TILE_BOTTOM_LEFT,
|
||||||
|
0,
|
||||||
|
(window->display->screen_height + 1) / 2,
|
||||||
|
window->display->screen_width / 2,
|
||||||
|
(window->display->screen_height + 1) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_tile_bottom_right(struct window* window)
|
||||||
|
{
|
||||||
|
window_tile(window, WINDOW_STATE_TILE_BOTTOM_RIGHT,
|
||||||
|
(window->display->screen_width + 1) / 2,
|
||||||
|
(window->display->screen_height + 1) / 2,
|
||||||
|
(window->display->screen_width + 1) / 2,
|
||||||
|
(window->display->screen_height + 1) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_notify_client_resize(struct window* window)
|
||||||
|
{
|
||||||
|
struct event_resize event;
|
||||||
|
event.window_id = window->window_id;
|
||||||
|
event.width = window_client_buffer(window).xres;
|
||||||
|
event.height = window_client_buffer(window).yres;
|
||||||
|
|
||||||
|
struct display_packet_header header;
|
||||||
|
header.message_id = EVENT_RESIZE;
|
||||||
|
header.message_length = sizeof(event);
|
||||||
|
|
||||||
|
assert(window->connection);
|
||||||
|
|
||||||
|
connection_schedule_transmit(window->connection, &header, sizeof(header));
|
||||||
|
connection_schedule_transmit(window->connection, &event, sizeof(event));
|
||||||
|
}
|
104
display/window.h
Normal file
104
display/window.h
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* window.h
|
||||||
|
* Window abstraction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WINDOW_H
|
||||||
|
#define WINDOW_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "framebuffer.h"
|
||||||
|
|
||||||
|
struct connection;
|
||||||
|
struct display;
|
||||||
|
|
||||||
|
static const size_t BORDER_WIDTH = 8;
|
||||||
|
static const size_t TITLE_HEIGHT = 28;
|
||||||
|
static const size_t RESIZE_GRACE = 16;
|
||||||
|
|
||||||
|
enum window_state
|
||||||
|
{
|
||||||
|
WINDOW_STATE_REGULAR,
|
||||||
|
WINDOW_STATE_MAXIMIZED,
|
||||||
|
WINDOW_STATE_MINIMIZED,
|
||||||
|
WINDOW_STATE_TILE_LEFT,
|
||||||
|
WINDOW_STATE_TILE_RIGHT,
|
||||||
|
WINDOW_STATE_TILE_TOP,
|
||||||
|
WINDOW_STATE_TILE_TOP_LEFT,
|
||||||
|
WINDOW_STATE_TILE_TOP_RIGHT,
|
||||||
|
WINDOW_STATE_TILE_BOTTOM,
|
||||||
|
WINDOW_STATE_TILE_BOTTOM_LEFT,
|
||||||
|
WINDOW_STATE_TILE_BOTTOM_RIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct window
|
||||||
|
{
|
||||||
|
struct display* display;
|
||||||
|
struct connection* connection;
|
||||||
|
struct window* above_window;
|
||||||
|
struct window* below_window;
|
||||||
|
struct framebuffer buffer;
|
||||||
|
char* title;
|
||||||
|
ssize_t left;
|
||||||
|
ssize_t top;
|
||||||
|
size_t width;
|
||||||
|
size_t height;
|
||||||
|
ssize_t saved_left;
|
||||||
|
ssize_t saved_top;
|
||||||
|
size_t saved_width;
|
||||||
|
size_t saved_height;
|
||||||
|
uint32_t window_id;
|
||||||
|
enum window_state window_state;
|
||||||
|
bool created;
|
||||||
|
bool show;
|
||||||
|
bool focus;
|
||||||
|
bool grab_input;
|
||||||
|
};
|
||||||
|
|
||||||
|
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_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_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_leftward(struct window* window);
|
||||||
|
void window_tile_rightward(struct window* window);
|
||||||
|
void window_tile_up(struct window* window);
|
||||||
|
void window_tile_down(struct window* window);
|
||||||
|
void window_tile_left(struct window* window);
|
||||||
|
void window_tile_right(struct window* window);
|
||||||
|
void window_tile_top(struct window* window);
|
||||||
|
void window_tile_top_left(struct window* window);
|
||||||
|
void window_tile_top_right(struct window* window);
|
||||||
|
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);
|
||||||
|
|
||||||
|
#endif
|
|
@ -15,7 +15,7 @@ BINARIES:=\
|
||||||
asteroids \
|
asteroids \
|
||||||
aquatinspitz \
|
aquatinspitz \
|
||||||
|
|
||||||
LIBS:=-ldispd
|
LIBS:=-ldispd -ldisplay
|
||||||
|
|
||||||
all: $(BINARIES)
|
all: $(BINARIES)
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,11 @@
|
||||||
#include <timespec.h>
|
#include <timespec.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <dispd.h>
|
#include <display.h>
|
||||||
|
|
||||||
|
uint32_t WINDOW_ID = 0;
|
||||||
|
uint32_t WINDOW_WIDTH = 800;
|
||||||
|
uint32_t WINDOW_HEIGHT = 512;
|
||||||
|
|
||||||
static inline float RandomFloat()
|
static inline float RandomFloat()
|
||||||
{
|
{
|
||||||
|
@ -60,7 +64,7 @@ static inline float RandomAngle()
|
||||||
|
|
||||||
static inline uint32_t MakeColor(uint8_t r, uint8_t g, uint8_t b)
|
static inline uint32_t MakeColor(uint8_t r, uint8_t g, uint8_t b)
|
||||||
{
|
{
|
||||||
return b << 0UL | g << 8UL | r << 16UL;
|
return b << 0UL | g << 8UL | r << 16UL | 0xFF << 24UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const size_t STARFIELD_WIDTH = 512UL;
|
static const size_t STARFIELD_WIDTH = 512UL;
|
||||||
|
@ -110,31 +114,6 @@ bool pop_is_key_just_down(int abskbkey)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FetchKeyboardInput()
|
|
||||||
{
|
|
||||||
// Read the keyboard input from the user.
|
|
||||||
const unsigned termmode = TERMMODE_KBKEY
|
|
||||||
| TERMMODE_SIGNAL
|
|
||||||
| TERMMODE_NONBLOCK;
|
|
||||||
if ( settermmode(0, termmode) )
|
|
||||||
error(1, errno, "settermmode");
|
|
||||||
uint32_t codepoint;
|
|
||||||
ssize_t numbytes;
|
|
||||||
while ( 0 < (numbytes = read(0, &codepoint, sizeof(codepoint))) )
|
|
||||||
{
|
|
||||||
int kbkey = KBKEY_DECODE(codepoint);
|
|
||||||
if( !kbkey )
|
|
||||||
continue;
|
|
||||||
int abskbkey = (kbkey < 0) ? -kbkey : kbkey;
|
|
||||||
if ( MAXKEYNUM <= (size_t) abskbkey )
|
|
||||||
continue;
|
|
||||||
bool is_key_down_event = 0 < kbkey;
|
|
||||||
if ( !keysdown[abskbkey] && is_key_down_event )
|
|
||||||
keyspending[abskbkey] = true;
|
|
||||||
keysdown[abskbkey] = is_key_down_event;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t xres;
|
static size_t xres;
|
||||||
static size_t yres;
|
static size_t yres;
|
||||||
static size_t bpp;
|
static size_t bpp;
|
||||||
|
@ -1143,25 +1122,85 @@ void Render()
|
||||||
obj->Render();
|
obj->Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void RunFrame(struct dispd_window* window)
|
|
||||||
|
void on_disconnect(void*)
|
||||||
{
|
{
|
||||||
struct dispd_framebuffer* fb = dispd_begin_render(window);
|
exit(0);
|
||||||
if ( !fb )
|
|
||||||
{
|
|
||||||
error(0, 0, "unable to begin rendering dispd window");
|
|
||||||
gamerunning = false;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
xres = dispd_get_framebuffer_width(fb);
|
|
||||||
yres = dispd_get_framebuffer_height(fb);
|
void on_quit(void*, uint32_t)
|
||||||
bpp = dispd_get_framebuffer_format(fb);
|
{
|
||||||
linesize = dispd_get_framebuffer_pitch(fb) / (bpp / 8);
|
exit(0);
|
||||||
framesize = dispd_get_framebuffer_pitch(fb) * yres;
|
}
|
||||||
buf = (uint32_t*) dispd_get_framebuffer_data(fb);
|
|
||||||
FetchKeyboardInput();
|
void on_resize(void*, uint32_t window_id, uint32_t width, uint32_t height)
|
||||||
|
{
|
||||||
|
if ( window_id != WINDOW_ID )
|
||||||
|
return;
|
||||||
|
WINDOW_WIDTH = width;
|
||||||
|
WINDOW_HEIGHT = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_keyboard(void*, uint32_t window_id, uint32_t codepoint)
|
||||||
|
{
|
||||||
|
if ( window_id != WINDOW_ID )
|
||||||
|
return;
|
||||||
|
int kbkey = KBKEY_DECODE(codepoint);
|
||||||
|
if( !kbkey )
|
||||||
|
return;
|
||||||
|
int abskbkey = (kbkey < 0) ? -kbkey : kbkey;
|
||||||
|
if ( MAXKEYNUM <= (size_t) abskbkey )
|
||||||
|
return;
|
||||||
|
bool is_key_down_event = 0 < kbkey;
|
||||||
|
if ( !keysdown[abskbkey] && is_key_down_event )
|
||||||
|
keyspending[abskbkey] = true;
|
||||||
|
keysdown[abskbkey] = is_key_down_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunFrame(struct display_connection* connection)
|
||||||
|
{
|
||||||
|
struct display_event_handlers handlers;
|
||||||
|
memset(&handlers, 0, sizeof(handlers));
|
||||||
|
handlers.disconnect_handler = on_disconnect;
|
||||||
|
handlers.quit_handler = on_quit;
|
||||||
|
handlers.resize_handler = on_resize;
|
||||||
|
handlers.keyboard_handler = on_keyboard;
|
||||||
|
|
||||||
|
while ( display_poll_event(connection, &handlers) == 0 );
|
||||||
|
|
||||||
|
size_t old_framesize = framesize;
|
||||||
|
|
||||||
|
xres = WINDOW_WIDTH;
|
||||||
|
yres = WINDOW_HEIGHT;
|
||||||
|
bpp = 32;
|
||||||
|
linesize = WINDOW_WIDTH;
|
||||||
|
framesize = WINDOW_WIDTH * sizeof(uint32_t) * WINDOW_HEIGHT;
|
||||||
|
if ( old_framesize != framesize )
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
buf = (uint32_t*) malloc(framesize);
|
||||||
|
}
|
||||||
|
|
||||||
GameLogic();
|
GameLogic();
|
||||||
Render();
|
Render();
|
||||||
dispd_finish_render(fb);
|
|
||||||
|
static int fps_counter = 0;
|
||||||
|
fps_counter++;
|
||||||
|
static time_t last_frame_sec = 0;
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
if ( now.tv_sec != last_frame_sec )
|
||||||
|
{
|
||||||
|
char* title = NULL;
|
||||||
|
asprintf(&title, "Asteroids (fps %i)", fps_counter);
|
||||||
|
display_title_window(connection, WINDOW_ID, title);
|
||||||
|
free(title);
|
||||||
|
fps_counter = 0;
|
||||||
|
last_frame_sec = now.tv_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_render_window(connection, WINDOW_ID, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, buf);
|
||||||
|
display_show_window(connection, WINDOW_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitGame()
|
void InitGame()
|
||||||
|
@ -1172,64 +1211,24 @@ void InitGame()
|
||||||
new AsteroidField;
|
new AsteroidField;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct termios saved_tio;
|
|
||||||
|
|
||||||
static void restore_terminal_on_exit(void)
|
|
||||||
{
|
|
||||||
tcsetattr(0, TCSAFLUSH, &saved_tio);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void restore_terminal_on_signal(int signum)
|
|
||||||
{
|
|
||||||
if ( signum == SIGTSTP )
|
|
||||||
{
|
|
||||||
struct termios tio;
|
|
||||||
tcgetattr(0, &tio);
|
|
||||||
tcsetattr(0, TCSAFLUSH, &saved_tio);
|
|
||||||
raise(SIGSTOP);
|
|
||||||
tcgetattr(0, &saved_tio);
|
|
||||||
tcsetattr(0, TCSAFLUSH, &tio);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tcsetattr(0, TCSAFLUSH, &saved_tio);
|
|
||||||
raise(signum);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
if ( !isatty(0) )
|
struct display_connection* connection = display_connect_default();
|
||||||
error(1, errno, "standard input");
|
if ( !connection && errno == ECONNREFUSED )
|
||||||
if ( tcgetattr(0, &saved_tio) < 0 )
|
display_spawn(argc, argv);
|
||||||
error(1, errno, "tcsetattr: standard input");
|
if ( !connection )
|
||||||
if ( atexit(restore_terminal_on_exit) != 0 )
|
error(1, errno, "Could not connect to display server");
|
||||||
error(1, errno, "atexit");
|
|
||||||
struct sigaction sa;
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
|
||||||
sa.sa_handler = restore_terminal_on_signal;
|
|
||||||
sigaction(SIGTSTP, &sa, NULL);
|
|
||||||
sa.sa_flags = SA_RESETHAND;
|
|
||||||
sigaction(SIGINT, &sa, NULL);
|
|
||||||
sigaction(SIGQUIT, &sa, NULL);
|
|
||||||
sigaction(SIGTERM, &sa, NULL);
|
|
||||||
|
|
||||||
if ( !dispd_initialize(&argc, &argv) )
|
display_create_window(connection, WINDOW_ID);
|
||||||
error(1, 0, "couldn't initialize dispd library");
|
display_resize_window(connection, WINDOW_ID, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
struct dispd_session* session = dispd_attach_default_session();
|
display_title_window(connection, WINDOW_ID, "Asteroids");
|
||||||
if ( !session )
|
|
||||||
error(1, 0, "couldn't attach to dispd default session");
|
|
||||||
if ( !dispd_session_setup_game_rgba(session) )
|
|
||||||
error(1, 0, "couldn't setup dispd rgba session");
|
|
||||||
struct dispd_window* window = dispd_create_window_game_rgba(session);
|
|
||||||
if ( !window )
|
|
||||||
error(1, 0, "couldn't create dispd rgba window");
|
|
||||||
|
|
||||||
InitGame();
|
InitGame();
|
||||||
gamerunning = true;
|
gamerunning = true;
|
||||||
for ( framenum = 0; gamerunning; framenum++ )
|
for ( framenum = 0; gamerunning; framenum++ )
|
||||||
RunFrame(window);
|
RunFrame(connection);
|
||||||
|
|
||||||
dispd_destroy_window(window);
|
display_disconnect(connection);
|
||||||
dispd_detach_session(session);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
2
libdisplay/.gitignore
vendored
Normal file
2
libdisplay/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*.a
|
||||||
|
*.o
|
34
libdisplay/Makefile
Normal file
34
libdisplay/Makefile
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
SOFTWARE_MEANT_FOR_SORTIX=1
|
||||||
|
include ../build-aux/platform.mak
|
||||||
|
include ../build-aux/compiler.mak
|
||||||
|
include ../build-aux/dirs.mak
|
||||||
|
|
||||||
|
OPTLEVEL?=-g -O2
|
||||||
|
CFLAGS?=$(OPTLEVEL)
|
||||||
|
|
||||||
|
CFLAGS:=$(CFLAGS) -Wall -Wextra
|
||||||
|
CPPFLAGS:=$(CPPFLAGS) -Iinclude
|
||||||
|
|
||||||
|
LIBRARY=libdisplay.a
|
||||||
|
|
||||||
|
OBJS=\
|
||||||
|
libdisplay.o \
|
||||||
|
|
||||||
|
all: $(LIBRARY)
|
||||||
|
|
||||||
|
.PHONY: all install uninstall clean
|
||||||
|
|
||||||
|
install: all
|
||||||
|
mkdir -p $(DESTDIR)$(LIBDIR)
|
||||||
|
cp $(LIBRARY) $(DESTDIR)$(LIBDIR)
|
||||||
|
mkdir -p $(DESTDIR)$(INCLUDEDIR)
|
||||||
|
cp -RTv include $(DESTDIR)$(INCLUDEDIR)
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(LIBRARY): $(OBJS)
|
||||||
|
$(AR) rcs $@ $(OBJS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(LIBRARY) *.o *.a
|
113
libdisplay/include/display-protocol.h
Normal file
113
libdisplay/include/display-protocol.h
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* display-protocol.h
|
||||||
|
* Display protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DISPLAY_PROTOCOL_H
|
||||||
|
#define DISPLAY_PROTOCOL_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct display_packet_header
|
||||||
|
{
|
||||||
|
uint32_t message_id;
|
||||||
|
uint32_t message_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DISPLAY_CREATE_WINDOW 0
|
||||||
|
struct display_create_window
|
||||||
|
{
|
||||||
|
uint32_t window_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DISPLAY_DESTROY_WINDOW 1
|
||||||
|
struct display_destroy_window
|
||||||
|
{
|
||||||
|
uint32_t window_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DISPLAY_RESIZE_WINDOW 2
|
||||||
|
struct display_resize_window
|
||||||
|
{
|
||||||
|
uint32_t window_id;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DISPLAY_RENDER_WINDOW 3
|
||||||
|
struct display_render_window
|
||||||
|
{
|
||||||
|
uint32_t window_id;
|
||||||
|
uint32_t left;
|
||||||
|
uint32_t top;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
/* width * height * sizeof(uint32_t) image bytes follows */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DISPLAY_TITLE_WINDOW 4
|
||||||
|
struct display_title_window
|
||||||
|
{
|
||||||
|
uint32_t window_id;
|
||||||
|
/* An UTF-8 string follows */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DISPLAY_SHOW_WINDOW 5
|
||||||
|
struct display_show_window
|
||||||
|
{
|
||||||
|
uint32_t window_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DISPLAY_HIDE_WINDOW 6
|
||||||
|
struct display_hide_window
|
||||||
|
{
|
||||||
|
uint32_t window_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DISPLAY_SHUTDOWN 7
|
||||||
|
struct display_shutdown
|
||||||
|
{
|
||||||
|
uint32_t code;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EVENT_DISCONNECT 0
|
||||||
|
struct event_disconnect
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EVENT_QUIT 1
|
||||||
|
struct event_quit
|
||||||
|
{
|
||||||
|
uint32_t window_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EVENT_RESIZE 2
|
||||||
|
struct event_resize
|
||||||
|
{
|
||||||
|
uint32_t window_id;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EVENT_KEYBOARD 3
|
||||||
|
struct event_keyboard
|
||||||
|
{
|
||||||
|
uint32_t window_id;
|
||||||
|
uint32_t codepoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
90
libdisplay/include/display.h
Normal file
90
libdisplay/include/display.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 2015, 2016, 2017 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* display.h
|
||||||
|
* Display client library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDE_DISPLAY_H
|
||||||
|
#define INCLUDE_DISPLAY_H
|
||||||
|
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct display_connection;
|
||||||
|
|
||||||
|
int display_spawn(int argc, char** argv);
|
||||||
|
|
||||||
|
struct display_connection* display_connect(const char* socket_path);
|
||||||
|
struct display_connection* display_connect_default(void);
|
||||||
|
void display_disconnect(struct display_connection* connection);
|
||||||
|
|
||||||
|
int display_connection_fd(struct display_connection* connection);
|
||||||
|
|
||||||
|
void display_shutdown(struct display_connection* connection, uint32_t code);
|
||||||
|
|
||||||
|
void display_create_window(struct display_connection* connection,
|
||||||
|
uint32_t window_id);
|
||||||
|
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);
|
||||||
|
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_title_window(struct display_connection* connection,
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
struct display_event_handlers
|
||||||
|
{
|
||||||
|
void* context;
|
||||||
|
display_event_disconnect_handler_t disconnect_handler;
|
||||||
|
display_event_quit_handler_t quit_handler;
|
||||||
|
display_event_resize_handler_t resize_handler;
|
||||||
|
display_event_keyboard_handler_t keyboard_handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
int display_poll_event(struct display_connection* connection,
|
||||||
|
struct display_event_handlers* handlers);
|
||||||
|
int display_wait_event(struct display_connection* connection,
|
||||||
|
struct display_event_handlers* handlers);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
859
libdisplay/include/nyan.h
Normal file
859
libdisplay/include/nyan.h
Normal file
|
@ -0,0 +1,859 @@
|
||||||
|
/*
|
||||||
|
* Pop Tart Cat animation frames
|
||||||
|
* Adapted from ToAruOS.
|
||||||
|
*/
|
||||||
|
#ifndef INCLUDE_NYAN_H
|
||||||
|
#define INCLUDE_NYAN_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static const char* const nyan_frame0[] = {
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
".,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,>>>>>>>,,,,,,,,>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&+++++++&&&&&&&&'''++'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++++++++++++++++++**''+'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++++++++++++++++++'**'''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,",
|
||||||
|
"+++#######++++++++''**''@$$$$$$-'*************',,,,,,,,,,,,,,,,,",
|
||||||
|
"###################''**'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,",
|
||||||
|
"####################''''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,",
|
||||||
|
"###=======########====''@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,",
|
||||||
|
"======================='@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
"===;;;;;;;.=======;;;;'''@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;'***''''''''''''''''''',,,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;'**'','*',,,,,'*','**',,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;,,,,.,,;;;.;;;;,,,'''',,'',,,,,,,'',,'',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const nyan_frame1[] = {
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,>>>>>>>,,,,,,,,>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&+++++++&&&&&&&&+++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++'+++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,",
|
||||||
|
"++++++++++++++++++'*'++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++#######++++++++'*''''@$$$$$$-$'*************',,,,,,,,,,,,,,,,",
|
||||||
|
"###################****'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,",
|
||||||
|
"###################''**'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,",
|
||||||
|
"###=======########==='''@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,",
|
||||||
|
"======================='@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,",
|
||||||
|
"===;;;;;;;========;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;;'**','*',,,,,,**','**',,,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;,,.,,,,;;;;;;;;,,,,''',,,'',,,,,,''',,''',,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,..,,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const nyan_frame2[] = {
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,..,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,.",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.",
|
||||||
|
">>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++&&&&&&&++++++++&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,",
|
||||||
|
"##+++++++########++++++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,",
|
||||||
|
"######################''@$$$$$$-$'*************',,,,,,,,,,,,,,,,",
|
||||||
|
"###################'''''@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,",
|
||||||
|
"==#######========#'****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,",
|
||||||
|
"==================='''='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,",
|
||||||
|
";;=======;;;;;;;;======'@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,",
|
||||||
|
";.;;;;;;;;;;;;;;;;;;;;;'*'''''''''''''''''''',,,,,,,,,,,,,,,,,,,",
|
||||||
|
".,.;;;;;;,,,,,,,,;;;;;;'**',**',,,,,,**','**',,,,,,,,,,,,,,,,,,,",
|
||||||
|
",.,,,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const nyan_frame3[] = {
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,",
|
||||||
|
">>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++&&&&&&&++++++++&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,",
|
||||||
|
"##+++++++########++++++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,",
|
||||||
|
"#####################'''@$$$$$$-$'*************',,,,,,,,,,,,,,,,",
|
||||||
|
"###################''**'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,",
|
||||||
|
"==#######========##****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,",
|
||||||
|
"=================='*'=='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,",
|
||||||
|
";;=======;;;;;;;;=='==='@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,;;;;;;;,,,,,,,,;;;;;'**','*',,,,,,'*','**',,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,''',,,'',,,,,,,'',,''',,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const nyan_frame4[] = {
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,",
|
||||||
|
",,,>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&+++++++&&&&&&&&+++++'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++++++'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++++++++++++++++++'''++'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,",
|
||||||
|
"+++#######+++++++'**''''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,",
|
||||||
|
"#################'****''@$$$$$$-'*************',,,,,,,,,,,,,,,,,",
|
||||||
|
"##################''''*'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,",
|
||||||
|
"###=======########==='''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,",
|
||||||
|
"======================='@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,",
|
||||||
|
"===;;;;;;;========;;;;''@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;''''@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;'***'''''''''''''''''''',,,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;,,,,,,,;;;;;;;;,,'**','**,,,,,,'**,'**',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,''',,,'',,,,,,,'',,''',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,..,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const nyan_frame5[] = {
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$''$$$@@','',,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$'**'-$$@''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&+++++++&&&&&&&&+++++'@$$$$$$$$'***$$$@'***',,,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++'+++'@$$$$$-$$'***''''****',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++++++++++++++++++'*'++'@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,",
|
||||||
|
"+++#######++++++++'*''''@$$$$$$$'*************',,,,,,,,,,,,,,,,,",
|
||||||
|
"###################****'@$$$$$$-'***.'****.'**',,,,,,,,,,,,,,,,,",
|
||||||
|
"###################''**'@$-$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,",
|
||||||
|
"###=======########==='''@$$$$$$$'*%%********%%',,,,,,,,,,,,,,,,,",
|
||||||
|
"======================='@@$$$-$$$'***''''''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
"===;;;;;;;========;;;;''@@@$$$$$$$'*********',,,,,,,,,,,,,,,,,,.",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;'*''@@@@@@@@@@''''''''',,,,,,,,,,,,,,,,,,,.",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;'***''''''''''''''''*',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;,,,,,,,;;;;;;;;,,'**','**,,,,,,'**,'**',,,,,,,,,,,,,,,,,,..,.",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const nyan_frame6[] = {
|
||||||
|
".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,..,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>,,,,,,,>>>>>>>>,,,,,,,'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++&&&&&&&++++++++&'''&&'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++++++++++++++++++'*''+'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++++++++++++++++++'**'''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,",
|
||||||
|
"##+++++++########++'**''@$$$$$$-'*************',,,,,,,,,,,,,,,,,",
|
||||||
|
"###################''**'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,",
|
||||||
|
"####################''''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,",
|
||||||
|
"==#######========#####''@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,",
|
||||||
|
"======================='@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
";;=======;;;;;;;;====='''@@@@@@@@@'*********',,,,,,,,,,,.,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;'***''''''''''''''''''',,,,,,,,,,.,,,.,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;'**'','*',,,,,'**,'**',,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,;;;;;;;,,,,,,,,;;;;'''',,'',,,,,,,'',,'',,,,,,,,,,,.,,,,,.,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const nyan_frame7[] = {
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>,,,,,,,>>>>>>>>,,,,,,,'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,",
|
||||||
|
"++&&&&&&&++++++++&&&&&&'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++'+++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,",
|
||||||
|
"++++++++++++++++++'*'++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,",
|
||||||
|
"##+++++++########+'*''''@$$$$$$-$'*************',,,,,,,,,,,,,,,,",
|
||||||
|
"###################****'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,",
|
||||||
|
"###################''**'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,",
|
||||||
|
"==#######========####'''@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,",
|
||||||
|
"======================='@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,",
|
||||||
|
";;=======;;;;;;;;======''@@@@@@@@@@'*********',,,.,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;;'**','*',,,,,,**','**',,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,;;;;;;;,,,,,,,,;;;;;''',,,'',,,,,,''',,''',,.,,,,.,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const nyan_frame8[] = {
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,..,...,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&+++++++&&&&&&&&+++++'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++#######++++++++#####'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,",
|
||||||
|
"######################''@$$$$$$-$'*************',,,,,,,,,,,,,,,,",
|
||||||
|
"###################'''''@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,",
|
||||||
|
"###=======########'****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,",
|
||||||
|
"==================='''='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,",
|
||||||
|
"===;;;;;;;========;;;;;'@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;;;'*'''''''''''''''''''',,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;,,,,,,,;;;;;;;;,,,,,'**',**',,,,,,**'.'**',,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const nyan_frame9[] = {
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&+++++++&&&&&&&&+++++'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,",
|
||||||
|
"+++#######++++++++#####'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,",
|
||||||
|
"#####################'''@$$$$$$-$'*************',,,,,,,,,,,,,,,,",
|
||||||
|
"###################''**'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,",
|
||||||
|
"###=======########=****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,",
|
||||||
|
"=================='*'=='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,",
|
||||||
|
"===;;;;;;;========;';;;'@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;,,,,,,,;;;;;;;;,,,,'**','*',,..,.**','**',,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,''',,,'',,,,.,''',,''',,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const nyan_frame10[] = {
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,",
|
||||||
|
"++&&&&&&&++++++++&&&&&&'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++++++'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++++++++++++++++++'''++'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,",
|
||||||
|
"##+++++++########'**''''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,",
|
||||||
|
"#################'****''@$$$$$$-'*************',,,,,,,,,,,,,,,,,",
|
||||||
|
"##################''''*'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,",
|
||||||
|
"==#######========####'''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,",
|
||||||
|
"======================='@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,",
|
||||||
|
";;=======;;;;;;;;=====''@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;;''''@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;'***'''''''''''''''''''',,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,;;;;;;;,,,,,,,,;;;'**'.'**..,,,,'**''**',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,''',,,'',,,,,,,''',''',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
".,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const nyan_frame11[] = {
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$''$$$@@','',,,,,,,,,,,,,,,,,,,",
|
||||||
|
"&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$'**'-$$@''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++&&&&&&&++++++++&&&&&&'@$$$$$$$$'***$$$@'***',,,,,,,,,,,,,,,,,,",
|
||||||
|
"+++++++++++++++++++'+++'@$$$$$-$$'***''''****',,,,,,,,,,,,,,,,,,",
|
||||||
|
"++++++++++++++++++'*'++'@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,",
|
||||||
|
"##+++++++########+'*''''@$$$$$$$'*************',,,,,,,,,,,,,,,,,",
|
||||||
|
"###################****'@$$$$$$-'***.'****.'**',,,,,,,,,,,,,,,,,",
|
||||||
|
"###################''**'@$-$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,",
|
||||||
|
"==#######========####'''@$$$$$$$'*%%********%%',,,,,,,,,,,,,,,,,",
|
||||||
|
"======================='@@$$$-$$$'***''''''**',,,,,,,,,,,,,,,,,,",
|
||||||
|
";;=======;;;;;;;;=.===''@@@$$$$$$$'*********',,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;.'*''@@@@@@@@@@''''''''',,,,,,,,,,,,,,,,,,,,",
|
||||||
|
";;;;;;;;;;;;;;;;;;;;'***''''''''''''''''*',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,;;;;;;;,,,,,,,.;;;'**','**,,,,,,'**''**',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
|
||||||
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"};
|
||||||
|
|
||||||
|
static const char* const* const nyan_frames[] = {
|
||||||
|
nyan_frame0,
|
||||||
|
nyan_frame1,
|
||||||
|
nyan_frame2,
|
||||||
|
nyan_frame3,
|
||||||
|
nyan_frame4,
|
||||||
|
nyan_frame5,
|
||||||
|
nyan_frame6,
|
||||||
|
nyan_frame7,
|
||||||
|
nyan_frame8,
|
||||||
|
nyan_frame9,
|
||||||
|
nyan_frame10,
|
||||||
|
nyan_frame11,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NYAN_FRAME_WIDTH 64
|
||||||
|
#define NYAN_FRAME_HEIGHT 64
|
||||||
|
|
||||||
|
static inline uint8_t nyan_palette_of_char(char c)
|
||||||
|
{
|
||||||
|
if ( c == ',' ) return 1;
|
||||||
|
if ( c == '.' ) return 2;
|
||||||
|
if ( c == '\'') return 3;
|
||||||
|
if ( c == '@' ) return 4;
|
||||||
|
if ( c == '$' ) return 5;
|
||||||
|
if ( c == '-' ) return 6;
|
||||||
|
if ( c == '>' ) return 7;
|
||||||
|
if ( c == '&' ) return 8;
|
||||||
|
if ( c == '+' ) return 9;
|
||||||
|
if ( c == '#' ) return 10;
|
||||||
|
if ( c == '=' ) return 11;
|
||||||
|
if ( c == ';' ) return 12;
|
||||||
|
if ( c == '*' ) return 13;
|
||||||
|
if ( c == '%' ) return 14;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t nyan_palette[1+14][4] =
|
||||||
|
{
|
||||||
|
{ 0, 0, 0, 0 }, // 0; Unused entry
|
||||||
|
{ 0, 0, 97, 200 }, // 1: , = Blue background
|
||||||
|
{ 255, 255, 255, 255 }, // 2: . = White stars
|
||||||
|
{ 46, 52, 54, 255 }, // 3: ' = Black border
|
||||||
|
{ 255, 255, 215, 255 }, // 4: @ = Tan poptart
|
||||||
|
{ 215, 135, 175, 255 }, // 5: $ = Pink potart
|
||||||
|
{ 215, 0, 135, 255 }, // 6: - = Red poptart
|
||||||
|
{ 239, 41, 41, 255 }, // 7: > = Red rainbow
|
||||||
|
{ 255, 95, 0, 255 }, // 8: & = Orange rainbow
|
||||||
|
{ 252, 233, 79, 255 }, // 9: + = Yellow rainbow
|
||||||
|
{ 138, 226, 52, 255 }, // 10: # = Green rainbow
|
||||||
|
{ 0, 135, 255, 255 }, // 11: = = Light blue rainbow
|
||||||
|
{ 0, 0, 175, 255 }, // 12: ; = Dark blue rainbow
|
||||||
|
{ 85, 87, 83, 255 }, // 13: * = Grey cat face
|
||||||
|
{ 85, 87, 83, 255 }, // 14: % = Pink cheeks
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
318
libdisplay/libdisplay.c
Normal file
318
libdisplay/libdisplay.c
Normal file
|
@ -0,0 +1,318 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 2015, 2016, 2017 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* libdisplay.c
|
||||||
|
* Display client library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
#include <endian.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ioleast.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <display.h>
|
||||||
|
|
||||||
|
#include "display-protocol.h"
|
||||||
|
|
||||||
|
int display_spawn(int argc, char** argv)
|
||||||
|
{
|
||||||
|
// TODO: Overflow.
|
||||||
|
char** new_argv = malloc((2 + argc + 1) * sizeof(char*));
|
||||||
|
if ( !new_argv )
|
||||||
|
return -1;
|
||||||
|
new_argv[0] = (char*) "display";
|
||||||
|
// TODO: Start the compositor in a special close-after-program-exists mode?
|
||||||
|
// And maybe go fullscreen / maximized by default?
|
||||||
|
new_argv[1] = (char*) "--";
|
||||||
|
for ( int i = 0; i < argc; i++ )
|
||||||
|
new_argv[2 + i] = argv[i];
|
||||||
|
new_argv[2 + argc] = NULL;
|
||||||
|
execvp(new_argv[0], new_argv);
|
||||||
|
free(new_argv);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_local_client_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 = (struct sockaddr_un*) malloc(addr_size);
|
||||||
|
if ( !sockaddr )
|
||||||
|
return -1;
|
||||||
|
sockaddr->sun_family = AF_LOCAL;
|
||||||
|
strcpy(sockaddr->sun_path, path);
|
||||||
|
int fd = socket(AF_LOCAL, SOCK_STREAM | flags, 0);
|
||||||
|
if ( fd < 0 )
|
||||||
|
return free(sockaddr), -1;
|
||||||
|
if ( connect(fd, (const struct sockaddr*) sockaddr, addr_size) < 0 )
|
||||||
|
return close(fd), free(sockaddr), -1;
|
||||||
|
free(sockaddr);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct display_connection
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct display_packet_header header;
|
||||||
|
size_t header_bytes;
|
||||||
|
uint8_t* payload;
|
||||||
|
size_t payload_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct display_connection* display_connect(const char* socket_path)
|
||||||
|
{
|
||||||
|
struct display_connection* connection =
|
||||||
|
(struct display_connection*) malloc(sizeof(struct display_connection));
|
||||||
|
if ( !connection )
|
||||||
|
return NULL;
|
||||||
|
memset(connection, 0, sizeof(*connection));
|
||||||
|
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));
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct display_connection* display_connect_default(void)
|
||||||
|
{
|
||||||
|
return display_connect(getenv("DISPLAY_SOCKET") ?
|
||||||
|
getenv("DISPLAY_SOCKET") :
|
||||||
|
"/run/display");
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_disconnect(struct display_connection* connection)
|
||||||
|
{
|
||||||
|
free(connection->payload);
|
||||||
|
close(connection->fd);
|
||||||
|
free(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
struct display_packet_header header;
|
||||||
|
header.message_id = message_id;
|
||||||
|
header.message_length = message_size + auxilerary_size;
|
||||||
|
writeall(connection->fd, &header, sizeof(header));
|
||||||
|
writeall(connection->fd, message, message_size);
|
||||||
|
writeall(connection->fd, auxilerary, auxilerary_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_shutdown(struct display_connection* connection, uint32_t code)
|
||||||
|
{
|
||||||
|
struct display_shutdown msg;
|
||||||
|
msg.code = code;
|
||||||
|
send_message_no_aux(connection, DISPLAY_SHUTDOWN, &msg, sizeof(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
struct display_resize_window msg;
|
||||||
|
msg.window_id = window_id;
|
||||||
|
msg.width = width;
|
||||||
|
msg.height = height;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
struct display_render_window msg;
|
||||||
|
msg.window_id = window_id;
|
||||||
|
msg.left = left;
|
||||||
|
msg.top = top;
|
||||||
|
msg.width = width;
|
||||||
|
msg.height = height;
|
||||||
|
send_message(connection, DISPLAY_RENDER_WINDOW, &msg, sizeof(msg),
|
||||||
|
data, sizeof(uint32_t) * width * height);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
struct display_hide_window msg;
|
||||||
|
msg.window_id = window_id;
|
||||||
|
send_message_no_aux(connection, DISPLAY_HIDE_WINDOW, &msg, sizeof(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool display_read_event(struct display_connection* connection)
|
||||||
|
{
|
||||||
|
while ( connection->header_bytes < sizeof(connection->header) )
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
ssize_t amount = read(connection->fd,
|
||||||
|
(uint8_t*) &connection->header + connection->header_bytes,
|
||||||
|
sizeof(connection->header) - connection->header_bytes);
|
||||||
|
if ( amount < 0 && (errno == EAGAIN || errno == EWOULDBLOCK) )
|
||||||
|
break;
|
||||||
|
if ( amount < 0 )
|
||||||
|
break;
|
||||||
|
if ( amount == 0 )
|
||||||
|
return false;
|
||||||
|
connection->header_bytes += amount;
|
||||||
|
}
|
||||||
|
if ( connection->header_bytes == sizeof(connection->header) &&
|
||||||
|
!connection->payload )
|
||||||
|
{
|
||||||
|
connection->payload = (uint8_t*) malloc(connection->header.message_length);
|
||||||
|
connection->payload_bytes = 0;
|
||||||
|
}
|
||||||
|
while ( connection->header_bytes == sizeof(connection->header) &&
|
||||||
|
connection->payload &&
|
||||||
|
connection->payload_bytes < connection->header.message_length )
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
ssize_t amount = read(connection->fd,
|
||||||
|
connection->payload + connection->payload_bytes,
|
||||||
|
connection->header.message_length - connection->payload_bytes);
|
||||||
|
if ( amount < 0 && (errno == EAGAIN || errno == EWOULDBLOCK) )
|
||||||
|
break;
|
||||||
|
if ( amount < 0 )
|
||||||
|
break;
|
||||||
|
if ( amount == 0 )
|
||||||
|
return false;
|
||||||
|
connection->payload_bytes += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int display_dispatch_event(struct display_connection* connection, struct display_event_handlers* handlers)
|
||||||
|
{
|
||||||
|
if ( connection->header_bytes == sizeof(connection->header) &&
|
||||||
|
connection->payload &&
|
||||||
|
connection->payload_bytes == connection->header.message_length )
|
||||||
|
{
|
||||||
|
// TODO: == instead of <= due to warning. Maybe all should be changed to
|
||||||
|
// use == instead.
|
||||||
|
if ( connection->header.message_id == EVENT_DISCONNECT &&
|
||||||
|
connection->header.message_length ==/*>=*/ sizeof(struct event_disconnect) )
|
||||||
|
{
|
||||||
|
struct event_disconnect* event = (struct event_disconnect*) connection->payload;
|
||||||
|
(void) event;
|
||||||
|
if ( handlers->disconnect_handler )
|
||||||
|
handlers->disconnect_handler(handlers->context);
|
||||||
|
else
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( connection->header.message_id == EVENT_QUIT &&
|
||||||
|
connection->header.message_length >= sizeof(struct event_quit) )
|
||||||
|
{
|
||||||
|
struct event_quit* event = (struct event_quit*) connection->payload;
|
||||||
|
if ( handlers->quit_handler )
|
||||||
|
handlers->quit_handler(handlers->context, event->window_id);
|
||||||
|
else
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( connection->header.message_id == EVENT_RESIZE &&
|
||||||
|
connection->header.message_length >= sizeof(struct event_resize) )
|
||||||
|
{
|
||||||
|
struct event_resize* event = (struct event_resize*) connection->payload;
|
||||||
|
if ( handlers->resize_handler )
|
||||||
|
handlers->resize_handler(handlers->context, event->window_id, event->width, event->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( connection->header.message_id == EVENT_KEYBOARD &&
|
||||||
|
connection->header.message_length >= sizeof(struct event_keyboard) )
|
||||||
|
{
|
||||||
|
struct event_keyboard* event = (struct event_keyboard*) connection->payload;
|
||||||
|
if ( handlers->keyboard_handler )
|
||||||
|
handlers->keyboard_handler(handlers->context, event->window_id, event->codepoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
connection->header_bytes = 0;
|
||||||
|
free(connection->payload), connection->payload = NULL;
|
||||||
|
connection->payload_bytes = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int display_event_read_hangup(struct display_event_handlers* handlers)
|
||||||
|
{
|
||||||
|
if ( handlers->disconnect_handler )
|
||||||
|
handlers->disconnect_handler(handlers->context);
|
||||||
|
else
|
||||||
|
exit(1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
fcntl(connection->fd, F_SETFL, fcntl(connection->fd, F_GETFL) & ~O_NONBLOCK);
|
||||||
|
if ( !read_success )
|
||||||
|
return display_event_read_hangup(handlers);
|
||||||
|
return display_dispatch_event(connection, 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);
|
||||||
|
return display_dispatch_event(connection, handlers);
|
||||||
|
}
|
2
libui/.gitignore
vendored
Normal file
2
libui/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*.a
|
||||||
|
*.o
|
36
libui/Makefile
Normal file
36
libui/Makefile
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
SOFTWARE_MEANT_FOR_SORTIX=1
|
||||||
|
include ../build-aux/platform.mak
|
||||||
|
include ../build-aux/compiler.mak
|
||||||
|
include ../build-aux/dirs.mak
|
||||||
|
|
||||||
|
OPTLEVEL?=-g -O2
|
||||||
|
CFLAGS?=$(OPTLEVEL)
|
||||||
|
|
||||||
|
CFLAGS:=$(CFLAGS) -Wall -Wextra
|
||||||
|
CPPFLAGS:=$(CPPFLAGS) -Iinclude
|
||||||
|
|
||||||
|
LIBRARY=libui.a
|
||||||
|
|
||||||
|
OBJS=\
|
||||||
|
framebuffer.o \
|
||||||
|
pixel.o \
|
||||||
|
vgafont.o \
|
||||||
|
|
||||||
|
all: $(LIBRARY)
|
||||||
|
|
||||||
|
.PHONY: all install clean
|
||||||
|
|
||||||
|
install: all
|
||||||
|
mkdir -p $(DESTDIR)$(LIBDIR)
|
||||||
|
cp $(LIBRARY) $(DESTDIR)$(LIBDIR)
|
||||||
|
mkdir -p $(DESTDIR)$(INCLUDEDIR)
|
||||||
|
cp -RTv include $(DESTDIR)$(INCLUDEDIR)
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(LIBRARY): $(OBJS)
|
||||||
|
$(AR) rcs $@ $(OBJS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(LIBRARY) *.o *.a
|
71
libui/framebuffer.c
Normal file
71
libui/framebuffer.c
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* framebuffer.c
|
||||||
|
* Framebuffer functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "framebuffer.h"
|
||||||
|
#include "pixel.h"
|
||||||
|
|
||||||
|
struct framebuffer framebuffer_crop(struct framebuffer fb,
|
||||||
|
size_t left,
|
||||||
|
size_t top,
|
||||||
|
size_t width,
|
||||||
|
size_t height)
|
||||||
|
{
|
||||||
|
// Crop the framebuffer horizontally.
|
||||||
|
if ( fb.xres < left )
|
||||||
|
left = fb.xres;
|
||||||
|
fb.buffer += left;
|
||||||
|
fb.xres -= left;
|
||||||
|
if ( width < fb.xres )
|
||||||
|
fb.xres = width;
|
||||||
|
|
||||||
|
// Crop the framebuffer vertically.
|
||||||
|
if ( fb.yres < top )
|
||||||
|
top = fb.yres;
|
||||||
|
fb.buffer += top * fb.pitch;
|
||||||
|
fb.yres -= top;
|
||||||
|
if ( height < fb.yres )
|
||||||
|
fb.yres = height;
|
||||||
|
|
||||||
|
return fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void framebuffer_copy_to_framebuffer(const struct framebuffer dst,
|
||||||
|
const struct framebuffer src)
|
||||||
|
{
|
||||||
|
for ( size_t y = 0; y < src.yres; y++ )
|
||||||
|
for ( size_t x = 0; x < src.xres; x++ )
|
||||||
|
framebuffer_set_pixel(dst, x, y, framebuffer_get_pixel(src, x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
void framebuffer_copy_to_framebuffer_blend(const struct framebuffer dst,
|
||||||
|
const struct framebuffer src)
|
||||||
|
{
|
||||||
|
for ( size_t y = 0; y < src.yres; y++ )
|
||||||
|
{
|
||||||
|
for ( size_t x = 0; x < src.xres; x++ )
|
||||||
|
{
|
||||||
|
uint32_t bg = framebuffer_get_pixel(dst, x, y);
|
||||||
|
uint32_t fg = framebuffer_get_pixel(src, x, y);
|
||||||
|
framebuffer_set_pixel(dst, x, y, blend_pixel(bg, fg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
libui/include/framebuffer.h
Normal file
63
libui/include/framebuffer.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* framebuffer.h
|
||||||
|
* Framebuffer functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FRAMEBUFFER_H
|
||||||
|
#define FRAMEBUFFER_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct framebuffer
|
||||||
|
{
|
||||||
|
size_t pitch;
|
||||||
|
uint32_t* buffer;
|
||||||
|
size_t xres;
|
||||||
|
size_t yres;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline uint32_t framebuffer_get_pixel(const struct framebuffer fb,
|
||||||
|
size_t x,
|
||||||
|
size_t y)
|
||||||
|
{
|
||||||
|
if ( fb.xres <= x || fb.yres <= y )
|
||||||
|
return 0;
|
||||||
|
return fb.buffer[y * fb.pitch + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void framebuffer_set_pixel(const struct framebuffer fb,
|
||||||
|
size_t x,
|
||||||
|
size_t y,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
if ( fb.xres <= x || fb.yres <= y )
|
||||||
|
return;
|
||||||
|
fb.buffer[y * fb.pitch + x] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct framebuffer framebuffer_crop(struct framebuffer fb,
|
||||||
|
size_t left,
|
||||||
|
size_t top,
|
||||||
|
size_t width,
|
||||||
|
size_t height);
|
||||||
|
void framebuffer_copy_to_framebuffer(const struct framebuffer dst,
|
||||||
|
const struct framebuffer src);
|
||||||
|
void framebuffer_copy_to_framebuffer_blend(const struct framebuffer dst,
|
||||||
|
const struct framebuffer src);
|
||||||
|
|
||||||
|
#endif
|
55
libui/include/pixel.h
Normal file
55
libui/include/pixel.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pixel.h
|
||||||
|
* Pixel functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PIXEL_H
|
||||||
|
#define PIXEL_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// TODO: This isn't the only pixel format in the world!
|
||||||
|
union color_rgba8
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t b;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t a;
|
||||||
|
};
|
||||||
|
uint32_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline uint32_t make_color_a(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
|
{
|
||||||
|
union color_rgba8 color;
|
||||||
|
color.r = r;
|
||||||
|
color.g = g;
|
||||||
|
color.b = b;
|
||||||
|
color.a = a;
|
||||||
|
return color.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t make_color(uint8_t r, uint8_t g, uint8_t b)
|
||||||
|
{
|
||||||
|
return make_color_a(r, g, b, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t blend_pixel(uint32_t bg_value, uint32_t fg_value);
|
||||||
|
|
||||||
|
#endif
|
41
libui/include/vgafont.h
Normal file
41
libui/include/vgafont.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 2015, 2016, 2017 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* vgafont.h
|
||||||
|
* VGA font rendering.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VGAFONT_H
|
||||||
|
#define VGAFONT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "framebuffer.h"
|
||||||
|
|
||||||
|
#define FONT_REALWIDTH 8
|
||||||
|
#define FONT_WIDTH 9
|
||||||
|
#define FONT_HEIGHT 16
|
||||||
|
#define FONT_CHARSIZE (FONT_REALWIDTH * FONT_HEIGHT / 8)
|
||||||
|
#define FONT_NUMCHARS 256
|
||||||
|
|
||||||
|
extern uint8_t font[FONT_CHARSIZE * FONT_NUMCHARS];
|
||||||
|
|
||||||
|
void load_font(void);
|
||||||
|
void render_char(struct framebuffer fb, wchar_t c, uint32_t color);
|
||||||
|
void render_text(struct framebuffer fb, const char* str, uint32_t color);
|
||||||
|
size_t render_text_columns(const char* str);
|
||||||
|
size_t render_text_width(const char* str);
|
||||||
|
|
||||||
|
#endif
|
38
libui/pixel.c
Normal file
38
libui/pixel.c
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pixel.c
|
||||||
|
* Pixel functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "pixel.h"
|
||||||
|
|
||||||
|
uint32_t blend_pixel(uint32_t bg_value, uint32_t fg_value)
|
||||||
|
{
|
||||||
|
union color_rgba8 fg; fg.value = fg_value;
|
||||||
|
union color_rgba8 bg; bg.value = bg_value;
|
||||||
|
if ( fg.a == 255 )
|
||||||
|
return fg.value;
|
||||||
|
if ( fg.a == 0 )
|
||||||
|
return bg.value;
|
||||||
|
union color_rgba8 ret;
|
||||||
|
ret.a = 255;
|
||||||
|
ret.r = ((255-fg.a)*bg.r + fg.a*fg.r) / 256;
|
||||||
|
ret.g = ((255-fg.a)*bg.g + fg.a*fg.g) / 256;
|
||||||
|
ret.b = ((255-fg.a)*bg.b + fg.a*fg.b) / 256;
|
||||||
|
return ret.value;
|
||||||
|
}
|
343
libui/vgafont.c
Normal file
343
libui/vgafont.c
Normal file
|
@ -0,0 +1,343 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 2015, 2016, 2017 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* vgafont.c
|
||||||
|
* VGA font rendering.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ioleast.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
|
#include "framebuffer.h"
|
||||||
|
#include "vgafont.h"
|
||||||
|
|
||||||
|
static const wchar_t REPLACEMENT_CHARACTER = 0xFFFD;
|
||||||
|
|
||||||
|
uint8_t font[FONT_CHARSIZE * FONT_NUMCHARS];
|
||||||
|
|
||||||
|
void load_font(void)
|
||||||
|
{
|
||||||
|
int fd = open("/dev/vgafont", O_RDONLY);
|
||||||
|
if ( fd < 0 )
|
||||||
|
err(1, "/dev/vgafont");
|
||||||
|
if ( readall(fd, font, sizeof(font)) != sizeof(font) )
|
||||||
|
err(1, "/dev/vgafont");
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Code_page_437
|
||||||
|
static inline int map_wide_to_vga_font(wchar_t c)
|
||||||
|
{
|
||||||
|
if ( 32 <= c && c < 127 )
|
||||||
|
return (int) c;
|
||||||
|
switch ( c )
|
||||||
|
{
|
||||||
|
case L'☺': return 1;
|
||||||
|
case L'☻': return 2;
|
||||||
|
case L'♥': return 3;
|
||||||
|
case L'♦': return 4;
|
||||||
|
case L'♣': return 5;
|
||||||
|
case L'♠': return 6;
|
||||||
|
case L'•': return 7;
|
||||||
|
case L'◘': return 8;
|
||||||
|
case L'○': return 9;
|
||||||
|
case L'◙': return 10;
|
||||||
|
case L'♂': return 11;
|
||||||
|
case L'♀': return 12;
|
||||||
|
case L'♪': return 13;
|
||||||
|
case L'♬': return 14;
|
||||||
|
case L'☼': return 15;
|
||||||
|
case L'►': return 16;
|
||||||
|
case L'◄': return 17;
|
||||||
|
case L'↕': return 18;
|
||||||
|
case L'‼': return 19;
|
||||||
|
case L'¶': return 20;
|
||||||
|
case L'§': return 21;
|
||||||
|
case L'▬': return 22;
|
||||||
|
case L'↨': return 23;
|
||||||
|
case L'↑': return 24;
|
||||||
|
case L'↓': return 25;
|
||||||
|
case L'→': return 26;
|
||||||
|
case L'←': return 27;
|
||||||
|
case L'∟': return 28;
|
||||||
|
case L'↔': return 29;
|
||||||
|
case L'▲': return 30;
|
||||||
|
case L'▼': return 31;
|
||||||
|
case L'⌂': return 127;
|
||||||
|
case L'Ç': return 128;
|
||||||
|
case L'ü': return 129;
|
||||||
|
case L'é': return 130;
|
||||||
|
case L'â': return 131;
|
||||||
|
case L'ä': return 132;
|
||||||
|
case L'à': return 133;
|
||||||
|
case L'å': return 134;
|
||||||
|
case L'ç': return 135;
|
||||||
|
case L'ê': return 136;
|
||||||
|
case L'ë': return 137;
|
||||||
|
case L'è': return 138;
|
||||||
|
case L'ï': return 139;
|
||||||
|
case L'î': return 140;
|
||||||
|
case L'ì': return 141;
|
||||||
|
case L'Ä': return 142;
|
||||||
|
case L'Å': return 143;
|
||||||
|
case L'É': return 144;
|
||||||
|
case L'æ': return 145;
|
||||||
|
case L'Æ': return 146;
|
||||||
|
case L'ô': return 147;
|
||||||
|
case L'ö': return 148;
|
||||||
|
case L'ò': return 149;
|
||||||
|
case L'û': return 150;
|
||||||
|
case L'ù': return 151;
|
||||||
|
case L'ÿ': return 152;
|
||||||
|
case L'Ö': return 153;
|
||||||
|
case L'Ü': return 154;
|
||||||
|
case L'¢': return 155;
|
||||||
|
case L'£': return 156;
|
||||||
|
case L'¥': return 157;
|
||||||
|
case L'₧': return 158;
|
||||||
|
case L'ƒ': return 159;
|
||||||
|
case L'á': return 160;
|
||||||
|
case L'í': return 161;
|
||||||
|
case L'ó': return 162;
|
||||||
|
case L'ú': return 163;
|
||||||
|
case L'ñ': return 164;
|
||||||
|
case L'Ñ': return 165;
|
||||||
|
case L'ª': return 166;
|
||||||
|
case L'º': return 167;
|
||||||
|
case L'¿': return 168;
|
||||||
|
case L'⌐': return 169;
|
||||||
|
case L'¬': return 170;
|
||||||
|
case L'½': return 171;
|
||||||
|
case L'¼': return 172;
|
||||||
|
case L'¡': return 173;
|
||||||
|
case L'«': return 174;
|
||||||
|
case L'»': return 175;
|
||||||
|
case L'░': return 176;
|
||||||
|
case L'▒': return 177;
|
||||||
|
case L'▓': return 178;
|
||||||
|
case L'│': return 179;
|
||||||
|
case L'┤': return 180;
|
||||||
|
case L'╡': return 181;
|
||||||
|
case L'╢': return 182;
|
||||||
|
case L'╖': return 183;
|
||||||
|
case L'╕': return 184;
|
||||||
|
case L'╣': return 185;
|
||||||
|
case L'║': return 186;
|
||||||
|
case L'╗': return 187;
|
||||||
|
case L'╝': return 188;
|
||||||
|
case L'╜': return 189;
|
||||||
|
case L'╛': return 190;
|
||||||
|
case L'┐': return 191;
|
||||||
|
case L'└': return 192;
|
||||||
|
case L'┴': return 193;
|
||||||
|
case L'┬': return 194;
|
||||||
|
case L'├': return 195;
|
||||||
|
case L'─': return 196;
|
||||||
|
case L'┼': return 197;
|
||||||
|
case L'╞': return 198;
|
||||||
|
case L'╟': return 199;
|
||||||
|
case L'╚': return 200;
|
||||||
|
case L'╔': return 201;
|
||||||
|
case L'╩': return 202;
|
||||||
|
case L'╦': return 203;
|
||||||
|
case L'╠': return 204;
|
||||||
|
case L'═': return 205;
|
||||||
|
case L'╬': return 206;
|
||||||
|
case L'╧': return 207;
|
||||||
|
case L'╨': return 208;
|
||||||
|
case L'╤': return 209;
|
||||||
|
case L'╥': return 210;
|
||||||
|
case L'╙': return 211;
|
||||||
|
case L'╘': return 212;
|
||||||
|
case L'╒': return 213;
|
||||||
|
case L'╓': return 214;
|
||||||
|
case L'╫': return 215;
|
||||||
|
case L'╪': return 216;
|
||||||
|
case L'┘': return 217;
|
||||||
|
case L'┌': return 218;
|
||||||
|
case L'█': return 219;
|
||||||
|
case L'▄': return 220;
|
||||||
|
case L'▌': return 221;
|
||||||
|
case L'▐': return 222;
|
||||||
|
case L'▀': return 223;
|
||||||
|
case L'α': return 224;
|
||||||
|
case L'ß': return 225; /* German sharp S U+00DF */
|
||||||
|
case L'β': return 225; /* Greek lowercase beta U+03B2 */
|
||||||
|
case L'Γ': return 226;
|
||||||
|
case L'π': return 227;
|
||||||
|
case L'Σ': return 228; /* Greek uppercase sigma U+03A3 */
|
||||||
|
case L'∑': return 228; /* n-ary summation sign U+2211 (replacement) */
|
||||||
|
case L'σ': return 229;
|
||||||
|
case L'µ': return 230;
|
||||||
|
case L'τ': return 231;
|
||||||
|
case L'Φ': return 232;
|
||||||
|
case L'Θ': return 233;
|
||||||
|
case L'Ω': return 234;
|
||||||
|
case L'δ': return 235; /* Greek lowercase delta U+03B4 */
|
||||||
|
case L'ð': return 235; /* Icelandic lowercase eth U+00F0 (replacement) */
|
||||||
|
case L'∂': return 235; /* Partial derivative sign U+2202 (replacement) */
|
||||||
|
case L'∞': return 236;
|
||||||
|
case L'φ': return 237; /* Greek lowercase phi U+03C6 */
|
||||||
|
case L'∅': return 237; /* Empty set sign U+2205 (replacement) */
|
||||||
|
case L'ϕ': return 237; /* Greek phi symbol in italics U+03D5 (replacement) */
|
||||||
|
case L'⌀': return 237; /* Diameter sign U+2300 (replacement) */
|
||||||
|
case L'ø': return 237; /* Latin lowercase O with stroke U+00F8 (replacement) */
|
||||||
|
case L'Ø': return 237; /* Latin uppercase O with stroke U+00D8 (replacement) */
|
||||||
|
case L'ε': return 238; /* Greek lowercase epsilon U+03B5 */
|
||||||
|
case L'∈': return 238; /* Element-of sign U+2208 */
|
||||||
|
case L'€': return 238; /* Euro sign U+20AC */
|
||||||
|
case L'∩': return 239;
|
||||||
|
case L'≡': return 240;
|
||||||
|
case L'±': return 241;
|
||||||
|
case L'≥': return 242;
|
||||||
|
case L'≤': return 243;
|
||||||
|
case L'⌠': return 244;
|
||||||
|
case L'⌡': return 245;
|
||||||
|
case L'÷': return 246;
|
||||||
|
case L'≈': return 247;
|
||||||
|
case L'°': return 248;
|
||||||
|
case L'∙': return 249;
|
||||||
|
case L'·': return 250;
|
||||||
|
case L'√': return 251;
|
||||||
|
case L'ⁿ': return 252;
|
||||||
|
case L'²': return 253;
|
||||||
|
case L'■': return 254;
|
||||||
|
default: return 0 <= c && c < 256 ? c : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t font_replacement_character[16] =
|
||||||
|
{
|
||||||
|
0b00000000,
|
||||||
|
0b00010000,
|
||||||
|
0b00111000,
|
||||||
|
0b01000100,
|
||||||
|
0b10111010,
|
||||||
|
0b10111010,
|
||||||
|
0b11110110,
|
||||||
|
0b11101110,
|
||||||
|
0b11101110,
|
||||||
|
0b11111110,
|
||||||
|
0b01101100,
|
||||||
|
0b00101000,
|
||||||
|
0b00010000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline const uint8_t* get_character_font(const uint8_t* font, int remap)
|
||||||
|
{
|
||||||
|
if ( remap < 0 )
|
||||||
|
return font_replacement_character;
|
||||||
|
return font + 16 * remap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_char(struct framebuffer fb, wchar_t wc, uint32_t color)
|
||||||
|
{
|
||||||
|
// TODO: Special case the rendering of some block drawing characters like in
|
||||||
|
// the kernel so pstree looks nice.
|
||||||
|
int remap = map_wide_to_vga_font(wc);
|
||||||
|
const uint8_t* charfont = get_character_font(font, remap);
|
||||||
|
uint32_t buffer[FONT_HEIGHT * (FONT_REALWIDTH+1)];
|
||||||
|
for ( size_t y = 0; y < FONT_HEIGHT; y++ )
|
||||||
|
{
|
||||||
|
uint8_t line_bitmap = charfont[y];
|
||||||
|
for ( size_t x = 0; x < FONT_REALWIDTH; x++ )
|
||||||
|
buffer[y * (FONT_REALWIDTH+1) + x] = line_bitmap & 1U << (7 - x) ? color : 0;
|
||||||
|
uint32_t last_color = 0;
|
||||||
|
if ( 0xB0 <= remap && remap <= 0xDF && (line_bitmap & 1) )
|
||||||
|
last_color = color;
|
||||||
|
buffer[y * (FONT_REALWIDTH+1) + 8] = last_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct framebuffer character_fb;
|
||||||
|
character_fb.xres = FONT_WIDTH;
|
||||||
|
character_fb.yres = FONT_HEIGHT;
|
||||||
|
character_fb.pitch = character_fb.xres;
|
||||||
|
character_fb.buffer = buffer;
|
||||||
|
|
||||||
|
framebuffer_copy_to_framebuffer_blend(fb, character_fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_text(struct framebuffer fb, const char* str, uint32_t color)
|
||||||
|
{
|
||||||
|
mbstate_t ps;
|
||||||
|
memset(&ps, 0, sizeof(ps));
|
||||||
|
size_t column = 0;
|
||||||
|
for ( size_t i = 0; true; i++ )
|
||||||
|
{
|
||||||
|
wchar_t wc;
|
||||||
|
size_t amount = mbrtowc(&wc, str + i, 1, &ps);
|
||||||
|
if ( amount == (size_t) -2 )
|
||||||
|
continue;
|
||||||
|
if ( amount == (size_t) -1 )
|
||||||
|
{
|
||||||
|
wc = REPLACEMENT_CHARACTER;
|
||||||
|
memset(&ps, 0, sizeof(ps));
|
||||||
|
}
|
||||||
|
if ( amount == (size_t) 0 )
|
||||||
|
break;
|
||||||
|
int width = wcwidth(wc);
|
||||||
|
if ( 0 < width )
|
||||||
|
{
|
||||||
|
render_char(framebuffer_crop(fb, FONT_REALWIDTH * column, 0,
|
||||||
|
fb.xres, fb.yres), wc, color);
|
||||||
|
column += width; // TODO: Overflow.
|
||||||
|
}
|
||||||
|
if ( amount == (size_t) -1 && str[i] == '\0' )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t render_text_columns(const char* str)
|
||||||
|
{
|
||||||
|
mbstate_t ps;
|
||||||
|
memset(&ps, 0, sizeof(ps));
|
||||||
|
size_t column = 0;
|
||||||
|
for ( size_t i = 0; true; i++ )
|
||||||
|
{
|
||||||
|
wchar_t wc;
|
||||||
|
size_t amount = mbrtowc(&wc, str + i, 1, &ps);
|
||||||
|
if ( amount == (size_t) -2 )
|
||||||
|
continue;
|
||||||
|
if ( amount == (size_t) -1 )
|
||||||
|
{
|
||||||
|
wc = REPLACEMENT_CHARACTER;
|
||||||
|
memset(&ps, 0, sizeof(ps));
|
||||||
|
}
|
||||||
|
if ( amount == (size_t) 0 )
|
||||||
|
break;
|
||||||
|
int width = wcwidth(wc);
|
||||||
|
if ( 0 < width )
|
||||||
|
column += width; // TODO: Overflow.
|
||||||
|
if ( amount == (size_t) -1 && str[i] == '\0' )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t render_text_width(const char* str)
|
||||||
|
{
|
||||||
|
// TODO: Overflow.
|
||||||
|
return FONT_WIDTH * render_text_columns(str);
|
||||||
|
}
|
2
nyan/.gitignore
vendored
Normal file
2
nyan/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
nyan
|
||||||
|
*.o
|
33
nyan/Makefile
Normal file
33
nyan/Makefile
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
SOFTWARE_MEANT_FOR_SORTIX=1
|
||||||
|
include ../build-aux/platform.mak
|
||||||
|
include ../build-aux/compiler.mak
|
||||||
|
include ../build-aux/dirs.mak
|
||||||
|
|
||||||
|
OPTLEVEL?=-g -O2
|
||||||
|
CFLAGS?=$(OPTLEVEL)
|
||||||
|
|
||||||
|
CFLAGS:=$(CFLAGS) -Wall -Wextra
|
||||||
|
|
||||||
|
PROGRAM=nyan
|
||||||
|
|
||||||
|
OBJS=\
|
||||||
|
nyan.o \
|
||||||
|
|
||||||
|
LIBS:=-lui -ldisplay
|
||||||
|
|
||||||
|
all: $(PROGRAM)
|
||||||
|
|
||||||
|
.PHONY: all install clean
|
||||||
|
|
||||||
|
install: all
|
||||||
|
mkdir -p $(DESTDIR)$(BINDIR)
|
||||||
|
install $(PROGRAM) $(DESTDIR)$(BINDIR)
|
||||||
|
|
||||||
|
$(PROGRAM): $(OBJS)
|
||||||
|
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) $(OBJS) -o $@ $(LIBS)
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(PROGRAM) *.o
|
181
nyan/nyan.c
Normal file
181
nyan/nyan.c
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* nyan.c
|
||||||
|
* Window with animated nyancat.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/keycodes.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <endian.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <error.h>
|
||||||
|
#include <ioleast.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <timespec.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <display.h>
|
||||||
|
#include <nyan.h>
|
||||||
|
|
||||||
|
#include "pixel.h"
|
||||||
|
|
||||||
|
uint32_t WINDOW_ID = 0;
|
||||||
|
uint32_t WINDOW_WIDTH = 0;
|
||||||
|
uint32_t WINDOW_HEIGHT = 0;
|
||||||
|
|
||||||
|
bool need_redraw = true;
|
||||||
|
bool need_show = true;
|
||||||
|
bool need_exit = false;
|
||||||
|
|
||||||
|
void on_disconnect(void* ctx)
|
||||||
|
{
|
||||||
|
(void) ctx;
|
||||||
|
need_exit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_quit(void* ctx, uint32_t window_id)
|
||||||
|
{
|
||||||
|
(void) ctx;
|
||||||
|
if ( window_id != WINDOW_ID )
|
||||||
|
return;
|
||||||
|
need_exit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_resize(void* ctx, uint32_t window_id, uint32_t width, uint32_t height)
|
||||||
|
{
|
||||||
|
(void) ctx;
|
||||||
|
if ( window_id != WINDOW_ID )
|
||||||
|
return;
|
||||||
|
need_redraw = true;
|
||||||
|
WINDOW_WIDTH = width;
|
||||||
|
WINDOW_HEIGHT = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_keyboard(void* ctx, uint32_t window_id, uint32_t codepoint)
|
||||||
|
{
|
||||||
|
(void) ctx;
|
||||||
|
if ( window_id != WINDOW_ID )
|
||||||
|
return;
|
||||||
|
(void) codepoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
(void) argc;
|
||||||
|
(void) argv;
|
||||||
|
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
|
||||||
|
struct display_connection* connection = display_connect_default();
|
||||||
|
if ( !connection && errno == ECONNREFUSED )
|
||||||
|
display_spawn(argc, argv);
|
||||||
|
if ( !connection )
|
||||||
|
error(1, errno, "Could not connect to display server");
|
||||||
|
|
||||||
|
WINDOW_WIDTH = 600;
|
||||||
|
WINDOW_HEIGHT = 600;
|
||||||
|
|
||||||
|
display_create_window(connection, WINDOW_ID);
|
||||||
|
display_resize_window(connection, WINDOW_ID, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
display_title_window(connection, WINDOW_ID, "Nyanyanyanyanyanyanya...");
|
||||||
|
|
||||||
|
struct timespec frame_duration = timespec_make(0, 90 * 1000 * 1000);
|
||||||
|
|
||||||
|
struct timespec last_frame;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &last_frame);
|
||||||
|
|
||||||
|
int frame_num = 0;
|
||||||
|
|
||||||
|
while ( !need_exit )
|
||||||
|
{
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
struct timespec since_last_frame = timespec_sub(now, last_frame);
|
||||||
|
|
||||||
|
if ( !need_redraw && timespec_lt(since_last_frame, frame_duration) )
|
||||||
|
{
|
||||||
|
struct timespec remainder = timespec_sub(frame_duration, since_last_frame);
|
||||||
|
if ( timespec_lt(remainder, timespec_make(0, 10 * 1000 * 1000)) )
|
||||||
|
remainder = timespec_make(0, 10 * 1000 * 1000);
|
||||||
|
nanosleep(&remainder, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( timespec_le(frame_duration, since_last_frame) )
|
||||||
|
{
|
||||||
|
if ( !nyan_frames[++frame_num] )
|
||||||
|
frame_num = 0;
|
||||||
|
need_redraw = true;
|
||||||
|
since_last_frame = timespec_sub(since_last_frame, frame_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( need_redraw )
|
||||||
|
{
|
||||||
|
last_frame = now;
|
||||||
|
|
||||||
|
uint32_t* framebuffer = (uint32_t*) malloc(sizeof(uint32_t) * WINDOW_WIDTH * WINDOW_HEIGHT);
|
||||||
|
|
||||||
|
const char* const* frame = nyan_frames[frame_num];
|
||||||
|
for ( size_t y = 0; y < WINDOW_HEIGHT; y++ )
|
||||||
|
{
|
||||||
|
int yi = y * NYAN_FRAME_HEIGHT / WINDOW_HEIGHT;
|
||||||
|
const char* line = frame[yi];
|
||||||
|
for ( size_t x = 0; x < WINDOW_WIDTH; x++ )
|
||||||
|
{
|
||||||
|
int xi = x * NYAN_FRAME_WIDTH / WINDOW_WIDTH;
|
||||||
|
char elem = line[xi];
|
||||||
|
const uint8_t* cc = nyan_palette[nyan_palette_of_char(elem)];
|
||||||
|
framebuffer[y * WINDOW_WIDTH + x] = make_color_a(cc[0], cc[1], cc[2], cc[3]);;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
display_render_window(connection, WINDOW_ID, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, framebuffer);
|
||||||
|
|
||||||
|
free(framebuffer);
|
||||||
|
|
||||||
|
need_redraw = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( need_show )
|
||||||
|
{
|
||||||
|
display_show_window(connection, WINDOW_ID);
|
||||||
|
need_show = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct display_event_handlers handlers;
|
||||||
|
memset(&handlers, 0, sizeof(handlers));
|
||||||
|
handlers.disconnect_handler = on_disconnect;
|
||||||
|
handlers.quit_handler = on_quit;
|
||||||
|
handlers.resize_handler = on_resize;
|
||||||
|
handlers.keyboard_handler = on_keyboard;
|
||||||
|
while ( display_poll_event(connection, &handlers) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
display_disconnect(connection);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
9
share/init/single-user-gui
Normal file
9
share/init/single-user-gui
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
require base no-await
|
||||||
|
require local no-await
|
||||||
|
|
||||||
|
tty tty1
|
||||||
|
need tty
|
||||||
|
|
||||||
|
cd "$HOME"
|
||||||
|
exit-code-meaning poweroff-reboot
|
||||||
|
exec display
|
8
share/init/sysinstall-gui
Normal file
8
share/init/sysinstall-gui
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
require base no-await
|
||||||
|
require local no-await
|
||||||
|
|
||||||
|
tty tty1
|
||||||
|
need tty
|
||||||
|
|
||||||
|
exec display terminal sysinstall
|
||||||
|
exit-code-meaning poweroff-reboot
|
8
share/init/sysupgrade-gui
Normal file
8
share/init/sysupgrade-gui
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
require base no-await
|
||||||
|
require local no-await
|
||||||
|
|
||||||
|
tty tty1
|
||||||
|
need tty
|
||||||
|
|
||||||
|
exec display terminal sysupgrade
|
||||||
|
exit-code-meaning poweroff-reboot
|
|
@ -241,6 +241,12 @@ Copy the
|
||||||
file (if it exists) into the installation?
|
file (if it exists) into the installation?
|
||||||
.It Sy empty_password Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
|
.It Sy empty_password Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
|
||||||
Allow insecure empty passwords for regular users?
|
Allow insecure empty passwords for regular users?
|
||||||
|
.It Sy enable_gui Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy yes )
|
||||||
|
Enable the
|
||||||
|
.Xr display 1
|
||||||
|
graphical user interface?
|
||||||
|
The choice is remembered in
|
||||||
|
.Xr session 5 .
|
||||||
.It Sy enable_ntpd Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
|
.It Sy enable_ntpd Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
|
||||||
Automatically get time from the network using
|
Automatically get time from the network using
|
||||||
.Xr ntpd 8 ?
|
.Xr ntpd 8 ?
|
||||||
|
|
|
@ -116,6 +116,16 @@ It depends on the
|
||||||
and
|
and
|
||||||
.Sy local
|
.Sy local
|
||||||
daemons.
|
daemons.
|
||||||
|
.It Sy single-user-gui
|
||||||
|
Like
|
||||||
|
.Sy single-user ,
|
||||||
|
but runs the root shell in
|
||||||
|
.Xr terminal 1
|
||||||
|
inside the
|
||||||
|
.Xr display 8
|
||||||
|
graphical user interface environment.
|
||||||
|
This operating system mode is insecure because it boots straight to root access
|
||||||
|
without a password.
|
||||||
.It Sy sysinstall
|
.It Sy sysinstall
|
||||||
Starts the operating system installer.
|
Starts the operating system installer.
|
||||||
This foreground daemon starts the
|
This foreground daemon starts the
|
||||||
|
@ -129,6 +139,16 @@ It depends on the
|
||||||
and
|
and
|
||||||
.Sy local
|
.Sy local
|
||||||
daemons.
|
daemons.
|
||||||
|
.It Sy sysinstall-gui
|
||||||
|
Like
|
||||||
|
.Sy sysinstall ,
|
||||||
|
but runs it in
|
||||||
|
.Xr terminal 1
|
||||||
|
inside the
|
||||||
|
.Xr display 8
|
||||||
|
graphical user interface environment.
|
||||||
|
This operating system mode is insecure because it boots straight to root access
|
||||||
|
without a password.
|
||||||
.It Sy sysupgrade
|
.It Sy sysupgrade
|
||||||
Starts the operating system upgrader.
|
Starts the operating system upgrader.
|
||||||
This foreground daemon starts the
|
This foreground daemon starts the
|
||||||
|
@ -142,6 +162,16 @@ It depends on the
|
||||||
and
|
and
|
||||||
.Sy local
|
.Sy local
|
||||||
daemons.
|
daemons.
|
||||||
|
.It Sy sysupgrade-gui
|
||||||
|
Like
|
||||||
|
.Sy sysupgrade ,
|
||||||
|
but runs it in
|
||||||
|
.Xr terminal 1
|
||||||
|
inside the
|
||||||
|
.Xr display 8
|
||||||
|
graphical user interface environment.
|
||||||
|
This operating system mode is insecure because it boots straight to root access
|
||||||
|
without a password.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The following daemons are provided by the system:
|
The following daemons are provided by the system:
|
||||||
|
|
|
@ -37,6 +37,20 @@ file can be created in any text editor and then made executable:
|
||||||
editor ~/.session
|
editor ~/.session
|
||||||
chmod +x ~/.session
|
chmod +x ~/.session
|
||||||
.Ed
|
.Ed
|
||||||
|
.Ss Graphical User Interface
|
||||||
|
.Xr display 1
|
||||||
|
can be selected as the user's graphical user interface with this executable
|
||||||
|
.Pa ~/.session
|
||||||
|
script:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
#!/bin/sh
|
||||||
|
exec display
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
.Xr display 1
|
||||||
|
will run the
|
||||||
|
.Xr displayrc 5
|
||||||
|
script on startup, which can be used to start programs.
|
||||||
.Ss Trianglix
|
.Ss Trianglix
|
||||||
.Xr trianglix 1
|
.Xr trianglix 1
|
||||||
can be selected as the user's triangle environment with this executable
|
can be selected as the user's triangle environment with this executable
|
||||||
|
|
|
@ -386,6 +386,14 @@ and
|
||||||
.Pp
|
.Pp
|
||||||
Please note that Sortix is not currently secure as a multi-user system and
|
Please note that Sortix is not currently secure as a multi-user system and
|
||||||
filesystem permissions are not enforced.
|
filesystem permissions are not enforced.
|
||||||
|
.Ss Graphical User Interface
|
||||||
|
You will be asked if you want to enable the graphical user interface.
|
||||||
|
If you answer yes, then the system-wide default
|
||||||
|
.Xr session 5
|
||||||
|
is configured to run
|
||||||
|
.Xr display 1
|
||||||
|
upon login.
|
||||||
|
Otherwise the user's preferred shell will be run upon login.
|
||||||
.Ss Network Time
|
.Ss Network Time
|
||||||
You will be asked if you want to enable the Network Time Protocol client
|
You will be asked if you want to enable the Network Time Protocol client
|
||||||
.Xr ntpd 8 ,
|
.Xr ntpd 8 ,
|
||||||
|
|
|
@ -514,6 +514,12 @@ ssh-keygen -t rsa -f liveconfig/root/.ssh/id_rsa -N "" -C "root@$hostname"
|
||||||
Consider omitting the
|
Consider omitting the
|
||||||
.Fl N
|
.Fl N
|
||||||
option and password protect the private key to protect it in the case of a leak.
|
option and password protect the private key to protect it in the case of a leak.
|
||||||
|
.Ss Boot to Console Instead of GUI By Default
|
||||||
|
To customize a release so it boots to a console instead of the GUI:
|
||||||
|
.Bd -literal
|
||||||
|
tix-iso-bootconfig --disable-gui bootconfig
|
||||||
|
tix-iso-add sortix.iso bootconfig
|
||||||
|
.Ed
|
||||||
.Ss Automatic Installation
|
.Ss Automatic Installation
|
||||||
To customize a release so it automatically installs itself per the
|
To customize a release so it automatically installs itself per the
|
||||||
.Xr autoinstall.conf 5 :
|
.Xr autoinstall.conf 5 :
|
||||||
|
|
|
@ -60,13 +60,13 @@ install: all
|
||||||
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-group
|
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-group
|
||||||
|
|
||||||
sysinstall: $(SYSINSTALL_OBJS)
|
sysinstall: $(SYSINSTALL_OBJS)
|
||||||
$(CC) $(SYSINSTALL_OBJS) -o $@ -lmount
|
$(CC) $(SYSINSTALL_OBJS) -o $@ -lmount -ldisplay
|
||||||
|
|
||||||
sysmerge: $(SYSMERGE_OBJS)
|
sysmerge: $(SYSMERGE_OBJS)
|
||||||
$(CC) $(SYSMERGE_OBJS) -o $@ -lmount
|
$(CC) $(SYSMERGE_OBJS) -o $@ -lmount
|
||||||
|
|
||||||
sysupgrade: $(SYSUPGRADE_OBJS)
|
sysupgrade: $(SYSUPGRADE_OBJS)
|
||||||
$(CC) $(SYSUPGRADE_OBJS) -o $@ -lmount
|
$(CC) $(SYSUPGRADE_OBJS) -o $@ -lmount -ldisplay
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -std=gnu11 -c $< -o $@
|
$(CC) $(CFLAGS) $(CPPFLAGS) -std=gnu11 -c $< -o $@
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
|
#include <display.h>
|
||||||
|
|
||||||
#include "autoconf.h"
|
#include "autoconf.h"
|
||||||
#include "execute.h"
|
#include "execute.h"
|
||||||
#include "interactive.h"
|
#include "interactive.h"
|
||||||
|
@ -259,3 +261,15 @@ bool missing_program(const char* program)
|
||||||
warnx("%s: Program is absent", program);
|
warnx("%s: Program is absent", program);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gui_shutdown(int code)
|
||||||
|
{
|
||||||
|
if ( getenv("DISPLAY_SOCKET") )
|
||||||
|
{
|
||||||
|
struct display_connection* connection = display_connect_default();
|
||||||
|
if ( connection )
|
||||||
|
display_shutdown(connection, code);
|
||||||
|
else
|
||||||
|
warn("display_connect_default");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -42,5 +42,6 @@ void password(char* buffer,
|
||||||
size_t buffer_size,
|
size_t buffer_size,
|
||||||
const char* question);
|
const char* question);
|
||||||
bool missing_program(const char* program);
|
bool missing_program(const char* program);
|
||||||
|
void gui_shutdown(int code);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -348,6 +348,7 @@ static bool etc_made = false;
|
||||||
static char etc[] = "/tmp/etc.XXXXXX";
|
static char etc[] = "/tmp/etc.XXXXXX";
|
||||||
static bool fs_made = false;
|
static bool fs_made = false;
|
||||||
static char fs[] = "/tmp/fs.XXXXXX";
|
static char fs[] = "/tmp/fs.XXXXXX";
|
||||||
|
static int exit_gui_code = -1;
|
||||||
|
|
||||||
static void unmount_all_but_root(void)
|
static void unmount_all_but_root(void)
|
||||||
{
|
{
|
||||||
|
@ -376,6 +377,14 @@ void exit_handler(void)
|
||||||
rmdir(fs);
|
rmdir(fs);
|
||||||
if ( etc_made )
|
if ( etc_made )
|
||||||
execute((const char*[]) { "rm", "-rf", etc, NULL }, "");
|
execute((const char*[]) { "rm", "-rf", etc, NULL }, "");
|
||||||
|
if ( 0 <= exit_gui_code )
|
||||||
|
gui_shutdown(exit_gui_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void exit_gui(int code)
|
||||||
|
{
|
||||||
|
exit_gui_code = code;
|
||||||
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cancel_on_sigint(int signum)
|
static void cancel_on_sigint(int signum)
|
||||||
|
@ -544,6 +553,7 @@ int main(void)
|
||||||
|
|
||||||
install_configurationf("upgrade.conf", "a", "src = yes\n");
|
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);
|
||||||
while ( kblayout_setable )
|
while ( kblayout_setable )
|
||||||
{
|
{
|
||||||
|
@ -918,7 +928,7 @@ int main(void)
|
||||||
{
|
{
|
||||||
prompt(input, sizeof(input), "confirm_install",
|
prompt(input, sizeof(input), "confirm_install",
|
||||||
"Install " BRAND_DISTRIBUTION_NAME "? "
|
"Install " BRAND_DISTRIBUTION_NAME "? "
|
||||||
"(yes/no/poweroff/reboot/halt)", "yes");
|
"(yes/no/exit/poweroff/reboot/halt)", "yes");
|
||||||
if ( !strcasecmp(input, "yes") )
|
if ( !strcasecmp(input, "yes") )
|
||||||
break;
|
break;
|
||||||
else if ( !strcasecmp(input, "no") )
|
else if ( !strcasecmp(input, "no") )
|
||||||
|
@ -929,12 +939,14 @@ int main(void)
|
||||||
"'halt' to cancel the installation.\n");
|
"'halt' to cancel the installation.\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if ( !strcasecmp(input, "poweroff") )
|
else if ( !strcasecmp(input, "exit") )
|
||||||
exit(0);
|
exit(0);
|
||||||
|
else if ( !strcasecmp(input, "poweroff") )
|
||||||
|
exit_gui(0);
|
||||||
else if ( !strcasecmp(input, "reboot") )
|
else if ( !strcasecmp(input, "reboot") )
|
||||||
exit(1);
|
exit_gui(1);
|
||||||
else if ( !strcasecmp(input, "halt") )
|
else if ( !strcasecmp(input, "halt") )
|
||||||
exit(2);
|
exit_gui(2);
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1293,6 +1305,27 @@ int main(void)
|
||||||
|
|
||||||
// TODO: Ask if networking should be disabled / enabled.
|
// TODO: Ask if networking should be disabled / enabled.
|
||||||
|
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
prompt(input, sizeof(input), "enable_gui",
|
||||||
|
"Enable graphical user interface?",
|
||||||
|
getenv("DISPLAY_SOCKET") ? "yes" : "no");
|
||||||
|
if ( strcasecmp(input, "no") == 0 )
|
||||||
|
break;
|
||||||
|
if ( strcasecmp(input, "yes") != 0 )
|
||||||
|
continue;
|
||||||
|
if ( !install_configurationf("etc/session", "w",
|
||||||
|
"#!sh\nexec display\n") ||
|
||||||
|
chmod("etc/session", 0755) < 0 )
|
||||||
|
{
|
||||||
|
warn("etc/session");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
text("Added 'exec display' to /etc/session\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
text("\n");
|
||||||
|
|
||||||
if ( !access_or_die("/tix/tixinfo/ntpd", F_OK) )
|
if ( !access_or_die("/tix/tixinfo/ntpd", F_OK) )
|
||||||
{
|
{
|
||||||
text("A Network Time Protocol client (ntpd) has been installed that "
|
text("A Network Time Protocol client (ntpd) has been installed that "
|
||||||
|
@ -1534,14 +1567,16 @@ int main(void)
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
prompt(input, sizeof(input), "finally",
|
prompt(input, sizeof(input), "finally",
|
||||||
"What now? (poweroff/reboot/halt/boot)", "boot");
|
"What now? (exit/poweroff/reboot/halt/boot)", "boot");
|
||||||
if ( !strcasecmp(input, "poweroff") )
|
if ( !strcasecmp(input, "exit") )
|
||||||
exit(0);
|
exit(0);
|
||||||
if ( !strcasecmp(input, "reboot") )
|
else if ( !strcasecmp(input, "poweroff") )
|
||||||
exit(1);
|
exit_gui(0);
|
||||||
if ( !strcasecmp(input, "halt") )
|
else if ( !strcasecmp(input, "reboot") )
|
||||||
exit(2);
|
exit_gui(1);
|
||||||
if ( !strcasecmp(input, "boot") )
|
else if ( !strcasecmp(input, "halt") )
|
||||||
|
exit_gui(2);
|
||||||
|
else if ( !strcasecmp(input, "boot") )
|
||||||
{
|
{
|
||||||
unmount_all_but_root();
|
unmount_all_but_root();
|
||||||
unsetenv("SYSINSTALL_TARGET");
|
unsetenv("SYSINSTALL_TARGET");
|
||||||
|
|
|
@ -73,6 +73,7 @@ static struct mountpoint* mountpoints;
|
||||||
static size_t mountpoints_used;
|
static size_t mountpoints_used;
|
||||||
static bool fs_made = false;
|
static bool fs_made = false;
|
||||||
static char fs[] = "/tmp/fs.XXXXXX";
|
static char fs[] = "/tmp/fs.XXXXXX";
|
||||||
|
static int exit_gui_code = -1;
|
||||||
|
|
||||||
static bool add_installation(struct blockdevice* bdev,
|
static bool add_installation(struct blockdevice* bdev,
|
||||||
struct release* release,
|
struct release* release,
|
||||||
|
@ -329,6 +330,14 @@ void exit_handler(void)
|
||||||
}
|
}
|
||||||
if ( fs_made )
|
if ( fs_made )
|
||||||
rmdir(fs);
|
rmdir(fs);
|
||||||
|
if ( 0 <= exit_gui_code )
|
||||||
|
gui_shutdown(exit_gui_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void exit_gui(int code)
|
||||||
|
{
|
||||||
|
exit_gui_code = code;
|
||||||
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cancel_on_sigint(int signum)
|
static void cancel_on_sigint(int signum)
|
||||||
|
@ -835,7 +844,7 @@ int main(void)
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
promptx(input, sizeof(input), "confirm_upgrade",
|
promptx(input, sizeof(input), "confirm_upgrade",
|
||||||
"Upgrade? (yes/no/poweroff/reboot/halt)", "yes", true);
|
"Upgrade? (yes/no/exit/poweroff/reboot/halt)", "yes", true);
|
||||||
if ( !strcasecmp(input, "yes") )
|
if ( !strcasecmp(input, "yes") )
|
||||||
break;
|
break;
|
||||||
else if ( !strcasecmp(input, "no") )
|
else if ( !strcasecmp(input, "no") )
|
||||||
|
@ -848,12 +857,14 @@ int main(void)
|
||||||
"'halt' or cancel the upgrade.\n");
|
"'halt' or cancel the upgrade.\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if ( !strcasecmp(input, "poweroff") )
|
else if ( !strcasecmp(input, "exit") )
|
||||||
exit(0);
|
exit(0);
|
||||||
|
else if ( !strcasecmp(input, "poweroff") )
|
||||||
|
exit_gui(0);
|
||||||
else if ( !strcasecmp(input, "reboot") )
|
else if ( !strcasecmp(input, "reboot") )
|
||||||
exit(1);
|
exit_gui(1);
|
||||||
else if ( !strcasecmp(input, "halt") )
|
else if ( !strcasecmp(input, "halt") )
|
||||||
exit(2);
|
exit_gui(2);
|
||||||
else if ( !strcasecmp(input, "!") )
|
else if ( !strcasecmp(input, "!") )
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
|
@ -991,12 +1002,14 @@ int main(void)
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
prompt(input, sizeof(input), "finally",
|
prompt(input, sizeof(input), "finally",
|
||||||
"What now? (poweroff/reboot/halt)", "reboot");
|
"What now? (exit/poweroff/reboot/halt)", "reboot");
|
||||||
if ( !strcasecmp(input, "poweroff") )
|
if ( !strcasecmp(input, "exit") )
|
||||||
return 0;
|
exit(0);
|
||||||
if ( !strcasecmp(input, "reboot") )
|
else if ( !strcasecmp(input, "poweroff") )
|
||||||
return 1;
|
exit_gui(0);
|
||||||
if ( !strcasecmp(input, "halt") )
|
else if ( !strcasecmp(input, "reboot") )
|
||||||
return 2;
|
exit_gui(1);
|
||||||
|
else if ( !strcasecmp(input, "halt") )
|
||||||
|
exit_gui(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
terminal/.gitignore
vendored
Normal file
2
terminal/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
terminal
|
||||||
|
*.o
|
33
terminal/Makefile
Normal file
33
terminal/Makefile
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
SOFTWARE_MEANT_FOR_SORTIX=1
|
||||||
|
include ../build-aux/platform.mak
|
||||||
|
include ../build-aux/compiler.mak
|
||||||
|
include ../build-aux/dirs.mak
|
||||||
|
|
||||||
|
OPTLEVEL?=-g -O2
|
||||||
|
CFLAGS?=$(OPTLEVEL)
|
||||||
|
|
||||||
|
CFLAGS:=$(CFLAGS) -Wall -Wextra
|
||||||
|
|
||||||
|
PROGRAM=terminal
|
||||||
|
|
||||||
|
OBJS=\
|
||||||
|
terminal.o \
|
||||||
|
|
||||||
|
LIBS:=-lui -ldisplay
|
||||||
|
|
||||||
|
all: $(PROGRAM)
|
||||||
|
|
||||||
|
.PHONY: all install clean
|
||||||
|
|
||||||
|
install: all
|
||||||
|
mkdir -p $(DESTDIR)$(BINDIR)
|
||||||
|
install $(PROGRAM) $(DESTDIR)$(BINDIR)
|
||||||
|
|
||||||
|
$(PROGRAM): $(OBJS)
|
||||||
|
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) $(OBJS) -o $@ $(LIBS)
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(PROGRAM) *.o
|
283
terminal/palette.h
Normal file
283
terminal/palette.h
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* palette.h
|
||||||
|
* Console color palette, matches the xterm palette with tango colors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PALETTE_H
|
||||||
|
#define PALETTE_H
|
||||||
|
|
||||||
|
static const uint32_t palette[256] =
|
||||||
|
{
|
||||||
|
0x000000,
|
||||||
|
0xcc0000,
|
||||||
|
0x3e9a06,
|
||||||
|
0xc4a000,
|
||||||
|
0x3465a4,
|
||||||
|
0x75507b,
|
||||||
|
0x06989a,
|
||||||
|
0xbfbfbf,
|
||||||
|
0x555753,
|
||||||
|
0xef2929,
|
||||||
|
0x8ae234,
|
||||||
|
0xfce94f,
|
||||||
|
0x729fcf,
|
||||||
|
0xad7fa8,
|
||||||
|
0x34e2e2,
|
||||||
|
0xffffff,
|
||||||
|
0x000000,
|
||||||
|
0x00005f,
|
||||||
|
0x000087,
|
||||||
|
0x0000af,
|
||||||
|
0x0000d7,
|
||||||
|
0x0000ff,
|
||||||
|
0x005f00,
|
||||||
|
0x005f5f,
|
||||||
|
0x005f87,
|
||||||
|
0x005faf,
|
||||||
|
0x005fd7,
|
||||||
|
0x005fff,
|
||||||
|
0x008700,
|
||||||
|
0x00875f,
|
||||||
|
0x008787,
|
||||||
|
0x0087af,
|
||||||
|
0x0087d7,
|
||||||
|
0x0087ff,
|
||||||
|
0x00af00,
|
||||||
|
0x00af5f,
|
||||||
|
0x00af87,
|
||||||
|
0x00afaf,
|
||||||
|
0x00afd7,
|
||||||
|
0x00afff,
|
||||||
|
0x00d700,
|
||||||
|
0x00d75f,
|
||||||
|
0x00d787,
|
||||||
|
0x00d7af,
|
||||||
|
0x00d7d7,
|
||||||
|
0x00d7ff,
|
||||||
|
0x00ff00,
|
||||||
|
0x00ff5f,
|
||||||
|
0x00ff87,
|
||||||
|
0x00ffaf,
|
||||||
|
0x00ffd7,
|
||||||
|
0x00ffff,
|
||||||
|
0x5f0000,
|
||||||
|
0x5f005f,
|
||||||
|
0x5f0087,
|
||||||
|
0x5f00af,
|
||||||
|
0x5f00d7,
|
||||||
|
0x5f00ff,
|
||||||
|
0x5f5f00,
|
||||||
|
0x5f5f5f,
|
||||||
|
0x5f5f87,
|
||||||
|
0x5f5faf,
|
||||||
|
0x5f5fd7,
|
||||||
|
0x5f5fff,
|
||||||
|
0x5f8700,
|
||||||
|
0x5f875f,
|
||||||
|
0x5f8787,
|
||||||
|
0x5f87af,
|
||||||
|
0x5f87d7,
|
||||||
|
0x5f87ff,
|
||||||
|
0x5faf00,
|
||||||
|
0x5faf5f,
|
||||||
|
0x5faf87,
|
||||||
|
0x5fafaf,
|
||||||
|
0x5fafd7,
|
||||||
|
0x5fafff,
|
||||||
|
0x5fd700,
|
||||||
|
0x5fd75f,
|
||||||
|
0x5fd787,
|
||||||
|
0x5fd7af,
|
||||||
|
0x5fd7d7,
|
||||||
|
0x5fd7ff,
|
||||||
|
0x5fff00,
|
||||||
|
0x5fff5f,
|
||||||
|
0x5fff87,
|
||||||
|
0x5fffaf,
|
||||||
|
0x5fffd7,
|
||||||
|
0x5fffff,
|
||||||
|
0x870000,
|
||||||
|
0x87005f,
|
||||||
|
0x870087,
|
||||||
|
0x8700af,
|
||||||
|
0x8700d7,
|
||||||
|
0x8700ff,
|
||||||
|
0x875f00,
|
||||||
|
0x875f5f,
|
||||||
|
0x875f87,
|
||||||
|
0x875faf,
|
||||||
|
0x875fd7,
|
||||||
|
0x875fff,
|
||||||
|
0x878700,
|
||||||
|
0x87875f,
|
||||||
|
0x878787,
|
||||||
|
0x8787af,
|
||||||
|
0x8787d7,
|
||||||
|
0x8787ff,
|
||||||
|
0x87af00,
|
||||||
|
0x87af5f,
|
||||||
|
0x87af87,
|
||||||
|
0x87afaf,
|
||||||
|
0x87afd7,
|
||||||
|
0x87afff,
|
||||||
|
0x87d700,
|
||||||
|
0x87d75f,
|
||||||
|
0x87d787,
|
||||||
|
0x87d7af,
|
||||||
|
0x87d7d7,
|
||||||
|
0x87d7ff,
|
||||||
|
0x87ff00,
|
||||||
|
0x87ff5f,
|
||||||
|
0x87ff87,
|
||||||
|
0x87ffaf,
|
||||||
|
0x87ffd7,
|
||||||
|
0x87ffff,
|
||||||
|
0xaf0000,
|
||||||
|
0xaf005f,
|
||||||
|
0xaf0087,
|
||||||
|
0xaf00af,
|
||||||
|
0xaf00d7,
|
||||||
|
0xaf00ff,
|
||||||
|
0xaf5f00,
|
||||||
|
0xaf5f5f,
|
||||||
|
0xaf5f87,
|
||||||
|
0xaf5faf,
|
||||||
|
0xaf5fd7,
|
||||||
|
0xaf5fff,
|
||||||
|
0xaf8700,
|
||||||
|
0xaf875f,
|
||||||
|
0xaf8787,
|
||||||
|
0xaf87af,
|
||||||
|
0xaf87d7,
|
||||||
|
0xaf87ff,
|
||||||
|
0xafaf00,
|
||||||
|
0xafaf5f,
|
||||||
|
0xafaf87,
|
||||||
|
0xafafaf,
|
||||||
|
0xafafd7,
|
||||||
|
0xafafff,
|
||||||
|
0xafd700,
|
||||||
|
0xafd75f,
|
||||||
|
0xafd787,
|
||||||
|
0xafd7af,
|
||||||
|
0xafd7d7,
|
||||||
|
0xafd7ff,
|
||||||
|
0xafff00,
|
||||||
|
0xafff5f,
|
||||||
|
0xafff87,
|
||||||
|
0xafffaf,
|
||||||
|
0xafffd7,
|
||||||
|
0xafffff,
|
||||||
|
0xd70000,
|
||||||
|
0xd7005f,
|
||||||
|
0xd70087,
|
||||||
|
0xd700af,
|
||||||
|
0xd700d7,
|
||||||
|
0xd700ff,
|
||||||
|
0xd75f00,
|
||||||
|
0xd75f5f,
|
||||||
|
0xd75f87,
|
||||||
|
0xd75faf,
|
||||||
|
0xd75fd7,
|
||||||
|
0xd75fff,
|
||||||
|
0xd78700,
|
||||||
|
0xd7875f,
|
||||||
|
0xd78787,
|
||||||
|
0xd787af,
|
||||||
|
0xd787d7,
|
||||||
|
0xd787ff,
|
||||||
|
0xd7af00,
|
||||||
|
0xd7af5f,
|
||||||
|
0xd7af87,
|
||||||
|
0xd7afaf,
|
||||||
|
0xd7afd7,
|
||||||
|
0xd7afff,
|
||||||
|
0xd7d700,
|
||||||
|
0xd7d75f,
|
||||||
|
0xd7d787,
|
||||||
|
0xd7d7af,
|
||||||
|
0xd7d7d7,
|
||||||
|
0xd7d7ff,
|
||||||
|
0xd7ff00,
|
||||||
|
0xd7ff5f,
|
||||||
|
0xd7ff87,
|
||||||
|
0xd7ffaf,
|
||||||
|
0xd7ffd7,
|
||||||
|
0xd7ffff,
|
||||||
|
0xff0000,
|
||||||
|
0xff005f,
|
||||||
|
0xff0087,
|
||||||
|
0xff00af,
|
||||||
|
0xff00d7,
|
||||||
|
0xff00ff,
|
||||||
|
0xff5f00,
|
||||||
|
0xff5f5f,
|
||||||
|
0xff5f87,
|
||||||
|
0xff5faf,
|
||||||
|
0xff5fd7,
|
||||||
|
0xff5fff,
|
||||||
|
0xff8700,
|
||||||
|
0xff875f,
|
||||||
|
0xff8787,
|
||||||
|
0xff87af,
|
||||||
|
0xff87d7,
|
||||||
|
0xff87ff,
|
||||||
|
0xffaf00,
|
||||||
|
0xffaf5f,
|
||||||
|
0xffaf87,
|
||||||
|
0xffafaf,
|
||||||
|
0xffafd7,
|
||||||
|
0xffafff,
|
||||||
|
0xffd700,
|
||||||
|
0xffd75f,
|
||||||
|
0xffd787,
|
||||||
|
0xffd7af,
|
||||||
|
0xffd7d7,
|
||||||
|
0xffd7ff,
|
||||||
|
0xffff00,
|
||||||
|
0xffff5f,
|
||||||
|
0xffff87,
|
||||||
|
0xffffaf,
|
||||||
|
0xffffd7,
|
||||||
|
0xffffff,
|
||||||
|
0x080808,
|
||||||
|
0x121212,
|
||||||
|
0x1c1c1c,
|
||||||
|
0x262626,
|
||||||
|
0x303030,
|
||||||
|
0x3a3a3a,
|
||||||
|
0x444444,
|
||||||
|
0x4e4e4e,
|
||||||
|
0x585858,
|
||||||
|
0x626262,
|
||||||
|
0x6c6c6c,
|
||||||
|
0x767676,
|
||||||
|
0x808080,
|
||||||
|
0x8a8a8a,
|
||||||
|
0x949494,
|
||||||
|
0x9e9e9e,
|
||||||
|
0xa8a8a8,
|
||||||
|
0xb2b2b2,
|
||||||
|
0xbcbcbc,
|
||||||
|
0xc6c6c6,
|
||||||
|
0xd0d0d0,
|
||||||
|
0xdadada,
|
||||||
|
0xe4e4e4,
|
||||||
|
0xeeeeee,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
1292
terminal/terminal.c
Normal file
1292
terminal/terminal.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -23,6 +23,7 @@ default=
|
||||||
directory=
|
directory=
|
||||||
enable_append_title=true
|
enable_append_title=true
|
||||||
enable_dhclient=
|
enable_dhclient=
|
||||||
|
enable_gui=
|
||||||
enable_network_drivers=
|
enable_network_drivers=
|
||||||
enable_ntpd=
|
enable_ntpd=
|
||||||
enable_src=
|
enable_src=
|
||||||
|
@ -56,12 +57,14 @@ for argument do
|
||||||
--default) previous_option=default ;;
|
--default) previous_option=default ;;
|
||||||
--disable-append-title) enable_append_title=false ;;
|
--disable-append-title) enable_append_title=false ;;
|
||||||
--disable-dhclient) enable_dhclient=false ;;
|
--disable-dhclient) enable_dhclient=false ;;
|
||||||
|
--disable-gui) enable_gui=false ;;
|
||||||
--disable-network-drivers) enable_network_drivers=false ;;
|
--disable-network-drivers) enable_network_drivers=false ;;
|
||||||
--disable-ntpd) enable_ntpd=false ;;
|
--disable-ntpd) enable_ntpd=false ;;
|
||||||
--disable-src) enable_src=false ;;
|
--disable-src) enable_src=false ;;
|
||||||
--disable-sshd) enable_sshd=false ;;
|
--disable-sshd) enable_sshd=false ;;
|
||||||
--enable-append-title) enable_append_title=true ;;
|
--enable-append-title) enable_append_title=true ;;
|
||||||
--enable-dhclient) enable_dhclient=true ;;
|
--enable-dhclient) enable_dhclient=true ;;
|
||||||
|
--enable-gui) enable_gui=true ;;
|
||||||
--enable-network-drivers) enable_network_drivers=true ;;
|
--enable-network-drivers) enable_network_drivers=true ;;
|
||||||
--enable-ntpd) enable_ntpd=true ;;
|
--enable-ntpd) enable_ntpd=true ;;
|
||||||
--enable-src) enable_src=true ;;
|
--enable-src) enable_src=true ;;
|
||||||
|
@ -162,6 +165,7 @@ mkdir -p -- "$directory/boot/grub"
|
||||||
echo "title_sysupgrade='***AUTOMATIC UPGRADE***'"
|
echo "title_sysupgrade='***AUTOMATIC UPGRADE***'"
|
||||||
fi
|
fi
|
||||||
print_enable_default_bool "$enable_dhclient" dhclient dhclient
|
print_enable_default_bool "$enable_dhclient" dhclient dhclient
|
||||||
|
print_enable_default_bool "$enable_gui" gui gui
|
||||||
print_enable_default "$enable_network_drivers" network_drivers network-drivers
|
print_enable_default "$enable_network_drivers" network_drivers network-drivers
|
||||||
print_enable_default_bool "$enable_src" src src
|
print_enable_default_bool "$enable_src" src src
|
||||||
print_enable_default_bool "$enable_sshd" sshd sshd
|
print_enable_default_bool "$enable_sshd" sshd sshd
|
||||||
|
|
|
@ -10,12 +10,14 @@
|
||||||
.Op Fl \-default Ns = Ns Ar default-boot-menu-option
|
.Op Fl \-default Ns = Ns Ar default-boot-menu-option
|
||||||
.Op Fl \-disable-append-title
|
.Op Fl \-disable-append-title
|
||||||
.Op Fl \-disable-dhclient
|
.Op Fl \-disable-dhclient
|
||||||
|
.Op Fl \-disable-gui
|
||||||
.Op Fl \-disable-network-drivers
|
.Op Fl \-disable-network-drivers
|
||||||
.Op Fl \-disable-ntpd
|
.Op Fl \-disable-ntpd
|
||||||
.Op Fl \-disable-src
|
.Op Fl \-disable-src
|
||||||
.Op Fl \-disable-sshd
|
.Op Fl \-disable-sshd
|
||||||
.Op Fl \-enable-append-title
|
.Op Fl \-enable-append-title
|
||||||
.Op Fl \-enable-dhclient
|
.Op Fl \-enable-dhclient
|
||||||
|
.Op Fl \-enable-gui
|
||||||
.Op Fl \-enable-network-drivers
|
.Op Fl \-enable-network-drivers
|
||||||
.Op Fl \-enable-ntpd
|
.Op Fl \-enable-ntpd
|
||||||
.Op Fl \-enable-src
|
.Op Fl \-enable-src
|
||||||
|
@ -105,6 +107,16 @@ GRUB variable to
|
||||||
causing the bootloader to load additional configuration that turns off the
|
causing the bootloader to load additional configuration that turns off the
|
||||||
.Xr dhclient 8
|
.Xr dhclient 8
|
||||||
daemon on boot.
|
daemon on boot.
|
||||||
|
.It Fl \-disable-gui
|
||||||
|
Disable the GUI by setting the
|
||||||
|
.Sy enable_gui
|
||||||
|
GRUB variable to
|
||||||
|
.Sy false ,
|
||||||
|
which makes the bootloader configuration not append
|
||||||
|
.Sy -gui
|
||||||
|
to the requested
|
||||||
|
.Xr init 8
|
||||||
|
target.
|
||||||
.It Fl \-disable-network-drivers
|
.It Fl \-disable-network-drivers
|
||||||
Disable network drivers by setting the
|
Disable network drivers by setting the
|
||||||
.Sy enable_network_drivers
|
.Sy enable_network_drivers
|
||||||
|
@ -152,6 +164,16 @@ GRUB variable to
|
||||||
selecting the default behavior of starting the
|
selecting the default behavior of starting the
|
||||||
.Xr dhclient 8
|
.Xr dhclient 8
|
||||||
daemon.
|
daemon.
|
||||||
|
.It Fl \-enable-gui
|
||||||
|
Enable the GUI by setting the
|
||||||
|
.Sy enable_gui
|
||||||
|
GRUB variable to
|
||||||
|
.Sy true ,
|
||||||
|
which makes the bootloader configuration append
|
||||||
|
.Sy -gui
|
||||||
|
to the requested
|
||||||
|
.Xr init 8
|
||||||
|
target.
|
||||||
.It Fl \-enable-network-drivers
|
.It Fl \-enable-network-drivers
|
||||||
Enable network drivers by setting the
|
Enable network drivers by setting the
|
||||||
.Sy enable_network_drivers
|
.Sy enable_network_drivers
|
||||||
|
@ -350,6 +372,12 @@ automatically using the SSH configuration found in the liveconfig directory:
|
||||||
tix-iso-bootconfig --liveconfig=liveconfig --enable-sshd bootconfig
|
tix-iso-bootconfig --liveconfig=liveconfig --enable-sshd bootconfig
|
||||||
tix-iso-add sortix.iso bootconfig
|
tix-iso-add sortix.iso bootconfig
|
||||||
.Ed
|
.Ed
|
||||||
|
.Ss Boot to Console Instead of GUI By Default
|
||||||
|
To customize a release so it boots to a console instead of the GUI:
|
||||||
|
.Bd -literal
|
||||||
|
tix-iso-bootconfig --disable-gui bootconfig
|
||||||
|
tix-iso-add sortix.iso bootconfig
|
||||||
|
.Ed
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr xorriso 1 ,
|
.Xr xorriso 1 ,
|
||||||
.Xr kernel 7 ,
|
.Xr kernel 7 ,
|
||||||
|
|
|
@ -15,7 +15,7 @@ LIBS:=-ldispd
|
||||||
|
|
||||||
all: $(BINARY)
|
all: $(BINARY)
|
||||||
|
|
||||||
.PHONY: all install uninstall clean
|
.PHONY: all install clean
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
mkdir -p $(DESTDIR)$(BINDIR)
|
mkdir -p $(DESTDIR)$(BINDIR)
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
|
|
||||||
static void suggest_logout(void)
|
static void suggest_logout(void)
|
||||||
{
|
{
|
||||||
|
if ( getenv("DISPLAY_SOCKET") )
|
||||||
|
fprintf(stderr, " Pressing Ctrl-Alt-Del to exit desktop.\n");
|
||||||
|
else
|
||||||
fprintf(stderr, " Exiting your shell normally to logout.\n");
|
fprintf(stderr, " Exiting your shell normally to logout.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
video-player/.gitignore
vendored
Normal file
1
video-player/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
video-player
|
26
video-player/Makefile
Normal file
26
video-player/Makefile
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
include ../build-aux/compiler.mak
|
||||||
|
include ../build-aux/version.mak
|
||||||
|
include ../build-aux/dirs.mak
|
||||||
|
|
||||||
|
OPTLEVEL?=-g -O2
|
||||||
|
CXXFLAGS?=$(OPTLEVEL)
|
||||||
|
|
||||||
|
CPPFLAGS:=$(CPPFLAGS)
|
||||||
|
CXXFLAGS:=$(CXXFLAGS) -Wall -Wextra -fno-exceptions -fno-rtti -fcheck-new
|
||||||
|
|
||||||
|
BINARY:=video-player
|
||||||
|
LIBS:=-lswscale -lavformat -lavcodec -lavutil -ldisplay
|
||||||
|
|
||||||
|
all: $(BINARY)
|
||||||
|
|
||||||
|
.PHONY: all install clean
|
||||||
|
|
||||||
|
%: %.cpp
|
||||||
|
$(CXX) -std=gnu++11 $(CPPFLAGS) $(CXXFLAGS) $< -o $@ $(LIBS)
|
||||||
|
|
||||||
|
install: all
|
||||||
|
mkdir -p $(DESTDIR)$(BINDIR)
|
||||||
|
install $(BINARY) $(DESTDIR)$(BINDIR)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(BINARY)
|
5
video-player/tixbuildinfo
Normal file
5
video-player/tixbuildinfo
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
tix.version=1
|
||||||
|
tix.class=srctix
|
||||||
|
pkg.name=video-player
|
||||||
|
pkg.build-libraries=libav
|
||||||
|
pkg.build-system=sortix-usual-makefile
|
274
video-player/video-player.cpp
Normal file
274
video-player/video-player.cpp
Normal file
|
@ -0,0 +1,274 @@
|
||||||
|
#define __STDC_CONSTANT_MACROS
|
||||||
|
#define __STDC_LIMIT_MACROS
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <error.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <timespec.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <display.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libswscale/swscale.h>
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
uint32_t WINDOW_ID = 0;
|
||||||
|
uint32_t WINDOW_WIDTH = 0;
|
||||||
|
uint32_t WINDOW_HEIGHT = 0;
|
||||||
|
|
||||||
|
bool need_show = true;
|
||||||
|
bool need_exit = false;
|
||||||
|
|
||||||
|
uint32_t* framebuffer = NULL;
|
||||||
|
size_t framebuffer_size = 0;
|
||||||
|
|
||||||
|
void on_disconnect(void*)
|
||||||
|
{
|
||||||
|
need_exit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_quit(void*, uint32_t window_id)
|
||||||
|
{
|
||||||
|
if ( window_id != WINDOW_ID )
|
||||||
|
return;
|
||||||
|
need_exit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_resize(void*, uint32_t window_id, uint32_t width, uint32_t height)
|
||||||
|
{
|
||||||
|
if ( window_id != WINDOW_ID )
|
||||||
|
return;
|
||||||
|
WINDOW_WIDTH = width;
|
||||||
|
WINDOW_HEIGHT = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_keyboard(void*, uint32_t window_id, uint32_t)
|
||||||
|
{
|
||||||
|
if ( window_id != WINDOW_ID )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DisplayVideoFrame(AVFrame* frame, struct display_connection* connection)
|
||||||
|
{
|
||||||
|
size_t framebuffer_needed = sizeof(uint32_t) * WINDOW_WIDTH * WINDOW_HEIGHT;
|
||||||
|
if ( framebuffer_size != framebuffer_needed )
|
||||||
|
{
|
||||||
|
framebuffer = (uint32_t*) realloc(framebuffer, framebuffer_size = framebuffer_needed);
|
||||||
|
memset(framebuffer, 255, framebuffer_needed);
|
||||||
|
}
|
||||||
|
|
||||||
|
SwsContext* sws_ctx = sws_getContext(frame->width, frame->height,
|
||||||
|
(PixelFormat) frame->format, WINDOW_WIDTH,
|
||||||
|
WINDOW_HEIGHT, PIX_FMT_RGB32, SWS_BILINEAR,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
assert(sws_ctx);
|
||||||
|
|
||||||
|
uint8_t* data_arr[1] = { (uint8_t*) framebuffer };
|
||||||
|
int stride_arr[1] = { (int) (sizeof(framebuffer[0]) * WINDOW_WIDTH) };
|
||||||
|
sws_scale(sws_ctx, frame->data, frame->linesize, 0, frame->height, data_arr,
|
||||||
|
stride_arr);
|
||||||
|
|
||||||
|
sws_freeContext(sws_ctx);
|
||||||
|
|
||||||
|
display_render_window(connection, WINDOW_ID, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, framebuffer);
|
||||||
|
|
||||||
|
struct display_event_handlers handlers;
|
||||||
|
memset(&handlers, 0, sizeof(handlers));
|
||||||
|
handlers.disconnect_handler = on_disconnect;
|
||||||
|
handlers.quit_handler = on_quit;
|
||||||
|
handlers.resize_handler = on_resize;
|
||||||
|
handlers.keyboard_handler = on_keyboard;
|
||||||
|
while ( display_poll_event(connection, &handlers) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayVideo(const char* path, struct display_connection* connection)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
int av_error;
|
||||||
|
AVFormatContext* format_ctx = NULL;
|
||||||
|
int video_stream_id;
|
||||||
|
int audio_stream_id;
|
||||||
|
AVStream* video_stream = NULL;
|
||||||
|
AVStream* audio_stream = NULL;
|
||||||
|
AVCodec* video_codec = NULL;
|
||||||
|
AVCodec* audio_codec = NULL;
|
||||||
|
AVCodecContext* video_codec_ctx = NULL;
|
||||||
|
AVCodecContext* audio_codec_ctx = NULL;
|
||||||
|
AVFrame* video_frame = NULL;
|
||||||
|
AVFrame* audio_frame = NULL;
|
||||||
|
AVPacket packet;
|
||||||
|
|
||||||
|
if ( (av_error = avformat_open_input(&format_ctx, path, NULL, NULL)) < 0 )
|
||||||
|
{
|
||||||
|
error(0, 0, "%s: cannot open: %i\n", path, av_error);
|
||||||
|
goto cleanup_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (av_error = avformat_find_stream_info(format_ctx, NULL)) < 0 )
|
||||||
|
{
|
||||||
|
error(0, 0, "%s: avformat_find_stream_info: %i\n", path, av_error);
|
||||||
|
goto cleanup_input;
|
||||||
|
}
|
||||||
|
|
||||||
|
video_stream_id = av_find_best_stream(format_ctx, AVMEDIA_TYPE_VIDEO, -1,
|
||||||
|
-1, &video_codec, 0);
|
||||||
|
audio_stream_id = av_find_best_stream(format_ctx, AVMEDIA_TYPE_AUDIO, -1,
|
||||||
|
-1, &audio_codec, 0);
|
||||||
|
|
||||||
|
if ( 0 <= video_stream_id )
|
||||||
|
video_stream = format_ctx->streams[video_stream_id];
|
||||||
|
if ( 0 <= audio_stream_id )
|
||||||
|
audio_stream = format_ctx->streams[audio_stream_id];
|
||||||
|
|
||||||
|
if ( !video_stream )
|
||||||
|
{
|
||||||
|
error(0, 0, "%s: no video stream found\n", path);
|
||||||
|
goto cleanup_input;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( video_codec && !(video_codec_ctx = avcodec_alloc_context3(video_codec)))
|
||||||
|
goto cleanup_input;
|
||||||
|
if ( audio_codec && !(audio_codec_ctx = avcodec_alloc_context3(audio_codec)))
|
||||||
|
goto cleanup_video_codec_ctx;
|
||||||
|
|
||||||
|
if ( video_codec_ctx )
|
||||||
|
{
|
||||||
|
video_codec_ctx->extradata = video_stream->codec->extradata;
|
||||||
|
video_codec_ctx->extradata_size = video_stream->codec->extradata_size;
|
||||||
|
if ( (av_error = avcodec_open2(video_codec_ctx, NULL, NULL)) < 0 )
|
||||||
|
goto cleanup_audio_codec_ctx;
|
||||||
|
}
|
||||||
|
if ( audio_codec_ctx )
|
||||||
|
{
|
||||||
|
audio_codec_ctx->extradata = audio_stream->codec->extradata;
|
||||||
|
audio_codec_ctx->extradata_size = audio_stream->codec->extradata_size;
|
||||||
|
if ( (av_error = avcodec_open2(audio_codec_ctx, NULL, NULL)) < 0 )
|
||||||
|
goto cleanup_audio_codec_ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !(video_frame = avcodec_alloc_frame()) )
|
||||||
|
goto cleanup_audio_codec_ctx;
|
||||||
|
if ( !(audio_frame = avcodec_alloc_frame()) )
|
||||||
|
goto cleanup_video_frame;
|
||||||
|
|
||||||
|
struct timespec next_frame_at;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &next_frame_at);
|
||||||
|
|
||||||
|
while ( !need_exit && 0 <= (av_error = av_read_frame(format_ctx, &packet)) )
|
||||||
|
{
|
||||||
|
int stream_index = packet.stream_index;
|
||||||
|
int packet_off = 0;
|
||||||
|
while ( stream_index == video_stream->index && packet_off < packet.size )
|
||||||
|
{
|
||||||
|
packet.data += packet_off; packet.size -= packet_off;
|
||||||
|
int got_frame;
|
||||||
|
int bytes_used = avcodec_decode_video2(video_codec_ctx, video_frame,
|
||||||
|
&got_frame, &packet);
|
||||||
|
packet.data -= packet_off; packet.size += packet_off;
|
||||||
|
|
||||||
|
if ( (av_error = bytes_used) < 0 )
|
||||||
|
goto break_decode_loop;
|
||||||
|
if ( !got_frame )
|
||||||
|
break;
|
||||||
|
packet_off += bytes_used;
|
||||||
|
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
while ( timespec_le(now, next_frame_at) )
|
||||||
|
{
|
||||||
|
struct timespec left = timespec_sub(next_frame_at, now);
|
||||||
|
clock_nanosleep(CLOCK_MONOTONIC, 0, &left, NULL);
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayVideoFrame(video_frame, connection);
|
||||||
|
|
||||||
|
uintmax_t usecs = video_codec_ctx->ticks_per_frame * 1000000 *
|
||||||
|
video_codec_ctx->time_base.num /
|
||||||
|
video_codec_ctx->time_base.den;
|
||||||
|
next_frame_at = timespec_add(next_frame_at, timespec_make(0, usecs * 1000));
|
||||||
|
}
|
||||||
|
while ( stream_index == audio_stream->index && packet_off < packet.size )
|
||||||
|
{
|
||||||
|
// TODO: Add sound support when an backend is available.
|
||||||
|
packet_off = packet.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break_decode_loop:
|
||||||
|
|
||||||
|
// TODO: Determine whether the are here because of EOF or whether an error
|
||||||
|
// occured and we need to print an error.
|
||||||
|
// TODO: Do we need to clean up the last packet or does the av_read_frame
|
||||||
|
// function do that for us upon error?
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
goto cleanup_audio_frame;
|
||||||
|
cleanup_audio_frame:
|
||||||
|
if ( audio_frame )
|
||||||
|
#if 55 <= LIBAVCODEC_VERSION_MAJOR
|
||||||
|
avcodec_free_frame(&audio_frame);
|
||||||
|
#else
|
||||||
|
av_free(audio_frame);
|
||||||
|
#endif
|
||||||
|
cleanup_video_frame:
|
||||||
|
if ( video_frame )
|
||||||
|
#if 55 <= LIBAVCODEC_VERSION_MAJOR
|
||||||
|
avcodec_free_frame(&video_frame);
|
||||||
|
#else
|
||||||
|
av_free(video_frame);
|
||||||
|
#endif
|
||||||
|
cleanup_audio_codec_ctx:
|
||||||
|
if ( audio_codec_ctx )
|
||||||
|
{
|
||||||
|
audio_codec_ctx->extradata = NULL;
|
||||||
|
avcodec_close(audio_codec_ctx);
|
||||||
|
av_free(audio_codec_ctx);
|
||||||
|
}
|
||||||
|
cleanup_video_codec_ctx:
|
||||||
|
if ( video_codec_ctx )
|
||||||
|
{
|
||||||
|
video_codec_ctx->extradata = NULL;
|
||||||
|
avcodec_close(video_codec_ctx);
|
||||||
|
av_free(video_codec_ctx);
|
||||||
|
}
|
||||||
|
cleanup_input:
|
||||||
|
avformat_close_input(&format_ctx);
|
||||||
|
cleanup_done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
struct display_connection* connection = display_connect_default();
|
||||||
|
if ( !connection && errno == ECONNREFUSED )
|
||||||
|
display_spawn(argc, argv);
|
||||||
|
if ( !connection )
|
||||||
|
error(1, errno, "Could not connect to display server");
|
||||||
|
|
||||||
|
av_register_all();
|
||||||
|
|
||||||
|
WINDOW_WIDTH = 800;
|
||||||
|
WINDOW_HEIGHT = 450;
|
||||||
|
|
||||||
|
display_create_window(connection, WINDOW_ID);
|
||||||
|
display_resize_window(connection, WINDOW_ID, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
display_show_window(connection, WINDOW_ID);
|
||||||
|
|
||||||
|
for ( int i = 1; i < argc; i++ )
|
||||||
|
{
|
||||||
|
display_title_window(connection, WINDOW_ID, argv[i]);
|
||||||
|
if ( !PlayVideo(argv[i], connection) )
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_disconnect(connection);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue