Quick and dirty display server nesting - lots of mouse event changes

This commit is contained in:
Kevin Lange 2014-05-26 12:43:22 -07:00
parent ed36fe9c7f
commit ab2a9f056f
8 changed files with 168 additions and 65 deletions

View File

@ -9,8 +9,8 @@ typedef enum {
typedef struct {
uint32_t magic;
int8_t x_difference;
int8_t y_difference;
int32_t x_difference;
int32_t y_difference;
mouse_click_t buttons;
} mouse_device_packet_t;

View File

@ -14,8 +14,8 @@ char * __kernel_version_format = "%d.%d.%d-%s";
/* Version numbers X.Y.Z */
int __kernel_version_major = 0;
int __kernel_version_minor = 7;
int __kernel_version_lower = 2;
int __kernel_version_minor = 8;
int __kernel_version_lower = 0;
/* Kernel build suffix, which doesn't necessarily
* mean anything, but can be used to distinguish

View File

@ -33,8 +33,8 @@ struct {
int nest_height;
} yutani_options = {
.nested = 0,
.nest_width = 0,
.nest_height = 0
.nest_width = 640,
.nest_height = 480,
};
@ -302,7 +302,7 @@ static yutani_server_window_t * server_window_create(yutani_globals_t * yg, int
win->anim_start = yg->tick_count;
char key[1024];
YUTANI_SHMKEY(key, 1024, win);
YUTANI_SHMKEY(yg->server_ident, key, 1024, win);
size_t size = (width * height * 4);
win->buffer = (uint8_t *)syscall_shm_obtain(key, &size);
@ -323,7 +323,7 @@ static uint32_t server_window_resize(yutani_globals_t * yg, yutani_server_window
{
char key[1024];
YUTANI_SHMKEY_EXP(key, 1024, win->newbufid);
YUTANI_SHMKEY_EXP(yg->server_ident, key, 1024, win->newbufid);
size_t size = (width * height * 4);
win->newbuffer = (uint8_t *)syscall_shm_obtain(key, &size);
@ -349,7 +349,7 @@ static void server_window_resize_finish(yutani_globals_t * yg, yutani_server_win
{
char key[1024];
YUTANI_SHMKEY_EXP(key, 1024, oldbufid);
YUTANI_SHMKEY_EXP(yg->server_ident, key, 1024, oldbufid);
spin_lock(&yg->redraw_lock);
syscall_shm_release(key);
spin_unlock(&yg->redraw_lock);
@ -361,6 +361,55 @@ static void server_window_resize_finish(yutani_globals_t * yg, yutani_server_win
mark_window(yg, win);
}
/**
* Nested Yutani input thread
*
* Handles keyboard and mouse events, as well as
* other Yutani events from the nested window.
*/
void * nested_input(void * _yg) {
yutani_globals_t * yg = _yg;
yutani_t * y = yutani_init();
while (1) {
yutani_msg_t * m = yutani_poll(yg->host_context);
if (m) {
switch (m->type) {
case YUTANI_MSG_KEY_EVENT:
{
struct yutani_msg_key_event * ke = (void*)m->data;
yutani_msg_t * m_ = yutani_msg_build_key_event(0, &ke->event, &ke->state);
int result = yutani_msg_send(y, m_);
free(m_);
}
break;
case YUTANI_MSG_WINDOW_MOUSE_EVENT:
{
struct yutani_msg_window_mouse_event * me = (void*)m->data;
mouse_device_packet_t packet;
packet.buttons = me->buttons;
packet.x_difference = me->new_x;
packet.y_difference = me->new_y;
yutani_msg_t * m_ = yutani_msg_build_mouse_event(0, &packet, YUTANI_MOUSE_EVENT_TYPE_ABSOLUTE);
int result = yutani_msg_send(y, m_);
free(m_);
}
break;
case YUTANI_MSG_SESSION_END:
fprintf(stderr, "[yutani-nested] Host session ended. Should exit.\n");
break;
default:
break;
}
}
free(m);
}
}
/**
* Mouse input thread
*
@ -377,7 +426,7 @@ void * mouse_input(void * garbage) {
while (1) {
int r = read(mfd, (char *)&packet, sizeof(mouse_device_packet_t));
if (r > 0) {
yutani_msg_t * m = yutani_msg_build_mouse_event(0, &packet);
yutani_msg_t * m = yutani_msg_build_mouse_event(0, &packet, YUTANI_MOUSE_EVENT_TYPE_RELATIVE);
int result = yutani_msg_send(y, m);
free(m);
}
@ -411,7 +460,7 @@ void * keyboard_input(void * garbage) {
}
#define FONT_PATH "/usr/share/fonts/"
#define FONT(a,b) {YUTANI_SERVER_IDENTIFIER ".fonts." a, FONT_PATH b}
#define FONT(a,b) {a, FONT_PATH b}
struct font_def {
char * identifier;
@ -447,11 +496,13 @@ static char * precache_shmfont(char * ident, char * name) {
return font;
}
static void load_fonts(void) {
static void load_fonts(yutani_globals_t * yg) {
int i = 0;
while (fonts[i].identifier) {
fprintf(stderr, "[compositor] Loading font %s -> %s\n", fonts[i].path, fonts[i].identifier);
precache_shmfont(fonts[i].identifier, fonts[i].path);
char tmp[100];
snprintf(tmp, 100, "sys.%s.fonts.%s", yg->server_ident, fonts[i].identifier);
fprintf(stderr, "[compositor] Loading font %s -> %s\n", fonts[i].path, tmp);
precache_shmfont(tmp, fonts[i].path);
++i;
}
}
@ -744,21 +795,28 @@ static void redraw_windows(yutani_globals_t * yg) {
draw_resizing_box(yg);
}
/*
* Draw the cursor.
* We may also want to draw other compositor elements, like effects, but those
* can also go in the stack order of the windows.
*/
draw_cursor(yg, tmp_mouse_x, tmp_mouse_y);
if (yutani_options.nested) {
flip(yg->backend_ctx);
/* XXX We can do a better job with this... */
yutani_flip(yg->host_context, yg->host_window);
} else {
/*
* Flip the updated areas. This minimizes writes to video memory,
* which is very important on real hardware where these writes are slow.
*/
cairo_set_operator(yg->real_ctx, CAIRO_OPERATOR_SOURCE);
cairo_translate(yg->real_ctx, 0, 0);
cairo_set_source_surface(yg->real_ctx, yg->framebuffer_surface, 0, 0);
cairo_paint(yg->real_ctx);
/*
* Draw the cursor.
* We may also want to draw other compositor elements, like effects, but those
* can also go in the stack order of the windows.
*/
draw_cursor(yg, tmp_mouse_x, tmp_mouse_y);
/*
* Flip the updated areas. This minimizes writes to video memory,
* which is very important on real hardware where these writes are slow.
*/
cairo_set_operator(yg->real_ctx, CAIRO_OPERATOR_SOURCE);
cairo_translate(yg->real_ctx, 0, 0);
cairo_set_source_surface(yg->real_ctx, yg->framebuffer_surface, 0, 0);
cairo_paint(yg->real_ctx);
}
while (yg->windows_to_remove->head) {
node_t * node = list_pop(yg->windows_to_remove);
@ -922,7 +980,7 @@ static void window_actually_close(yutani_globals_t * yg, yutani_server_window_t
{
char key[1024];
YUTANI_SHMKEY_EXP(key, 1024, w->bufid);
YUTANI_SHMKEY_EXP(yg->server_ident, key, 1024, w->bufid);
/* We actually call this from the render thread, so we already have the lock. */
//spin_lock(&yg->redraw_lock);
syscall_shm_release(key);
@ -1148,8 +1206,13 @@ static void mouse_start_resize(yutani_globals_t * yg) {
}
static void handle_mouse_event(yutani_globals_t * yg, struct yutani_msg_mouse_event * me) {
yg->mouse_x += me->event.x_difference * 3;
yg->mouse_y -= me->event.y_difference * 3;
if (me->type == YUTANI_MOUSE_EVENT_TYPE_RELATIVE) {
yg->mouse_x += me->event.x_difference * 3;
yg->mouse_y -= me->event.y_difference * 3;
} else if (me->type == YUTANI_MOUSE_EVENT_TYPE_ABSOLUTE) {
yg->mouse_x = me->event.x_difference * 3;
yg->mouse_y = me->event.y_difference * 3;
}
if (yg->mouse_x < 0) yg->mouse_x = 0;
if (yg->mouse_y < 0) yg->mouse_y = 0;
@ -1293,7 +1356,14 @@ int main(int argc, char * argv[]) {
yutani_globals_t * yg = malloc(sizeof(yutani_globals_t));
memset(yg, 0x00, sizeof(yutani_globals_t));
yg->backend_ctx = init_graphics_fullscreen_double_buffer();
if (yutani_options.nested) {
yg->host_context = yutani_init();
yg->host_window = yutani_window_create(yg->host_context, yutani_options.nest_width, yutani_options.nest_height);
yg->backend_ctx = init_graphics_yutani_double_buffer(yg->host_window);
} else {
yg->backend_ctx = init_graphics_fullscreen_double_buffer();
}
if (!yg->backend_ctx) {
free(yg);
@ -1308,14 +1378,22 @@ int main(int argc, char * argv[]) {
flip(yg->backend_ctx);
yg->backend_framebuffer = yg->backend_ctx->backbuffer;
yg->pex_endpoint = "compositor";
setenv("DISPLAY", yg->pex_endpoint, 1);
FILE * server = pex_bind(yg->pex_endpoint);
if (yutani_options.nested) {
char * name = malloc(sizeof(char) * 64);
snprintf(name, 64, "compositor-nest-%d", getpid());
yg->server_ident = name;
} else {
/* XXX check if this already exists? */
yg->server_ident = "compositor";
}
setenv("DISPLAY", yg->server_ident, 1);
FILE * server = pex_bind(yg->server_ident);
yg->server = server;
fprintf(stderr, "[yutani] Loading fonts...\n");
load_fonts();
load_fonts(yg);
fprintf(stderr, "[yutani] Done.\n");
load_sprite_png(&yg->mouse_sprite, "/usr/share/arrow.png");
@ -1333,12 +1411,19 @@ int main(int argc, char * argv[]) {
yutani_cairo_init(yg);
pthread_t mouse_thread;
pthread_create(&mouse_thread, NULL, mouse_input, NULL);
pthread_t keyboard_thread;
pthread_create(&keyboard_thread, NULL, keyboard_input, NULL);
pthread_t render_thread;
pthread_t nested_thread;
if (yutani_options.nested) {
/* Nested Yutani-Yutani mouse+keyboard */
pthread_create(&nested_thread, NULL, nested_input, yg);
} else {
/* Toaru mouse+keyboard driver */
pthread_create(&mouse_thread, NULL, mouse_input, NULL);
pthread_create(&keyboard_thread, NULL, keyboard_input, NULL);
}
pthread_create(&render_thread, NULL, redraw, yg);
if (!fork()) {

View File

@ -90,7 +90,7 @@ typedef struct {
sprite_t mouse_sprite;
char * pex_endpoint;
char * server_ident;
yutani_server_window_t * focused_window;
FILE * server;
@ -127,6 +127,9 @@ typedef struct {
list_t * windows_to_remove;
yutani_t * host_context;
yutani_window_t * host_window;
} yutani_globals_t;
struct key_bind {

View File

@ -788,7 +788,10 @@ void term_clear(int i) {
char * loadMemFont(char * name, char * ident, size_t * size) {
size_t s = 0;
int error;
char * font = (char *)syscall_shm_obtain(ident, &s);
char tmp[100];
snprintf(tmp, 100, "sys.%s.fonts.%s", yctx->server_ident, ident);
char * font = (char *)syscall_shm_obtain(tmp, &s);
*size = s;
return font;
}
@ -1257,16 +1260,16 @@ int main(int argc, char ** argv) {
/* XXX Use shmemfont library */
font = loadMemFont("/usr/share/fonts/DejaVuSansMono.ttf", YUTANI_SERVER_IDENTIFIER ".fonts.monospace", &s);
font = loadMemFont("/usr/share/fonts/DejaVuSansMono.ttf", "monospace", &s);
error = FT_New_Memory_Face(library, font, s, 0, &face); if (error) return 1;
font = loadMemFont("/usr/share/fonts/DejaVuSansMono-Bold.ttf", YUTANI_SERVER_IDENTIFIER ".fonts.monospace.bold", &s);
font = loadMemFont("/usr/share/fonts/DejaVuSansMono-Bold.ttf", "monospace.bold", &s);
error = FT_New_Memory_Face(library, font, s, 0, &face_bold); if (error) return 1;
font = loadMemFont("/usr/share/fonts/DejaVuSansMono-Oblique.ttf", YUTANI_SERVER_IDENTIFIER ".fonts.monospace.italic", &s);
font = loadMemFont("/usr/share/fonts/DejaVuSansMono-Oblique.ttf", "monospace.italic", &s);
error = FT_New_Memory_Face(library, font, s, 0, &face_italic); if (error) return 1;
font = loadMemFont("/usr/share/fonts/DejaVuSansMono-BoldOblique.ttf", YUTANI_SERVER_IDENTIFIER ".fonts.monospace.bolditalic", &s);
font = loadMemFont("/usr/share/fonts/DejaVuSansMono-BoldOblique.ttf", "monospace.bolditalic", &s);
error = FT_New_Memory_Face(library, font, s, 0, &face_bold_italic); if (error) return 1;
error = FT_New_Face(library, "/usr/share/fonts/VLGothic.ttf", 0, &face_extra);

View File

@ -35,7 +35,10 @@ static void _load_font(int i, char * name) {
char * font;
size_t s = 0;
int error;
font = (char *)syscall_shm_obtain(name, &s);
char tmp[100];
snprintf(tmp, 100, "sys.%s%s", getenv("DISPLAY"), name);
font = (char *)syscall_shm_obtain(tmp, &s);
error = FT_New_Memory_Face(library, font, s, 0, &faces[i]);
error = FT_Set_Pixel_Sizes(faces[i], FONT_SIZE, FONT_SIZE);
}
@ -47,14 +50,14 @@ static void _load_font_f(int i, char * path) {
}
static void _load_fonts() {
_load_font(FONT_SANS_SERIF, YUTANI_SERVER_IDENTIFIER ".fonts.sans-serif");
_load_font(FONT_SANS_SERIF_BOLD, YUTANI_SERVER_IDENTIFIER ".fonts.sans-serif.bold");
_load_font(FONT_SANS_SERIF_ITALIC, YUTANI_SERVER_IDENTIFIER ".fonts.sans-serif.italic");
_load_font(FONT_SANS_SERIF_BOLD_ITALIC, YUTANI_SERVER_IDENTIFIER ".fonts.sans-serif.bolditalic");
_load_font(FONT_MONOSPACE, YUTANI_SERVER_IDENTIFIER ".fonts.monospace");
_load_font(FONT_MONOSPACE_BOLD, YUTANI_SERVER_IDENTIFIER ".fonts.monospace.bold");
_load_font(FONT_MONOSPACE_ITALIC, YUTANI_SERVER_IDENTIFIER ".fonts.monospace.italic");
_load_font(FONT_MONOSPACE_BOLD_ITALIC, YUTANI_SERVER_IDENTIFIER ".fonts.monospace.bolditalic");
_load_font(FONT_SANS_SERIF, ".fonts.sans-serif");
_load_font(FONT_SANS_SERIF_BOLD, ".fonts.sans-serif.bold");
_load_font(FONT_SANS_SERIF_ITALIC, ".fonts.sans-serif.italic");
_load_font(FONT_SANS_SERIF_BOLD_ITALIC, ".fonts.sans-serif.bolditalic");
_load_font(FONT_MONOSPACE, ".fonts.monospace");
_load_font(FONT_MONOSPACE_BOLD, ".fonts.monospace.bold");
_load_font(FONT_MONOSPACE_ITALIC, ".fonts.monospace.italic");
_load_font(FONT_MONOSPACE_BOLD_ITALIC, ".fonts.monospace.bolditalic");
_load_font_f(FONT_JAPANESE, "/usr/share/fonts/VLGothic.ttf");
_load_font_f(FONT_SYMBOLA, "/usr/share/fonts/Symbola.ttf");
}

View File

@ -170,7 +170,7 @@ yutani_msg_t * yutani_msg_build_key_event(yutani_wid_t wid, key_event_t * event,
return msg;
}
yutani_msg_t * yutani_msg_build_mouse_event(yutani_wid_t wid, mouse_device_packet_t * event) {
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);
@ -182,6 +182,7 @@ yutani_msg_t * yutani_msg_build_mouse_event(yutani_wid_t wid, mouse_device_packe
mw->wid = wid;
memcpy(&mw->event, event, sizeof(mouse_device_packet_t));
mw->type = type;
return msg;
}
@ -440,7 +441,9 @@ yutani_t * yutani_init(void) {
if (!getenv("DISPLAY")) {
return NULL;
}
FILE * c = pex_connect(getenv("DISPLAY"));
char * server_name = getenv("DISPLAY");
FILE * c = pex_connect(server_name);
if (!c) return NULL; /* Connection failed. */
@ -453,6 +456,7 @@ yutani_t * yutani_init(void) {
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;
@ -477,7 +481,7 @@ yutani_window_t * yutani_window_create(yutani_t * y, int width, int height) {
hashmap_set(y->windows, (void*)win->wid, win);
char key[1024];
YUTANI_SHMKEY(key, 1024, win);
YUTANI_SHMKEY(y->server_ident, key, 1024, win);
size_t size = (width * height * 4);
win->buffer = (uint8_t *)syscall_shm_obtain(key, &size);
@ -504,7 +508,7 @@ void yutani_close(yutani_t * y, yutani_window_t * win) {
/* Now destroy our end of the window */
{
char key[1024];
YUTANI_SHMKEY_EXP(key, 1024, win->bufid);
YUTANI_SHMKEY_EXP(y->server_ident, key, 1024, win->bufid);
syscall_shm_release(key);
}
@ -560,7 +564,7 @@ void yutani_window_resize_accept(yutani_t * yctx, yutani_window_t * window, uint
/* Allocate the buffer */
{
char key[1024];
YUTANI_SHMKEY(key, 1024, window);
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);
@ -571,7 +575,7 @@ void yutani_window_resize_done(yutani_t * yctx, yutani_window_t * window) {
/* Destroy the old buffer */
{
char key[1024];
YUTANI_SHMKEY_EXP(key, 1024, window->oldbufid);
YUTANI_SHMKEY_EXP(yctx->server_ident, key, 1024, window->oldbufid);
syscall_shm_release(key);
}

View File

@ -10,9 +10,8 @@
#include "mouse.h"
#include "list.h"
#define YUTANI_SERVER_IDENTIFIER "sys.compositor"
#define YUTANI_SHMKEY(buf,sz,win) snprintf(buf, sz, "%s.%d", YUTANI_SERVER_IDENTIFIER, win->bufid);
#define YUTANI_SHMKEY_EXP(buf,sz,bufid) snprintf(buf, sz, "%s.%d", YUTANI_SERVER_IDENTIFIER, bufid);
#define YUTANI_SHMKEY(server_ident,buf,sz,win) snprintf(buf, sz, "sys.%s.%d", server_ident, win->bufid);
#define YUTANI_SHMKEY_EXP(server_ident,buf,sz,bufid) snprintf(buf, sz, "sys.%s.%d", server_ident, bufid);
typedef unsigned int yutani_wid_t;
@ -26,6 +25,8 @@ typedef struct yutani_context {
hashmap_t * windows;
list_t * queued;
char * server_ident;
} yutani_t;
typedef struct yutani_message {
@ -95,6 +96,7 @@ struct yutani_msg_window_mouse_event {
struct yutani_msg_mouse_event {
yutani_wid_t wid;
mouse_device_packet_t event;
int32_t type;
};
struct yutani_msg_flip_region {
@ -212,6 +214,9 @@ typedef struct yutani_window {
#define YUTANI_MOUSE_EVENT_LEAVE 5
#define YUTANI_MOUSE_EVENT_ENTER 6
#define YUTANI_MOUSE_EVENT_TYPE_RELATIVE 0
#define YUTANI_MOUSE_EVENT_TYPE_ABSOLUTE 1
#define YUTANI_BIND_PASSTHROUGH 0
#define YUTANI_BIND_STEAL 1
@ -233,7 +238,7 @@ yutani_msg_t * yutani_msg_build_window_new(uint32_t width, uint32_t height);
yutani_msg_t * yutani_msg_build_window_init(yutani_wid_t wid, uint32_t width, uint32_t height, uint32_t bufid);
yutani_msg_t * yutani_msg_build_flip(yutani_wid_t);
yutani_msg_t * yutani_msg_build_key_event(yutani_wid_t wid, key_event_t * event, key_event_state_t * state);
yutani_msg_t * yutani_msg_build_mouse_event(yutani_wid_t wid, mouse_device_packet_t * event);
yutani_msg_t * yutani_msg_build_mouse_event(yutani_wid_t wid, mouse_device_packet_t * event, int32_t type);
yutani_msg_t * yutani_msg_build_window_close(yutani_wid_t wid);
yutani_msg_t * yutani_msg_build_window_stack(yutani_wid_t wid, int z);
yutani_msg_t * yutani_msg_build_window_focus_change(yutani_wid_t wid, int focused);