Port stuff from old compositor

lots of stacking functionality ported
still need window focus and mouse events, plus mouse move and other
server-side control...
This commit is contained in:
Kevin Lange 2014-04-06 20:42:29 -07:00
parent 4002901d0d
commit 58f32b064d
8 changed files with 575 additions and 9 deletions

View File

@ -41,6 +41,70 @@ static int next_wid(void) {
return _next++;
}
static void rebalance_windows(yutani_globals_t * yg) {
uint32_t i = 1;
for (; i < YUTANI_ZORDER_TOP; ++i) {
if (!yg->zlist[i]) break;
}
uint32_t j = i + 1;
for (; j < YUTANI_ZORDER_TOP; ++j) {
if (!yg->zlist[j]) break;
}
if (j == i + 1) {
return;
} else {
for (j = i; j < YUTANI_ZORDER_TOP; ++j) {
yg->zlist[j] = yg->zlist[j+1];
if (yg->zlist[j+1] == NULL) return;
yg->zlist[j]->z = j;
}
}
}
static void reorder_window(yutani_globals_t * yg, yutani_server_window_t * window, uint16_t new_zed) {
if (!window) {
return;
}
int z = window->z;
window->z = new_zed;
if (yg->zlist[z] == window) {
yg->zlist[z] = NULL;
}
if (new_zed == 0 || new_zed == YUTANI_ZORDER_TOP) {
yg->zlist[new_zed] = window;
if (z != new_zed) {
rebalance_windows(yg);
}
return;
}
if (yg->zlist[new_zed] != window) {
reorder_window(yg, yg->zlist[new_zed], new_zed + 1);
yg->zlist[new_zed ] = window;
}
if (z != new_zed) {
rebalance_windows(yg);
}
}
static void unorder_window(yutani_globals_t * yg, yutani_server_window_t * w) {
if (yg->zlist[w->z] == w) {
yg->zlist[w->z] = NULL;
}
rebalance_windows(yg);
}
int best_z_option(yutani_globals_t * yg) {
for (int i = 1; i < YUTANI_ZORDER_TOP; ++i) {
if (!yg->zlist[i]) return i;
}
return -1;
}
static yutani_server_window_t * server_window_create(yutani_globals_t * yg, int width, int height, uint32_t owner) {
yutani_server_window_t * win = malloc(sizeof(yutani_server_window_t));
@ -51,7 +115,8 @@ static yutani_server_window_t * server_window_create(yutani_globals_t * yg, int
win->x = 0;
win->y = 0;
win->z = 0;
win->z = best_z_option(yg);
yg->zlist[win->z] = win;
win->width = width;
win->height = height;
win->bufid = next_buf_id();
@ -298,9 +363,10 @@ static void redraw_windows(yutani_globals_t * yg) {
* but calculating that may be more trouble than it's worth;
* we also need to render windows in stacking order...
*/
foreach(node, yg->windows) {
yutani_server_window_t * win = (void*)node->value;
yutani_blit_window(yg, win, NULL);
for (unsigned int i = 0; i <= YUTANI_ZORDER_MAX; ++i) {
if (yg->zlist[i]) {
yutani_blit_window(yg, yg->zlist[i], NULL);
}
}
/*
@ -341,6 +407,7 @@ void yutani_cairo_init(yutani_globals_t * yg) {
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();
yg->width = yg->backend_ctx->width;
yg->height = yg->backend_ctx->height;
@ -465,6 +532,15 @@ int main(int argc, char * argv[]) {
hashmap_remove(yg->wids_to_windows, (void *)wc->wid);
list_remove(yg->windows, list_index_of(yg->windows, w));
list_insert(yg->update_list, w);
unorder_window(yg, w);
redraw_windows(yg);
}
} break;
case YUTANI_MSG_WINDOW_STACK: {
struct yutani_msg_window_stack * ws = (void *)m->data;
yutani_server_window_t * w = hashmap_get(yg->wids_to_windows, (void *)ws->wid);
if (w) {
reorder_window(yg, w, ws->z);
redraw_windows(yg);
}
} break;

View File

@ -11,9 +11,6 @@
#define MOUSE_OFFSET_X 26
#define MOUSE_OFFSET_Y 26
#define YUTANI_ZORDER_TOP 0xFFFF
#define YUTANI_ZORDER_BOTTOM 0x0000
#define YUTANI_BYTE_DEPTH 4
typedef enum {
@ -62,6 +59,7 @@ typedef struct {
list_t * windows;
hashmap_t * wids_to_windows;
yutani_server_window_t * zlist[0x10000];
list_t * update_list;

View File

@ -402,7 +402,7 @@ int main (int argc, char ** argv) {
if (!_session_pid) {
setenv("PATH", "/usr/bin:/bin", 0);
syscall_setuid(uid);
char * args[] = {"/bin/terminal-beta", NULL};
char * args[] = {"/bin/gsession-beta", NULL};
execvp(args[0], args);
}

View File

@ -0,0 +1,84 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <syscall.h>
#include <signal.h>
#define LINE_LEN 1024
void set_username() {
FILE * passwd = fopen("/etc/passwd", "r");
char line[LINE_LEN];
int uid = syscall_getuid();
while (fgets(line, LINE_LEN, passwd) != NULL) {
line[strlen(line)-1] = '\0';
char *p, *tokens[10], *last;
int i = 0;
for ((p = strtok_r(line, ":", &last)); p;
(p = strtok_r(NULL, ":", &last)), i++) {
if (i < 511) tokens[i] = p;
}
tokens[i] = NULL;
if (atoi(tokens[2]) == uid) {
setenv("USER", tokens[0], 1);
}
}
fclose(passwd);
}
void set_homedir() {
char * user = getenv("USER");
if (user) {
char path[512];
sprintf(path,"/home/%s", user);
setenv("HOME",path,1);
} else {
setenv("HOME","/",1);
}
}
void set_path() {
setenv("PATH", "/bin", 0);
}
int main(int argc, char * argv[]) {
/* Starts a graphical session and then spins waiting for a kill (logout) signal */
/* Load some session variables */
set_username();
set_homedir();
set_path();
int _wallpaper_pid = fork();
if (!_wallpaper_pid) {
char * args[] = {"/bin/wallpaper-beta", NULL};
execvp(args[0], args);
}
int _panel_pid = fork();
if (!_panel_pid) {
char * args[] = {"/bin/panel-beta", NULL};
execvp(args[0], args);
}
int _terminal_pid = fork();
if (!_terminal_pid) {
char * args[] = {"/bin/terminal-beta", NULL};
execvp(args[0], args);
}
syscall_wait(_panel_pid);
printf("Session leader has exited. Sending INT signals to %d.\n", _wallpaper_pid);
kill(_wallpaper_pid, SIGINT);
printf("Waiting on wallpaper.\n");
syscall_wait(_wallpaper_pid);
printf("Session has ended.\n");
}

View File

@ -0,0 +1,187 @@
/* vim: tabstop=4 shiftwidth=4 noexpandtab
*
* Panel
*
* Provides a graphical panel with a clock, and
* hopefully more things in the future.
*/
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/utsname.h>
#define PANEL_HEIGHT 28
#include "lib/pthread.h"
#include "lib/yutani.h"
#include "lib/graphics.h"
#include "lib/shmemfonts.h"
sprite_t * sprites[128];
sprite_t alpha_tmp;
gfx_context_t * ctx;
yutani_t * yctx;
yutani_window_t * panel;
int width;
int height;
int center_x(int x) {
return (width - x) / 2;
}
int center_y(int y) {
return (height - y) / 2;
}
void init_sprite(int i, char * filename, char * alpha) {
sprites[i] = malloc(sizeof(sprite_t));
load_sprite(sprites[i], filename);
if (alpha) {
sprites[i]->alpha = 1;
load_sprite(&alpha_tmp, alpha);
sprites[i]->masks = alpha_tmp.bitmap;
} else {
sprites[i]->alpha = ALPHA_OPAQUE;
}
}
void init_sprite_png(int i, char * filename) {
sprites[i] = malloc(sizeof(sprite_t));
load_sprite_png(sprites[i], filename);
}
#define FONT_SIZE 14
#define TIME_LEFT 108
#define DATE_WIDTH 70
volatile int _continue = 1;
void sig_int(int sig) {
printf("Received shutdown signal in panel!\n");
_continue = 0;
}
#if 0
void panel_check_click(w_mouse_t * evt) {
if (evt->command == WE_MOUSECLICK) {
printf("Click!\n");
if (evt->new_x >= width - 24 ) {
printf("Clicked log-out button. Good bye!\n");
_continue = 0;
}
}
}
#endif
void * clock_thread(void * garbage) {
size_t buf_size = panel->width * panel->height * sizeof(uint32_t);
char * buf = malloc(buf_size);
memcpy(buf, ctx->backbuffer, buf_size);
struct timeval now;
int last = 0;
struct tm * timeinfo;
char buffer[80];
struct utsname u;
uname(&u);
/* UTF-8 Strings FTW! */
uint8_t * os_name_ = "とあるOS";
uint8_t final[512];
uint32_t l = snprintf(final, 512, "%s %s", os_name_, u.release);
uint32_t txt_color = rgb(230,230,230);
int t = 0;
while (_continue) {
/* Redraw the background by memcpy (super speedy) */
memcpy(ctx->backbuffer, buf, buf_size);
gettimeofday(&now, NULL);
if (now.tv_sec != last) {
last = now.tv_sec;
timeinfo = localtime((time_t *)&now.tv_sec);
strftime(buffer, 80, "%H:%M:%S", timeinfo);
set_font_face(FONT_SANS_SERIF_BOLD);
set_font_size(16);
draw_string(ctx, width - TIME_LEFT, 19, txt_color, buffer);
strftime(buffer, 80, "%A", timeinfo);
set_font_face(FONT_SANS_SERIF);
set_font_size(9);
t = draw_string_width(buffer);
t = (DATE_WIDTH - t) / 2;
draw_string(ctx, width - TIME_LEFT - DATE_WIDTH + t, 11, txt_color, buffer);
strftime(buffer, 80, "%h %e", timeinfo);
set_font_face(FONT_SANS_SERIF_BOLD);
set_font_size(9);
t = draw_string_width(buffer);
t = (DATE_WIDTH - t) / 2;
draw_string(ctx, width - TIME_LEFT - DATE_WIDTH + t, 21, txt_color, buffer);
set_font_face(FONT_SANS_SERIF);
set_font_size(14);
draw_string(ctx, 10, 18, txt_color, final);
draw_sprite(ctx, sprites[1], width - 23, 1); /* Logout button */
flip(ctx);
yutani_flip(yctx, panel);
}
usleep(500000);
}
}
int main (int argc, char ** argv) {
yctx = yutani_init();
width = yctx->display_width;
height = yctx->display_height;
init_shmemfonts();
set_font_size(14);
/* Create the panel */
panel = yutani_window_create(yctx, width, PANEL_HEIGHT);
yutani_set_stack(yctx, panel, YUTANI_ZORDER_TOP);
ctx = init_graphics_yutani_double_buffer(panel);
draw_fill(ctx, rgba(0,0,0,0));
flip(ctx);
yutani_flip(yctx, panel);
init_sprite_png(0, "/usr/share/panel.png");
init_sprite_png(1, "/usr/share/icons/panel-shutdown.png");
for (uint32_t i = 0; i < width; i += sprites[0]->width) {
draw_sprite(ctx, sprites[0], i, 0);
}
flip(ctx);
syscall_signal(2, sig_int);
pthread_t _clock_thread;
pthread_create(&_clock_thread, NULL, clock_thread, NULL);
while (_continue) {
yutani_msg_t * m = yutani_poll(yctx);
if (m) {
if (m->type == YUTANI_MSG_MOUSE_EVENT) {
/* Do something */
}
free(m);
}
}
yutani_close(yctx, panel);
return 0;
}

View File

@ -0,0 +1,188 @@
/* vim: tabstop=4 shiftwidth=4 noexpandtab
*
* Wallpaper renderer.
*
*/
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <math.h>
#include "lib/yutani.h"
#include "lib/graphics.h"
#include "lib/shmemfonts.h"
sprite_t * sprites[128];
sprite_t alpha_tmp;
#define ICON_X 24
#define ICON_TOP_Y 40
#define ICON_SPACING_Y 74
#define ICON_WIDTH 48
uint16_t win_width;
uint16_t win_height;
gfx_context_t * ctx;
int center_x(int x) {
return (win_width - x) / 2;
}
int center_y(int y) {
return (win_height - y) / 2;
}
static int event_pipe;
typedef struct {
char * icon;
char * appname;
char * title;
} application_t;
application_t applications[] = {
{"/usr/share/icons/utilities-terminal.png", "terminal", "Terminal"},
{"/usr/share/icons/applications-painting.png", "draw", "Draw!"},
{"/usr/share/icons/applications-simulation.png", "game", "RPG Demo"},
{"/usr/share/icons/julia.png", "julia", "Julia Fractals"},
{NULL, NULL, NULL}
};
volatile int _continue = 1;
void sig_int(int sig) {
printf("Received shutdown signal in wallpaper!\n");
_continue = 0;
char buf = '1';
write(event_pipe, &buf, 1);
}
void launch_application(char * app) {
if (!fork()) {
char name[512];
sprintf(name, "/bin/%s", app);
printf("Starting %s\n", name);
char * args[] = {name, NULL};
execvp(args[0], args);
exit(1);
}
}
char * next_run_activate = NULL;
#if 0
void wallpaper_check_click(w_mouse_t * evt) {
if (evt->command == WE_MOUSECLICK) {
printf("Click!\n");
if (evt->new_x > ICON_X && evt->new_x < ICON_X + ICON_WIDTH) {
uint32_t i = 0;
while (1) {
if (!applications[i].icon) {
break;
}
if ((evt->new_y > ICON_TOP_Y + ICON_SPACING_Y * i) &&
(evt->new_y < ICON_TOP_Y + ICON_SPACING_Y + ICON_SPACING_Y * i)) {
printf("Launching application \"%s\"...\n", applications[i].title);
next_run_activate = applications[i].appname;
char buf = '1';
write(event_pipe, &buf, 1);
}
++i;
}
/* Within the icon range */
}
}
}
#endif
void init_sprite_png(int i, char * filename) {
sprites[i] = malloc(sizeof(sprite_t));
load_sprite_png(sprites[i], filename);
}
int main (int argc, char ** argv) {
yutani_t * yctx = yutani_init();
int width = yctx->display_width;
int height = yctx->display_height;
char f_name[512];
sprintf(f_name, "%s/.wallpaper.png", getenv("HOME"));
FILE * f = fopen(f_name, "r");
if (f) {
fclose(f);
init_sprite_png(0, f_name);
} else {
init_sprite_png(0, "/usr/share/wallpaper.png");
}
float x = (float)width / (float)sprites[0]->width;
float y = (float)height / (float)sprites[0]->height;
int nh = (int)(x * (float)sprites[0]->height);
int nw = (int)(y * (float)sprites[0]->width);;
sprites[1] = create_sprite(width, height, ALPHA_OPAQUE);
gfx_context_t * tmp = init_graphics_sprite(sprites[1]);
if (nw > width) {
draw_sprite_scaled(tmp, sprites[0], (width - nw) / 2, 0, nw, height);
} else {
draw_sprite_scaled(tmp, sprites[0], 0, (height - nh) / 2, width, nh);
}
free(tmp);
win_width = width;
win_height = height;
/* Do something with a window */
yutani_window_t * wina = yutani_window_create(yctx, width, height);
assert(wina);
// window_reorder (wina, 0);
yutani_set_stack(yctx, wina, YUTANI_ZORDER_BOTTOM);
ctx = init_graphics_yutani_double_buffer(wina);
draw_sprite(ctx, sprites[1], 0, 0);
flip(ctx);
syscall_signal(2, sig_int);
flip(ctx);
init_shmemfonts();
/* Load Application Shortcuts */
uint32_t i = 0;
while (1) {
if (!applications[i].icon) {
break;
}
printf("Loading png %s\n", applications[i].icon);
init_sprite_png(i+1, applications[i].icon);
draw_sprite(ctx, sprites[i+1], ICON_X, ICON_TOP_Y + ICON_SPACING_Y * i);
int str_w = draw_string_width(applications[i].title) / 2;
int str_x = ICON_X + ICON_WIDTH / 2 - str_w;
int str_y = ICON_TOP_Y + ICON_SPACING_Y * i + ICON_WIDTH + 14;
draw_string_shadow(ctx, str_x, str_y, rgb(255,255,255), applications[i].title, rgb(0,0,0), 2, 1, 1, 3.0);
++i;
}
flip(ctx);
yutani_flip(yctx, wina);
while (1) {
yutani_msg_t * m = yutani_poll(yctx);
if (m) {
if (m->type == YUTANI_MSG_MOUSE_EVENT) {
/* Do something */
}
free(m);
}
}
yutani_close(yctx, wina);
return 0;
}

View File

@ -181,6 +181,22 @@ yutani_msg_t * yutani_msg_build_window_move(yutani_wid_t wid, int32_t x, int32_t
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;
}
int yutani_msg_send(yutani_t * y, yutani_msg_t * msg) {
return pex_reply(y->sock, msg->size, (char *)msg);
}
@ -255,13 +271,18 @@ void yutani_close(yutani_t * y, yutani_window_t * win) {
free(m);
}
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);
}
gfx_context_t * init_graphics_yutani(yutani_window_t * window) {
gfx_context_t * out = malloc(sizeof(gfx_context_t));
out->width = window->width;

View File

@ -65,6 +65,11 @@ struct yutani_msg_key_event {
key_event_t event;
};
struct yutani_msg_window_stack {
yutani_wid_t wid;
int z;
};
struct yutani_msg_mouse_event {
yutani_wid_t wid;
mouse_device_packet_t event;
@ -95,12 +100,17 @@ typedef struct yutani_window {
#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_GOODBYE 0x000000F0
/* Server responses */
#define YUTANI_MSG_WELCOME 0x00010001
#define YUTANI_MSG_WINDOW_INIT 0x00010002
#define YUTANI_ZORDER_MAX 0xFFFF
#define YUTANI_ZORDER_TOP 0xFFFF
#define YUTANI_ZORDER_BOTTOM 0x0000
yutani_msg_t * yutani_wait_for(yutani_t * y, uint32_t type);
yutani_msg_t * yutani_poll(yutani_t * y);
@ -112,6 +122,7 @@ 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);
yutani_msg_t * yutani_msg_build_mouse_event(yutani_wid_t wid, mouse_device_packet_t * event);
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);
int yutani_msg_send(yutani_t * y, yutani_msg_t * msg);
yutani_t * yutani_context_create(FILE * socket);
@ -120,6 +131,7 @@ yutani_window_t * yutani_window_create(yutani_t * y, int width, int height);
void yutani_flip(yutani_t * y, yutani_window_t * win);
void yutani_window_move(yutani_t * yctx, yutani_window_t * window, int x, int y);
void yutani_close(yutani_t * y, yutani_window_t * win);
void yutani_set_stack(yutani_t *, yutani_window_t *, int);
gfx_context_t * init_graphics_yutani(yutani_window_t * window);
gfx_context_t * init_graphics_yutani_double_buffer(yutani_window_t * window);