@@ -18,18 +18,20 @@

#include "lib/list.h"
#include "lib/graphics.h"
#include "lib/compositing.h"
#include "../kernel/include/signal.h"
#include "lib/window.h"

//DEFN_SYSCALL0(getpid, 9)
//DEFN_SYSCALL0(mkpipe, 21)
#if 0
DEFN_SYSCALL2(shm_obtain, 35, char *, int)
DEFN_SYSCALL1(shm_release, 36, char *)
DEFN_SYSCALL2(send_signal, 37, int, int)
DEFN_SYSCALL2(sys_signal, 38, int, int)
DEFN_SYSCALL2(share_fd, 39, int, int)
DEFN_SYSCALL1(get_fd, 40, int)
#endif

DECL_SYSCALL0(mkpipe);


/* For terminal, not for us */
#define FREETYPE 1

@@ -38,34 +40,13 @@ sprite_t * sprites[128];
#define WIN_D 32
#define WIN_B (WIN_D / 8)

typedef struct process_windows process_windows_t;

typedef struct {
uint32_t wid; /* Window identifier */
process_windows_t * owner; /* Owning process (back ptr) */

uint16_t width; /* Buffer width in pixels */
uint16_t height; /* Buffer height in pixels */

int32_t x; /* X coordinate of upper-left corner */
int32_t y; /* Y coordinate of upper-left corner */
uint16_t z; /* Stack order */

void * buffer; /* Window buffer */
uint16_t bufid; /* We occasionally replace the buffer; each is uniquely-indexed */
} window_t;

struct process_windows {
uint32_t pid;

int event_pipe; /* Pipe to send events through */
int command_pipe; /* Pipe on which we receive commands */

list_t * windows;
};

list_t * process_list;

extern window_t * init_window (process_windows_t * pw, wid_t wid, int32_t x, int32_t y, uint16_t width, uint16_t height, uint16_t index);
extern void free_window (window_t * window);
extern void resize_window_buffer (window_t * window, uint16_t left, uint16_t top, uint16_t width, uint16_t height);

