From e39c08965e1a47fe316bfb2309923dd5e1938ca2 Mon Sep 17 00:00:00 2001 From: Kevin Lange Date: Mon, 14 Apr 2014 22:42:40 -0700 Subject: [PATCH] Bring back rotation --- userspace/gui/compositor/compositor-beta.c | 190 +++++++++++++++++---- userspace/gui/compositor/yutani_int.h | 11 +- 2 files changed, 161 insertions(+), 40 deletions(-) diff --git a/userspace/gui/compositor/compositor-beta.c b/userspace/gui/compositor/compositor-beta.c index 748ee3ae..bbd3e6a0 100644 --- a/userspace/gui/compositor/compositor-beta.c +++ b/userspace/gui/compositor/compositor-beta.c @@ -95,6 +95,14 @@ static int parse_args(int argc, char * argv[], int * out) { return 0; } +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; +} + static void spin_lock(int volatile * lock) { while(__sync_lock_test_and_set(lock, 0x01)) { syscall_yield(); @@ -115,6 +123,44 @@ static int next_wid(void) { return _next++; } +static void device_to_window(yutani_server_window_t * window, int32_t x, int32_t y, int32_t * out_x, int32_t * out_y) { + *out_x = x - window->x; + *out_y = y - window->y; + + double t_x = *out_x - (window->width / 2); + double t_y = *out_y - (window->height / 2); + + double s = sin(-M_PI * (window->rotation/ 180.0)); + double c = cos(-M_PI * (window->rotation/ 180.0)); + + double n_x = t_x * c - t_y * s; + double n_y = t_x * s + t_y * c; + + *out_x = (int32_t)n_x + (window->width / 2); + *out_y = (int32_t)n_y + (window->height / 2); +} + +static void window_to_device(yutani_server_window_t * window, int32_t x, int32_t y, int32_t * out_x, int32_t * out_y) { + + if (!window->rotation) { + *out_x = window->x + x; + *out_y = window->y + y; + return; + } + + double t_x = x - (window->width / 2); + double t_y = y - (window->height / 2); + + double s = sin(M_PI * (window->rotation/ 180.0)); + double c = cos(M_PI * (window->rotation/ 180.0)); + + double n_x = t_x * c - t_y * s; + double n_y = t_x * s + t_y * c; + + *out_x = (int32_t)n_x + (window->width / 2) + window->x; + *out_y = (int32_t)n_y + (window->height / 2) + window->y; +} + static void rebalance_windows(yutani_globals_t * yg) { uint32_t i = 1; for (; i < YUTANI_ZORDER_TOP; ++i) { @@ -246,6 +292,7 @@ static yutani_server_window_t * server_window_create(yutani_globals_t * yg, int win->width = width; win->height = height; win->bufid = next_buf_id(); + win->rotation = 0; char key[1024]; YUTANI_SHMKEY(key, 1024, win); @@ -426,22 +473,22 @@ static int yutani_blit_window(yutani_globals_t * yg, yutani_server_window_t * wi /* Calcuate radians from degrees */ /* XXX Window rotation is disabled until damage rects can take it into account */ -#if 0 - double r = window->rotation * M_PI / 180.0; + if (window->rotation != 0) { + double r = M_PI * (((double)window->rotation) / 180.0); - /* Rotate the render context about the center of the window */ - cairo_translate(cr, (int)( window->width / 2), (int)( window->height / 2)); - cairo_rotate(cr, r); - cairo_translate(cr, (int)(-window->width / 2), (int)(-window->height / 2)); + /* Rotate the render context about the center of the window */ + cairo_translate(cr, (int)( window->width / 2), (int)( (int)window->height / 2)); + cairo_rotate(cr, r); + cairo_translate(cr, (int)(-window->width / 2), (int)(-window->height / 2)); - /* Rotate the selectbuffer context about the center of the window */ - cairo_translate(cs, (int)( window->width / 2), (int)( window->height / 2)); - cairo_rotate(cs, r); - cairo_translate(cs, (int)(-window->width / 2), (int)(-window->height / 2)); + /* Rotate the selectbuffer context about the center of the window */ + cairo_translate(cs, (int)( window->width / 2), (int)( window->height / 2)); + cairo_rotate(cs, r); + cairo_translate(cs, (int)(-window->width / 2), (int)(-window->height / 2)); - /* Prefer faster filter when rendering rotated windows */ - cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_FAST); -#endif + /* Prefer faster filter when rendering rotated windows */ + cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_FAST); + } } /* Paint window */ @@ -466,6 +513,32 @@ static int yutani_blit_window(yutani_globals_t * yg, yutani_server_window_t * wi cairo_restore(cr); cairo_restore(cs); +#ifdef YUTANI_DEBUG_WINDOW_BOUNDS + cairo_save(cr); + + int32_t t_x, t_y; + int32_t s_x, s_y; + int32_t r_x, r_y; + int32_t q_x, q_y; + + window_to_device(window, 0, 0, &t_x, &t_y); + window_to_device(window, window->width, window->height, &s_x, &s_y); + window_to_device(window, 0, window->height, &r_x, &r_y); + window_to_device(window, window->width, 0, &q_x, &q_y); + cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7); + cairo_set_line_width(cr, 2.0); + + cairo_move_to(cr, t_x, t_y); + cairo_line_to(cr, s_x, s_y); + cairo_stroke(cr); + + cairo_move_to(cr, r_x, r_y); + cairo_line_to(cr, q_x, q_y); + cairo_stroke(cr); + + cairo_restore(cr); +#endif + return 0; } @@ -514,11 +587,7 @@ static void redraw_windows(yutani_globals_t * yg) { */ for (unsigned int i = 0; i <= YUTANI_ZORDER_MAX; ++i) { if (yg->zlist[i]) { - 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); - } + yutani_blit_window(yg, yg->zlist[i], yg->zlist[i]->x, yg->zlist[i]->y); } } @@ -587,10 +656,36 @@ 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; + + if (window->rotation == 0) { + rect->x = window->x; + rect->y = window->y; + rect->width = window->width; + rect->height = window->height; + } else { + int32_t ul_x, ul_y; + int32_t ll_x, ll_y; + int32_t ur_x, ur_y; + int32_t lr_x, lr_y; + + window_to_device(window, 0, 0, &ul_x, &ul_y); + window_to_device(window, 0, window->height, &ll_x, &ll_y); + window_to_device(window, window->width, 0, &ur_x, &ur_y); + window_to_device(window, window->width, window->height, &lr_x, &lr_y); + + /* Calculate bounds */ + + int32_t left_bound = min(min(ul_x, ll_x), min(ur_x, lr_x)); + int32_t top_bound = min(min(ul_y, ll_y), min(ur_y, lr_y)); + + int32_t right_bound = max(max(ul_x, ll_x), max(ur_x, lr_x)); + int32_t bottom_bound = max(max(ul_y, ll_y), max(ur_y, lr_y)); + + rect->x = left_bound; + rect->y = top_bound; + rect->width = right_bound - left_bound; + rect->height = bottom_bound - top_bound; + } spin_lock(&yg->update_list_lock); list_insert(yg->update_list, rect); @@ -613,10 +708,38 @@ static void handle_key_event(yutani_globals_t * yg, struct yutani_msg_key_event yutani_server_window_t * focused = get_focused(yg); memcpy(&yg->kbd_state, &ke->state, sizeof(key_event_state_t)); if (focused) { + if ((ke->event.action == KEY_ACTION_DOWN) && + (ke->event.modifiers & KEY_MOD_LEFT_CTRL) && + (ke->event.keycode == 'z')) { + mark_window(yg,focused); + focused->rotation -= 5; + mark_window(yg,focused); + return; + } + if ((ke->event.action == KEY_ACTION_DOWN) && + (ke->event.modifiers & KEY_MOD_LEFT_CTRL) && + (ke->event.keycode == 'x')) { + mark_window(yg,focused); + focused->rotation += 5; + mark_window(yg,focused); + return; + } + if ((ke->event.action == KEY_ACTION_DOWN) && + (ke->event.modifiers & KEY_MOD_LEFT_CTRL) && + (ke->event.keycode == 'c')) { + mark_window(yg,focused); + focused->rotation = 0; + mark_window(yg,focused); + return; + } + yutani_msg_t * response = yutani_msg_build_key_event(focused->wid, &ke->event, &ke->state); pex_send(yg->server, focused->owner, response->size, (char *)response); free(response); + } + + /* Other events? */ } static void handle_mouse_event(yutani_globals_t * yg, struct yutani_msg_mouse_event * me) { @@ -644,38 +767,35 @@ static void handle_mouse_event(yutani_globals_t * yg, struct yutani_msg_mouse_ev 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) && (!yg->kbd_state.k_alt)) { set_focused_at(yg, yg->mouse_x / MOUSE_SCALE, yg->mouse_y / MOUSE_SCALE); + yg->mouse_moved = 0; } } 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); + 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; + mark_window(yg, yg->mouse_window); } } break; case YUTANI_MOUSE_STATE_DRAGGING: { + if (!(me->event.buttons & yg->mouse_drag_button)) { + } else { + + } } break; case YUTANI_MOUSE_STATE_RESIZING: @@ -764,6 +884,7 @@ int main(int argc, char * argv[]) { if (m->magic != YUTANI_MSG__MAGIC) { fprintf(stderr, "[yutani-server] Message has bad magic. (Should eject client, but will instead skip this message.) 0x%x\n", m->magic); + free(p); continue; } @@ -787,9 +908,6 @@ int main(int argc, char * argv[]) { yutani_server_window_t * w = hashmap_get(yg->wids_to_windows, (void *)wf->wid); if (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: { diff --git a/userspace/gui/compositor/yutani_int.h b/userspace/gui/compositor/yutani_int.h index a7869a84..6ed21418 100644 --- a/userspace/gui/compositor/yutani_int.h +++ b/userspace/gui/compositor/yutani_int.h @@ -29,13 +29,15 @@ typedef struct { signed long y; unsigned short z; - uint32_t width; - uint32_t height; + int32_t width; + int32_t height; uint8_t * buffer; uint32_t bufid; uint32_t owner; + + int16_t rotation; } yutani_server_window_t; typedef struct { @@ -79,11 +81,12 @@ typedef struct { 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; + int mouse_drag_button; + int mouse_moved; + key_event_state_t kbd_state; } yutani_globals_t;