Basic window movement in Yutani

This commit is contained in:
Kevin Lange 2014-04-13 21:52:16 -07:00
parent 6db3fe2ec2
commit 17f176c888
3 changed files with 144 additions and 23 deletions

View File

@ -35,12 +35,6 @@ struct {
.nest_height = 0
};
/* XXX this should be in lib/mouse.h? */
#define MOUSE_BUTTON_LEFT 0x01
#define MOUSE_BUTTON_RIGHT 0x02
#define MOUSE_BUTTON_MIDDLE 0x04
static int usage(char * argv[]) {
fprintf(stderr,
"Yutani - Window Compositor\n"
@ -101,6 +95,16 @@ static int parse_args(int argc, char * argv[], int * out) {
return 0;
}
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);
}
static int next_buf_id(void) {
static int _next = 1;
return _next++;
@ -377,6 +381,11 @@ yutani_server_window_t * top_at(yutani_globals_t * yg, uint16_t x, uint16_t y) {
return hashmap_get(yg->wids_to_windows, (void *)w);
}
static void set_focused_at(yutani_globals_t * yg, int x, int y) {
yutani_server_window_t * n_focused = top_at(yg, x, y);
set_focused_window(yg, n_focused);
}
static int window_is_top(yutani_globals_t * yg, yutani_server_window_t * window) {
/* For now, just use simple z-order */
return window->z == YUTANI_ZORDER_TOP;
@ -387,12 +396,7 @@ static int window_is_bottom(yutani_globals_t * yg, yutani_server_window_t * wind
return window->z == YUTANI_ZORDER_BOTTOM;
}
static int yutani_blit_window(yutani_globals_t * yg, yutani_server_window_t * window, yutani_server_window_t * modifiers) {
/* If there are no modifiers to be set, use the window's existing setup */
if (!modifiers) {
modifiers = window;
}
static int yutani_blit_window(yutani_globals_t * yg, yutani_server_window_t * window, int x, int y) {
/* Obtain the previously initialized cairo contexts */
cairo_t * cr = yg->framebuffer_ctx;
@ -413,8 +417,8 @@ static int yutani_blit_window(yutani_globals_t * yg, yutani_server_window_t * wi
* Offset the rendering context appropriately for the position of the window
* based on the modifier paramters
*/
cairo_translate(cr, modifiers->x, modifiers->y);
cairo_translate(cs, modifiers->x, modifiers->y);
cairo_translate(cr, x, y);
cairo_translate(cs, x, y);
/* Top and bottom windows can not be rotated. */
if (!window_is_top(yg, window) && !window_is_bottom(yg, window)) {
@ -482,15 +486,18 @@ static void redraw_windows(yutani_globals_t * yg) {
yg->last_mouse_y = tmp_mouse_y;
/* Calculate damage regions from currently queued updates */
spin_lock(&yg->update_list_lock);
while (yg->update_list->length) {
node_t * win = list_dequeue(yg->update_list);
yutani_server_window_t * window = (yutani_server_window_t *)win->value;
yutani_damage_rect_t * rect = (void *)win->value;
/* We add a clip region for each window in the update queue */
has_updates = 1;
yutani_add_clip(yg, window->x, window->y, window->width, window->height);
yutani_add_clip(yg, rect->x, rect->y, rect->width, rect->height);
free(rect);
free(win);
}
spin_unlock(&yg->update_list_lock);
/* Render */
if (has_updates) {
@ -504,7 +511,11 @@ static void redraw_windows(yutani_globals_t * yg) {
*/
for (unsigned int i = 0; i <= YUTANI_ZORDER_MAX; ++i) {
if (yg->zlist[i]) {
yutani_blit_window(yg, yg->zlist[i], NULL);
if (yg->zlist[i] == yg->mouse_window) {
yutani_blit_window(yg, yg->zlist[i], yg->mouse_win_x_p, yg->mouse_win_y_p);
} else {
yutani_blit_window(yg, yg->zlist[i], yg->zlist[i]->x, yg->zlist[i]->y);
}
}
}
@ -548,6 +559,7 @@ void yutani_cairo_init(yutani_globals_t * yg) {
yg->real_ctx = cairo_create(yg->real_surface);
yg->update_list = list_create();
yg->update_list_lock = 0;
}
void * redraw(void * in) {
@ -570,13 +582,91 @@ void * redraw(void * in) {
}
}
static void mark_window(yutani_globals_t * yg, yutani_server_window_t * window) {
yutani_damage_rect_t * rect = malloc(sizeof(yutani_damage_rect_t));
rect->x = window->x;
rect->y = window->y;
rect->width = window->width;
rect->height = window->height;
spin_lock(&yg->update_list_lock);
list_insert(yg->update_list, rect);
spin_unlock(&yg->update_list_lock);
}
static void mark_region(yutani_globals_t * yg, int x, int y, int width, int height) {
yutani_damage_rect_t * rect = malloc(sizeof(yutani_damage_rect_t));
rect->x = x;
rect->y = y;
rect->width = width;
rect->height = height;
spin_lock(&yg->update_list_lock);
list_insert(yg->update_list, rect);
spin_unlock(&yg->update_list_lock);
}
static void handle_mouse_event(yutani_globals_t * yg, struct yutani_msg_mouse_event * me) {
/* XXX handle focus change, drag, etc. */
if (me->event.buttons & MOUSE_BUTTON_LEFT) {
yutani_server_window_t * n_focused = top_at(yg, yg->mouse_x / MOUSE_SCALE, yg->mouse_y / MOUSE_SCALE);
fprintf(stderr, "[yutani-server] Window at %dx%d is %d (%dx%d)\n", yg->mouse_x / MOUSE_SCALE, yg->mouse_y / MOUSE_SCALE, n_focused->wid, n_focused->width, n_focused->height);
set_focused_window(yg, n_focused);
switch (yg->mouse_state) {
case YUTANI_MOUSE_STATE_NORMAL:
{
if ((me->event.buttons & YUTANI_MOUSE_BUTTON_LEFT) && (k_alt)) {
set_focused_at(yg, yg->mouse_x / MOUSE_SCALE, yg->mouse_y / MOUSE_SCALE);
yg->mouse_window = get_focused(yg);
if (yg->mouse_window) {
if (yg->mouse_window->z == YUTANI_ZORDER_BOTTOM || yg->mouse_window->z == YUTANI_ZORDER_TOP) {
yg->mouse_state = YUTANI_MOUSE_STATE_NORMAL;
yg->mouse_window = NULL;
} else {
yg->mouse_state = YUTANI_MOUSE_STATE_MOVING;
yg->mouse_init_x = yg->mouse_x;
yg->mouse_init_y = yg->mouse_y;
yg->mouse_win_x = yg->mouse_window->x;
yg->mouse_win_y = yg->mouse_window->y;
yg->mouse_win_x_p = yg->mouse_win_x;
yg->mouse_win_y_p = yg->mouse_win_y;
make_top(yg, yg->mouse_window);
}
}
} else if ((me->event.buttons & YUTANI_MOUSE_BUTTON_LEFT) && (!k_alt)) {
set_focused_at(yg, yg->mouse_x / MOUSE_SCALE, yg->mouse_y / MOUSE_SCALE);
}
}
break;
case YUTANI_MOUSE_STATE_MOVING:
{
if (!(me->event.buttons & YUTANI_MOUSE_BUTTON_LEFT)) {
yg->mouse_window->x = yg->mouse_win_x + (yg->mouse_x - yg->mouse_init_x) / MOUSE_SCALE;
yg->mouse_window->y = yg->mouse_win_y + (yg->mouse_y - yg->mouse_init_y) / MOUSE_SCALE;
yg->mouse_window = NULL;
yg->mouse_state = YUTANI_MOUSE_STATE_NORMAL;
} else {
int _x_p = yg->mouse_win_x_p;
int _y_p = yg->mouse_win_y_p;
yg->mouse_win_x_p = yg->mouse_win_x + (yg->mouse_x - yg->mouse_init_x) / MOUSE_SCALE;
yg->mouse_win_y_p = yg->mouse_win_y + (yg->mouse_y - yg->mouse_init_y) / MOUSE_SCALE;
mark_window(yg, yg->mouse_window);
mark_region(yg, yg->mouse_win_x_p, yg->mouse_win_y_p, yg->mouse_window->width, yg->mouse_window->height);
mark_region(yg, _x_p, _y_p, yg->mouse_window->width, yg->mouse_window->height);
}
}
break;
case YUTANI_MOUSE_STATE_DRAGGING:
{
}
break;
case YUTANI_MOUSE_STATE_RESIZING:
{
}
break;
default:
/* XXX ? */
break;
}
}
@ -677,7 +767,10 @@ int main(int argc, char * argv[]) {
struct yutani_msg_flip * wf = (void *)m->data;
yutani_server_window_t * w = hashmap_get(yg->wids_to_windows, (void *)wf->wid);
if (w) {
list_insert(yg->update_list, w);
mark_window(yg, w);
if (w == yg->mouse_window) {
mark_region(yg, yg->mouse_win_x_p, yg->mouse_win_y_p, yg->mouse_window->width, yg->mouse_window->height);
}
}
} break;
case YUTANI_MSG_KEY_EVENT: {
@ -724,7 +817,7 @@ int main(int argc, char * argv[]) {
/* XXX free window */
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);
mark_window(yg, w);
unorder_window(yg, w);
if (w == yg->focused_window) {
yg->focused_window = NULL;

View File

@ -64,6 +64,7 @@ typedef struct {
yutani_server_window_t * zlist[0x10000];
list_t * update_list;
volatile int update_list_lock;
sprite_t mouse_sprite;
@ -71,6 +72,17 @@ typedef struct {
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_win_x_p;
int mouse_win_y_p;
int mouse_init_x;
int mouse_init_y;
} yutani_globals_t;

View File

@ -120,6 +120,22 @@ typedef struct yutani_window {
#define YUTANI_ZORDER_TOP 0xFFFF
#define YUTANI_ZORDER_BOTTOM 0x0000
#define YUTANI_MOUSE_BUTTON_LEFT 0x01
#define YUTANI_MOUSE_BUTTON_RIGHT 0x02
#define YUTANI_MOUSE_BUTTON_MIDDLE 0x04
#define YUTANI_MOUSE_STATE_NORMAL 0
#define YUTANI_MOUSE_STATE_MOVING 1
#define YUTANI_MOUSE_STATE_DRAGGING 2
#define YUTANI_MOUSE_STATE_RESIZING 3
typedef struct {
int x;
int y;
unsigned int width;
unsigned int height;
} yutani_damage_rect_t;
yutani_msg_t * yutani_wait_for(yutani_t * y, uint32_t type);
yutani_msg_t * yutani_poll(yutani_t * y);