@@ -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 ;
}