process_windows_t * get_process_windows (uint32_t pid) {
foreach(n, process_list) {
process_windows_t * pw = (process_windows_t *)n->value;
@@ -77,7 +58,7 @@ process_windows_t * get_process_windows (uint32_t pid) {
return NULL;
}

window_t * get_window (uint32_t wid) {
static window_t * get_window (wid_t wid) {
foreach (n, process_list) {
process_windows_t * pw = (process_windows_t *)n->value;
foreach (m, pw->windows) {
@@ -95,8 +76,6 @@ void init_process_list () {
process_list = list_create();
}

#define TO_WINDOW_OFFSET(x,y) (((x) - window->x) + ((y) - window->y) * window->width)
#define DIRECT_OFFSET(x,y) ((x) + (y) * window->width)


int32_t min(int32_t a, int32_t b) {
@@ -130,53 +109,9 @@ uint8_t is_top(window_t *window, uint16_t x, uint16_t y) {
}


window_t * init_window (process_windows_t * pw, int32_t x, int32_t y, uint16_t width, uint16_t height, uint16_t index) {
static int _last_wid = 0;

window_t * window = malloc(sizeof(window_t));
if (!window) {
printf("[compositor] SEVERE: Could not malloc a window_t!");
return NULL;
}

window->owner = pw;
window->wid = _last_wid++;
window->bufid = 0;

window->width = width;
window->height = height;
window->x = x;
window->y = y;
window->z = index;

char key[256];
SHMKEY(key, 256, window);
window->buffer = (uint8_t *)syscall_shm_obtain(key, (width * height * WIN_B));
if (!window->buffer) {
printf("[compositor] SEVERE: Could not create a buffer for a new window for pid %d!", pw->pid);
free(window);
return NULL;
}

list_insert(pw->windows, window);

return window;
}

void resize_window (window_t * window, uint16_t width, uint16_t height) {
window->width = width;
window->height = height;

/* Release the old buffer */
char key[256];
SHMKEY(key, 256, window);
syscall_shm_release(key);

/* Create the new one */
window->bufid++;
SHMKEY(key, 256, window);
window->buffer = (uint8_t *)syscall_shm_obtain(key, (width * height * WIN_B));
}
/* Internal drawing functions */

void redraw_window(window_t *window, uint16_t x, uint16_t y, uint16_t width, uint16_t height) {
if (!window) {
@@ -191,10 +126,12 @@ void redraw_window(window_t *window, uint16_t x, uint16_t y, uint16_t width, uin
for (uint16_t y = _lo_y; y < _hi_y; ++y) {
for (uint16_t x = _lo_x; x < _hi_x; ++x) {
if (is_top(window, x, y)) {
#if 0
assert(0 <= x);
assert(x < GFX_W);
assert(0 <= y);
assert(y < GFX_H);
#endif

GFX(x,y) = ((uint32_t *)window->buffer)[TO_WINDOW_OFFSET(x,y)];
}
@@ -210,28 +147,23 @@ void redraw_full_window (window_t * window) {
redraw_window(window, (uint16_t)0, (uint16_t)0, window->width, window->height);
}

void destroy_window (window_t * window) {
/* Free the window buffer */
char key[256];
SHMKEY(key, 256, window);
syscall_shm_release(key);

/* Now, kill the object itself */
process_windows_t * pw = window->owner;
wid_t volatile _next_wid = 0;

node_t * n = list_find(pw->windows, window);
list_delete(pw->windows, n);
free(n);
void send_window_event (process_windows_t * pw, uint8_t event, w_window_t packet) {
/* Construct the header */
wins_packet_t header;
header.command_type = event;
header.packet_size = sizeof(w_window_t);

#if 0
/* Does the owner have any windows themselves? */
if (pw->windows->length == 0) {
delete_process(pw);
}
#endif
/* Send them */
// XXX: we have a race condition here
write(pw->event_pipe, &header, sizeof(wins_packet_t));
write(pw->event_pipe, &packet, sizeof(w_window_t));
syscall_send_signal(pw->pid, 35); // SIGWINEVENT
}

void sig_window_command (int sig) {
void process_window_command (int sig) {
foreach(n, process_list) {
process_windows_t * pw = (process_windows_t *)n->value;

@@ -245,19 +177,20 @@ void sig_window_command (int sig) {

switch (header.command_type) {
case WC_NEWWINDOW:
/* No packet */
read(pw->command_pipe, &wwt, sizeof(w_window_t));
init_window(pw, wwt.left, wwt.top, wwt.width, wwt.height, 0); //XXX: an actual index
init_window(pw, _next_wid++, wwt.left, wwt.top, wwt.width, wwt.height, 0); //XXX: an actual index
send_window_event(pw, WE_NEWWINDOW, wwt);
break;

case WC_RESIZE:
read(pw->command_pipe, &wwt, sizeof(w_window_t));
resize_window(get_window(wwt.wid), /*wwt.left, wwt.top,*/ wwt.width, wwt.height);
resize_window_buffer(get_window(wwt.wid), wwt.left, wwt.top, wwt.width, wwt.height);
send_window_event(pw, WE_RESIZED, wwt);
break;

case WC_DESTROY:
read(pw->command_pipe, &wwt, sizeof(w_window_t));
destroy_window(get_window(wwt.wid));
free_window(get_window(wwt.wid));
break;

case WC_DAMAGE:
@@ -266,7 +199,7 @@ void sig_window_command (int sig) {
break;

default:
printf("[compositor] WARN: Unknown command type %d...\n");
printf("[compositor] WARN: Unknown command type %d...\n", header.command_type);
void * nullbuf = malloc(header.packet_size);
read(pw->command_pipe, nullbuf, header.packet_size);
free(nullbuf);
@@ -278,65 +211,8 @@ void sig_window_command (int sig) {
}
}

void window_set_point(window_t * window, uint16_t x, uint16_t y, uint32_t color) {
#if 0
printf("window_set_point(0x%x, %d, %d) = 0x%x\n", window->buffer, x, y, color);
if (!window) {
return;
}
#endif
if (x < 0 || y < 0 || x >= window->width || y >= window->height)
return;

((uint32_t *)window->buffer)[DIRECT_OFFSET(x,y)] = color;
}

void window_draw_line(window_t * window, uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1, uint32_t color) {
int deltax = abs(x1 - x0);
int deltay = abs(y1 - y0);
int sx = (x0 < x1) ? 1 : -1;
int sy = (y0 < y1) ? 1 : -1;
int error = deltax - deltay;
while (1) {
window_set_point(window, x0, y0, color);
if (x0 == x1 && y0 == y1) break;
int e2 = 2 * error;
if (e2 > -deltay) {
error -= deltay;
x0 += sx;
}
if (e2 < deltax) {
error += deltax;
y0 += sy;
}
}
}

void window_draw_sprite(window_t * window, sprite_t * sprite, uint16_t x, uint16_t y) {
int x_hi = min(sprite->width, (window->width - x));
int y_hi = min(sprite->height, (window->height - y));

for (uint16_t _y = 0; _y < y_hi; ++_y) {
for (uint16_t _x = 0; _x < x_hi; ++_x) {
if (sprite->alpha) {
/* Technically, unsupported! */
window_set_point(window, x + _x, y + _y, SPRITE(sprite, _x, _y));
} else {
if (SPRITE(sprite,_x,_y) != sprite->blank) {
window_set_point(window, x + _x, y + _y, SPRITE(sprite, _x, _y));
}
}
}
}
}

void window_fill(window_t *window, uint32_t color) {
for (uint16_t i = 0; i < window->height; ++i) {
for (uint16_t j = 0; j < window->width; ++j) {
((uint32_t *)window->buffer)[DIRECT_OFFSET(j,i)] = color;
}
}
}

void waitabit() {
int x = time(NULL);
@@ -349,22 +225,28 @@ void waitabit() {
/* Request page system */


wins_server_global_t * _request_page;
wins_server_global_t volatile * _request_page;

void init_request_system () {
_request_page = (wins_server_global_t *)syscall_shm_obtain(WINS_SERVER_IDENTIFIER, sizeof(wins_server_global_t));
if (!_request_page) {
printf("Compositor could not get a shm block for its request page! Bailing...");
fprintf(stderr, "[wins] Could not get a shm block for its request page! Bailing...");
exit(-1);
}

_request_page->lock = 0;
_request_page->server_done = 0;
_request_page->client_done = 0;
_request_page->client_pid = 0;
_request_page->event_pipe = 0;
_request_page->command_pipe = 0;
_request_page->magic = WINS_MAGIC;
_request_page->lock = 0;
_request_page->server_done = 0;
_request_page->client_done = 0;
_request_page->client_pid = 0;
_request_page->event_pipe = 0;
_request_page->command_pipe = 0;

_request_page->server_pid = getpid();
_request_page->server_width = graphics_width;
_request_page->server_height = graphics_height;
_request_page->server_depth = graphics_depth;

_request_page->magic = WINS_MAGIC;
}

void process_request () {
@@ -377,8 +259,10 @@ void process_request () {

_request_page->event_pipe = syscall_share_fd(pw->event_pipe, pw->pid);
_request_page->command_pipe = syscall_share_fd(pw->command_pipe, pw->pid);
_request_page->client_pid = 0;
_request_page->server_done = 1;

list_insert(process_list, pw);
printf("A client (%d) replied to\n", pw->pid);
}
}

@@ -401,10 +285,7 @@ void delete_process (process_windows_t * pw) {


void init_signal_handlers () {
syscall_sys_signal(SIGWINEVENT, (uintptr_t)sig_window_command);
syscall_sys_signal(SIGWINEVENT, (uintptr_t)sig_window_command);
syscall_sys_signal(SIGWINEVENT, (uintptr_t)sig_window_command);
syscall_sys_signal(SIGWINEVENT, (uintptr_t)sig_window_command);
syscall_sys_signal(35, (uintptr_t)process_window_command); // SIGWINEVENT
}


@@ -586,12 +467,12 @@ void init_base_windows () {

#if 1
/* Create the background window */
window_t * root = init_window(pw, 0, 0, graphics_width, graphics_height, 0);
window_t * root = init_window(pw, _next_wid++, 0, 0, graphics_width, graphics_height, 0);
window_draw_sprite(root, sprites[1], 0, 0);
redraw_full_window(root);

/* Create the panel */
window_t * panel = init_window(pw, 0, 0, graphics_width, 24, -1);
window_t * panel = init_window(pw, _next_wid++, 0, 0, graphics_width, 24, -1);
window_fill(panel, rgb(0,120,230));
init_sprite(2, "/usr/share/panel.bmp", NULL);
for (uint32_t i = 0; i < graphics_width; i += sprites[2]->width) {
@@ -644,43 +525,22 @@ int main(int argc, char ** argv) {
init_base_windows();

process_windows_t * rootpw = get_process_windows(getpid());
assert(rootpw);

if (!rootpw) {
printf("? No root process window?\n");
while (1) {

}
printf("[compositor] SEVERE: No root process windows!\n");
return 1;
}

#define WINA_WIDTH 300
#define WINA_HEIGHT 300
window_t * wina = init_window(rootpw, 10, 10, WINA_WIDTH, WINA_HEIGHT, 1);
window_fill(wina, rgb(0,255,0));

#define WINB_WIDTH 700
#define WINB_HEIGHT 700
window_t * winb = init_window(rootpw, 120, 120, WINB_WIDTH, WINB_HEIGHT, 2);
window_fill(winb, rgb(0,0,255));

redraw_full_window(wina);
redraw_full_window(winb);

#if 0
flip();
#endif

if (!fork()) {
char * args[] = {"/bin/drawlines", NULL};
execve(args[0], args, NULL);
}
printf("waiting for clients...\n");
/* Sit in a run loop */
while (1) {
window_draw_line(wina, rand() % WINA_WIDTH, rand() % WINA_WIDTH, rand() % WINA_HEIGHT, rand() % WINA_HEIGHT, rgb(rand() % 255,rand() % 255,rand() % 255));
window_draw_line(winb, rand() % WINB_WIDTH, rand() % WINB_WIDTH, rand() % WINB_HEIGHT, rand() % WINB_HEIGHT, rgb(rand() % 255,rand() % 255,rand() % 255));
redraw_full_window(wina);
redraw_full_window(winb);
#if 0
redraw_window(&root);
redraw_window(&panel);
flip();
#endif
process_request();
waitabit(); // XXX: Can't we deschedule?
}

// XXX: Better have SIGINT/SIGSTOP handlers
return 0;
}
@@ -0,0 +1,45 @@
#include <stdlib.h>
#include <assert.h>

#include "lib/window.h"


int32_t min(int32_t a, int32_t b) {
return (a < b) ? a : b;
}

int32_t max(int32_t a, int32_t b) {
return (a > b) ? a : b;
}

int main (int argc, char ** argv) {
if (argc < 5) {
printf("usage: %s left top width height\n", argv[0]);
return -1;
}

int left = atoi(argv[1]);
int top = atoi(argv[2]);
int width = atoi(argv[3]);
int height = atoi(argv[4]);

setup_windowing();

/* Do something with a window */
#define WINA_WIDTH 300
#define WINA_HEIGHT 300
window_t * wina = window_create(0, 0, WINA_WIDTH, WINA_HEIGHT);
assert(wina);
window_fill(wina, rgb(0,255,0));
window_redraw_full(wina);

while (1) {
window_draw_line(wina, rand() % WINA_WIDTH, rand() % WINA_WIDTH, rand() % WINA_HEIGHT, rand() % WINA_HEIGHT, rgb(rand() % 255,rand() % 255,rand() % 255));
window_redraw_full(wina);
}

//window_destroy(window); // (will close on exit)
teardown_windowing();

return 0;
}

This file was deleted.

This file was deleted.

Large diffs are not rendered by default.

@@ -0,0 +1,171 @@
/* vim: tabstop=4 shiftwidth=4 noexpandtab
*
* Compositing and Window Management Library
*/

#ifndef COMPOSITING_H
#define COMPOSITING_H

#include <stdint.h>

#include "list.h"
#include "graphics.h"


DECL_SYSCALL2(shm_obtain, char *, int);
DECL_SYSCALL1(shm_release, char *);
DECL_SYSCALL2(send_signal, int, int);
DECL_SYSCALL2(sys_signal, int, int);
DECL_SYSCALL2(share_fd, int, int);
DECL_SYSCALL1(get_fd, int);


/* Connection */
typedef struct {
/* Control flow structures */
volatile uint8_t lock; /* Spinlock byte */

/* LOCK REQUIRED REGION */
volatile uint8_t client_done; /* Client has finished work */
volatile uint8_t server_done; /* Server has finished work */

/* The actual data passed back and forth */
pid_t client_pid; /* Actively communicating client process */
uintptr_t event_pipe; /* Client event pipe (ie, mouse, keyboard) */
uintptr_t command_pipe; /* Client command pipe (ie, resize) */
/* END LOCK REQUIRED REGION */

/* Data about the system */
pid_t server_pid; /* The wins -- for signals */
uint16_t server_width; /* Screen resolution, width */
uint16_t server_height; /* Screen resolution, height */
uint8_t server_depth; /* Native screen depth (in bits) */

uint32_t magic;
} wins_server_global_t;


/* Commands and Events */
typedef struct {
uint8_t command_type; /* Command or event specifier */
size_t packet_size; /* Size of the *remaining* packet data */
} wins_packet_t;

#define WINS_PACKET(p) ((char *)((uintptr_t)p + sizeof(wins_packet_t)))

#define WINS_SERVER_IDENTIFIER "sys.compositor"
#define WINS_MAGIC 0xDECADE99


/* Commands */
#define WC_NEWWINDOW 0x00 /* New Window */
#define WC_RESIZE 0x01 /* Resize and move an existing window */
#define WC_DESTROY 0x02 /* Destroy an existing window */
#define WC_DAMAGE 0x03 /* Damage window (redraw region) */

/* Events */
#define WE_KEYDOWN 0x10 /* A key has been pressed down */
#define WE_KEYUP 0x11 /* RESERVED: Key up [UNUSED] */
#define WE_MOUSEMOVE 0x20 /* The mouse has moved (to the given coordinates) */
#define WE_MOUSEENTER 0x21 /* The mouse has entered your window (at the given coordinates) */
#define WE_MOUSELEAVE 0x22 /* The mouse has left your window (at the given coordinates) */
#define WE_MOUSECLICK 0x23 /* A mouse button has been pressed that was not previously pressed */
#define WE_MOUSEUP 0x24 /* A mouse button has been released */
#define WE_NEWWINDOW 0x30 /* A new window has been created */
#define WE_RESIZED 0x31 /* Your window has been resized or moved */

#define WE_GROUP_MASK 0xF0
#define WE_KEY_EVT 0x10 /* Some sort of keyboard event */
#define WE_MOUSE_EVT 0x20 /* Some sort of mouse event */
#define WE_WINDOW_EVT 0x30 /* Some sort of window event */

typedef uint16_t wid_t;

typedef struct {
wid_t wid; /* or none for new window */
uint16_t left; /* X coordinate */
uint16_t top; /* Y coordinate */
uint16_t width; /* Width of window or region */
uint16_t height; /* Height of window or region */
uint8_t command; /* The command (duplicated) */
} w_window_t;

typedef struct {
wid_t wid;
uint16_t key;
uint8_t command;
} w_keyboard_t;

typedef struct {
wid_t wid;
uint16_t old_x;
uint16_t old_y;
uint16_t new_x;
uint16_t new_y;
uint8_t buttons;
uint8_t command;
} w_mouse_t;

#define MOUSE_BUTTON_LEFT 0x01
#define MOUSE_BUTTON_RIGHT 0x02
#define MOUSE_BUTTON_MIDDLE 0x04


#define SHMKEY(buf,sz,win) snprintf(buf, sz, "%s.%d.%d.%d", WINS_SERVER_IDENTIFIER, win->owner->pid, win->wid, win->bufid);


/* Windows */
typedef struct process_windows process_windows_t;

typedef struct {
wid_t wid; /* Window identifier */
process_windows_t * owner; /* Owning process (back ptr) */

uint16_t width; /* Buffer width in pixels */
uint16_t height; /* Buffer height in pixels */

/* UNUSED IN CLIENT */
int32_t x; /* X coordinate of upper-left corner */
int32_t y; /* Y coordinate of upper-left corner */
uint16_t z; /* Stack order */
/* END UNUSED IN CLIENT */

uint8_t * buffer; /* Window buffer */
uint16_t bufid; /* We occasionally replace the buffer; each is uniquely-indexed */
} window_t;

struct process_windows {
uint32_t pid;

int event_pipe; /* Pipe to send events through */
int command_pipe; /* Pipe on which we receive commands */

list_t * windows;
};



/* Client Windowing */

int setup_windowing ();
void teardown_windowing ();

window_t * window_create (uint16_t left, uint16_t top, uint16_t width, uint16_t height);
void window_resize (window_t * window, uint16_t left, uint16_t top, uint16_t width, uint16_t height);
void window_redraw (window_t * window, uint16_t left, uint16_t top, uint16_t width, uint16_t height);
void window_redraw_full (window_t * window);
void window_destroy (window_t * window);

w_keyboard_t * poll_keyboard();
w_mouse_t * poll_mouse();

#define TO_WINDOW_OFFSET(x,y) (((x) - window->x) + ((y) - window->y) * window->width)
#define DIRECT_OFFSET(x,y) ((x) + (y) * window->width)

void window_set_point(window_t * window, uint16_t x, uint16_t y, uint32_t color);
void window_draw_line(window_t * window, uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1, uint32_t color);
void window_draw_sprite(window_t * window, sprite_t * sprite, uint16_t x, uint16_t y);
void window_fill(window_t *window, uint32_t color);


#endif