Add display server.
This commit is contained in:
parent
0305241095
commit
4a455be70a
60 changed files with 6847 additions and 123 deletions
5
Makefile
5
Makefile
|
@ -7,12 +7,15 @@ MODULES=\
|
|||
libc \
|
||||
libm \
|
||||
dispd \
|
||||
libdisplay \
|
||||
libmount \
|
||||
libui \
|
||||
bench \
|
||||
carray \
|
||||
checksum \
|
||||
dhclient \
|
||||
disked \
|
||||
display \
|
||||
dnsconfig \
|
||||
editor \
|
||||
ext \
|
||||
|
@ -26,12 +29,14 @@ kblayout \
|
|||
kblayout-compiler \
|
||||
login \
|
||||
mkinitrd \
|
||||
nyan \
|
||||
ping \
|
||||
regress \
|
||||
rw \
|
||||
sf \
|
||||
sh \
|
||||
sysinstall \
|
||||
terminal \
|
||||
tix \
|
||||
trianglix \
|
||||
update-initrd \
|
||||
|
|
|
@ -195,6 +195,7 @@ fi
|
|||
set enable_src=true
|
||||
set enable_network_drivers=
|
||||
set enable_dhclient=true
|
||||
set enable_gui=true
|
||||
set enable_ntpd=false
|
||||
set enable_sshd=false
|
||||
|
||||
|
@ -208,6 +209,7 @@ export no_random_seed
|
|||
export enable_src
|
||||
export enable_network_drivers
|
||||
export enable_dhclient
|
||||
export enable_gui
|
||||
export enable_ntpd
|
||||
export enable_sshd
|
||||
EOF
|
||||
|
@ -396,10 +398,11 @@ menuentry() {
|
|||
echo
|
||||
printf "menuentry \"Sortix (%s)\" {\n" "$1"
|
||||
if [ -n "$2" ]; then
|
||||
printf " load_sortix %s\n" "$2"
|
||||
#printf " load_sortix '"
|
||||
#printf '%s' "$2" | sed "s,','\\'',g"
|
||||
#printf "'\n"
|
||||
printf " if \$enable_gui; then\n"
|
||||
printf " load_sortix %s-gui\n" "$2"
|
||||
printf " else\n"
|
||||
printf " load_sortix %s\n" "$2"
|
||||
printf " fi\n"
|
||||
else
|
||||
printf " load_sortix\n"
|
||||
fi
|
||||
|
@ -412,7 +415,7 @@ menu_title="\$base_menu_title"
|
|||
hook_menu_pre
|
||||
EOF
|
||||
|
||||
menuentry "live environment" '-- /sbin/init'
|
||||
menuentry "live environment" '-- /sbin/init --target=single-user'
|
||||
menuentry "new installation" '-- /sbin/init --target=sysinstall'
|
||||
menuentry "upgrade existing installation" '-- /sbin/init --target=sysupgrade'
|
||||
|
||||
|
@ -440,6 +443,18 @@ menu_title="\$base_menu_title - Advanced Options"
|
|||
|
||||
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
|
||||
menuentry "Disable loading source code" {
|
||||
enable_src=false
|
||||
|
|
|
@ -151,6 +151,7 @@ EOF
|
|||
tix-iso-bootconfig \
|
||||
--random-seed \
|
||||
--timeout=0 \
|
||||
--disable-gui \
|
||||
--liveconfig=liveconfig \
|
||||
bootconfig
|
||||
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 \
|
||||
aquatinspitz \
|
||||
|
||||
LIBS:=-ldispd
|
||||
LIBS:=-ldispd -ldisplay
|
||||
|
||||
all: $(BINARIES)
|
||||
|
||||
|
|
|
@ -36,7 +36,11 @@
|
|||
#include <timespec.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()
|
||||
{
|
||||
|
@ -60,7 +64,7 @@ static inline float RandomAngle()
|
|||
|
||||
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;
|
||||
|
@ -110,31 +114,6 @@ bool pop_is_key_just_down(int abskbkey)
|
|||
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 yres;
|
||||
static size_t bpp;
|
||||
|
@ -1143,25 +1122,85 @@ void Render()
|
|||
obj->Render();
|
||||
}
|
||||
}
|
||||
void RunFrame(struct dispd_window* window)
|
||||
|
||||
void on_disconnect(void*)
|
||||
{
|
||||
struct dispd_framebuffer* fb = dispd_begin_render(window);
|
||||
if ( !fb )
|
||||
{
|
||||
error(0, 0, "unable to begin rendering dispd window");
|
||||
gamerunning = false;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void on_quit(void*, uint32_t)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
xres = dispd_get_framebuffer_width(fb);
|
||||
yres = dispd_get_framebuffer_height(fb);
|
||||
bpp = dispd_get_framebuffer_format(fb);
|
||||
linesize = dispd_get_framebuffer_pitch(fb) / (bpp / 8);
|
||||
framesize = dispd_get_framebuffer_pitch(fb) * yres;
|
||||
buf = (uint32_t*) dispd_get_framebuffer_data(fb);
|
||||
FetchKeyboardInput();
|
||||
|
||||
GameLogic();
|
||||
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()
|
||||
|
@ -1172,64 +1211,24 @@ void InitGame()
|
|||
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[])
|
||||
{
|
||||
if ( !isatty(0) )
|
||||
error(1, errno, "standard input");
|
||||
if ( tcgetattr(0, &saved_tio) < 0 )
|
||||
error(1, errno, "tcsetattr: standard input");
|
||||
if ( atexit(restore_terminal_on_exit) != 0 )
|
||||
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);
|
||||
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");
|
||||
|
||||
if ( !dispd_initialize(&argc, &argv) )
|
||||
error(1, 0, "couldn't initialize dispd library");
|
||||
struct dispd_session* session = dispd_attach_default_session();
|
||||
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");
|
||||
display_create_window(connection, WINDOW_ID);
|
||||
display_resize_window(connection, WINDOW_ID, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
display_title_window(connection, WINDOW_ID, "Asteroids");
|
||||
|
||||
InitGame();
|
||||
gamerunning = true;
|
||||
for ( framenum = 0; gamerunning; framenum++ )
|
||||
RunFrame(window);
|
||||
RunFrame(connection);
|
||||
|
||||
dispd_destroy_window(window);
|
||||
dispd_detach_session(session);
|
||||
display_disconnect(connection);
|
||||
|
||||
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
|
|
@ -116,6 +116,16 @@ It depends on the
|
|||
and
|
||||
.Sy local
|
||||
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
|
||||
Starts the operating system installer.
|
||||
This foreground daemon starts the
|
||||
|
@ -129,6 +139,16 @@ It depends on the
|
|||
and
|
||||
.Sy local
|
||||
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
|
||||
Starts the operating system upgrader.
|
||||
This foreground daemon starts the
|
||||
|
@ -142,6 +162,16 @@ It depends on the
|
|||
and
|
||||
.Sy local
|
||||
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
|
||||
.Pp
|
||||
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
|
||||
chmod +x ~/.session
|
||||
.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
|
||||
.Xr trianglix 1
|
||||
can be selected as the user's triangle environment with this executable
|
||||
|
|
|
@ -385,6 +385,14 @@ and
|
|||
.Pp
|
||||
Please note that Sortix is not currently secure as a multi-user system and
|
||||
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
|
||||
You will be asked if you want to enable the Network Time Protocol client
|
||||
.Xr ntpd 8 ,
|
||||
|
|
|
@ -513,6 +513,12 @@ ssh-keygen -t rsa -f liveconfig/root/.ssh/id_rsa -N "" -C "root@$hostname"
|
|||
Consider omitting the
|
||||
.Fl N
|
||||
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
|
||||
.Sh SEE ALSO
|
||||
.Xr xorriso 1 ,
|
||||
.Xr development 7 ,
|
||||
|
|
|
@ -59,13 +59,13 @@ install: all
|
|||
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-group
|
||||
|
||||
sysinstall: $(SYSINSTALL_OBJS)
|
||||
$(CC) $(SYSINSTALL_OBJS) -o $@ -lmount
|
||||
$(CC) $(SYSINSTALL_OBJS) -o $@ -lmount -ldisplay
|
||||
|
||||
sysmerge: $(SYSMERGE_OBJS)
|
||||
$(CC) $(SYSMERGE_OBJS) -o $@ -lmount
|
||||
|
||||
sysupgrade: $(SYSUPGRADE_OBJS)
|
||||
$(CC) $(SYSUPGRADE_OBJS) -o $@ -lmount
|
||||
$(CC) $(SYSUPGRADE_OBJS) -o $@ -lmount -ldisplay
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -std=gnu11 -c $< -o $@
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include <termios.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <display.h>
|
||||
|
||||
#include "execute.h"
|
||||
#include "interactive.h"
|
||||
|
||||
|
@ -237,3 +239,15 @@ bool missing_program(const char* program)
|
|||
warnx("%s: Program is absent", program);
|
||||
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,
|
||||
const char* question);
|
||||
bool missing_program(const char* program);
|
||||
void gui_shutdown(int code);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -346,6 +346,7 @@ static bool etc_made = false;
|
|||
static char etc[] = "/tmp/etc.XXXXXX";
|
||||
static bool fs_made = false;
|
||||
static char fs[] = "/tmp/fs.XXXXXX";
|
||||
static int exit_gui_code = -1;
|
||||
|
||||
static void unmount_all_but_root(void)
|
||||
{
|
||||
|
@ -374,6 +375,14 @@ void exit_handler(void)
|
|||
rmdir(fs);
|
||||
if ( etc_made )
|
||||
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);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
@ -487,6 +496,7 @@ int main(void)
|
|||
|
||||
install_configurationf("upgrade.conf", "a", "src = yes\n");
|
||||
|
||||
// TODO: GUI support.
|
||||
bool kblayout_setable = 0 <= tcgetblob(0, "kblayout", NULL, 0);
|
||||
while ( kblayout_setable )
|
||||
{
|
||||
|
@ -847,7 +857,7 @@ int main(void)
|
|||
{
|
||||
prompt(input, sizeof(input), "confirm_install",
|
||||
"Install " BRAND_DISTRIBUTION_NAME "? "
|
||||
"(yes/no/poweroff/reboot/halt)", "yes");
|
||||
"(yes/no/exit/poweroff/reboot/halt)", "yes");
|
||||
if ( !strcasecmp(input, "yes") )
|
||||
break;
|
||||
else if ( !strcasecmp(input, "no") )
|
||||
|
@ -858,12 +868,14 @@ int main(void)
|
|||
"'halt' to cancel the installation.\n");
|
||||
continue;
|
||||
}
|
||||
else if ( !strcasecmp(input, "poweroff") )
|
||||
else if ( !strcasecmp(input, "exit") )
|
||||
exit(0);
|
||||
else if ( !strcasecmp(input, "poweroff") )
|
||||
exit_gui(0);
|
||||
else if ( !strcasecmp(input, "reboot") )
|
||||
exit(1);
|
||||
exit_gui(1);
|
||||
else if ( !strcasecmp(input, "halt") )
|
||||
exit(2);
|
||||
exit_gui(2);
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
@ -1199,6 +1211,27 @@ int main(void)
|
|||
|
||||
// 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) )
|
||||
{
|
||||
text("A Network Time Protocol client (ntpd) has been installed that "
|
||||
|
@ -1440,14 +1473,16 @@ int main(void)
|
|||
while ( true )
|
||||
{
|
||||
prompt(input, sizeof(input), "finally",
|
||||
"What now? (poweroff/reboot/halt/boot)", "boot");
|
||||
if ( !strcasecmp(input, "poweroff") )
|
||||
"What now? (exit/poweroff/reboot/halt/boot)", "boot");
|
||||
if ( !strcasecmp(input, "exit") )
|
||||
exit(0);
|
||||
if ( !strcasecmp(input, "reboot") )
|
||||
exit(1);
|
||||
if ( !strcasecmp(input, "halt") )
|
||||
exit(2);
|
||||
if ( !strcasecmp(input, "boot") )
|
||||
else if ( !strcasecmp(input, "poweroff") )
|
||||
exit_gui(0);
|
||||
else if ( !strcasecmp(input, "reboot") )
|
||||
exit_gui(1);
|
||||
else if ( !strcasecmp(input, "halt") )
|
||||
exit_gui(2);
|
||||
else if ( !strcasecmp(input, "boot") )
|
||||
{
|
||||
unmount_all_but_root();
|
||||
unsetenv("SYSINSTALL_TARGET");
|
||||
|
|
|
@ -71,6 +71,7 @@ static struct mountpoint* mountpoints;
|
|||
static size_t mountpoints_used;
|
||||
static bool fs_made = false;
|
||||
static char fs[] = "/tmp/fs.XXXXXX";
|
||||
static int exit_gui_code = -1;
|
||||
|
||||
static bool add_installation(struct blockdevice* bdev,
|
||||
struct release* release,
|
||||
|
@ -327,6 +328,14 @@ void exit_handler(void)
|
|||
}
|
||||
if ( fs_made )
|
||||
rmdir(fs);
|
||||
if ( 0 <= exit_gui_code )
|
||||
gui_shutdown(exit_gui_code);
|
||||
}
|
||||
|
||||
void exit_gui(int code)
|
||||
{
|
||||
exit_gui_code = code;
|
||||
exit(code);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
@ -778,7 +787,7 @@ int main(void)
|
|||
while ( true )
|
||||
{
|
||||
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") )
|
||||
break;
|
||||
else if ( !strcasecmp(input, "no") )
|
||||
|
@ -791,12 +800,14 @@ int main(void)
|
|||
"'halt' or cancel the upgrade.\n");
|
||||
continue;
|
||||
}
|
||||
else if ( !strcasecmp(input, "poweroff") )
|
||||
else if ( !strcasecmp(input, "exit") )
|
||||
exit(0);
|
||||
else if ( !strcasecmp(input, "poweroff") )
|
||||
exit_gui(0);
|
||||
else if ( !strcasecmp(input, "reboot") )
|
||||
exit(1);
|
||||
exit_gui(1);
|
||||
else if ( !strcasecmp(input, "halt") )
|
||||
exit(2);
|
||||
exit_gui(2);
|
||||
else if ( !strcasecmp(input, "!") )
|
||||
break;
|
||||
else
|
||||
|
@ -934,12 +945,14 @@ int main(void)
|
|||
while ( true )
|
||||
{
|
||||
prompt(input, sizeof(input), "finally",
|
||||
"What now? (poweroff/reboot/halt)", "reboot");
|
||||
if ( !strcasecmp(input, "poweroff") )
|
||||
return 0;
|
||||
if ( !strcasecmp(input, "reboot") )
|
||||
return 1;
|
||||
if ( !strcasecmp(input, "halt") )
|
||||
return 2;
|
||||
"What now? (exit/poweroff/reboot/halt)", "reboot");
|
||||
if ( !strcasecmp(input, "exit") )
|
||||
exit(0);
|
||||
else if ( !strcasecmp(input, "poweroff") )
|
||||
exit_gui(0);
|
||||
else if ( !strcasecmp(input, "reboot") )
|
||||
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
|
1294
terminal/terminal.c
Normal file
1294
terminal/terminal.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -23,6 +23,7 @@ default=
|
|||
directory=
|
||||
enable_append_title=true
|
||||
enable_dhclient=
|
||||
enable_gui=
|
||||
enable_network_drivers=
|
||||
enable_ntpd=
|
||||
enable_src=
|
||||
|
@ -56,12 +57,14 @@ for argument do
|
|||
--default) previous_option=default ;;
|
||||
--disable-append-title) enable_append_title=false ;;
|
||||
--disable-dhclient) enable_dhclient=false ;;
|
||||
--disable-gui) enable_gui=false ;;
|
||||
--disable-network-drivers) enable_network_drivers=false ;;
|
||||
--disable-ntpd) enable_ntpd=false ;;
|
||||
--disable-src) enable_src=false ;;
|
||||
--disable-sshd) enable_sshd=false ;;
|
||||
--enable-append-title) enable_append_title=true ;;
|
||||
--enable-dhclient) enable_dhclient=true ;;
|
||||
--enable-gui) enable_gui=true ;;
|
||||
--enable-network-drivers) enable_network_drivers=true ;;
|
||||
--enable-ntpd) enable_ntpd=true ;;
|
||||
--enable-src) enable_src=true ;;
|
||||
|
@ -148,6 +151,7 @@ mkdir -p -- "$directory/boot/grub"
|
|||
printf 'timeout="%s"\n' "$timeout"
|
||||
fi
|
||||
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_bool "$enable_src" src src
|
||||
print_enable_default_bool "$enable_sshd" sshd sshd
|
||||
|
|
|
@ -10,12 +10,14 @@
|
|||
.Op Fl \-default Ns = Ns Ar default-boot-menu-option
|
||||
.Op Fl \-disable-append-title
|
||||
.Op Fl \-disable-dhclient
|
||||
.Op Fl \-disable-gui
|
||||
.Op Fl \-disable-network-drivers
|
||||
.Op Fl \-disable-ntpd
|
||||
.Op Fl \-disable-src
|
||||
.Op Fl \-disable-sshd
|
||||
.Op Fl \-enable-append-title
|
||||
.Op Fl \-enable-dhclient
|
||||
.Op Fl \-enable-gui
|
||||
.Op Fl \-enable-network-drivers
|
||||
.Op Fl \-enable-ntpd
|
||||
.Op Fl \-enable-src
|
||||
|
@ -105,6 +107,16 @@ GRUB variable to
|
|||
causing the bootloader to load additional configuration that turns off the
|
||||
.Xr dhclient 8
|
||||
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
|
||||
Disable network drivers by setting the
|
||||
.Sy enable_network_drivers
|
||||
|
@ -152,6 +164,16 @@ GRUB variable to
|
|||
selecting the default behavior of starting the
|
||||
.Xr dhclient 8
|
||||
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
|
||||
Enable network drivers by setting the
|
||||
.Sy enable_network_drivers
|
||||
|
@ -343,6 +365,12 @@ automatically using the SSH configuration found in the liveconfig directory:
|
|||
tix-iso-bootconfig --liveconfig=liveconfig --enable-sshd bootconfig
|
||||
tix-iso-add sortix.iso bootconfig
|
||||
.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
|
||||
.Xr xorriso 1 ,
|
||||
.Xr kernel 7 ,
|
||||
|
|
|
@ -15,7 +15,7 @@ LIBS:=-ldispd
|
|||
|
||||
all: $(BINARY)
|
||||
|
||||
.PHONY: all install uninstall clean
|
||||
.PHONY: all install clean
|
||||
|
||||
install: all
|
||||
mkdir -p $(DESTDIR)$(BINDIR)
|
||||
|
|
|
@ -29,7 +29,10 @@
|
|||
|
||||
static void suggest_logout(void)
|
||||
{
|
||||
fprintf(stderr, " Exiting your shell normally to logout.\n");
|
||||
if ( getenv("DISPLAY_SOCKET") )
|
||||
fprintf(stderr, " Pressing Ctrl-Alt-Del to exit desktop.\n");
|
||||
else
|
||||
fprintf(stderr, " Exiting your shell normally to logout.\n");
|
||||
}
|
||||
|
||||
enum category
|
||||
|
|
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