Bring back rotation

This commit is contained in:
Kevin Lange 2014-04-14 22:42:40 -07:00
parent 00ecfff45f
commit e39c08965e
2 changed files with 161 additions and 40 deletions

View File

@ -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: {

View File

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