just gobs of stuff
This commit is contained in:
parent
a1f60853ed
commit
8cd1bd4b8a
37
Makefile
37
Makefile
@ -1,4 +1,4 @@
|
||||
APPS=init hello sh ls
|
||||
APPS=init hello sh ls terminal uname compositor drawlines background session
|
||||
|
||||
CC=i686-pc-toaru-gcc
|
||||
AR=i686-pc-toaru-ar
|
||||
@ -41,11 +41,32 @@ base/lib/libtoaru_graphics.so: lib/graphics.c lib/graphics.h
|
||||
base/lib/libtoaru_list.so: lib/list.c lib/list.h
|
||||
$(CC) -o $@ $(CFLAGS) -shared -fPIC $<
|
||||
|
||||
base/lib/libtoaru_hashmap.so: lib/hashmap.c lib/hashmap.h base/lib/libtoaru_list.so
|
||||
$(CC) -o $@ $(CFLAGS) -shared -fPIC $< -ltoaru_list
|
||||
|
||||
base/lib/libtoaru_kbd.so: lib/kbd.c lib/kbd.h
|
||||
$(CC) -o $@ $(CFLAGS) -shared -fPIC $<
|
||||
|
||||
base/lib/libtoaru_pthread.so: lib/pthread.c lib/pthread.h
|
||||
$(CC) -o $@ $(CFLAGS) -shared -fPIC $<
|
||||
|
||||
base/lib/libtoaru_pex.so: lib/pex.c lib/pex.h
|
||||
$(CC) -o $@ $(CFLAGS) -shared -fPIC $<
|
||||
|
||||
base/lib/libtoaru_dlfcn.so: lib/dlfcn.c lib/dlfcn.h
|
||||
$(CC) -o $@ $(CFLAGS) -shared -fPIC $<
|
||||
|
||||
base/lib/libtoaru_yutani.so: lib/yutani.c lib/yutani.h base/lib/libtoaru_graphics.so
|
||||
$(CC) -o $@ $(CFLAGS) -shared -fPIC $< -ltoaru_graphics
|
||||
|
||||
base/lib/libtoaru_rline.so: lib/rline.c lib/rline.h base/lib/libtoaru_kbd.so
|
||||
$(CC) -o $@ $(CFLAGS) -shared -fPIC $< base/lib/libtoaru_kbd.so
|
||||
$(CC) -o $@ $(CFLAGS) -shared -fPIC $< -ltoaru_kbd
|
||||
|
||||
base/lib/libtoaru_termemu.so: lib/termemu.c lib/termemu.h base/lib/libtoaru_graphics.so
|
||||
$(CC) -o $@ $(CFLAGS) -shared -fPIC $< -ltoaru_graphics
|
||||
|
||||
base/lib/libtoaru_decorations.so: lib/decorations.c lib/decorations.h base/lib/libtoaru_graphics.so
|
||||
$(CC) -o $@ $(CFLAGS) -shared -fPIC $< -ltoaru_graphics
|
||||
|
||||
base/bin/init: init.c base/lib/libnihc.a | dirs
|
||||
$(CC) -static -Wl,-static $(CFLAGS) -o $@ $< $(LIBS)
|
||||
@ -56,6 +77,18 @@ base/bin/sh: sh.c base/lib/libnihc.so base/lib/libtoaru_list.so base/lib/libtoar
|
||||
base/bin/hello: hello.c base/lib/libnihc.so base/lib/libtoaru_graphics.so
|
||||
$(CC) $(CFLAGS) -o $@ $< -ltoaru_graphics $(LIBS)
|
||||
|
||||
base/bin/terminal: terminal.c base/lib/libnihc.so base/lib/libtoaru_graphics.so base/lib/libtoaru_yutani.so base/lib/libtoaru_decorations.so base/lib/libtoaru_dlfcn.so base/lib/libtoaru_list.so base/lib/libtoaru_kbd.so base/lib/libtoaru_termemu.so
|
||||
$(CC) $(CFLAGS) -o $@ $< -ltoaru_termemu -ltoaru_decorations -ltoaru_yutani -ltoaru_graphics -ltoaru_pex -ltoaru_hashmap -ltoaru_dlfcn -ltoaru_kbd -ltoaru_list $(LIBS)
|
||||
|
||||
base/bin/background: background.c base/lib/libnihc.so base/lib/libtoaru_graphics.so base/lib/libtoaru_yutani.so base/lib/libtoaru_pthread.so
|
||||
$(CC) $(CFLAGS) -o $@ $< -ltoaru_yutani -ltoaru_graphics -ltoaru_pex -ltoaru_pthread -ltoaru_hashmap -ltoaru_list $(LIBS)
|
||||
|
||||
base/bin/drawlines: drawlines.c base/lib/libnihc.so base/lib/libtoaru_graphics.so base/lib/libtoaru_yutani.so base/lib/libtoaru_pthread.so
|
||||
$(CC) $(CFLAGS) -o $@ $< -ltoaru_yutani -ltoaru_graphics -ltoaru_pex -ltoaru_pthread -ltoaru_hashmap -ltoaru_list $(LIBS)
|
||||
|
||||
base/bin/compositor: compositor.c base/lib/libnihc.so base/lib/libtoaru_graphics.so base/lib/libtoaru_list.so base/lib/libtoaru_kbd.so base/lib/libtoaru_pthread.so base/lib/libtoaru_pex.so base/lib/libtoaru_yutani.so base/lib/libtoaru_hashmap.so
|
||||
$(CC) $(CFLAGS) -o $@ $< -ltoaru_yutani -ltoaru_pthread -ltoaru_pex -ltoaru_graphics -ltoaru_kbd -ltoaru_hashmap -ltoaru_list $(LIBS)
|
||||
|
||||
base/bin/ls: ls.c base/lib/libnihc.so base/lib/libtoaru_list.so
|
||||
$(CC) $(CFLAGS) -o $@ $< -ltoaru_list $(LIBS)
|
||||
|
||||
|
37
background.c
Normal file
37
background.c
Normal file
@ -0,0 +1,37 @@
|
||||
#include "lib/yutani.h"
|
||||
#include "lib/graphics.h"
|
||||
|
||||
static yutani_t * yctx;
|
||||
static yutani_window_t * wina;
|
||||
static gfx_context_t * ctx;
|
||||
|
||||
|
||||
int main (int argc, char ** argv) {
|
||||
yctx = yutani_init();
|
||||
wina = yutani_window_create(yctx, yctx->display_width, yctx->display_height);
|
||||
yutani_window_move(yctx, wina, 0, 0);
|
||||
yutani_set_stack(yctx, wina, YUTANI_ZORDER_BOTTOM);
|
||||
ctx = init_graphics_yutani(wina);
|
||||
draw_fill(ctx, rgb(110,110,110));
|
||||
|
||||
int should_exit = 0;
|
||||
|
||||
while (!should_exit) {
|
||||
yutani_msg_t * m = yutani_poll(yctx);
|
||||
if (m) {
|
||||
switch (m->type) {
|
||||
case YUTANI_MSG_SESSION_END:
|
||||
should_exit = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(m);
|
||||
}
|
||||
|
||||
yutani_close(yctx, wina);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
BIN
base/mouse.bmp
Normal file
BIN
base/mouse.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
2628
compositor.c
Normal file
2628
compositor.c
Normal file
File diff suppressed because it is too large
Load Diff
116
drawlines.c
Normal file
116
drawlines.c
Normal file
@ -0,0 +1,116 @@
|
||||
/* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2013-2014 Kevin Lange
|
||||
*/
|
||||
/*
|
||||
* drawlines
|
||||
*
|
||||
* Test application to draw lines to a window.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lib/yutani.h"
|
||||
#include "lib/graphics.h"
|
||||
#include "lib/pthread.h"
|
||||
|
||||
#define TRACE_APP_NAME "drawlines"
|
||||
#include "lib/trace.h"
|
||||
|
||||
static int left, top, width, height;
|
||||
|
||||
static yutani_t * yctx;
|
||||
static yutani_window_t * wina;
|
||||
static gfx_context_t * ctx;
|
||||
static int should_exit = 0;
|
||||
|
||||
static int32_t min(int32_t a, int32_t b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
static int32_t max(int32_t a, int32_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
uint32_t __attribute__ ((pure)) krand(void) {
|
||||
static uint32_t x = 123456789;
|
||||
static uint32_t y = 362436069;
|
||||
static uint32_t z = 521288629;
|
||||
static uint32_t w = 88675123;
|
||||
|
||||
uint32_t t;
|
||||
|
||||
t = x ^ (x << 11);
|
||||
x = y; y = z; z = w;
|
||||
return w = w ^ (w >> 19) ^ t ^ (t >> 8);
|
||||
}
|
||||
|
||||
void * draw_thread(void * garbage) {
|
||||
(void)garbage;
|
||||
while (!should_exit) {
|
||||
draw_line(ctx, krand() % width, krand() % width, krand() % height, krand() % height, rgb(krand() % 255,krand() % 255,krand() % 255));
|
||||
yutani_flip(yctx, wina);
|
||||
usleep(16666);
|
||||
}
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
int main (int argc, char ** argv) {
|
||||
left = 100;
|
||||
top = 100;
|
||||
width = 500;
|
||||
height = 500;
|
||||
|
||||
TRACE("Starting drawlines.");
|
||||
yctx = yutani_init();
|
||||
TRACE("Creating a window.");
|
||||
wina = yutani_window_create(yctx, width, height);
|
||||
TRACE("Move.");
|
||||
yutani_window_move(yctx, wina, left, top);
|
||||
TRACE("Advertise icon.");
|
||||
yutani_window_advertise_icon(yctx, wina, "drawlines", "drawlines");
|
||||
|
||||
TRACE("Init graphics.");
|
||||
ctx = init_graphics_yutani(wina);
|
||||
draw_fill(ctx, rgb(0,0,0));
|
||||
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL, draw_thread, NULL);
|
||||
|
||||
while (!should_exit) {
|
||||
yutani_msg_t * m = yutani_poll(yctx);
|
||||
if (m) {
|
||||
switch (m->type) {
|
||||
case YUTANI_MSG_KEY_EVENT:
|
||||
{
|
||||
struct yutani_msg_key_event * ke = (void*)m->data;
|
||||
if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
|
||||
should_exit = 1;
|
||||
syscall_yield();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_WINDOW_MOUSE_EVENT:
|
||||
{
|
||||
struct yutani_msg_window_mouse_event * me = (void*)m->data;
|
||||
if (me->command == YUTANI_MOUSE_EVENT_DOWN && me->buttons & YUTANI_MOUSE_BUTTON_LEFT) {
|
||||
yutani_window_drag_start(yctx, wina);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_SESSION_END:
|
||||
should_exit = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(m);
|
||||
}
|
||||
|
||||
yutani_close(yctx, wina);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <va_list.h>
|
||||
|
||||
@ -19,6 +21,7 @@ extern FILE * fopen(const char *path, const char *mode);
|
||||
extern int fclose(FILE * stream);
|
||||
extern int fseek(FILE * stream, long offset, int whence);
|
||||
extern long ftell(FILE * stream);
|
||||
extern FILE * fdopen(int fd, const char *mode);
|
||||
|
||||
extern size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream);
|
||||
extern size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE * stream);
|
||||
@ -35,3 +38,4 @@ extern int fputs(const char *s, FILE *stream);
|
||||
extern int fputc(int c, FILE *stream);
|
||||
extern int fgetc(FILE *stream);
|
||||
|
||||
extern void setbuf(FILE * stream, char * buf);
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#define SIGEV_NONE 1
|
||||
#define SIGEV_SIGNAL 2
|
||||
#define SIGEV_THREAD 3
|
||||
|
@ -12,3 +12,4 @@ struct timezone {
|
||||
int tz_dsttime; /* type of DST correction */
|
||||
};
|
||||
|
||||
extern int gettimeofday(struct timeval *p, void *z);
|
||||
|
6
init.c
6
init.c
@ -4,7 +4,7 @@
|
||||
#include <wait.h>
|
||||
|
||||
void set_console() {
|
||||
int _stdin = syscall_open("/dev/ttyS0", 0, 0);
|
||||
int _stdin = syscall_open("/dev/null", 0, 0);
|
||||
int _stdout = syscall_open("/dev/ttyS0", 1, 0);
|
||||
int _stderr = syscall_open("/dev/ttyS0", 1, 0);
|
||||
|
||||
@ -40,9 +40,7 @@ int main(int argc, char * argv[]) {
|
||||
set_console();
|
||||
|
||||
char * _argv[] = {
|
||||
"/bin/hello",
|
||||
"--argument1",
|
||||
"--argument2",
|
||||
"/bin/compositor",
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
280
lib/decorations.c
Normal file
280
lib/decorations.c
Normal file
@ -0,0 +1,280 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2012-2017 Kevin Lange
|
||||
*
|
||||
* Client-side Window Decoration library
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include "lib/graphics.h"
|
||||
#include "lib/yutani.h"
|
||||
//#include "lib/shmemfonts.h"
|
||||
#include "lib/dlfcn.h"
|
||||
|
||||
#include "decorations.h"
|
||||
|
||||
uint32_t decor_top_height = 33;
|
||||
uint32_t decor_bottom_height = 6;
|
||||
uint32_t decor_left_width = 6;
|
||||
uint32_t decor_right_width = 6;
|
||||
|
||||
#define TEXT_OFFSET_X 10
|
||||
#define TEXT_OFFSET_Y 16
|
||||
|
||||
#define BORDERCOLOR rgb(60,60,60)
|
||||
#define BORDERCOLOR_INACTIVE rgb(30,30,30)
|
||||
#define BACKCOLOR rgb(20,20,20)
|
||||
#define TEXTCOLOR rgb(230,230,230)
|
||||
#define TEXTCOLOR_INACTIVE rgb(140,140,140)
|
||||
|
||||
void (*decor_render_decorations)(yutani_window_t *, gfx_context_t *, char *, int) = NULL;
|
||||
int (*decor_check_button_press)(yutani_window_t *, int x, int y) = NULL;
|
||||
|
||||
static void (*callback_close)(yutani_window_t *) = NULL;
|
||||
static void (*callback_resize)(yutani_window_t *) = NULL;
|
||||
|
||||
static int close_enough(struct yutani_msg_window_mouse_event * me) {
|
||||
#if 0
|
||||
return (me->command == YUTANI_MOUSE_EVENT_RAISE &&
|
||||
sqrt(pow(me->new_x - me->old_x, 2.0) + pow(me->new_y - me->old_y, 2.0)) < 10.0);
|
||||
#else
|
||||
return (me->command == YUTANI_MOUSE_EVENT_RAISE &&
|
||||
pow(pow(me->new_x - me->old_x, 2.0) + pow(me->new_y - me->old_y, 2.0), -1.0) < 10.0);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void render_decorations_simple(yutani_window_t * window, gfx_context_t * ctx, char * title, int decors_active) {
|
||||
|
||||
uint32_t color = BORDERCOLOR;
|
||||
if (decors_active == DECOR_INACTIVE) {
|
||||
color = BORDERCOLOR_INACTIVE;
|
||||
}
|
||||
|
||||
|
||||
for (uint32_t i = 0; i < window->height; ++i) {
|
||||
GFX(ctx, 0, i) = color;
|
||||
GFX(ctx, window->width - 1, i) = color;
|
||||
}
|
||||
|
||||
for (uint32_t i = 1; i < decor_top_height; ++i) {
|
||||
for (uint32_t j = 1; j < window->width - 1; ++j) {
|
||||
GFX(ctx, j, i) = BACKCOLOR;
|
||||
}
|
||||
}
|
||||
|
||||
if (decors_active == DECOR_INACTIVE) {
|
||||
//draw_string(ctx, TEXT_OFFSET_X, TEXT_OFFSET_Y, TEXTCOLOR_INACTIVE, title);
|
||||
//draw_string(ctx, window->width - 20, TEXT_OFFSET_Y, TEXTCOLOR_INACTIVE, "✕");
|
||||
} else {
|
||||
//draw_string(ctx, TEXT_OFFSET_X, TEXT_OFFSET_Y, TEXTCOLOR, title);
|
||||
//draw_string(ctx, window->width - 20, TEXT_OFFSET_Y, TEXTCOLOR, "✕");
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < window->width; ++i) {
|
||||
GFX(ctx, i, 0) = color;
|
||||
GFX(ctx, i, decor_top_height - 1) = color;
|
||||
GFX(ctx, i, window->height - 1) = color;
|
||||
}
|
||||
}
|
||||
|
||||
static int check_button_press_simple(yutani_window_t * window, int x, int y) {
|
||||
if (x >= window->width - 20 && x <= window->width - 2 && y >= 2) {
|
||||
return DECOR_CLOSE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void initialize_simple() {
|
||||
decor_top_height = 24;
|
||||
decor_bottom_height = 1;
|
||||
decor_left_width = 1;
|
||||
decor_right_width = 1;
|
||||
|
||||
decor_render_decorations = render_decorations_simple;
|
||||
decor_check_button_press = check_button_press_simple;
|
||||
}
|
||||
|
||||
void render_decorations(yutani_window_t * window, gfx_context_t * ctx, char * title) {
|
||||
if (!window) return;
|
||||
if (!window->focused) {
|
||||
decor_render_decorations(window, ctx, title, DECOR_INACTIVE);
|
||||
} else {
|
||||
decor_render_decorations(window, ctx, title, DECOR_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
void render_decorations_inactive(yutani_window_t * window, gfx_context_t * ctx, char * title) {
|
||||
if (!window) return;
|
||||
decor_render_decorations(window, ctx, title, DECOR_INACTIVE);
|
||||
}
|
||||
|
||||
void init_decorations() {
|
||||
//init_shmemfonts();
|
||||
|
||||
char * tmp = getenv("WM_THEME");
|
||||
char * theme = tmp ? strdup(tmp) : NULL;
|
||||
|
||||
if (!theme || !strcmp(theme, "simple")) {
|
||||
initialize_simple();
|
||||
} else {
|
||||
char * options = strchr(theme,',');
|
||||
if (options) {
|
||||
*options = '\0';
|
||||
options++;
|
||||
}
|
||||
char lib_name[100];
|
||||
sprintf(lib_name, "libtoaru-decor-%s.so", theme);
|
||||
void * theme_lib = dlopen(lib_name, 0);
|
||||
if (!theme_lib) {
|
||||
goto _theme_error;
|
||||
}
|
||||
void (*theme_init)(char *) = dlsym(theme_lib, "decor_init");
|
||||
if (!theme_init) {
|
||||
goto _theme_error;
|
||||
}
|
||||
theme_init(options);
|
||||
return;
|
||||
|
||||
_theme_error:
|
||||
fprintf(stderr, "decorations: could not load theme `%s`: %s\n", theme, dlerror());
|
||||
initialize_simple();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t decor_width() {
|
||||
return decor_left_width + decor_right_width;
|
||||
}
|
||||
|
||||
uint32_t decor_height() {
|
||||
return decor_top_height + decor_bottom_height;
|
||||
}
|
||||
|
||||
void decor_set_close_callback(void (*callback)(yutani_window_t *)) {
|
||||
callback_close = callback;
|
||||
}
|
||||
|
||||
void decor_set_resize_callback(void (*callback)(yutani_window_t *)) {
|
||||
callback_resize = callback;
|
||||
}
|
||||
|
||||
static int within_decors(yutani_window_t * window, int x, int y) {
|
||||
if ((x <= decor_left_width || x >= window->width - decor_right_width) && (x > 0 && x < window->width)) return 1;
|
||||
if ((y <= decor_top_height || y >= window->height - decor_bottom_height) && (y > 0 && y < window->height)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LEFT_SIDE (me->new_x <= decor_left_width)
|
||||
#define RIGHT_SIDE (me->new_x >= window->width - decor_right_width)
|
||||
#define TOP_SIDE (me->new_y <= decor_top_height)
|
||||
#define BOTTOM_SIDE (me->new_y >= window->height - decor_bottom_height)
|
||||
|
||||
static yutani_scale_direction_t check_resize_direction(struct yutani_msg_window_mouse_event * me, yutani_window_t * window) {
|
||||
yutani_scale_direction_t resize_direction = SCALE_NONE;
|
||||
if (LEFT_SIDE && !TOP_SIDE && !BOTTOM_SIDE) {
|
||||
resize_direction = SCALE_LEFT;
|
||||
} else if (RIGHT_SIDE && !TOP_SIDE && !BOTTOM_SIDE) {
|
||||
resize_direction = SCALE_RIGHT;
|
||||
} else if (BOTTOM_SIDE && !LEFT_SIDE && !RIGHT_SIDE) {
|
||||
resize_direction = SCALE_DOWN;
|
||||
} else if (BOTTOM_SIDE && LEFT_SIDE) {
|
||||
resize_direction = SCALE_DOWN_LEFT;
|
||||
} else if (BOTTOM_SIDE && RIGHT_SIDE) {
|
||||
resize_direction = SCALE_DOWN_RIGHT;
|
||||
} else if (TOP_SIDE && LEFT_SIDE) {
|
||||
resize_direction = SCALE_UP_LEFT;
|
||||
} else if (TOP_SIDE && RIGHT_SIDE) {
|
||||
resize_direction = SCALE_UP_RIGHT;
|
||||
} else if (TOP_SIDE && (me->new_y < 5)) {
|
||||
resize_direction = SCALE_UP;
|
||||
}
|
||||
return resize_direction;
|
||||
}
|
||||
|
||||
static int old_resize_direction = SCALE_NONE;
|
||||
|
||||
int decor_handle_event(yutani_t * yctx, yutani_msg_t * m) {
|
||||
if (m) {
|
||||
switch (m->type) {
|
||||
case YUTANI_MSG_WINDOW_MOUSE_EVENT:
|
||||
{
|
||||
struct yutani_msg_window_mouse_event * me = (void*)m->data;
|
||||
yutani_window_t * window = hashmap_get(yctx->windows, (void*)me->wid);
|
||||
if (!window) return 0;
|
||||
if (within_decors(window, me->new_x, me->new_y)) {
|
||||
int button = decor_check_button_press(window, me->new_x, me->new_y);
|
||||
if (me->command == YUTANI_MOUSE_EVENT_DOWN && me->buttons & YUTANI_MOUSE_BUTTON_LEFT) {
|
||||
if (!button) {
|
||||
/* Resize edges */
|
||||
yutani_scale_direction_t resize_direction = check_resize_direction(me, window);
|
||||
|
||||
if (resize_direction != SCALE_NONE) {
|
||||
yutani_window_resize_start(yctx, window, resize_direction);
|
||||
}
|
||||
|
||||
if (me->new_y < decor_top_height && resize_direction == SCALE_NONE) {
|
||||
yutani_window_drag_start(yctx, window);
|
||||
}
|
||||
return DECOR_OTHER;
|
||||
}
|
||||
}
|
||||
if (me->command == YUTANI_MOUSE_EVENT_MOVE) {
|
||||
if (!button) {
|
||||
/* Resize edges */
|
||||
yutani_scale_direction_t resize_direction = check_resize_direction(me, window);
|
||||
if (resize_direction != old_resize_direction) {
|
||||
if (resize_direction == SCALE_NONE) {
|
||||
yutani_window_show_mouse(yctx, window, YUTANI_CURSOR_TYPE_RESET);
|
||||
} else {
|
||||
switch (resize_direction) {
|
||||
case SCALE_UP:
|
||||
case SCALE_DOWN:
|
||||
yutani_window_show_mouse(yctx, window, YUTANI_CURSOR_TYPE_RESIZE_VERTICAL);
|
||||
break;
|
||||
case SCALE_LEFT:
|
||||
case SCALE_RIGHT:
|
||||
yutani_window_show_mouse(yctx, window, YUTANI_CURSOR_TYPE_RESIZE_HORIZONTAL);
|
||||
break;
|
||||
case SCALE_DOWN_RIGHT:
|
||||
case SCALE_UP_LEFT:
|
||||
yutani_window_show_mouse(yctx, window, YUTANI_CURSOR_TYPE_RESIZE_UP_DOWN);
|
||||
break;
|
||||
case SCALE_DOWN_LEFT:
|
||||
case SCALE_UP_RIGHT:
|
||||
yutani_window_show_mouse(yctx, window, YUTANI_CURSOR_TYPE_RESIZE_DOWN_UP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
old_resize_direction = resize_direction;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (me->command == YUTANI_MOUSE_EVENT_CLICK || close_enough(me)) {
|
||||
/* Determine if we clicked on a button */
|
||||
switch (button) {
|
||||
case DECOR_CLOSE:
|
||||
if (callback_close) callback_close(window);
|
||||
break;
|
||||
case DECOR_RESIZE:
|
||||
if (callback_resize) callback_resize(window);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return button;
|
||||
}
|
||||
} else {
|
||||
if (old_resize_direction != SCALE_NONE) {
|
||||
yutani_window_show_mouse(yctx, window, YUTANI_CURSOR_TYPE_RESET);
|
||||
old_resize_direction = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
54
lib/decorations.h
Normal file
54
lib/decorations.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
*
|
||||
* Decoration Library Headers
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "graphics.h"
|
||||
#include "yutani.h"
|
||||
|
||||
extern uint32_t decor_top_height;
|
||||
extern uint32_t decor_bottom_height;
|
||||
extern uint32_t decor_left_width;
|
||||
extern uint32_t decor_right_width;
|
||||
|
||||
/*
|
||||
* Render decorations to a window. A buffer pointer is
|
||||
* provided so that you may render in double-buffered mode.
|
||||
*
|
||||
* Run me at least once for each window, and any time you may need to
|
||||
* redraw them.
|
||||
*/
|
||||
extern void render_decorations(yutani_window_t * window, gfx_context_t * ctx, char * title);
|
||||
extern void render_decorations_inactive(yutani_window_t * window, gfx_context_t * ctx, char * title);
|
||||
|
||||
/*
|
||||
* Used by decoration libraries to set callbacks
|
||||
*/
|
||||
extern void (*decor_render_decorations)(yutani_window_t *, gfx_context_t *, char *, int);
|
||||
extern int (*decor_check_button_press)(yutani_window_t *, int x, int y);
|
||||
|
||||
/*
|
||||
* Run me once to set things up
|
||||
*/
|
||||
extern void init_decorations();
|
||||
|
||||
extern uint32_t decor_width();
|
||||
extern uint32_t decor_height();
|
||||
|
||||
extern int decor_handle_event(yutani_t * yctx, yutani_msg_t * m);
|
||||
|
||||
/* Callbacks for handle_event */
|
||||
extern void decor_set_close_callback(void (*callback)(yutani_window_t *));
|
||||
extern void decor_set_resize_callback(void (*callback)(yutani_window_t *));
|
||||
|
||||
/* Responses from handle_event */
|
||||
#define DECOR_OTHER 1
|
||||
#define DECOR_CLOSE 2
|
||||
#define DECOR_RESIZE 3
|
||||
|
||||
#define DECOR_ACTIVE 0
|
||||
#define DECOR_INACTIVE 1
|
||||
|
23
lib/dlfcn.c
Normal file
23
lib/dlfcn.c
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Stub library for providing dlopen, dlclose, dlsym.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static char * error = "dlopen functions not available";
|
||||
|
||||
void * __attribute__((weak)) dlopen(const char * filename, int flags) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int __attribute__((weak)) dlclose(void * handle) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void * dlsym(void * handle, const char * symbol) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * dlerror(void) {
|
||||
return error;
|
||||
}
|
11
lib/dlfcn.h
Normal file
11
lib/dlfcn.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#define RTLD_LAZY 0
|
||||
#define RTLD_NOW 1
|
||||
|
||||
|
||||
extern void * dlopen(const char *, int);
|
||||
extern int dlclose(void *);
|
||||
extern void * dlsym(void *, const char *);
|
||||
extern char * dlerror(void);
|
||||
|
20
lib/mouse.h
Normal file
20
lib/mouse.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
LEFT_CLICK = 0x01,
|
||||
RIGHT_CLICK = 0x02,
|
||||
MIDDLE_CLICK = 0x04,
|
||||
|
||||
MOUSE_SCROLL_UP = 0x10,
|
||||
MOUSE_SCROLL_DOWN = 0x20,
|
||||
} mouse_click_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
int32_t x_difference;
|
||||
int32_t y_difference;
|
||||
mouse_click_t buttons;
|
||||
} mouse_device_packet_t;
|
||||
|
||||
#define MOUSE_MAGIC 0xFEED1234
|
||||
|
61
lib/pex.c
Normal file
61
lib/pex.c
Normal file
@ -0,0 +1,61 @@
|
||||
/* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2014 Kevin Lange
|
||||
*/
|
||||
#include <alloca.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "pex.h"
|
||||
|
||||
size_t pex_send(FILE * sock, unsigned int rcpt, size_t size, char * blob) {
|
||||
assert(size <= MAX_PACKET_SIZE);
|
||||
pex_header_t * broadcast = malloc(sizeof(pex_header_t) + size);
|
||||
broadcast->target = rcpt;
|
||||
memcpy(broadcast->data, blob, size);
|
||||
size_t out = write(fileno(sock), broadcast, sizeof(pex_header_t) + size);
|
||||
free(broadcast);
|
||||
return out;
|
||||
}
|
||||
|
||||
size_t pex_broadcast(FILE * sock, size_t size, char * blob) {
|
||||
return pex_send(sock, 0, size, blob);
|
||||
}
|
||||
|
||||
size_t pex_listen(FILE * sock, pex_packet_t * packet) {
|
||||
return read(fileno(sock), packet, PACKET_SIZE);
|
||||
}
|
||||
|
||||
size_t pex_reply(FILE * sock, size_t size, char * blob) {
|
||||
return write(fileno(sock), blob, size);
|
||||
}
|
||||
|
||||
size_t pex_recv(FILE * sock, char * blob) {
|
||||
memset(blob, 0, MAX_PACKET_SIZE);
|
||||
return read(fileno(sock), blob, MAX_PACKET_SIZE);
|
||||
}
|
||||
|
||||
FILE * pex_connect(char * target) {
|
||||
char tmp[100];
|
||||
sprintf(tmp, "/dev/pex/%s", target);
|
||||
FILE * out = fopen(tmp, "r+");
|
||||
setbuf(out, NULL);
|
||||
return out;
|
||||
}
|
||||
|
||||
FILE * pex_bind(char * target) {
|
||||
char tmp[100];
|
||||
sprintf(tmp, "/dev/pex/%s", target);
|
||||
FILE * out = fopen(tmp, "a+");
|
||||
setbuf(out, NULL);
|
||||
return out;
|
||||
}
|
||||
|
||||
size_t pex_query(FILE * sock) {
|
||||
return ioctl(fileno(sock), IOCTL_PACKETFS_QUEUED, NULL);
|
||||
}
|
29
lib/pex.h
Normal file
29
lib/pex.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct pex_packet {
|
||||
uintptr_t source;
|
||||
size_t size;
|
||||
uint8_t data[];
|
||||
} pex_packet_t;
|
||||
#define MAX_PACKET_SIZE 1024
|
||||
#define PACKET_SIZE (sizeof(pex_packet_t) + MAX_PACKET_SIZE)
|
||||
|
||||
typedef struct pex_header {
|
||||
uintptr_t target;
|
||||
uint8_t data[];
|
||||
} pex_header_t;
|
||||
|
||||
size_t pex_send(FILE * sock, unsigned int rcpt, size_t size, char * blob);
|
||||
size_t pex_broadcast(FILE * sock, size_t size, char * blob);
|
||||
size_t pex_listen(FILE * sock, pex_packet_t * packet);
|
||||
|
||||
size_t pex_reply(FILE * sock, size_t size, char * blob);
|
||||
size_t pex_recv(FILE * sock, char * blob);
|
||||
size_t pex_query(FILE * sock);
|
||||
|
||||
FILE * pex_bind(char * target);
|
||||
FILE * pex_connect(char * target);
|
||||
|
42
lib/pthread.c
Normal file
42
lib/pthread.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2012-2014 Kevin Lange
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <syscall.h>
|
||||
#include <signal.h>
|
||||
#include "pthread.h"
|
||||
|
||||
#define PTHREAD_STACK_SIZE 0x100000
|
||||
|
||||
int clone(uintptr_t a,uintptr_t b,void* c) {
|
||||
return syscall_clone(a,b,c);
|
||||
}
|
||||
int gettid() {
|
||||
return syscall_gettid();
|
||||
}
|
||||
|
||||
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg) {
|
||||
char * stack = malloc(PTHREAD_STACK_SIZE);
|
||||
uintptr_t stack_top = (uintptr_t)stack + PTHREAD_STACK_SIZE;
|
||||
thread->stack = stack;
|
||||
thread->id = clone(stack_top, (uintptr_t)start_routine, arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_kill(pthread_t thread, int sig) {
|
||||
return kill(thread.id, sig);
|
||||
}
|
||||
|
||||
void pthread_exit(void * value) {
|
||||
/* Perform nice cleanup */
|
||||
#if 0
|
||||
/* XXX: LOCK */
|
||||
free(stack);
|
||||
/* XXX: Return value!? */
|
||||
#endif
|
||||
uintptr_t magic_exit_target = 0xFFFFB00F;
|
||||
void (*magic_exit_func)(void) = (void *)magic_exit_target;
|
||||
magic_exit_func();
|
||||
}
|
19
lib/pthread.h
Normal file
19
lib/pthread.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <syscall.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
char * stack;
|
||||
void * ret_val;
|
||||
} pthread_t;
|
||||
typedef unsigned int pthread_attr_t;
|
||||
|
||||
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg);
|
||||
void pthread_exit(void * value);
|
||||
int pthread_kill(pthread_t thread, int sig);
|
||||
|
||||
int clone(uintptr_t,uintptr_t,void*);
|
||||
int gettid();
|
||||
|
14
lib/spinlock.h
Normal file
14
lib/spinlock.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef spin_lock
|
||||
static void spin_lock(int volatile * lock) {
|
||||
while(__sync_lock_test_and_set(lock, 0x01)) {
|
||||
syscall_yield();
|
||||
}
|
||||
}
|
||||
|
||||
static void spin_unlock(int volatile * lock) {
|
||||
__sync_lock_release(lock);
|
||||
}
|
||||
#endif
|
||||
|
589
lib/termemu.c
Normal file
589
lib/termemu.c
Normal file
@ -0,0 +1,589 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2014 Kevin Lange
|
||||
*
|
||||
* Portable library for terminal emulation.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <syscall.h>
|
||||
|
||||
#include "lib/graphics.h"
|
||||
#include "lib/termemu.h"
|
||||
|
||||
|
||||
#include "lib/spinlock.h"
|
||||
#define _spin_lock spin_lock
|
||||
#define _spin_unlock spin_unlock
|
||||
|
||||
#define MAX_ARGS 1024
|
||||
|
||||
static wchar_t box_chars[] = L"▒␉␌␍␊°±␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥";
|
||||
|
||||
/* Returns the lower of two shorts */
|
||||
static uint16_t min(uint16_t a, uint16_t b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
/* Returns the higher of two shorts */
|
||||
static uint16_t max(uint16_t a, uint16_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
/* Write the contents of the buffer, as they were all non-escaped data. */
|
||||
static void ansi_dump_buffer(term_state_t * s) {
|
||||
for (int i = 0; i < s->buflen; ++i) {
|
||||
s->callbacks->writer(s->buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add to the internal buffer for the ANSI parser */
|
||||
static void ansi_buf_add(term_state_t * s, char c) {
|
||||
if (s->buflen >= TERM_BUF_LEN-1) return;
|
||||
s->buffer[s->buflen] = c;
|
||||
s->buflen++;
|
||||
s->buffer[s->buflen] = '\0';
|
||||
}
|
||||
|
||||
static int to_eight(uint32_t codepoint, char * out) {
|
||||
memset(out, 0x00, 7);
|
||||
|
||||
if (codepoint < 0x0080) {
|
||||
out[0] = (char)codepoint;
|
||||
} else if (codepoint < 0x0800) {
|
||||
out[0] = 0xC0 | (codepoint >> 6);
|
||||
out[1] = 0x80 | (codepoint & 0x3F);
|
||||
} else if (codepoint < 0x10000) {
|
||||
out[0] = 0xE0 | (codepoint >> 12);
|
||||
out[1] = 0x80 | ((codepoint >> 6) & 0x3F);
|
||||
out[2] = 0x80 | (codepoint & 0x3F);
|
||||
} else if (codepoint < 0x200000) {
|
||||
out[0] = 0xF0 | (codepoint >> 18);
|
||||
out[1] = 0x80 | ((codepoint >> 12) & 0x3F);
|
||||
out[2] = 0x80 | ((codepoint >> 6) & 0x3F);
|
||||
out[3] = 0x80 | ((codepoint) & 0x3F);
|
||||
} else if (codepoint < 0x4000000) {
|
||||
out[0] = 0xF8 | (codepoint >> 24);
|
||||
out[1] = 0x80 | (codepoint >> 18);
|
||||
out[2] = 0x80 | ((codepoint >> 12) & 0x3F);
|
||||
out[3] = 0x80 | ((codepoint >> 6) & 0x3F);
|
||||
out[4] = 0x80 | ((codepoint) & 0x3F);
|
||||
} else {
|
||||
out[0] = 0xF8 | (codepoint >> 30);
|
||||
out[1] = 0x80 | ((codepoint >> 24) & 0x3F);
|
||||
out[2] = 0x80 | ((codepoint >> 18) & 0x3F);
|
||||
out[3] = 0x80 | ((codepoint >> 12) & 0x3F);
|
||||
out[4] = 0x80 | ((codepoint >> 6) & 0x3F);
|
||||
out[5] = 0x80 | ((codepoint) & 0x3F);
|
||||
}
|
||||
|
||||
return strlen(out);
|
||||
}
|
||||
|
||||
|
||||
static void _ansi_put(term_state_t * s, char c) {
|
||||
term_callbacks_t * callbacks = s->callbacks;
|
||||
switch (s->escape) {
|
||||
case 0:
|
||||
/* We are not escaped, check for escape character */
|
||||
if (c == ANSI_ESCAPE) {
|
||||
/*
|
||||
* Enable escape mode, setup a buffer,
|
||||
* fill the buffer, get out of here.
|
||||
*/
|
||||
s->escape = 1;
|
||||
s->buflen = 0;
|
||||
ansi_buf_add(s, c);
|
||||
return;
|
||||
} else if (c == 0) {
|
||||
return;
|
||||
} else {
|
||||
if (s->box && c >= 'a' && c <= 'z') {
|
||||
char buf[7];
|
||||
char *w = (char *)&buf;
|
||||
to_eight(box_chars[c-'a'], w);
|
||||
while (*w) {
|
||||
callbacks->writer(*w);
|
||||
w++;
|
||||
}
|
||||
} else {
|
||||
callbacks->writer(c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
/* We're ready for [ */
|
||||
if (c == ANSI_BRACKET) {
|
||||
s->escape = 2;
|
||||
ansi_buf_add(s, c);
|
||||
} else if (c == ANSI_BRACKET_RIGHT) {
|
||||
s->escape = 3;
|
||||
ansi_buf_add(s, c);
|
||||
} else if (c == ANSI_OPEN_PAREN) {
|
||||
s->escape = 4;
|
||||
ansi_buf_add(s, c);
|
||||
} else if (c == 'T') {
|
||||
s->escape = 5;
|
||||
ansi_buf_add(s, c);
|
||||
} else {
|
||||
/* This isn't a bracket, we're not actually escaped!
|
||||
* Get out of here! */
|
||||
ansi_dump_buffer(s);
|
||||
callbacks->writer(c);
|
||||
s->escape = 0;
|
||||
s->buflen = 0;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (c >= ANSI_LOW && c <= ANSI_HIGH) {
|
||||
/* Woah, woah, let's see here. */
|
||||
char * pch; /* tokenizer pointer */
|
||||
char * save; /* strtok_r pointer */
|
||||
char * argv[MAX_ARGS]; /* escape arguments */
|
||||
/* Get rid of the front of the buffer */
|
||||
strtok_r(s->buffer,"[",&save);
|
||||
pch = strtok_r(NULL,";",&save);
|
||||
/* argc = Number of arguments, obviously */
|
||||
int argc = 0;
|
||||
while (pch != NULL) {
|
||||
argv[argc] = (char *)pch;
|
||||
++argc;
|
||||
if (argc > MAX_ARGS)
|
||||
break;
|
||||
pch = strtok_r(NULL,";",&save);
|
||||
}
|
||||
/* Alright, let's do this */
|
||||
switch (c) {
|
||||
case ANSI_EXT_IOCTL:
|
||||
{
|
||||
if (argc > 0) {
|
||||
int arg = atoi(argv[0]);
|
||||
switch (arg) {
|
||||
case 1:
|
||||
callbacks->redraw_cursor();
|
||||
break;
|
||||
#if 0
|
||||
case 1555:
|
||||
if (argc > 1) {
|
||||
callbacks->set_font_size(atof(argv[1]));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ANSI_SCP:
|
||||
{
|
||||
s->save_x = callbacks->get_csr_x();
|
||||
s->save_y = callbacks->get_csr_y();
|
||||
}
|
||||
break;
|
||||
case ANSI_RCP:
|
||||
{
|
||||
callbacks->set_csr(s->save_x, s->save_y);
|
||||
}
|
||||
break;
|
||||
case ANSI_SGR:
|
||||
/* Set Graphics Rendition */
|
||||
if (argc == 0) {
|
||||
/* Default = 0 */
|
||||
argv[0] = "0";
|
||||
argc = 1;
|
||||
}
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
int arg = atoi(argv[i]);
|
||||
if (arg >= 100 && arg < 110) {
|
||||
/* Bright background */
|
||||
s->bg = 8 + (arg - 100);
|
||||
s->flags |= ANSI_SPECBG;
|
||||
} else if (arg >= 90 && arg < 100) {
|
||||
/* Bright foreground */
|
||||
s->fg = 8 + (arg - 90);
|
||||
} else if (arg >= 40 && arg < 49) {
|
||||
/* Set background */
|
||||
s->bg = arg - 40;
|
||||
s->flags |= ANSI_SPECBG;
|
||||
} else if (arg == 49) {
|
||||
s->bg = TERM_DEFAULT_BG;
|
||||
s->flags &= ~ANSI_SPECBG;
|
||||
} else if (arg >= 30 && arg < 39) {
|
||||
/* Set Foreground */
|
||||
s->fg = arg - 30;
|
||||
} else if (arg == 39) {
|
||||
/* Default Foreground */
|
||||
s->fg = 7;
|
||||
} else if (arg == 24) {
|
||||
/* Underline off */
|
||||
s->flags &= ~ANSI_UNDERLINE;
|
||||
} else if (arg == 23) {
|
||||
/* Oblique off */
|
||||
s->flags &= ~ANSI_ITALIC;
|
||||
} else if (arg == 21 || arg == 22) {
|
||||
/* Bold off */
|
||||
s->flags &= ~ANSI_BOLD;
|
||||
} else if (arg == 9) {
|
||||
/* X-OUT */
|
||||
s->flags |= ANSI_CROSS;
|
||||
} else if (arg == 7) {
|
||||
/* INVERT: Swap foreground / background */
|
||||
uint32_t temp = s->fg;
|
||||
s->fg = s->bg;
|
||||
s->bg = temp;
|
||||
} else if (arg == 6) {
|
||||
/* proprietary RGBA color support */
|
||||
if (i == 0) { break; }
|
||||
if (i < argc) {
|
||||
int r = atoi(argv[i+1]);
|
||||
int g = atoi(argv[i+2]);
|
||||
int b = atoi(argv[i+3]);
|
||||
int a = atoi(argv[i+4]);
|
||||
if (a == 0) a = 1; /* Override a = 0 */
|
||||
uint32_t c = rgba(r,g,b,a);
|
||||
if (atoi(argv[i-1]) == 48) {
|
||||
s->bg = c;
|
||||
s->flags |= ANSI_SPECBG;
|
||||
} else if (atoi(argv[i-1]) == 38) {
|
||||
s->fg = c;
|
||||
}
|
||||
i += 4;
|
||||
}
|
||||
} else if (arg == 5) {
|
||||
/* Supposed to be blink; instead, support X-term 256 colors */
|
||||
if (i == 0) { break; }
|
||||
if (i < argc) {
|
||||
if (atoi(argv[i-1]) == 48) {
|
||||
/* Background to i+1 */
|
||||
s->bg = atoi(argv[i+1]);
|
||||
s->flags |= ANSI_SPECBG;
|
||||
} else if (atoi(argv[i-1]) == 38) {
|
||||
/* Foreground to i+1 */
|
||||
s->fg = atoi(argv[i+1]);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
} else if (arg == 4) {
|
||||
/* UNDERLINE */
|
||||
s->flags |= ANSI_UNDERLINE;
|
||||
} else if (arg == 3) {
|
||||
/* ITALIC: Oblique */
|
||||
s->flags |= ANSI_ITALIC;
|
||||
} else if (arg == 2) {
|
||||
/* Konsole RGB color support */
|
||||
if (i == 0) { break; }
|
||||
if (i < argc - 2) {
|
||||
int r = atoi(argv[i+1]);
|
||||
int g = atoi(argv[i+2]);
|
||||
int b = atoi(argv[i+3]);
|
||||
uint32_t c = rgb(r,g,b);
|
||||
if (atoi(argv[i-1]) == 48) {
|
||||
/* Background to i+1 */
|
||||
s->bg = c;
|
||||
s->flags |= ANSI_SPECBG;
|
||||
} else if (atoi(argv[i-1]) == 38) {
|
||||
/* Foreground to i+1 */
|
||||
s->fg = c;
|
||||
}
|
||||
i += 3;
|
||||
}
|
||||
} else if (arg == 1) {
|
||||
/* BOLD/BRIGHT: Brighten the output color */
|
||||
s->flags |= ANSI_BOLD;
|
||||
} else if (arg == 0) {
|
||||
/* Reset everything */
|
||||
s->fg = TERM_DEFAULT_FG;
|
||||
s->bg = TERM_DEFAULT_BG;
|
||||
s->flags = TERM_DEFAULT_FLAGS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ANSI_SHOW:
|
||||
if (argc > 0) {
|
||||
if (!strcmp(argv[0], "?1049")) {
|
||||
callbacks->cls(2);
|
||||
callbacks->set_csr(0,0);
|
||||
} else if (!strcmp(argv[0], "?1000")) {
|
||||
s->mouse_on = 1;
|
||||
} else if (!strcmp(argv[0], "?1002")) {
|
||||
s->mouse_on = 2;
|
||||
} else if (!strcmp(argv[0], "?25")) {
|
||||
callbacks->set_csr_on(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ANSI_HIDE:
|
||||
if (argc > 0) {
|
||||
if (!strcmp(argv[0], "?1049")) {
|
||||
/* TODO: Unimplemented */
|
||||
} else if (!strcmp(argv[0], "?1000")) {
|
||||
s->mouse_on = 0;
|
||||
} else if (!strcmp(argv[0], "?1002")) {
|
||||
s->mouse_on = 0;
|
||||
} else if (!strcmp(argv[0], "?25")) {
|
||||
callbacks->set_csr_on(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ANSI_CUF:
|
||||
{
|
||||
int i = 1;
|
||||
if (argc) {
|
||||
i = atoi(argv[0]);
|
||||
}
|
||||
callbacks->set_csr(min(callbacks->get_csr_x() + i, s->width - 1), callbacks->get_csr_y());
|
||||
}
|
||||
break;
|
||||
case ANSI_CUU:
|
||||
{
|
||||
int i = 1;
|
||||
if (argc) {
|
||||
i = atoi(argv[0]);
|
||||
}
|
||||
callbacks->set_csr(callbacks->get_csr_x(), max(callbacks->get_csr_y() - i, 0));
|
||||
}
|
||||
break;
|
||||
case ANSI_CUD:
|
||||
{
|
||||
int i = 1;
|
||||
if (argc) {
|
||||
i = atoi(argv[0]);
|
||||
}
|
||||
callbacks->set_csr(callbacks->get_csr_x(), min(callbacks->get_csr_y() + i, s->height - 1));
|
||||
}
|
||||
break;
|
||||
case ANSI_CUB:
|
||||
{
|
||||
int i = 1;
|
||||
if (argc) {
|
||||
i = atoi(argv[0]);
|
||||
}
|
||||
callbacks->set_csr(max(callbacks->get_csr_x() - i,0), callbacks->get_csr_y());
|
||||
}
|
||||
break;
|
||||
case ANSI_CHA:
|
||||
if (argc < 1) {
|
||||
callbacks->set_csr(0,callbacks->get_csr_y());
|
||||
} else {
|
||||
callbacks->set_csr(min(max(atoi(argv[0]), 1), s->width) - 1, callbacks->get_csr_y());
|
||||
}
|
||||
break;
|
||||
case ANSI_CUP:
|
||||
if (argc < 2) {
|
||||
callbacks->set_csr(0,0);
|
||||
} else {
|
||||
callbacks->set_csr(min(max(atoi(argv[1]), 1), s->width) - 1, min(max(atoi(argv[0]), 1), s->height) - 1);
|
||||
}
|
||||
break;
|
||||
case ANSI_ED:
|
||||
if (argc < 1) {
|
||||
callbacks->cls(0);
|
||||
} else {
|
||||
callbacks->cls(atoi(argv[0]));
|
||||
}
|
||||
break;
|
||||
case ANSI_EL:
|
||||
{
|
||||
int what = 0, x = 0, y = 0;
|
||||
if (argc >= 1) {
|
||||
what = atoi(argv[0]);
|
||||
}
|
||||
if (what == 0) {
|
||||
x = callbacks->get_csr_x();
|
||||
y = s->width;
|
||||
} else if (what == 1) {
|
||||
x = 0;
|
||||
y = callbacks->get_csr_x();
|
||||
} else if (what == 2) {
|
||||
x = 0;
|
||||
y = s->width;
|
||||
}
|
||||
for (int i = x; i < y; ++i) {
|
||||
callbacks->set_cell(i, callbacks->get_csr_y(), ' ');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ANSI_DSR:
|
||||
{
|
||||
char out[24];
|
||||
sprintf(out, "\033[%d;%dR", callbacks->get_csr_y() + 1, callbacks->get_csr_x() + 1);
|
||||
callbacks->input_buffer_stuff(out);
|
||||
}
|
||||
break;
|
||||
case ANSI_SU:
|
||||
{
|
||||
int how_many = 1;
|
||||
if (argc > 0) {
|
||||
how_many = atoi(argv[0]);
|
||||
}
|
||||
callbacks->scroll(how_many);
|
||||
}
|
||||
break;
|
||||
case ANSI_SD:
|
||||
{
|
||||
int how_many = 1;
|
||||
if (argc > 0) {
|
||||
how_many = atoi(argv[0]);
|
||||
}
|
||||
callbacks->scroll(-how_many);
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
{
|
||||
int how_many = 1;
|
||||
if (argc > 0) {
|
||||
how_many = atoi(argv[0]);
|
||||
}
|
||||
for (int i = 0; i < how_many; ++i) {
|
||||
callbacks->writer(' ');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (argc < 1) {
|
||||
callbacks->set_csr(callbacks->get_csr_x(), 0);
|
||||
} else {
|
||||
callbacks->set_csr(callbacks->get_csr_x(), atoi(argv[0]) - 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Meh */
|
||||
break;
|
||||
}
|
||||
/* Set the states */
|
||||
if (s->flags & ANSI_BOLD && s->fg < 9) {
|
||||
callbacks->set_color(s->fg % 8 + 8, s->bg);
|
||||
} else {
|
||||
callbacks->set_color(s->fg, s->bg);
|
||||
}
|
||||
/* Clear out the buffer */
|
||||
s->buflen = 0;
|
||||
s->escape = 0;
|
||||
return;
|
||||
} else {
|
||||
/* Still escaped */
|
||||
ansi_buf_add(s, c);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (c == '\007') {
|
||||
/* Tokenize on semicolons, like we always do */
|
||||
char * pch; /* tokenizer pointer */
|
||||
char * save; /* strtok_r pointer */
|
||||
char * argv[MAX_ARGS]; /* escape arguments */
|
||||
/* Get rid of the front of the buffer */
|
||||
strtok_r(s->buffer,"]",&save);
|
||||
pch = strtok_r(NULL,";",&save);
|
||||
/* argc = Number of arguments, obviously */
|
||||
int argc = 0;
|
||||
while (pch != NULL) {
|
||||
argv[argc] = (char *)pch;
|
||||
++argc;
|
||||
if (argc > MAX_ARGS) break;
|
||||
pch = strtok_r(NULL,";",&save);
|
||||
}
|
||||
/* Start testing the first argument for what command to use */
|
||||
if (argv[0]) {
|
||||
if (!strcmp(argv[0], "1")) {
|
||||
if (argc > 1) {
|
||||
callbacks->set_title(argv[1]);
|
||||
}
|
||||
} /* Currently, no other options */
|
||||
}
|
||||
/* Clear out the buffer */
|
||||
s->buflen = 0;
|
||||
s->escape = 0;
|
||||
return;
|
||||
} else {
|
||||
/* Still escaped */
|
||||
if (c == '\n' || s->buflen == 255) {
|
||||
ansi_dump_buffer(s);
|
||||
callbacks->writer(c);
|
||||
s->buflen = 0;
|
||||
s->escape = 0;
|
||||
return;
|
||||
}
|
||||
ansi_buf_add(s, c);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (c == '0') {
|
||||
s->box = 1;
|
||||
} else if (c == 'B') {
|
||||
s->box = 0;
|
||||
} else {
|
||||
ansi_dump_buffer(s);
|
||||
callbacks->writer(c);
|
||||
}
|
||||
s->escape = 0;
|
||||
s->buflen = 0;
|
||||
break;
|
||||
case 5:
|
||||
if (c == 'q') {
|
||||
char out[24];
|
||||
sprintf(out, "\033T%d;%dq", callbacks->get_cell_width(), callbacks->get_cell_height());
|
||||
callbacks->input_buffer_stuff(out);
|
||||
s->escape = 0;
|
||||
s->buflen = 0;
|
||||
} else if (c == 's') {
|
||||
s->img_collected = 0;
|
||||
s->escape = 6;
|
||||
s->img_size = sizeof(uint32_t) * callbacks->get_cell_width() * callbacks->get_cell_height();
|
||||
if (!s->img_data) {
|
||||
s->img_data = malloc(s->img_size);
|
||||
}
|
||||
memset(s->img_data, 0x00, s->img_size);
|
||||
} else {
|
||||
ansi_dump_buffer(s);
|
||||
callbacks->writer(c);
|
||||
s->escape = 0;
|
||||
s->buflen = 0;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
s->img_data[s->img_collected++] = c;
|
||||
if (s->img_collected == s->img_size) {
|
||||
callbacks->set_cell_contents(callbacks->get_csr_x(), callbacks->get_csr_y(), s->img_data);
|
||||
callbacks->set_csr(min(callbacks->get_csr_x() + 1, s->width - 1), callbacks->get_csr_y());
|
||||
s->escape = 0;
|
||||
s->buflen = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ansi_put(term_state_t * s, char c) {
|
||||
_spin_lock(&s->lock);
|
||||
_ansi_put(s, c);
|
||||
_spin_unlock(&s->lock);
|
||||
}
|
||||
|
||||
term_state_t * ansi_init(term_state_t * s, int w, int y, term_callbacks_t * callbacks_in) {
|
||||
|
||||
if (!s) {
|
||||
s = malloc(sizeof(term_state_t));
|
||||
}
|
||||
|
||||
memset(s, 0x00, sizeof(term_state_t));
|
||||
|
||||
/* Terminal Defaults */
|
||||
s->fg = TERM_DEFAULT_FG; /* Light grey */
|
||||
s->bg = TERM_DEFAULT_BG; /* Black */
|
||||
s->flags = TERM_DEFAULT_FLAGS; /* Nothing fancy*/
|
||||
s->width = w;
|
||||
s->height = y;
|
||||
s->box = 0;
|
||||
s->callbacks = callbacks_in;
|
||||
s->callbacks->set_color(s->fg, s->bg);
|
||||
s->mouse_on = 0;
|
||||
|
||||
return s;
|
||||
}
|
110
lib/termemu.h
Normal file
110
lib/termemu.h
Normal file
@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _KERNEL_
|
||||
# include <types.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define TERM_BUF_LEN 128
|
||||
|
||||
/* A terminal cell represents a single character on screen */
|
||||
typedef struct {
|
||||
uint32_t c; /* codepoint */
|
||||
uint32_t fg; /* background indexed color */
|
||||
uint32_t bg; /* foreground indexed color */
|
||||
uint32_t flags; /* other flags */
|
||||
} term_cell_t;
|
||||
|
||||
typedef struct {
|
||||
void (*writer)(char);
|
||||
void (*set_color)(uint32_t, uint32_t);
|
||||
void (*set_csr)(int,int);
|
||||
int (*get_csr_x)(void);
|
||||
int (*get_csr_y)(void);
|
||||
void (*set_cell)(int,int,uint32_t);
|
||||
void (*cls)(int);
|
||||
void (*scroll)(int);
|
||||
void (*redraw_cursor)(void);
|
||||
void (*input_buffer_stuff)(char *);
|
||||
void (*set_font_size)(float);
|
||||
void (*set_title)(char *);
|
||||
void (*set_cell_contents)(int,int,char *);
|
||||
int (*get_cell_width)(void);
|
||||
int (*get_cell_height)(void);
|
||||
void (*set_csr_on)(int);
|
||||
} term_callbacks_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t x; /* Current cursor location */
|
||||
uint16_t y; /* " " " */
|
||||
uint16_t save_x; /* Last cursor save */
|
||||
uint16_t save_y;
|
||||
uint32_t width; /* Terminal width */
|
||||
uint32_t height; /* " height */
|
||||
uint32_t fg; /* Current foreground color */
|
||||
uint32_t bg; /* Current background color */
|
||||
uint8_t flags; /* Bright, etc. */
|
||||
uint8_t escape; /* Escape status */
|
||||
uint8_t box;
|
||||
uint8_t buflen; /* Buffer Length */
|
||||
char buffer[TERM_BUF_LEN]; /* Previous buffer */
|
||||
term_callbacks_t * callbacks;
|
||||
int volatile lock;
|
||||
uint8_t mouse_on;
|
||||
uint32_t img_collected;
|
||||
uint32_t img_size;
|
||||
char * img_data;
|
||||
} term_state_t;
|
||||
|
||||
/* Triggers escape mode. */
|
||||
#define ANSI_ESCAPE 27
|
||||
/* Escape verify */
|
||||
#define ANSI_BRACKET '['
|
||||
#define ANSI_BRACKET_RIGHT ']'
|
||||
#define ANSI_OPEN_PAREN '('
|
||||
/* Anything in this range (should) exit escape mode. */
|
||||
#define ANSI_LOW 'A'
|
||||
#define ANSI_HIGH 'z'
|
||||
/* Escape commands */
|
||||
#define ANSI_CUU 'A' /* CUrsor Up */
|
||||
#define ANSI_CUD 'B' /* CUrsor Down */
|
||||
#define ANSI_CUF 'C' /* CUrsor Forward */
|
||||
#define ANSI_CUB 'D' /* CUrsor Back */
|
||||
#define ANSI_CNL 'E' /* Cursor Next Line */
|
||||
#define ANSI_CPL 'F' /* Cursor Previous Line */
|
||||
#define ANSI_CHA 'G' /* Cursor Horizontal Absolute */
|
||||
#define ANSI_CUP 'H' /* CUrsor Position */
|
||||
#define ANSI_ED 'J' /* Erase Data */
|
||||
#define ANSI_EL 'K' /* Erase in Line */
|
||||
#define ANSI_SU 'S' /* Scroll Up */
|
||||
#define ANSI_SD 'T' /* Scroll Down */
|
||||
#define ANSI_HVP 'f' /* Horizontal & Vertical Pos. */
|
||||
#define ANSI_SGR 'm' /* Select Graphic Rendition */
|
||||
#define ANSI_DSR 'n' /* Device Status Report */
|
||||
#define ANSI_SCP 's' /* Save Cursor Position */
|
||||
#define ANSI_RCP 'u' /* Restore Cursor Position */
|
||||
#define ANSI_HIDE 'l' /* DECTCEM - Hide Cursor */
|
||||
#define ANSI_SHOW 'h' /* DECTCEM - Show Cursor */
|
||||
/* Display flags */
|
||||
#define ANSI_BOLD 0x01
|
||||
#define ANSI_UNDERLINE 0x02
|
||||
#define ANSI_ITALIC 0x04
|
||||
#define ANSI_ALTFONT 0x08 /* Character should use alternate font */
|
||||
#define ANSI_SPECBG 0x10
|
||||
#define ANSI_BORDER 0x20
|
||||
#define ANSI_WIDE 0x40 /* Character is double width */
|
||||
#define ANSI_CROSS 0x80 /* And that's all I'm going to support (for now) */
|
||||
#define ANSI_EXT_IMG 0x100 /* Cell is actually an image, use fg color as pointer */
|
||||
|
||||
#define ANSI_EXT_IOCTL 'z' /* These are special escapes only we support */
|
||||
|
||||
/* Default color settings */
|
||||
#define TERM_DEFAULT_FG 0x07 /* Index of default foreground */
|
||||
#define TERM_DEFAULT_BG 0x10 /* Index of default background */
|
||||
#define TERM_DEFAULT_FLAGS 0x00 /* Default flags for a cell */
|
||||
#define TERM_DEFAULT_OPAC 0xF2 /* For background, default transparency */
|
||||
|
||||
term_state_t * ansi_init(term_state_t * s, int w, int y, term_callbacks_t * callbacks_in);
|
||||
void ansi_put(term_state_t * s, char c);
|
||||
|
12
lib/trace.h
Normal file
12
lib/trace.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifndef TRACE
|
||||
#define TRACE(msg,...) do { \
|
||||
struct timeval t; gettimeofday(&t, NULL); \
|
||||
fprintf(stderr, "%06d.%06d [" TRACE_APP_NAME "] %s:%05d - " msg "\n", t.tv_sec, t.tv_usec, __FILE__, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#endif
|
59
lib/utf8decode.h
Normal file
59
lib/utf8decode.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define UTF8_ACCEPT 0
|
||||
#define UTF8_REJECT 1
|
||||
|
||||
static const uint8_t utf8d[] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
|
||||
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
|
||||
0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
|
||||
0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
|
||||
0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
|
||||
1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
|
||||
1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
|
||||
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
|
||||
};
|
||||
|
||||
static uint32_t inline
|
||||
decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
|
||||
uint32_t type = utf8d[byte];
|
||||
|
||||
*codep = (*state != UTF8_ACCEPT) ?
|
||||
(byte & 0x3fu) | (*codep << 6) :
|
||||
(0xff >> type) & (byte);
|
||||
|
||||
*state = utf8d[256 + *state*16 + type];
|
||||
return *state;
|
||||
}
|
||||
|
884
lib/yutani.c
Normal file
884
lib/yutani.c
Normal file
@ -0,0 +1,884 @@
|
||||
/* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2014 Kevin Lange
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
#include "yutani.h"
|
||||
#include "mouse.h"
|
||||
|
||||
#include "lib/pex.h"
|
||||
#include "lib/graphics.h"
|
||||
#include "lib/kbd.h"
|
||||
#include "lib/hashmap.h"
|
||||
#include "lib/list.h"
|
||||
|
||||
yutani_msg_t * yutani_wait_for(yutani_t * y, uint32_t type) {
|
||||
do {
|
||||
yutani_msg_t * out;
|
||||
size_t size;
|
||||
{
|
||||
char tmp[MAX_PACKET_SIZE];
|
||||
size = pex_recv(y->sock, tmp);
|
||||
out = malloc(size);
|
||||
memcpy(out, tmp, size);
|
||||
}
|
||||
|
||||
if (out->type == type) {
|
||||
return out;
|
||||
} else {
|
||||
list_insert(y->queued, out);
|
||||
}
|
||||
} while (1); /* XXX: (!y->abort) */
|
||||
}
|
||||
|
||||
size_t yutani_query(yutani_t * y) {
|
||||
if (y->queued->length > 0) return 1;
|
||||
return pex_query(y->sock);
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_poll(yutani_t * y) {
|
||||
yutani_msg_t * out;
|
||||
|
||||
if (y->queued->length > 0) {
|
||||
node_t * node = list_dequeue(y->queued);
|
||||
out = (yutani_msg_t *)node->value;
|
||||
free(node);
|
||||
return out;
|
||||
}
|
||||
|
||||
size_t size;
|
||||
{
|
||||
char tmp[MAX_PACKET_SIZE];
|
||||
size = pex_recv(y->sock, tmp);
|
||||
out = malloc(size);
|
||||
memcpy(out, tmp, size);
|
||||
}
|
||||
|
||||
if (out->type == YUTANI_MSG_WELCOME) {
|
||||
struct yutani_msg_welcome * mw = (void *)out->data;
|
||||
y->display_width = mw->display_width;
|
||||
y->display_height = mw->display_height;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_poll_async(yutani_t * y) {
|
||||
if (yutani_query(y) > 0) {
|
||||
return yutani_poll(y);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_hello(void) {
|
||||
size_t s = sizeof(struct yutani_message);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_HELLO;
|
||||
msg->size = s;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_flip(yutani_wid_t wid) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_flip);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_FLIP;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_flip * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_welcome(uint32_t width, uint32_t height) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_welcome);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WELCOME;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_welcome * mw = (void *)msg->data;
|
||||
|
||||
mw->display_width = width;
|
||||
mw->display_height = height;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_new(uint32_t width, uint32_t height) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_new);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_NEW;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_new * mw = (void *)msg->data;
|
||||
|
||||
mw->width = width;
|
||||
mw->height = height;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_new_flags(uint32_t width, uint32_t height, uint32_t flags) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_new_flags);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_NEW_FLAGS;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_new_flags * mw = (void *)msg->data;
|
||||
|
||||
mw->width = width;
|
||||
mw->height = height;
|
||||
mw->flags = flags;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_init(yutani_wid_t wid, uint32_t width, uint32_t height, uint32_t bufid) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_init);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_INIT;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_init * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->width = width;
|
||||
mw->height = height;
|
||||
mw->bufid = bufid;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_close(yutani_wid_t wid) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_close);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_CLOSE;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_close * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_key_event(yutani_wid_t wid, key_event_t * event, key_event_state_t * state) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_key_event);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_KEY_EVENT;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_key_event * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
memcpy(&mw->event, event, sizeof(key_event_t));
|
||||
memcpy(&mw->state, state, sizeof(key_event_state_t));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_mouse_event(yutani_wid_t wid, mouse_device_packet_t * event, int32_t type) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_mouse_event);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_MOUSE_EVENT;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_mouse_event * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
memcpy(&mw->event, event, sizeof(mouse_device_packet_t));
|
||||
mw->type = type;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_move(yutani_wid_t wid, int32_t x, int32_t y) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_move);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_MOVE;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_move * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->x = x;
|
||||
mw->y = y;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_stack(yutani_wid_t wid, int z) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_stack);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_STACK;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_stack * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->z = z;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_focus_change(yutani_wid_t wid, int focused) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_focus_change);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_FOCUS_CHANGE;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_focus_change * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->focused = focused;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_mouse_event(yutani_wid_t wid, int32_t new_x, int32_t new_y, int32_t old_x, int32_t old_y, uint8_t buttons, uint8_t command) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_mouse_event);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_MOUSE_EVENT;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_mouse_event * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->new_x = new_x;
|
||||
mw->new_y = new_y;
|
||||
mw->old_x = old_x;
|
||||
mw->old_y = old_y;
|
||||
mw->buttons = buttons;
|
||||
mw->command = command;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_flip_region(yutani_wid_t wid, int32_t x, int32_t y, int32_t width, int32_t height) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_flip_region);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_FLIP_REGION;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_flip_region * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->x = x;
|
||||
mw->y = y;
|
||||
mw->width = width;
|
||||
mw->height = height;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_resize(uint32_t type, yutani_wid_t wid, uint32_t width, uint32_t height, uint32_t bufid) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_resize);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = type;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_resize * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->width = width;
|
||||
mw->height = height;
|
||||
mw->bufid = bufid;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_advertise(yutani_wid_t wid, uint32_t flags, uint16_t * offsets, size_t length, char * data) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_advertise) + length;
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_ADVERTISE;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_advertise * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->flags = flags;
|
||||
mw->size = length;
|
||||
if (offsets) {
|
||||
memcpy(mw->offsets, offsets, sizeof(uint16_t)*5);
|
||||
} else {
|
||||
memset(mw->offsets, 0, sizeof(uint16_t)*5);
|
||||
}
|
||||
if (data) {
|
||||
memcpy(mw->strings, data, mw->size);
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_subscribe(void) {
|
||||
size_t s = sizeof(struct yutani_message);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_SUBSCRIBE;
|
||||
msg->size = s;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_unsubscribe(void) {
|
||||
size_t s = sizeof(struct yutani_message);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_UNSUBSCRIBE;
|
||||
msg->size = s;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_query_windows(void) {
|
||||
size_t s = sizeof(struct yutani_message);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_QUERY_WINDOWS;
|
||||
msg->size = s;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_notify(void) {
|
||||
size_t s = sizeof(struct yutani_message);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_NOTIFY;
|
||||
msg->size = s;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_session_end(void) {
|
||||
size_t s = sizeof(struct yutani_message);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_SESSION_END;
|
||||
msg->size = s;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_focus(yutani_wid_t wid) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_focus);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_FOCUS;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_focus * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_key_bind(kbd_key_t key, kbd_mod_t mod, int response) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_key_bind);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_KEY_BIND;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_key_bind * mw = (void *)msg->data;
|
||||
|
||||
mw->key = key;
|
||||
mw->modifiers = mod;
|
||||
mw->response = response;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_drag_start(yutani_wid_t wid) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_drag_start);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_DRAG_START;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_drag_start * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_update_shape(yutani_wid_t wid, int set_shape) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_update_shape);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_UPDATE_SHAPE;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_update_shape * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->set_shape = set_shape;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_warp_mouse(yutani_wid_t wid, int32_t x, int32_t y) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_warp_mouse);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_WARP_MOUSE;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_warp_mouse * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->x = x;
|
||||
mw->y = y;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_show_mouse(yutani_wid_t wid, int32_t show_mouse) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_show_mouse);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_SHOW_MOUSE;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_show_mouse * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->show_mouse = show_mouse;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_window_resize_start(yutani_wid_t wid, yutani_scale_direction_t direction) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_resize_start);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_WINDOW_RESIZE_START;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_window_resize_start * mw = (void *)msg->data;
|
||||
|
||||
mw->wid = wid;
|
||||
mw->direction = direction;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_timer_request(uint32_t precision, uint32_t flags) {
|
||||
size_t s = sizeof(struct yutani_message) + sizeof(struct yutani_msg_timer_request);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_TIMER_REQUEST;
|
||||
msg->size = s;
|
||||
|
||||
struct yutani_msg_timer_request * tr = (void *)msg->data;
|
||||
|
||||
tr->precision = precision;
|
||||
tr->flags = flags;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
yutani_msg_t * yutani_msg_build_timer_tick(void) {
|
||||
size_t s = sizeof(struct yutani_message);
|
||||
yutani_msg_t * msg = malloc(s);
|
||||
|
||||
msg->magic = YUTANI_MSG__MAGIC;
|
||||
msg->type = YUTANI_MSG_TIMER_TICK;
|
||||
msg->size = s;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
int yutani_msg_send(yutani_t * y, yutani_msg_t * msg) {
|
||||
int result = pex_reply(y->sock, msg->size, (char *)msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
yutani_t * yutani_context_create(FILE * socket) {
|
||||
yutani_t * out = malloc(sizeof(yutani_t));
|
||||
|
||||
out->sock = socket;
|
||||
out->display_width = 0;
|
||||
out->display_height = 0;
|
||||
out->windows = hashmap_create_int(10);
|
||||
out->queued = list_create();
|
||||
return out;
|
||||
}
|
||||
|
||||
yutani_t * yutani_init(void) {
|
||||
/* XXX: Display, etc? */
|
||||
char * server_name = getenv("DISPLAY");
|
||||
if (!server_name) {
|
||||
server_name = "compositor";
|
||||
}
|
||||
FILE * c = pex_connect(server_name);
|
||||
|
||||
if (!c) {
|
||||
fprintf(stderr, "Pex connection failed?\n");
|
||||
return NULL; /* Connection failed. */
|
||||
}
|
||||
|
||||
yutani_t * y = yutani_context_create(c);
|
||||
yutani_msg_t * m = yutani_msg_build_hello();
|
||||
int result = yutani_msg_send(y, m);
|
||||
free(m);
|
||||
|
||||
m = yutani_wait_for(y, YUTANI_MSG_WELCOME);
|
||||
struct yutani_msg_welcome * mw = (void *)&m->data;
|
||||
y->display_width = mw->display_width;
|
||||
y->display_height = mw->display_height;
|
||||
y->server_ident = server_name;
|
||||
free(m);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
yutani_window_t * yutani_window_create_flags(yutani_t * y, int width, int height, uint32_t flags) {
|
||||
yutani_window_t * win = malloc(sizeof(yutani_window_t));
|
||||
|
||||
yutani_msg_t * m = yutani_msg_build_window_new_flags(width, height, flags);
|
||||
int result = yutani_msg_send(y, m);
|
||||
free(m);
|
||||
|
||||
m = yutani_wait_for(y, YUTANI_MSG_WINDOW_INIT);
|
||||
struct yutani_msg_window_init * mw = (void *)&m->data;
|
||||
|
||||
win->width = mw->width;
|
||||
win->height = mw->height;
|
||||
win->bufid = mw->bufid;
|
||||
win->wid = mw->wid;
|
||||
win->focused = 0;
|
||||
|
||||
hashmap_set(y->windows, (void*)win->wid, win);
|
||||
|
||||
char key[1024];
|
||||
YUTANI_SHMKEY(y->server_ident, key, 1024, win);
|
||||
|
||||
size_t size = (width * height * 4);
|
||||
win->buffer = (uint8_t *)syscall_shm_obtain(key, &size);
|
||||
return win;
|
||||
|
||||
}
|
||||
|
||||
yutani_window_t * yutani_window_create(yutani_t * y, int width, int height) {
|
||||
return yutani_window_create_flags(y,width,height,0);
|
||||
}
|
||||
|
||||
void yutani_flip(yutani_t * y, yutani_window_t * win) {
|
||||
yutani_msg_t * m = yutani_msg_build_flip(win->wid);
|
||||
int result = yutani_msg_send(y, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_flip_region(yutani_t * yctx, yutani_window_t * win, int32_t x, int32_t y, int32_t width, int32_t height) {
|
||||
yutani_msg_t * m = yutani_msg_build_flip_region(win->wid, x, y, width, height);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_close(yutani_t * y, yutani_window_t * win) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_close(win->wid);
|
||||
int result = yutani_msg_send(y, m);
|
||||
free(m);
|
||||
|
||||
/* Now destroy our end of the window */
|
||||
{
|
||||
char key[1024];
|
||||
YUTANI_SHMKEY_EXP(y->server_ident, key, 1024, win->bufid);
|
||||
syscall_shm_release(key);
|
||||
}
|
||||
|
||||
hashmap_remove(y->windows, (void*)win->wid);
|
||||
free(win);
|
||||
}
|
||||
|
||||
void yutani_window_move(yutani_t * yctx, yutani_window_t * window, int x, int y) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_move(window->wid, x, y);
|
||||
int reuslt = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_set_stack(yutani_t * yctx, yutani_window_t * window, int z) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_stack(window->wid, z);
|
||||
int reuslt = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_window_resize(yutani_t * yctx, yutani_window_t * window, uint32_t width, uint32_t height) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_resize(YUTANI_MSG_RESIZE_REQUEST, window->wid, width, height, 0);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_window_resize_offer(yutani_t * yctx, yutani_window_t * window, uint32_t width, uint32_t height) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_resize(YUTANI_MSG_RESIZE_OFFER, window->wid, width, height, 0);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_window_resize_accept(yutani_t * yctx, yutani_window_t * window, uint32_t width, uint32_t height) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_resize(YUTANI_MSG_RESIZE_ACCEPT, window->wid, width, height, 0);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
|
||||
/* Now wait for the new bufid */
|
||||
m = yutani_wait_for(yctx, YUTANI_MSG_RESIZE_BUFID);
|
||||
struct yutani_msg_window_resize * wr = (void*)m->data;
|
||||
|
||||
if (window->wid != wr->wid) {
|
||||
/* I am not sure what to do here. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update the window */
|
||||
window->width = wr->width;
|
||||
window->height = wr->height;
|
||||
window->oldbufid = window->bufid;
|
||||
window->bufid = wr->bufid;
|
||||
free(m);
|
||||
|
||||
/* Allocate the buffer */
|
||||
{
|
||||
char key[1024];
|
||||
YUTANI_SHMKEY(yctx->server_ident, key, 1024, window);
|
||||
|
||||
size_t size = (window->width * window->height * 4);
|
||||
window->buffer = (uint8_t *)syscall_shm_obtain(key, &size);
|
||||
}
|
||||
}
|
||||
|
||||
void yutani_window_resize_done(yutani_t * yctx, yutani_window_t * window) {
|
||||
/* Destroy the old buffer */
|
||||
{
|
||||
char key[1024];
|
||||
YUTANI_SHMKEY_EXP(yctx->server_ident, key, 1024, window->oldbufid);
|
||||
syscall_shm_release(key);
|
||||
}
|
||||
|
||||
yutani_msg_t * m = yutani_msg_build_window_resize(YUTANI_MSG_RESIZE_DONE, window->wid, window->width, window->height, window->bufid);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_window_advertise(yutani_t * yctx, yutani_window_t * window, char * name) {
|
||||
|
||||
uint32_t flags = 0; /* currently, no client flags */
|
||||
uint16_t offsets[5] = {0,0,0,0,0};
|
||||
uint32_t length = 0;
|
||||
char * strings;
|
||||
|
||||
if (!name) {
|
||||
length = 1;
|
||||
strings = " ";
|
||||
} else {
|
||||
length = strlen(name) + 1;
|
||||
strings = name;
|
||||
/* All the other offsets will point to null characters */
|
||||
offsets[1] = strlen(name);
|
||||
offsets[2] = strlen(name);
|
||||
offsets[3] = strlen(name);
|
||||
offsets[4] = strlen(name);
|
||||
}
|
||||
|
||||
yutani_msg_t * m = yutani_msg_build_window_advertise(window->wid, flags, offsets, length, strings);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_window_advertise_icon(yutani_t * yctx, yutani_window_t * window, char * name, char * icon) {
|
||||
|
||||
uint32_t flags = 0; /* currently no client flags */
|
||||
uint16_t offsets[5] = {0,0,0,0,0};
|
||||
uint32_t length = strlen(name) + strlen(icon) + 2;
|
||||
char * strings = malloc(length);
|
||||
|
||||
if (name) {
|
||||
memcpy(&strings[0], name, strlen(name)+1);
|
||||
offsets[0] = 0;
|
||||
offsets[1] = strlen(name);
|
||||
offsets[2] = strlen(name);
|
||||
offsets[3] = strlen(name);
|
||||
offsets[4] = strlen(name);
|
||||
}
|
||||
if (icon) {
|
||||
memcpy(&strings[offsets[1]+1], icon, strlen(icon)+1);
|
||||
offsets[1] = strlen(name)+1;
|
||||
offsets[2] = strlen(name)+1+strlen(icon);
|
||||
offsets[3] = strlen(name)+1+strlen(icon);
|
||||
offsets[4] = strlen(name)+1+strlen(icon);
|
||||
}
|
||||
|
||||
yutani_msg_t * m = yutani_msg_build_window_advertise(window->wid, flags, offsets, length, strings);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
free(strings);
|
||||
}
|
||||
|
||||
void yutani_subscribe_windows(yutani_t * y) {
|
||||
yutani_msg_t * m = yutani_msg_build_subscribe();
|
||||
int result = yutani_msg_send(y, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_unsubscribe_windows(yutani_t * y) {
|
||||
yutani_msg_t * m = yutani_msg_build_unsubscribe();
|
||||
int result = yutani_msg_send(y, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_query_windows(yutani_t * y) {
|
||||
yutani_msg_t * m = yutani_msg_build_query_windows();
|
||||
int result = yutani_msg_send(y, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_session_end(yutani_t * y) {
|
||||
yutani_msg_t * m = yutani_msg_build_session_end();
|
||||
int result = yutani_msg_send(y, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_focus_window(yutani_t * yctx, yutani_wid_t wid) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_focus(wid);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_key_bind(yutani_t * yctx, kbd_key_t key, kbd_mod_t mod, int response) {
|
||||
yutani_msg_t * m = yutani_msg_build_key_bind(key,mod,response);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_window_drag_start(yutani_t * yctx, yutani_window_t * window) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_drag_start(window->wid);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_window_drag_start_wid(yutani_t * yctx, yutani_wid_t wid) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_drag_start(wid);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_window_update_shape(yutani_t * yctx, yutani_window_t * window, int set_shape) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_update_shape(window->wid, set_shape);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_window_warp_mouse(yutani_t * yctx, yutani_window_t * window, int32_t x, int32_t y) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_warp_mouse(window->wid, x, y);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_window_show_mouse(yutani_t * yctx, yutani_window_t * window, int32_t show_mouse) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_show_mouse(window->wid, show_mouse);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_window_resize_start(yutani_t * yctx, yutani_window_t * window, yutani_scale_direction_t direction) {
|
||||
yutani_msg_t * m = yutani_msg_build_window_resize_start(window->wid, direction);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
void yutani_timer_request(yutani_t * yctx, uint32_t precision, uint32_t flags) {
|
||||
yutani_msg_t * m = yutani_msg_build_timer_request(precision, flags);
|
||||
int result = yutani_msg_send(yctx, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
gfx_context_t * init_graphics_yutani(yutani_window_t * window) {
|
||||
gfx_context_t * out = malloc(sizeof(gfx_context_t));
|
||||
out->width = window->width;
|
||||
out->height = window->height;
|
||||
out->depth = 32;
|
||||
out->size = GFX_H(out) * GFX_W(out) * GFX_B(out);
|
||||
out->buffer = window->buffer;
|
||||
out->backbuffer = out->buffer;
|
||||
return out;
|
||||
}
|
||||
|
||||
gfx_context_t * init_graphics_yutani_double_buffer(yutani_window_t * window) {
|
||||
gfx_context_t * out = init_graphics_yutani(window);
|
||||
out->backbuffer = malloc(GFX_B(out) * GFX_W(out) * GFX_H(out));
|
||||
return out;
|
||||
}
|
||||
|
||||
void reinit_graphics_yutani(gfx_context_t * out, yutani_window_t * window) {
|
||||
out->width = window->width;
|
||||
out->height = window->height;
|
||||
out->depth = 32;
|
||||
out->size = GFX_H(out) * GFX_W(out) * GFX_B(out);
|
||||
if (out->buffer == out->backbuffer) {
|
||||
out->buffer = window->buffer;
|
||||
out->backbuffer = out->buffer;
|
||||
} else {
|
||||
out->buffer = window->buffer;
|
||||
out->backbuffer = realloc(out->backbuffer, GFX_B(out) * GFX_W(out) * GFX_H(out));
|
||||
}
|
||||
}
|
||||
|
||||
void release_graphics_yutani(gfx_context_t * gfx) {
|
||||
if (gfx->backbuffer != gfx->buffer) {
|
||||
free(gfx->backbuffer);
|
||||
}
|
||||
free(gfx);
|
||||
}
|
471
lib/yutani.h
Normal file
471
lib/yutani.h
Normal file
@ -0,0 +1,471 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hashmap.h"
|
||||
#include "graphics.h"
|
||||
#include "kbd.h"
|
||||
#include "mouse.h"
|
||||
#include "list.h"
|
||||
|
||||
#define YUTANI_SHMKEY(server_ident,buf,sz,win) sprintf(buf, "sys.%s.%d", server_ident, win->bufid);
|
||||
#define YUTANI_SHMKEY_EXP(server_ident,buf,sz,bufid) sprintf(buf, "sys.%s.%d", server_ident, bufid);
|
||||
|
||||
typedef unsigned int yutani_wid_t;
|
||||
|
||||
typedef enum {
|
||||
SCALE_AUTO,
|
||||
|
||||
SCALE_UP,
|
||||
SCALE_DOWN,
|
||||
SCALE_LEFT,
|
||||
SCALE_RIGHT,
|
||||
|
||||
SCALE_UP_LEFT,
|
||||
SCALE_UP_RIGHT,
|
||||
SCALE_DOWN_LEFT,
|
||||
SCALE_DOWN_RIGHT,
|
||||
|
||||
SCALE_NONE,
|
||||
} yutani_scale_direction_t;
|
||||
|
||||
typedef struct yutani_context {
|
||||
FILE * sock;
|
||||
|
||||
/* XXX list of displays? */
|
||||
/* XXX display struct with more information? */
|
||||
size_t display_width;
|
||||
size_t display_height;
|
||||
|
||||
hashmap_t * windows;
|
||||
list_t * queued;
|
||||
|
||||
char * server_ident;
|
||||
} yutani_t;
|
||||
|
||||
typedef struct yutani_message {
|
||||
uint32_t magic;
|
||||
uint32_t type;
|
||||
uint32_t size;
|
||||
char data[];
|
||||
} yutani_msg_t;
|
||||
|
||||
struct yutani_msg_welcome {
|
||||
uint32_t display_width;
|
||||
uint32_t display_height;
|
||||
};
|
||||
|
||||
struct yutani_msg_flip {
|
||||
yutani_wid_t wid;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_close {
|
||||
yutani_wid_t wid;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_new {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_new_flags {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_init {
|
||||
yutani_wid_t wid;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t bufid;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_move {
|
||||
yutani_wid_t wid;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
};
|
||||
|
||||
struct yutani_msg_key_event {
|
||||
yutani_wid_t wid;
|
||||
key_event_t event;
|
||||
key_event_state_t state;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_stack {
|
||||
yutani_wid_t wid;
|
||||
int z;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_focus_change {
|
||||
yutani_wid_t wid;
|
||||
int focused;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_mouse_event {
|
||||
yutani_wid_t wid;
|
||||
int32_t new_x;
|
||||
int32_t new_y;
|
||||
int32_t old_x;
|
||||
int32_t old_y;
|
||||
uint8_t buttons;
|
||||
uint8_t command;
|
||||
};
|
||||
|
||||
struct yutani_msg_mouse_event {
|
||||
yutani_wid_t wid;
|
||||
mouse_device_packet_t event;
|
||||
int32_t type;
|
||||
};
|
||||
|
||||
struct yutani_msg_flip_region {
|
||||
yutani_wid_t wid;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_resize {
|
||||
yutani_wid_t wid;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t bufid;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_advertise {
|
||||
yutani_wid_t wid;
|
||||
uint32_t flags; /* Types, focused, etc. */
|
||||
uint16_t offsets[5]; /* Name, Icon, and three reserved slots */
|
||||
uint32_t size;
|
||||
char strings[];
|
||||
};
|
||||
|
||||
struct yutani_msg_window_focus {
|
||||
yutani_wid_t wid;
|
||||
};
|
||||
|
||||
struct yutani_msg_key_bind {
|
||||
kbd_key_t key;
|
||||
kbd_mod_t modifiers;
|
||||
int response;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_drag_start {
|
||||
yutani_wid_t wid;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_update_shape {
|
||||
yutani_wid_t wid;
|
||||
int set_shape;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_warp_mouse {
|
||||
yutani_wid_t wid;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_show_mouse {
|
||||
yutani_wid_t wid;
|
||||
int32_t show_mouse;
|
||||
};
|
||||
|
||||
struct yutani_msg_window_resize_start {
|
||||
yutani_wid_t wid;
|
||||
yutani_scale_direction_t direction;
|
||||
};
|
||||
|
||||
struct yutani_msg_timer_request {
|
||||
uint32_t precision;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
typedef struct yutani_window {
|
||||
yutani_wid_t wid;
|
||||
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
uint8_t * buffer;
|
||||
uint32_t bufid;/* We occasionally replace the buffer; each is uniquely-indexed */
|
||||
|
||||
uint8_t focused;
|
||||
|
||||
uint32_t oldbufid;
|
||||
} yutani_window_t;
|
||||
|
||||
/* Magic value */
|
||||
#define YUTANI_MSG__MAGIC 0xABAD1DEA
|
||||
|
||||
/* Client messages */
|
||||
#define YUTANI_MSG_HELLO 0x00000001
|
||||
#define YUTANI_MSG_WINDOW_NEW 0x00000002
|
||||
#define YUTANI_MSG_FLIP 0x00000003
|
||||
#define YUTANI_MSG_KEY_EVENT 0x00000004
|
||||
#define YUTANI_MSG_MOUSE_EVENT 0x00000005
|
||||
#define YUTANI_MSG_WINDOW_MOVE 0x00000006
|
||||
#define YUTANI_MSG_WINDOW_CLOSE 0x00000007
|
||||
#define YUTANI_MSG_WINDOW_SHOW 0x00000008
|
||||
#define YUTANI_MSG_WINDOW_HIDE 0x00000009
|
||||
#define YUTANI_MSG_WINDOW_STACK 0x0000000A
|
||||
#define YUTANI_MSG_WINDOW_FOCUS_CHANGE 0x0000000B
|
||||
#define YUTANI_MSG_WINDOW_MOUSE_EVENT 0x0000000C
|
||||
#define YUTANI_MSG_FLIP_REGION 0x0000000D
|
||||
#define YUTANI_MSG_WINDOW_NEW_FLAGS 0x0000000E
|
||||
|
||||
#define YUTANI_MSG_RESIZE_REQUEST 0x00000010
|
||||
#define YUTANI_MSG_RESIZE_OFFER 0x00000011
|
||||
#define YUTANI_MSG_RESIZE_ACCEPT 0x00000012
|
||||
#define YUTANI_MSG_RESIZE_BUFID 0x00000013
|
||||
#define YUTANI_MSG_RESIZE_DONE 0x00000014
|
||||
|
||||
/* Some session management / de stuff */
|
||||
#define YUTANI_MSG_WINDOW_ADVERTISE 0x00000020
|
||||
#define YUTANI_MSG_SUBSCRIBE 0x00000021
|
||||
#define YUTANI_MSG_UNSUBSCRIBE 0x00000022
|
||||
#define YUTANI_MSG_NOTIFY 0x00000023
|
||||
#define YUTANI_MSG_QUERY_WINDOWS 0x00000024
|
||||
#define YUTANI_MSG_WINDOW_FOCUS 0x00000025
|
||||
#define YUTANI_MSG_WINDOW_DRAG_START 0x00000026
|
||||
#define YUTANI_MSG_WINDOW_WARP_MOUSE 0x00000027
|
||||
#define YUTANI_MSG_WINDOW_SHOW_MOUSE 0x00000028
|
||||
#define YUTANI_MSG_WINDOW_RESIZE_START 0x00000029
|
||||
|
||||
#define YUTANI_MSG_SESSION_END 0x00000030
|
||||
|
||||
#define YUTANI_MSG_KEY_BIND 0x00000040
|
||||
|
||||
#define YUTANI_MSG_WINDOW_UPDATE_SHAPE 0x00000050
|
||||
|
||||
#define YUTANI_MSG_GOODBYE 0x000000F0
|
||||
|
||||
/* Timing Event Requests */
|
||||
#define YUTANI_MSG_TIMER_REQUEST 0x00000100
|
||||
#define YUTANI_MSG_TIMER_TICK 0x00000101
|
||||
|
||||
/* Server responses */
|
||||
#define YUTANI_MSG_WELCOME 0x00010001
|
||||
#define YUTANI_MSG_WINDOW_INIT 0x00010002
|
||||
|
||||
/*
|
||||
* YUTANI_ZORDER
|
||||
*
|
||||
* Specifies which stack set a window should appear in.
|
||||
*/
|
||||
#define YUTANI_ZORDER_MAX 0xFFFF
|
||||
#define YUTANI_ZORDER_TOP 0xFFFF
|
||||
#define YUTANI_ZORDER_BOTTOM 0x0000
|
||||
|
||||
/*
|
||||
* YUTANI_MOUSE_BUTTON
|
||||
*
|
||||
* Button specifiers. Multiple specifiers may be set.
|
||||
*/
|
||||
#define YUTANI_MOUSE_BUTTON_LEFT 0x01
|
||||
#define YUTANI_MOUSE_BUTTON_RIGHT 0x02
|
||||
#define YUTANI_MOUSE_BUTTON_MIDDLE 0x04
|
||||
#define YUTANI_MOUSE_SCROLL_UP 0x10
|
||||
#define YUTANI_MOUSE_SCROLL_DOWN 0x20
|
||||
|
||||
/*
|
||||
* YUTANI_MOUSE_STATE
|
||||
*
|
||||
* The mouse has for effective states internally:
|
||||
*
|
||||
* NORMAL: The mouse is performing normally.
|
||||
* MOVING: The mouse is engaged in moving a window.
|
||||
* DRAGGING: The mouse is down and sending drag events.
|
||||
* RESIZING: The mouse is engaged in resizing a window.
|
||||
*/
|
||||
#define YUTANI_MOUSE_STATE_NORMAL 0
|
||||
#define YUTANI_MOUSE_STATE_MOVING 1
|
||||
#define YUTANI_MOUSE_STATE_DRAGGING 2
|
||||
#define YUTANI_MOUSE_STATE_RESIZING 3
|
||||
#define YUTANI_MOUSE_STATE_ROTATING 4
|
||||
|
||||
/*
|
||||
* YUTANI_MOUSE_EVENT
|
||||
*
|
||||
* Mouse events have different types.
|
||||
*
|
||||
* Most of these should be self-explanatory.
|
||||
*
|
||||
* CLICK: A down-up click has occured.
|
||||
* DRAG: The mouse is down and moving.
|
||||
* RAISE: A mouse button was released.
|
||||
* DOWN: A mouse button has been pressed.
|
||||
* MOVE: The mouse has moved without a mouse button pressed.
|
||||
* LEAVE: The mouse has left the given window.
|
||||
* ENTER: The mouse has entered the given window.
|
||||
*/
|
||||
#define YUTANI_MOUSE_EVENT_CLICK 0
|
||||
#define YUTANI_MOUSE_EVENT_DRAG 1
|
||||
#define YUTANI_MOUSE_EVENT_RAISE 2
|
||||
#define YUTANI_MOUSE_EVENT_DOWN 3
|
||||
#define YUTANI_MOUSE_EVENT_MOVE 4
|
||||
#define YUTANI_MOUSE_EVENT_LEAVE 5
|
||||
#define YUTANI_MOUSE_EVENT_ENTER 6
|
||||
|
||||
/*
|
||||
* YUTANI_MOUSE_EVENT_TYPE
|
||||
*
|
||||
* (For mouse drivers)
|
||||
*
|
||||
* RELATIVE: Mouse positions are relative to the previous reported location.
|
||||
* ABSOLUTE: Mouse positions are in absolute coordinates.
|
||||
*/
|
||||
#define YUTANI_MOUSE_EVENT_TYPE_RELATIVE 0
|
||||
#define YUTANI_MOUSE_EVENT_TYPE_ABSOLUTE 1
|
||||
|
||||
/*
|
||||
* YUTANI_BIND
|
||||
*
|
||||
* Used to control keyboard binding modes.
|
||||
*
|
||||
* PASSTHROUGH: The key event will continue to the window that would have normally received.
|
||||
* STEAL: The key event will not be passed to the next window and is stolen by the bound window.
|
||||
*/
|
||||
#define YUTANI_BIND_PASSTHROUGH 0
|
||||
#define YUTANI_BIND_STEAL 1
|
||||
|
||||
/*
|
||||
* YUTANI_SHAPE_THRESHOLD
|
||||
*
|
||||
* Used with yutani_window_update_shape to set the alpha threshold for window shaping.
|
||||
* All windows are shaped based on their transparency (alpha channel). The default
|
||||
* mode is NONE - meaning the alpha channel is ignored.
|
||||
*
|
||||
* NONE: The window is always clickable, regardless of alpha transparency.
|
||||
* CLEAR: Only completely clear (alpha = 0) regions will pass through.
|
||||
* HALF: Threshold of 50% - alpha values below 127 will pass through. Good for most cases.
|
||||
* ANY: Any amount of alpha transparency will pass through - only fully opaque regions are kept.
|
||||
* PASSTHROUGH: All clicks pass through. Useful for tooltips / overlays.
|
||||
*/
|
||||
#define YUTANI_SHAPE_THRESHOLD_NONE 0
|
||||
#define YUTANI_SHAPE_THRESHOLD_CLEAR 1
|
||||
#define YUTANI_SHAPE_THRESHOLD_HALF 127
|
||||
#define YUTANI_SHAPE_THRESHOLD_ANY 255
|
||||
#define YUTANI_SHAPE_THRESHOLD_PASSTHROUGH 256
|
||||
|
||||
/*
|
||||
* YUTANI_CURSOR_TYPE
|
||||
*
|
||||
* Used with SHOW_MOUSE to set the cursor type for this window.
|
||||
* Note that modifications made to the cursor will only display
|
||||
* while it the current window is active and that cursor settings
|
||||
* are per-window, not per-application.
|
||||
*
|
||||
* HIDE: Disable the mouse cursor. Useful for games.
|
||||
* NORMAL: The normal arrow cursor.
|
||||
* DRAG: A 4-directional arrow.
|
||||
* RESIZE_VERTICAL: An up-down arrow / resize indicator.
|
||||
* RESIZE_HORIZONTAL: A left-right arrow / resize indicator.
|
||||
* RESIZE_UP_DOWN: A diagonal \-shaped arrow.
|
||||
* RESIZE_DOWN_UP: A diagonal /-shaped arrow.
|
||||
*
|
||||
* RESET: If the cursor was previously hidden, hide it again.
|
||||
* Otherwise, show the normal cursor. Allows for decorator
|
||||
* to set resize cursors without having to know if a window
|
||||
* had set the default mode to HIDE.
|
||||
*/
|
||||
#define YUTANI_CURSOR_TYPE_RESET -1
|
||||
#define YUTANI_CURSOR_TYPE_HIDE 0
|
||||
#define YUTANI_CURSOR_TYPE_NORMAL 1
|
||||
#define YUTANI_CURSOR_TYPE_DRAG 2
|
||||
#define YUTANI_CURSOR_TYPE_RESIZE_VERTICAL 3
|
||||
#define YUTANI_CURSOR_TYPE_RESIZE_HORIZONTAL 4
|
||||
#define YUTANI_CURSOR_TYPE_RESIZE_UP_DOWN 5
|
||||
#define YUTANI_CURSOR_TYPE_RESIZE_DOWN_UP 6
|
||||
|
||||
/*
|
||||
* YUTANI_WINDOW_FLAG
|
||||
*
|
||||
* Flags for new windows describing how the window
|
||||
* should be created.
|
||||
*/
|
||||
#define YUTANI_WINDOW_FLAG_NO_STEAL_FOCUS (1 << 0)
|
||||
#define YUTANI_WINDOW_FLAG_DISALLOW_DRAG (1 << 1)
|
||||
#define YUTANI_WINDOW_FLAG_DISALLOW_RESIZE (1 << 2)
|
||||
#define YUTANI_WINDOW_FLAG_ALT_ANIMATION (1 << 3)
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
} yutani_damage_rect_t;
|
||||
|
||||
extern yutani_msg_t * yutani_wait_for(yutani_t * y, uint32_t type);
|
||||
extern yutani_msg_t * yutani_poll(yutani_t * y);
|
||||
extern yutani_msg_t * yutani_poll_async(yutani_t * y);
|
||||
extern size_t yutani_query(yutani_t * y);
|
||||
|
||||
extern yutani_msg_t * yutani_msg_build_hello(void);
|
||||
extern yutani_msg_t * yutani_msg_build_welcome(uint32_t width, uint32_t height);
|
||||
extern yutani_msg_t * yutani_msg_build_window_new(uint32_t width, uint32_t height);
|
||||
extern yutani_msg_t * yutani_msg_build_window_new_flags(uint32_t width, uint32_t height, uint32_t flags);
|
||||
extern yutani_msg_t * yutani_msg_build_window_init(yutani_wid_t wid, uint32_t width, uint32_t height, uint32_t bufid);
|
||||
extern yutani_msg_t * yutani_msg_build_flip(yutani_wid_t);
|
||||
extern yutani_msg_t * yutani_msg_build_key_event(yutani_wid_t wid, key_event_t * event, key_event_state_t * state);
|
||||
extern yutani_msg_t * yutani_msg_build_mouse_event(yutani_wid_t wid, mouse_device_packet_t * event, int32_t type);
|
||||
extern yutani_msg_t * yutani_msg_build_window_move(yutani_wid_t wid, int32_t x, int32_t y);
|
||||
extern yutani_msg_t * yutani_msg_build_window_close(yutani_wid_t wid);
|
||||
extern yutani_msg_t * yutani_msg_build_window_stack(yutani_wid_t wid, int z);
|
||||
extern yutani_msg_t * yutani_msg_build_window_focus_change(yutani_wid_t wid, int focused);
|
||||
extern yutani_msg_t * yutani_msg_build_window_mouse_event(yutani_wid_t wid, int32_t new_x, int32_t new_y, int32_t old_x, int32_t old_y, uint8_t buttons, uint8_t command);
|
||||
extern yutani_msg_t * yutani_msg_build_window_resize(uint32_t type, yutani_wid_t wid, uint32_t width, uint32_t height, uint32_t bufid);
|
||||
extern yutani_msg_t * yutani_msg_build_window_advertise(yutani_wid_t wid, uint32_t flags, uint16_t * offsets, size_t length, char * data);
|
||||
extern yutani_msg_t * yutani_msg_build_subscribe(void);
|
||||
extern yutani_msg_t * yutani_msg_build_unsubscribe(void);
|
||||
extern yutani_msg_t * yutani_msg_build_query(void);
|
||||
extern yutani_msg_t * yutani_msg_build_notify(void);
|
||||
extern yutani_msg_t * yutani_msg_build_session_end(void);
|
||||
extern yutani_msg_t * yutani_msg_build_window_focus(yutani_wid_t wid);
|
||||
extern yutani_msg_t * yutani_msg_build_key_bind(kbd_key_t key, kbd_mod_t mod, int response);
|
||||
extern yutani_msg_t * yutani_msg_build_window_drag_start(yutani_wid_t wid);
|
||||
extern yutani_msg_t * yutani_msg_build_window_update_shape(yutani_wid_t wid, int set_shape);
|
||||
extern yutani_msg_t * yutani_msg_build_window_warp_mouse(yutani_wid_t wid, int32_t x, int32_t y);
|
||||
extern yutani_msg_t * yutani_msg_build_window_show_mouse(yutani_wid_t wid, int32_t show_mouse);
|
||||
extern yutani_msg_t * yutani_msg_build_window_resize_start(yutani_wid_t wid, yutani_scale_direction_t direction);
|
||||
extern yutani_msg_t * yutani_msg_build_timer_request(uint32_t precision, uint32_t flags);
|
||||
extern yutani_msg_t * yutani_msg_build_timer_tick(void);
|
||||
|
||||
|
||||
extern int yutani_msg_send(yutani_t * y, yutani_msg_t * msg);
|
||||
extern yutani_t * yutani_context_create(FILE * socket);
|
||||
extern yutani_t * yutani_init(void);
|
||||
extern yutani_window_t * yutani_window_create(yutani_t * y, int width, int height);
|
||||
extern yutani_window_t * yutani_window_create_flags(yutani_t * y, int width, int height, uint32_t flags);
|
||||
extern void yutani_flip(yutani_t * y, yutani_window_t * win);
|
||||
extern void yutani_window_move(yutani_t * yctx, yutani_window_t * window, int x, int y);
|
||||
extern void yutani_close(yutani_t * y, yutani_window_t * win);
|
||||
extern void yutani_set_stack(yutani_t *, yutani_window_t *, int);
|
||||
extern void yutani_flip_region(yutani_t *, yutani_window_t * win, int32_t x, int32_t y, int32_t width, int32_t height);
|
||||
extern void yutani_window_resize(yutani_t * yctx, yutani_window_t * window, uint32_t width, uint32_t height);
|
||||
extern void yutani_window_resize_offer(yutani_t * yctx, yutani_window_t * window, uint32_t width, uint32_t height);
|
||||
extern void yutani_window_resize_accept(yutani_t * yctx, yutani_window_t * window, uint32_t width, uint32_t height);
|
||||
extern void yutani_window_resize_done(yutani_t * yctx, yutani_window_t * window);
|
||||
extern void yutani_window_advertise(yutani_t * yctx, yutani_window_t * window, char * name);
|
||||
extern void yutani_window_advertise_icon(yutani_t * yctx, yutani_window_t * window, char * name, char * icon);
|
||||
extern void yutani_subscribe_windows(yutani_t * y);
|
||||
extern void yutani_unsubscribe_windows(yutani_t * y);
|
||||
extern void yutani_query_windows(yutani_t * y);
|
||||
extern void yutani_session_end(yutani_t * y);
|
||||
extern void yutani_focus_window(yutani_t * y, yutani_wid_t wid);
|
||||
extern void yutani_key_bind(yutani_t * yctx, kbd_key_t key, kbd_mod_t mod, int response);
|
||||
extern void yutani_window_drag_start(yutani_t * yctx, yutani_window_t * window);
|
||||
extern void yutani_window_update_shape(yutani_t * yctx, yutani_window_t * window, int set_shape);
|
||||
extern void yutani_window_warp_mouse(yutani_t * yctx, yutani_window_t * window, int32_t x, int32_t y);
|
||||
extern void yutani_window_show_mouse(yutani_t * yctx, yutani_window_t * window, int32_t show_mouse);
|
||||
extern void yutani_window_resize_start(yutani_t * yctx, yutani_window_t * window, yutani_scale_direction_t direction);
|
||||
extern void yutani_timer_request(yutani_t * yctx, uint32_t precision, uint32_t flags);
|
||||
|
||||
|
||||
extern gfx_context_t * init_graphics_yutani(yutani_window_t * window);
|
||||
extern gfx_context_t * init_graphics_yutani_double_buffer(yutani_window_t * window);
|
||||
extern void reinit_graphics_yutani(gfx_context_t * out, yutani_window_t * window);
|
||||
extern void release_graphics_yutani(gfx_context_t * gfx);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <string.h>
|
||||
|
||||
extern char ** environ;
|
||||
extern int _environ_size;
|
||||
|
||||
char * getenv(const char *name) {
|
||||
char ** e = environ;
|
||||
|
@ -71,6 +71,7 @@ extern void _init();
|
||||
extern void _fini();
|
||||
|
||||
char ** environ;
|
||||
int _environ_size = 0;
|
||||
|
||||
void _exit(int val){
|
||||
_fini();
|
||||
|
40
libc/stdio.c
40
libc/stdio.c
@ -21,9 +21,32 @@ FILE * stdout = &_stdout;
|
||||
FILE * stderr = &_stderr;
|
||||
|
||||
FILE * fopen(const char *path, const char *mode) {
|
||||
// TODO parse mode
|
||||
|
||||
int fd = syscall_open(path, 0, 0);
|
||||
const char * x = mode;
|
||||
|
||||
int flags = 0;
|
||||
int mask = 0;
|
||||
|
||||
while (*x) {
|
||||
if (*x == 'a') {
|
||||
flags |= 0x08;
|
||||
flags |= 0x01;
|
||||
}
|
||||
if (*x == 'w') {
|
||||
flags |= 0x01;
|
||||
}
|
||||
if (*x == '+') {
|
||||
if (flags & 0x01) {
|
||||
flags |= 0x200;
|
||||
mask = 0666;
|
||||
} else {
|
||||
flags |= 0x01;
|
||||
}
|
||||
}
|
||||
++x;
|
||||
}
|
||||
|
||||
int fd = syscall_open(path, flags, mask);
|
||||
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
@ -35,6 +58,13 @@ FILE * fopen(const char *path, const char *mode) {
|
||||
return out;
|
||||
}
|
||||
|
||||
FILE * fdopen(int fd, const char *mode){
|
||||
FILE * out = malloc(sizeof(FILE));
|
||||
out->fd = fd;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int fclose(FILE * stream) {
|
||||
return syscall_close(stream->fd);
|
||||
}
|
||||
@ -48,7 +78,7 @@ int fseek(FILE * stream, long offset, int whence) {
|
||||
}
|
||||
|
||||
long ftell(FILE * stream) {
|
||||
return fseek(stream, 0, SEEK_CUR);
|
||||
return syscall_lseek(stream->fd, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
|
||||
@ -143,3 +173,7 @@ char *fgets(char *s, int size, FILE *stream) {
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void setbuf(FILE * stream, char * buf) {
|
||||
// ...
|
||||
}
|
||||
|
@ -151,3 +151,8 @@ ssize_t readlink(const char * name, char * buf, size_t len) {
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int usleep(useconds_t usec) {
|
||||
syscall_nanosleep(0, usec / 10000);
|
||||
return 0;
|
||||
}
|
||||
|
1096
libc/wcwidth.c
Normal file
1096
libc/wcwidth.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,14 +16,14 @@
|
||||
|
||||
extern char** environ;
|
||||
|
||||
//#include <_xlog.h>
|
||||
#define _XLOG(...)
|
||||
|
||||
#define TRACE_APP_NAME "ld.so"
|
||||
#define TRACE_LD(...)
|
||||
#define TRACE_LD(...) do { if (__trace_ld) { TRACE(__VA_ARGS__); } } while (0)
|
||||
|
||||
static int __trace_ld = 0;
|
||||
|
||||
#include "../lib/trace.h"
|
||||
|
||||
#include "../lib/list.c"
|
||||
#include "../lib/hashmap.c"
|
||||
|
||||
@ -75,45 +75,32 @@ static char * find_lib(const char * file) {
|
||||
|
||||
if (strchr(file, '/')) return strdup(file);
|
||||
|
||||
_XLOG("checking path");
|
||||
char * path = getenv("LD_LIBRARY_PATH");
|
||||
if (!path) {
|
||||
path = "/usr/lib:/lib:/opt/lib";
|
||||
}
|
||||
_XLOG("path is");
|
||||
_XLOG(path);
|
||||
char * xpath = strdup(path);
|
||||
int found = 0;
|
||||
char * p, * tokens[10], * last;
|
||||
int i = 0;
|
||||
for ((p = strtok_r(xpath, ":", &last)); p; p = strtok_r(NULL, ":", &last)) {
|
||||
_XLOG("step");
|
||||
_XLOG(p);
|
||||
int r;
|
||||
struct stat stat_buf;
|
||||
_XLOG("malloc");
|
||||
char * exe = malloc(strlen(p) + strlen(file) + 2);
|
||||
_XLOG(exe);
|
||||
_XLOG("strcpy");
|
||||
memcpy(exe, p, strlen(p) + 1);
|
||||
//strcpy(exe, p);
|
||||
_XLOG("strcat");
|
||||
strcat(exe, "/");
|
||||
_XLOG("strcat");
|
||||
strcat(exe, file);
|
||||
_XLOG("stat");
|
||||
|
||||
r = stat(exe, &stat_buf);
|
||||
if (r != 0) {
|
||||
free(exe);
|
||||
continue;
|
||||
}
|
||||
_XLOG("found");
|
||||
return exe;
|
||||
}
|
||||
free(xpath);
|
||||
|
||||
_XLOG("not found");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -125,24 +112,20 @@ static elf_t * open_object(const char * path) {
|
||||
return _main_obj;
|
||||
}
|
||||
|
||||
_XLOG("hashmap check");
|
||||
if (hashmap_has(objects_map, (void*)path)) {
|
||||
elf_t * object = hashmap_get(objects_map, (void*)path);
|
||||
object->loaded = 1;
|
||||
return object;
|
||||
}
|
||||
|
||||
_XLOG("find lib");
|
||||
char * file = find_lib(path);
|
||||
if (!file) {
|
||||
last_error = "Could not find library.";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_XLOG("open");
|
||||
FILE * f = fopen(file, "r");
|
||||
|
||||
_XLOG("free string");
|
||||
free(file);
|
||||
|
||||
if (!f) {
|
||||
@ -150,7 +133,6 @@ static elf_t * open_object(const char * path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_XLOG("hash set");
|
||||
elf_t * object = calloc(1, sizeof(elf_t));
|
||||
hashmap_set(objects_map, (void*)path, object);
|
||||
|
||||
@ -161,7 +143,6 @@ static elf_t * open_object(const char * path) {
|
||||
|
||||
object->file = f;
|
||||
|
||||
_XLOG("header read");
|
||||
size_t r = fread(&object->header, sizeof(Elf32_Header), 1, object->file);
|
||||
|
||||
if (!r) {
|
||||
@ -274,17 +255,12 @@ static int object_postload(elf_t * object) {
|
||||
|
||||
/* Load section string table */
|
||||
{
|
||||
_XLOG("Load section string table.");
|
||||
Elf32_Shdr shdr;
|
||||
fseek(object->file, object->header.e_shoff + object->header.e_shentsize * object->header.e_shstrndx, SEEK_SET);
|
||||
_XLOG("read");
|
||||
fread(&shdr, object->header.e_shentsize, 1, object->file);
|
||||
object->string_table = malloc(shdr.sh_size);
|
||||
_XLOG("seek");
|
||||
fseek(object->file, shdr.sh_offset, SEEK_SET);
|
||||
_XLOG("read");
|
||||
fread(object->string_table, shdr.sh_size, 1, object->file);
|
||||
_XLOG("Done.");
|
||||
}
|
||||
|
||||
if (object->dynamic) {
|
||||
@ -600,7 +576,6 @@ int main(int argc, char * argv[]) {
|
||||
char * file = argv[1];
|
||||
size_t arg_offset = 1;
|
||||
|
||||
_XLOG("ld starting");
|
||||
|
||||
if (!strcmp(argv[1], "-e")) {
|
||||
arg_offset = 3;
|
||||
@ -608,7 +583,7 @@ int main(int argc, char * argv[]) {
|
||||
}
|
||||
|
||||
char * trace_ld_env = getenv("LD_DEBUG");
|
||||
if (trace_ld_env && (!strcmp(trace_ld_env,"1") || !strcmp(trace_ld_env,"yes"))) {
|
||||
if ((trace_ld_env && (!strcmp(trace_ld_env,"1") || !strcmp(trace_ld_env,"yes")))) {
|
||||
__trace_ld = 1;
|
||||
}
|
||||
|
||||
@ -622,24 +597,19 @@ int main(int argc, char * argv[]) {
|
||||
ex++;
|
||||
}
|
||||
|
||||
_XLOG("Opening main object");
|
||||
elf_t * main_obj = open_object(file);
|
||||
_main_obj = main_obj;
|
||||
_XLOG("Done.");
|
||||
|
||||
if (!main_obj) {
|
||||
//fprintf(stderr, "%s: error: failed to open object '%s'.\n", argv[0], file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
_XLOG("calculating sizes");
|
||||
size_t main_size = object_calculate_size(main_obj);
|
||||
uintptr_t end_addr = object_load(main_obj, 0x0);
|
||||
|
||||
_XLOG("post load");
|
||||
object_postload(main_obj);
|
||||
|
||||
_XLOG("find relocations");
|
||||
object_find_copy_relocations(main_obj);
|
||||
|
||||
hashmap_t * libs = hashmap_create(10);
|
||||
@ -651,38 +621,30 @@ int main(int argc, char * argv[]) {
|
||||
list_t * ctor_libs = list_create();
|
||||
list_t * init_libs = list_create();
|
||||
|
||||
_XLOG("loading dependencies");
|
||||
TRACE_LD("Loading dependencies.");
|
||||
node_t * item;
|
||||
while (item = list_pop(main_obj->dependencies)) {
|
||||
_XLOG("loading a dependency");
|
||||
while (end_addr & 0xFFF) {
|
||||
end_addr++;
|
||||
}
|
||||
|
||||
char * lib_name = item->value;
|
||||
_XLOG(lib_name);
|
||||
if (!strcmp(lib_name, "libg.so")) goto nope;
|
||||
_XLOG("opening it");
|
||||
elf_t * lib = open_object(lib_name);
|
||||
if (!lib) {
|
||||
//fprintf(stderr, "Failed to load dependency '%s'.\n", lib_name);
|
||||
_XLOG("Failure to load!");
|
||||
return 1;
|
||||
}
|
||||
hashmap_set(libs, lib_name, lib);
|
||||
|
||||
_XLOG("loading it");
|
||||
TRACE_LD("Loading %s at 0x%x", lib_name, end_addr);
|
||||
end_addr = object_load(lib, end_addr);
|
||||
object_postload(lib);
|
||||
_XLOG("relocating it");
|
||||
TRACE_LD("Relocating %s", lib_name);
|
||||
object_relocate(lib);
|
||||
|
||||
fclose(lib->file);
|
||||
|
||||
_XLOG("queing its constructors");
|
||||
/* Execute constructors */
|
||||
if (lib->ctors || lib->init_array) {
|
||||
list_insert(ctor_libs, lib);
|
||||
@ -694,7 +656,6 @@ int main(int argc, char * argv[]) {
|
||||
nope:
|
||||
free(item);
|
||||
}
|
||||
_XLOG("done with that, time to relocate some shit");
|
||||
|
||||
TRACE_LD("Relocating main object");
|
||||
object_relocate(main_obj);
|
||||
|
30
session.c
Normal file
30
session.c
Normal file
@ -0,0 +1,30 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <syscall.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
|
||||
int _background_pid = fork();
|
||||
if (!_background_pid) {
|
||||
char * args[] = {"/bin/background", NULL};
|
||||
execvp(args[0], args);
|
||||
}
|
||||
int _terminal_pid = fork();
|
||||
if (!_terminal_pid) {
|
||||
char * args[] = {"/bin/terminal", NULL};
|
||||
execvp(args[0], args);
|
||||
}
|
||||
|
||||
wait(NULL);
|
||||
|
||||
int pid;
|
||||
do {
|
||||
pid = waitpid(-1, NULL, 0);
|
||||
} while ((pid > 0) || (pid == -1 && errno == EINTR));
|
||||
|
||||
return 0;
|
||||
}
|
1727
terminal-font.h
Normal file
1727
terminal-font.h
Normal file
File diff suppressed because it is too large
Load Diff
265
terminal-palette.h
Normal file
265
terminal-palette.h
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Terminal palette
|
||||
*/
|
||||
|
||||
#define PALETTE_COLORS 256
|
||||
|
||||
uint32_t term_colors[PALETTE_COLORS] = {
|
||||
/* black */ 0x2e3436,
|
||||
/* red */ 0xcc0000,
|
||||
/* green */ 0x3e9a06,
|
||||
/* brown */ 0xc4a000,
|
||||
/* navy */ 0x3465a4,
|
||||
/* purple */ 0x75507b,
|
||||
/* d cyan */ 0x06989a,
|
||||
/* gray */ 0xeeeeec,
|
||||
/* d gray */ 0x555753,
|
||||
/* red */ 0xef2929,
|
||||
/* green */ 0x8ae234,
|
||||
/* yellow */ 0xfce94f,
|
||||
/* blue */ 0x729fcf,
|
||||
/* magenta*/ 0xad7fa8,
|
||||
/* cyan */ 0x34e2e2,
|
||||
/* white */ 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,
|
||||
};
|
||||
|
1596
terminal.c
Normal file
1596
terminal.c
Normal file
File diff suppressed because it is too large
Load Diff
117
uname.c
Normal file
117
uname.c
Normal file
@ -0,0 +1,117 @@
|
||||
/* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2013 Kevin Lange
|
||||
*/
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
*
|
||||
* uname
|
||||
*
|
||||
* Prints the kernel version information.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <syscall.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define FLAG_SYSNAME 0x01
|
||||
#define FLAG_NODENAME 0x02
|
||||
#define FLAG_RELEASE 0x04
|
||||
#define FLAG_VERSION 0x08
|
||||
#define FLAG_MACHINE 0x10
|
||||
|
||||
#define FLAG_ALL (FLAG_SYSNAME|FLAG_NODENAME|FLAG_RELEASE|FLAG_VERSION|FLAG_MACHINE)
|
||||
|
||||
#define _ITALIC "\033[3m"
|
||||
#define _END "\033[0m\n"
|
||||
|
||||
void show_usage(int argc, char * argv[]) {
|
||||
fprintf(stderr,
|
||||
"uname - Print system version information.\n"
|
||||
"\n"
|
||||
"usage: %s [-asnrvm]\n"
|
||||
"\n"
|
||||
" -a " _ITALIC "Print the standard uname string we all love" _END
|
||||
" -s " _ITALIC "Print kernel name" _END
|
||||
" -n " _ITALIC "Print system name" _END
|
||||
" -r " _ITALIC "Print kernel version number" _END
|
||||
" -v " _ITALIC "Print the extra kernel version information" _END
|
||||
" -m " _ITALIC "Print the architecture name" _END
|
||||
"\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
struct utsname u;
|
||||
|
||||
int c;
|
||||
int flags = 0;
|
||||
int space = 0;
|
||||
|
||||
#if 0
|
||||
while ((c = getopt(argc, argv, "ahmnrsv")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
flags |= FLAG_ALL;
|
||||
break;
|
||||
case 's':
|
||||
flags |= FLAG_SYSNAME;
|
||||
break;
|
||||
case 'n':
|
||||
flags |= FLAG_NODENAME;
|
||||
break;
|
||||
case 'r':
|
||||
flags |= FLAG_RELEASE;
|
||||
break;
|
||||
case 'v':
|
||||
flags |= FLAG_VERSION;
|
||||
break;
|
||||
case 'm':
|
||||
flags |= FLAG_MACHINE;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
show_usage(argc, argv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
flags |= FLAG_ALL;
|
||||
#endif
|
||||
|
||||
uname(&u);
|
||||
|
||||
if (!flags) {
|
||||
/* By default, we just print the kernel name */
|
||||
flags = FLAG_SYSNAME;
|
||||
}
|
||||
|
||||
if (flags & FLAG_SYSNAME) {
|
||||
if (space++) printf(" ");
|
||||
printf("%s", u.sysname);
|
||||
}
|
||||
|
||||
if (flags & FLAG_NODENAME) {
|
||||
if (space++) printf(" ");
|
||||
printf("%s", u.nodename);
|
||||
}
|
||||
|
||||
if (flags & FLAG_RELEASE) {
|
||||
if (space++) printf(" ");
|
||||
printf("%s", u.release);
|
||||
}
|
||||
|
||||
if (flags & FLAG_VERSION) {
|
||||
if (space++) printf(" ");
|
||||
printf("%s", u.version);
|
||||
}
|
||||
|
||||
if (flags & FLAG_MACHINE) {
|
||||
if (space++) printf(" ");
|
||||
printf("%s", u.machine);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
192
yutani_int.h
Normal file
192
yutani_int.h
Normal file
@ -0,0 +1,192 @@
|
||||
#pragma once
|
||||
|
||||
#include "lib/yutani.h"
|
||||
#include "lib/list.h"
|
||||
#include "lib/hashmap.h"
|
||||
#include "lib/graphics.h"
|
||||
#include "lib/kbd.h"
|
||||
|
||||
#define MOUSE_SCALE 3
|
||||
#define MOUSE_OFFSET_X 26
|
||||
#define MOUSE_OFFSET_Y 26
|
||||
|
||||
#define YUTANI_BYTE_DEPTH 4
|
||||
|
||||
#define YUTANI_SCREENSHOT_FULL 1
|
||||
#define YUTANI_SCREENSHOT_WINDOW 2
|
||||
|
||||
typedef void cairo_t;
|
||||
typedef void cairo_surface_t;
|
||||
|
||||
typedef enum {
|
||||
YUTANI_EFFECT_NONE,
|
||||
YUTANI_EFFECT_FADE_IN,
|
||||
YUTANI_EFFECT_FADE_OUT,
|
||||
YUTANI_EFFECT_MINIMIZE,
|
||||
YUTANI_EFFECT_UNMINIMIZE,
|
||||
} yutani_effect;
|
||||
|
||||
static int yutani_animation_lengths[] = {
|
||||
0,
|
||||
200,
|
||||
200,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
yutani_wid_t wid;
|
||||
|
||||
signed long x;
|
||||
signed long y;
|
||||
unsigned short z;
|
||||
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
|
||||
uint8_t * buffer;
|
||||
uint32_t bufid;
|
||||
|
||||
uint32_t owner;
|
||||
|
||||
int16_t rotation;
|
||||
|
||||
uint32_t newbufid;
|
||||
uint8_t * newbuffer;
|
||||
|
||||
uint32_t client_flags;
|
||||
uint16_t client_offsets[5];
|
||||
uint32_t client_length;
|
||||
char * client_strings;
|
||||
|
||||
int anim_mode;
|
||||
uint32_t anim_start;
|
||||
|
||||
int alpha_threshold;
|
||||
int show_mouse;
|
||||
|
||||
int tiled;
|
||||
int32_t untiled_width;
|
||||
int32_t untiled_height;
|
||||
|
||||
int default_mouse;
|
||||
uint32_t server_flags;
|
||||
|
||||
int opacity;
|
||||
} yutani_server_window_t;
|
||||
|
||||
typedef struct {
|
||||
/* XXX multiple displays */
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
|
||||
cairo_surface_t * framebuffer_surface;
|
||||
cairo_surface_t * real_surface;
|
||||
cairo_t * framebuffer_ctx;
|
||||
cairo_t * real_ctx;
|
||||
|
||||
void * backend_framebuffer;
|
||||
gfx_context_t * backend_ctx;
|
||||
|
||||
signed int mouse_x;
|
||||
signed int mouse_y;
|
||||
|
||||
signed int last_mouse_x;
|
||||
signed int last_mouse_y;
|
||||
|
||||
list_t * windows;
|
||||
hashmap_t * wids_to_windows;
|
||||
|
||||
yutani_server_window_t * bottom_z;
|
||||
list_t * mid_zs;
|
||||
yutani_server_window_t * top_z;
|
||||
|
||||
list_t * update_list;
|
||||
volatile int update_list_lock;
|
||||
|
||||
sprite_t mouse_sprite;
|
||||
|
||||
char * server_ident;
|
||||
|
||||
yutani_server_window_t * focused_window;
|
||||
FILE * server;
|
||||
|
||||
int mouse_state;
|
||||
yutani_server_window_t * mouse_window;
|
||||
|
||||
int mouse_win_x;
|
||||
int mouse_win_y;
|
||||
int mouse_init_x;
|
||||
int mouse_init_y;
|
||||
int mouse_init_r;
|
||||
|
||||
int mouse_drag_button;
|
||||
int mouse_moved;
|
||||
|
||||
int32_t mouse_click_x;
|
||||
int32_t mouse_click_y;
|
||||
|
||||
key_event_state_t kbd_state;
|
||||
|
||||
yutani_server_window_t * resizing_window;
|
||||
int32_t resizing_w;
|
||||
int32_t resizing_h;
|
||||
|
||||
list_t * window_subscribers;
|
||||
|
||||
uint32_t start_time;
|
||||
|
||||
volatile int redraw_lock;
|
||||
|
||||
yutani_server_window_t * old_hover_window;
|
||||
|
||||
hashmap_t * key_binds;
|
||||
|
||||
list_t * windows_to_remove;
|
||||
|
||||
yutani_t * host_context;
|
||||
yutani_window_t * host_window;
|
||||
|
||||
hashmap_t * clients_to_windows;
|
||||
|
||||
int debug_bounds;
|
||||
int debug_shapes;
|
||||
|
||||
int screenshot_frame;
|
||||
|
||||
uint32_t start_subtime;
|
||||
|
||||
yutani_scale_direction_t resizing_direction;
|
||||
int32_t resizing_offset_x;
|
||||
int32_t resizing_offset_y;
|
||||
int resizing_button;
|
||||
|
||||
sprite_t mouse_sprite_drag;
|
||||
sprite_t mouse_sprite_resize_v;
|
||||
sprite_t mouse_sprite_resize_h;
|
||||
sprite_t mouse_sprite_resize_da;
|
||||
sprite_t mouse_sprite_resize_db;
|
||||
|
||||
int current_cursor;
|
||||
int resize_on_next;
|
||||
|
||||
uint32_t timer_precison;
|
||||
list_t * timer_subscribers;
|
||||
|
||||
uint32_t last_mouse_buttons;
|
||||
|
||||
uint32_t stride;
|
||||
|
||||
int32_t mouse_click_x_orig;
|
||||
int32_t mouse_click_y_orig;
|
||||
} yutani_globals_t;
|
||||
|
||||
struct key_bind {
|
||||
unsigned int owner;
|
||||
int response;
|
||||
};
|
||||
|
||||
static void mark_window(yutani_globals_t * yg, yutani_server_window_t * window);
|
||||
static void window_actually_close(yutani_globals_t * yg, yutani_server_window_t * w);
|
||||
static void notify_subscribers(yutani_globals_t * yg);
|
||||
|
Loading…
Reference in New Issue
Block a user