1 /* Copyright (C) 2007-2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 ** GNU General Public License for more details.
11 */
12 #include "android/skin/window.h"
13 #include "android/skin/image.h"
14 #include "android/skin/scaler.h"
15 #include "android/charmap.h"
16 #include "android/utils/debug.h"
17 #include "android/utils/system.h"
18 #include "android/hw-sensors.h"
19 #include <SDL_syswm.h>
20 #include "user-events.h"
21 #include <math.h>
22
23 #include "framebuffer.h"
24
25 /* when shrinking, we reduce the pixel ratio by this fixed amount */
26 #define SHRINK_SCALE 0.6
27
28 /* maximum value of LCD brighness */
29 #define LCD_BRIGHTNESS_MIN 0
30 #define LCD_BRIGHTNESS_DEFAULT 128
31 #define LCD_BRIGHTNESS_MAX 255
32
33 typedef struct Background {
34 SkinImage* image;
35 SkinRect rect;
36 SkinPos origin;
37 } Background;
38
39 static void
background_done(Background * back)40 background_done( Background* back )
41 {
42 skin_image_unref( &back->image );
43 }
44
45 static void
background_init(Background * back,SkinBackground * sback,SkinLocation * loc,SkinRect * frame)46 background_init( Background* back, SkinBackground* sback, SkinLocation* loc, SkinRect* frame )
47 {
48 SkinRect r;
49
50 back->image = skin_image_rotate( sback->image, loc->rotation );
51 skin_rect_rotate( &r, &sback->rect, loc->rotation );
52 r.pos.x += loc->anchor.x;
53 r.pos.y += loc->anchor.y;
54
55 back->origin = r.pos;
56 skin_rect_intersect( &back->rect, &r, frame );
57 }
58
59 static void
background_redraw(Background * back,SkinRect * rect,SDL_Surface * surface)60 background_redraw( Background* back, SkinRect* rect, SDL_Surface* surface )
61 {
62 SkinRect r;
63
64 if (skin_rect_intersect( &r, rect, &back->rect ) )
65 {
66 SDL_Rect rd, rs;
67
68 rd.x = r.pos.x;
69 rd.y = r.pos.y;
70 rd.w = r.size.w;
71 rd.h = r.size.h;
72
73 rs.x = r.pos.x - back->origin.x;
74 rs.y = r.pos.y - back->origin.y;
75 rs.w = r.size.w;
76 rs.h = r.size.h;
77
78 SDL_BlitSurface( skin_image_surface(back->image), &rs, surface, &rd );
79 //SDL_UpdateRects( surface, 1, &rd );
80 }
81 }
82
83
84 typedef struct ADisplay {
85 SkinRect rect;
86 SkinPos origin;
87 SkinRotation rotation;
88 SkinSize datasize; /* framebuffer size */
89 void* data; /* framebuffer pixels */
90 QFrameBuffer* qfbuff;
91 SkinImage* onion; /* onion image */
92 SkinRect onion_rect; /* onion rect, if any */
93 int brightness;
94 } ADisplay;
95
96 static void
display_done(ADisplay * disp)97 display_done( ADisplay* disp )
98 {
99 disp->data = NULL;
100 disp->qfbuff = NULL;
101 skin_image_unref( &disp->onion );
102 }
103
104 static int
display_init(ADisplay * disp,SkinDisplay * sdisp,SkinLocation * loc,SkinRect * frame)105 display_init( ADisplay* disp, SkinDisplay* sdisp, SkinLocation* loc, SkinRect* frame )
106 {
107 skin_rect_rotate( &disp->rect, &sdisp->rect, loc->rotation );
108 disp->rect.pos.x += loc->anchor.x;
109 disp->rect.pos.y += loc->anchor.y;
110
111 disp->rotation = (loc->rotation + sdisp->rotation) & 3;
112 switch (disp->rotation) {
113 case SKIN_ROTATION_0:
114 disp->origin = disp->rect.pos;
115 break;
116
117 case SKIN_ROTATION_90:
118 disp->origin.x = disp->rect.pos.x + disp->rect.size.w;
119 disp->origin.y = disp->rect.pos.y;
120 break;
121
122 case SKIN_ROTATION_180:
123 disp->origin.x = disp->rect.pos.x + disp->rect.size.w;
124 disp->origin.y = disp->rect.pos.y + disp->rect.size.h;
125 break;
126
127 default:
128 disp->origin.x = disp->rect.pos.x;
129 disp->origin.y = disp->rect.pos.y + disp->rect.size.h;
130 break;
131 }
132 skin_size_rotate( &disp->datasize, &sdisp->rect.size, sdisp->rotation );
133 skin_rect_intersect( &disp->rect, &disp->rect, frame );
134 #if 0
135 fprintf(stderr, "... display_init rect.pos(%d,%d) rect.size(%d,%d) datasize(%d,%d)\n",
136 disp->rect.pos.x, disp->rect.pos.y,
137 disp->rect.size.w, disp->rect.size.h,
138 disp->datasize.w, disp->datasize.h);
139 #endif
140 disp->qfbuff = sdisp->qfbuff;
141 disp->data = sdisp->qfbuff->pixels;
142 disp->onion = NULL;
143
144 disp->brightness = LCD_BRIGHTNESS_DEFAULT;
145
146 return (disp->data == NULL) ? -1 : 0;
147 }
148
rgb565_to_argb32(uint32_t pix)149 static __inline__ uint32_t rgb565_to_argb32( uint32_t pix )
150 {
151 uint32_t r = ((pix & 0xf800) << 8) | ((pix & 0xe000) << 3);
152 uint32_t g = ((pix & 0x07e0) << 5) | ((pix & 0x0600) >> 1);
153 uint32_t b = ((pix & 0x001f) << 3) | ((pix & 0x001c) >> 2);
154
155 return 0xff000000 | r | g | b;
156 }
157
158
159 static void
display_set_onion(ADisplay * disp,SkinImage * onion,SkinRotation rotation,int blend)160 display_set_onion( ADisplay* disp, SkinImage* onion, SkinRotation rotation, int blend )
161 {
162 int onion_w, onion_h;
163 SkinRect* rect = &disp->rect;
164 SkinRect* orect = &disp->onion_rect;
165
166 rotation = (rotation + disp->rotation) & 3;
167
168 skin_image_unref( &disp->onion );
169 disp->onion = skin_image_clone_full( onion, rotation, blend );
170
171 onion_w = skin_image_w(disp->onion);
172 onion_h = skin_image_h(disp->onion);
173
174 switch (rotation) {
175 case SKIN_ROTATION_0:
176 orect->pos = rect->pos;
177 break;
178
179 case SKIN_ROTATION_90:
180 orect->pos.x = rect->pos.x + rect->size.w - onion_w;
181 orect->pos.y = rect->pos.y;
182 break;
183
184 case SKIN_ROTATION_180:
185 orect->pos.x = rect->pos.x + rect->size.w - onion_w;
186 orect->pos.y = rect->pos.y + rect->size.h - onion_h;
187 break;
188
189 default:
190 orect->pos.x = rect->pos.x;
191 orect->pos.y = rect->pos.y + rect->size.h - onion_h;
192 }
193 orect->size.w = onion_w;
194 orect->size.h = onion_h;
195 }
196
197 #define DOT_MATRIX 0
198
199 #if DOT_MATRIX
200
201 static void
dotmatrix_dither_argb32(unsigned char * pixels,int x,int y,int w,int h,int pitch)202 dotmatrix_dither_argb32( unsigned char* pixels, int x, int y, int w, int h, int pitch )
203 {
204 static const unsigned dotmatrix_argb32[16] = {
205 0x003f00, 0x00003f, 0x3f0000, 0x000000,
206 0x3f3f3f, 0x000000, 0x3f3f3f, 0x000000,
207 0x3f0000, 0x000000, 0x003f00, 0x00003f,
208 0x3f3f3f, 0x000000, 0x3f3f3f, 0x000000
209 };
210
211 int yy = y & 3;
212
213 pixels += 4*x + y*pitch;
214
215 for ( ; h > 0; h-- ) {
216 unsigned* line = (unsigned*) pixels;
217 int nn, xx = x & 3;
218
219 for (nn = 0; nn < w; nn++) {
220 unsigned c = line[nn];
221
222 c = c - ((c >> 2) & dotmatrix_argb32[(yy << 2)|xx]);
223
224 xx = (xx + 1) & 3;
225 line[nn] = c;
226 }
227
228 yy = (yy + 1) & 3;
229 pixels += pitch;
230 }
231 }
232
233 #endif /* DOT_MATRIX */
234
235 /* technical note about the lightness emulation
236 *
237 * we try to emulate something that looks like the Dream's
238 * non-linear LCD lightness, without going too dark or bright.
239 *
240 * the default lightness is around 105 (about 40%) and we prefer
241 * to keep full RGB colors at that setting, to not alleviate
242 * developers who will not understand why the emulator's colors
243 * look slightly too dark.
244 *
245 * we also want to implement a 'bright' mode by de-saturating
246 * colors towards bright white.
247 *
248 * All of this leads to the implementation below that looks like
249 * the following:
250 *
251 * if (level == MIN)
252 * screen is off
253 *
254 * if (level > MIN && level < LOW)
255 * interpolate towards black, with
256 * MINALPHA = 0.2
257 * alpha = MINALPHA + (1-MINALPHA)*(level-MIN)/(LOW-MIN)
258 *
259 * if (level >= LOW && level <= HIGH)
260 * keep full RGB colors
261 *
262 * if (level > HIGH)
263 * interpolate towards bright white, with
264 * MAXALPHA = 0.6
265 * alpha = MAXALPHA*(level-HIGH)/(MAX-HIGH)
266 *
267 * we probably want some sort of power law instead of interpolating
268 * linearly, but frankly, this is sufficient for most uses.
269 */
270
271 #define LCD_BRIGHTNESS_LOW 80
272 #define LCD_BRIGHTNESS_HIGH 180
273
274 #define LCD_ALPHA_LOW_MIN 0.2
275 #define LCD_ALPHA_HIGH_MAX 0.6
276
277 /* treat as special value to turn screen off */
278 #define LCD_BRIGHTNESS_OFF LCD_BRIGHTNESS_MIN
279
280 static void
lcd_brightness_argb32(unsigned char * pixels,SkinRect * r,int pitch,int brightness)281 lcd_brightness_argb32( unsigned char* pixels, SkinRect* r, int pitch, int brightness )
282 {
283 const unsigned b_min = LCD_BRIGHTNESS_MIN;
284 const unsigned b_max = LCD_BRIGHTNESS_MAX;
285 const unsigned b_low = LCD_BRIGHTNESS_LOW;
286 const unsigned b_high = LCD_BRIGHTNESS_HIGH;
287
288 unsigned alpha = brightness;
289 int w = r->size.w;
290 int h = r->size.h;
291
292 if (alpha <= b_min)
293 alpha = b_min;
294 else if (alpha > b_max)
295 alpha = b_max;
296
297 pixels += 4*r->pos.x + r->pos.y*pitch;
298
299 if (alpha < b_low)
300 {
301 const unsigned alpha_min = (255*LCD_ALPHA_LOW_MIN);
302 const unsigned alpha_range = (255 - alpha_min);
303
304 alpha = alpha_min + ((alpha - b_min)*alpha_range) / (b_low - b_min);
305
306 for ( ; h > 0; h-- ) {
307 unsigned* line = (unsigned*) pixels;
308 int nn;
309
310 for (nn = 0; nn < w; nn++) {
311 unsigned c = line[nn];
312 unsigned ag = (c >> 8) & 0x00ff00ff;
313 unsigned rb = (c) & 0x00ff00ff;
314
315 ag = (ag*alpha) & 0xff00ff00;
316 rb = ((rb*alpha) >> 8) & 0x00ff00ff;
317
318 line[nn] = (unsigned)(ag | rb);
319 }
320 pixels += pitch;
321 }
322 }
323 else if (alpha > LCD_BRIGHTNESS_HIGH) /* 'superluminous' mode */
324 {
325 const unsigned alpha_max = (255*LCD_ALPHA_HIGH_MAX);
326 const unsigned alpha_range = (255-alpha_max);
327 unsigned ialpha;
328
329 alpha = ((alpha - b_high)*alpha_range) / (b_max - b_high);
330 ialpha = 255-alpha;
331
332 for ( ; h > 0; h-- ) {
333 unsigned* line = (unsigned*) pixels;
334 int nn;
335
336 for (nn = 0; nn < w; nn++) {
337 unsigned c = line[nn];
338 unsigned ag = (c >> 8) & 0x00ff00ff;
339 unsigned rb = (c) & 0x00ff00ff;
340
341 /* interpolate towards bright white, i.e. 0x00ffffff */
342 ag = ((ag*ialpha + 0x00ff00ff*alpha)) & 0xff00ff00;
343 rb = ((rb*ialpha + 0x00ff00ff*alpha) >> 8) & 0x00ff00ff;
344
345 line[nn] = (unsigned)(ag | rb);
346 }
347 pixels += pitch;
348 }
349 }
350 }
351
352
353 /* this is called when the LCD framebuffer is off */
354 static void
lcd_off_argb32(unsigned char * pixels,SkinRect * r,int pitch)355 lcd_off_argb32( unsigned char* pixels, SkinRect* r, int pitch )
356 {
357 int x = r->pos.x;
358 int y = r->pos.y;
359 int w = r->size.w;
360 int h = r->size.h;
361
362 pixels += 4*x + y*pitch;
363 for ( ; h > 0; h-- ) {
364 memset( pixels, 0, w*4 );
365 pixels += pitch;
366 }
367 }
368
369
370 static void
display_redraw(ADisplay * disp,SkinRect * rect,SDL_Surface * surface)371 display_redraw( ADisplay* disp, SkinRect* rect, SDL_Surface* surface )
372 {
373 SkinRect r;
374
375 if (skin_rect_intersect( &r, rect, &disp->rect ))
376 {
377 int x = r.pos.x - disp->rect.pos.x;
378 int y = r.pos.y - disp->rect.pos.y;
379 int w = r.size.w;
380 int h = r.size.h;
381 int disp_w = disp->rect.size.w;
382 int disp_h = disp->rect.size.h;
383 int dst_pitch = surface->pitch;
384 uint8_t* dst_line = (uint8_t*)surface->pixels + r.pos.x*4 + r.pos.y*dst_pitch;
385 int src_pitch = disp->datasize.w*2;
386 uint8_t* src_line = (uint8_t*)disp->data;
387 int yy, xx;
388 #if 0
389 fprintf(stderr, "--- display redraw r.pos(%d,%d) r.size(%d,%d) "
390 "disp.pos(%d,%d) disp.size(%d,%d) datasize(%d,%d) rect.pos(%d,%d) rect.size(%d,%d)\n",
391 r.pos.x - disp->rect.pos.x, r.pos.y - disp->rect.pos.y, w, h, disp->rect.pos.x, disp->rect.pos.y,
392 disp->rect.size.w, disp->rect.size.h, disp->datasize.w, disp->datasize.h,
393 rect->pos.x, rect->pos.y, rect->size.w, rect->size.h );
394 #endif
395 SDL_LockSurface( surface );
396
397 if (disp->brightness == LCD_BRIGHTNESS_OFF)
398 {
399 lcd_off_argb32( surface->pixels, &r, dst_pitch );
400 }
401 else
402 {
403 switch ( disp->rotation & 3 )
404 {
405 case ANDROID_ROTATION_0:
406 src_line += x*2 + y*src_pitch;
407
408 for (yy = h; yy > 0; yy--)
409 {
410 uint32_t* dst = (uint32_t*)dst_line;
411 uint16_t* src = (uint16_t*)src_line;
412
413 for (xx = 0; xx < w; xx++) {
414 dst[xx] = rgb565_to_argb32(src[xx]);
415 }
416 src_line += src_pitch;
417 dst_line += dst_pitch;
418 }
419 break;
420
421 case ANDROID_ROTATION_90:
422 src_line += y*2 + (disp_w - x - 1)*src_pitch;
423
424 for (yy = h; yy > 0; yy--)
425 {
426 uint32_t* dst = (uint32_t*)dst_line;
427 uint8_t* src = src_line;
428
429 for (xx = w; xx > 0; xx--)
430 {
431 dst[0] = rgb565_to_argb32(((uint16_t*)src)[0]);
432 src -= src_pitch;
433 dst += 1;
434 }
435 src_line += 2;
436 dst_line += dst_pitch;
437 }
438 break;
439
440 case ANDROID_ROTATION_180:
441 src_line += (disp_w -1 - x)*2 + (disp_h-1-y)*src_pitch;
442
443 for (yy = h; yy > 0; yy--)
444 {
445 uint16_t* src = (uint16_t*)src_line;
446 uint32_t* dst = (uint32_t*)dst_line;
447
448 for (xx = w; xx > 0; xx--) {
449 dst[0] = rgb565_to_argb32(src[0]);
450 src -= 1;
451 dst += 1;
452 }
453
454 src_line -= src_pitch;
455 dst_line += dst_pitch;
456 }
457 break;
458
459 default: /* ANDROID_ROTATION_270 */
460 src_line += (disp_h-1-y)*2 + x*src_pitch;
461
462 for (yy = h; yy > 0; yy--)
463 {
464 uint32_t* dst = (uint32_t*)dst_line;
465 uint8_t* src = src_line;
466
467 for (xx = w; xx > 0; xx--) {
468 dst[0] = rgb565_to_argb32(((uint16_t*)src)[0]);
469 dst += 1;
470 src += src_pitch;
471 }
472 src_line -= 2;
473 dst_line += dst_pitch;
474 }
475 }
476 #if DOT_MATRIX
477 dotmatrix_dither_argb32( surface->pixels, r.pos.x, r.pos.y, r.size.w, r.size.h, surface->pitch );
478 #endif
479 /* apply lightness */
480 lcd_brightness_argb32( surface->pixels, &r, surface->pitch, disp->brightness );
481 }
482 SDL_UnlockSurface( surface );
483
484 /* Apply onion skin */
485 if (disp->onion != NULL) {
486 SkinRect r2;
487
488 if ( skin_rect_intersect( &r2, &r, &disp->onion_rect ) ) {
489 SDL_Rect rs, rd;
490
491 rd.x = r2.pos.x;
492 rd.y = r2.pos.y;
493 rd.w = r2.size.w;
494 rd.h = r2.size.h;
495
496 rs.x = rd.x - disp->onion_rect.pos.x;
497 rs.y = rd.y - disp->onion_rect.pos.y;
498 rs.w = rd.w;
499 rs.h = rd.h;
500
501 SDL_BlitSurface( skin_image_surface(disp->onion), &rs, surface, &rd );
502 }
503 }
504
505 SDL_UpdateRect( surface, r.pos.x, r.pos.y, w, h );
506 }
507 }
508
509
510 typedef struct Button {
511 SkinImage* image;
512 SkinRect rect;
513 SkinPos origin;
514 Background* background;
515 unsigned keycode;
516 int down;
517 } Button;
518
519 static void
button_done(Button * button)520 button_done( Button* button )
521 {
522 skin_image_unref( &button->image );
523 button->background = NULL;
524 }
525
526 static void
button_init(Button * button,SkinButton * sbutton,SkinLocation * loc,Background * back,SkinRect * frame,SkinLayout * slayout)527 button_init( Button* button, SkinButton* sbutton, SkinLocation* loc, Background* back, SkinRect* frame, SkinLayout* slayout )
528 {
529 SkinRect r;
530
531 button->image = skin_image_rotate( sbutton->image, loc->rotation );
532 button->background = back;
533 button->keycode = sbutton->keycode;
534 button->down = 0;
535
536 if (slayout->has_dpad_rotation) {
537 /* Dpad keys must be rotated if the skin provides a 'dpad-rotation' field.
538 * this is used as a counter-measure to the fact that the framework always assumes
539 * that the physical D-Pad has been rotated when in landscape mode.
540 */
541 button->keycode = android_keycode_rotate( button->keycode, -slayout->dpad_rotation );
542 }
543
544 skin_rect_rotate( &r, &sbutton->rect, loc->rotation );
545 r.pos.x += loc->anchor.x;
546 r.pos.y += loc->anchor.y;
547 button->origin = r.pos;
548 skin_rect_intersect( &button->rect, &r, frame );
549 }
550
551 static void
button_redraw(Button * button,SkinRect * rect,SDL_Surface * surface)552 button_redraw( Button* button, SkinRect* rect, SDL_Surface* surface )
553 {
554 SkinRect r;
555
556 if (skin_rect_intersect( &r, rect, &button->rect ))
557 {
558 if ( button->down && button->image != SKIN_IMAGE_NONE )
559 {
560 SDL_Rect rs, rd;
561
562 rs.x = r.pos.x - button->origin.x;
563 rs.y = r.pos.y - button->origin.y;
564 rs.w = r.size.w;
565 rs.h = r.size.h;
566
567 rd.x = r.pos.x;
568 rd.y = r.pos.y;
569 rd.w = r.size.w;
570 rd.h = r.size.h;
571
572 if (button->image != SKIN_IMAGE_NONE) {
573 SDL_BlitSurface( skin_image_surface(button->image), &rs, surface, &rd );
574 if (button->down > 1)
575 SDL_BlitSurface( skin_image_surface(button->image), &rs, surface, &rd );
576 }
577 }
578 }
579 }
580
581
582 typedef struct {
583 char tracking;
584 char inside;
585 SkinPos pos;
586 ADisplay* display;
587 } FingerState;
588
589 static void
finger_state_reset(FingerState * finger)590 finger_state_reset( FingerState* finger )
591 {
592 finger->tracking = 0;
593 finger->inside = 0;
594 }
595
596 typedef struct {
597 Button* pressed;
598 Button* hover;
599 } ButtonState;
600
601 static void
button_state_reset(ButtonState * button)602 button_state_reset( ButtonState* button )
603 {
604 button->pressed = NULL;
605 button->hover = NULL;
606 }
607
608 typedef struct {
609 char tracking;
610 SkinTrackBall* ball;
611 SkinRect rect;
612 SkinWindow* window;
613 } BallState;
614
615 static void
ball_state_reset(BallState * state,SkinWindow * window)616 ball_state_reset( BallState* state, SkinWindow* window )
617 {
618 state->tracking = 0;
619 state->ball = NULL;
620
621 state->rect.pos.x = 0;
622 state->rect.pos.y = 0;
623 state->rect.size.w = 0;
624 state->rect.size.h = 0;
625 state->window = window;
626 }
627
628 static void
ball_state_redraw(BallState * state,SkinRect * rect,SDL_Surface * surface)629 ball_state_redraw( BallState* state, SkinRect* rect, SDL_Surface* surface )
630 {
631 SkinRect r;
632
633 if (skin_rect_intersect( &r, rect, &state->rect ))
634 skin_trackball_draw( state->ball, 0, 0, surface );
635 }
636
637 static void
ball_state_show(BallState * state,int enable)638 ball_state_show( BallState* state, int enable )
639 {
640 if (enable) {
641 if ( !state->tracking ) {
642 state->tracking = 1;
643 SDL_ShowCursor(0);
644 SDL_WM_GrabInput( SDL_GRAB_ON );
645 skin_trackball_refresh( state->ball );
646 skin_window_redraw( state->window, &state->rect );
647 }
648 } else {
649 if ( state->tracking ) {
650 state->tracking = 0;
651 SDL_WM_GrabInput( SDL_GRAB_OFF );
652 SDL_ShowCursor(1);
653 skin_window_redraw( state->window, &state->rect );
654 }
655 }
656 }
657
658
659 static void
ball_state_set(BallState * state,SkinTrackBall * ball)660 ball_state_set( BallState* state, SkinTrackBall* ball )
661 {
662 ball_state_show( state, 0 );
663
664 state->ball = ball;
665 if (ball != NULL) {
666 SDL_Rect sr;
667
668 skin_trackball_rect( ball, &sr );
669 state->rect.pos.x = sr.x;
670 state->rect.pos.y = sr.y;
671 state->rect.size.w = sr.w;
672 state->rect.size.h = sr.h;
673 }
674 }
675
676 typedef struct Layout {
677 int num_buttons;
678 int num_backgrounds;
679 int num_displays;
680 unsigned color;
681 Button* buttons;
682 Background* backgrounds;
683 ADisplay* displays;
684 SkinRect rect;
685 SkinLayout* slayout;
686 } Layout;
687
688 #define LAYOUT_LOOP_BUTTONS(layout,button) \
689 do { \
690 Button* __button = (layout)->buttons; \
691 Button* __button_end = __button + (layout)->num_buttons; \
692 for ( ; __button < __button_end; __button ++ ) { \
693 Button* button = __button;
694
695 #define LAYOUT_LOOP_END_BUTTONS \
696 } \
697 } while (0);
698
699 #define LAYOUT_LOOP_DISPLAYS(layout,display) \
700 do { \
701 ADisplay* __display = (layout)->displays; \
702 ADisplay* __display_end = __display + (layout)->num_displays; \
703 for ( ; __display < __display_end; __display ++ ) { \
704 ADisplay* display = __display;
705
706 #define LAYOUT_LOOP_END_DISPLAYS \
707 } \
708 } while (0);
709
710
711 static void
layout_done(Layout * layout)712 layout_done( Layout* layout )
713 {
714 int nn;
715
716 for (nn = 0; nn < layout->num_buttons; nn++)
717 button_done( &layout->buttons[nn] );
718
719 for (nn = 0; nn < layout->num_backgrounds; nn++)
720 background_done( &layout->backgrounds[nn] );
721
722 for (nn = 0; nn < layout->num_displays; nn++)
723 display_done( &layout->displays[nn] );
724
725 qemu_free( layout->buttons );
726 layout->buttons = NULL;
727
728 qemu_free( layout->backgrounds );
729 layout->backgrounds = NULL;
730
731 qemu_free( layout->displays );
732 layout->displays = NULL;
733
734 layout->num_buttons = 0;
735 layout->num_backgrounds = 0;
736 layout->num_displays = 0;
737 }
738
739 static int
layout_init(Layout * layout,SkinLayout * slayout)740 layout_init( Layout* layout, SkinLayout* slayout )
741 {
742 int n_buttons, n_backgrounds, n_displays;
743
744 /* first, count the number of elements of each kind */
745 n_buttons = 0;
746 n_backgrounds = 0;
747 n_displays = 0;
748
749 layout->color = slayout->color;
750 layout->slayout = slayout;
751
752 SKIN_LAYOUT_LOOP_LOCS(slayout,loc)
753 SkinPart* part = loc->part;
754
755 if ( part->background->valid )
756 n_backgrounds += 1;
757 if ( part->display->valid )
758 n_displays += 1;
759
760 SKIN_PART_LOOP_BUTTONS(part, sbutton)
761 n_buttons += 1;
762 sbutton=sbutton;
763 SKIN_PART_LOOP_END
764 SKIN_LAYOUT_LOOP_END
765
766 layout->num_buttons = n_buttons;
767 layout->num_backgrounds = n_backgrounds;
768 layout->num_displays = n_displays;
769
770 /* now allocate arrays, then populate them */
771 AARRAY_NEW0(layout->buttons, n_buttons);
772 AARRAY_NEW0(layout->backgrounds, n_backgrounds);
773 AARRAY_NEW0(layout->displays, n_displays);
774
775 if (layout->buttons == NULL && n_buttons > 0) goto Fail;
776 if (layout->backgrounds == NULL && n_backgrounds > 0) goto Fail;
777 if (layout->displays == NULL && n_displays > 0) goto Fail;
778
779 n_buttons = 0;
780 n_backgrounds = 0;
781 n_displays = 0;
782
783 layout->rect.pos.x = 0;
784 layout->rect.pos.y = 0;
785 layout->rect.size = slayout->size;
786
787 SKIN_LAYOUT_LOOP_LOCS(slayout,loc)
788 SkinPart* part = loc->part;
789 Background* back = NULL;
790
791 if ( part->background->valid ) {
792 back = layout->backgrounds + n_backgrounds;
793 background_init( back, part->background, loc, &layout->rect );
794 n_backgrounds += 1;
795 }
796 if ( part->display->valid ) {
797 ADisplay* disp = layout->displays + n_displays;
798 display_init( disp, part->display, loc, &layout->rect );
799 n_displays += 1;
800 }
801
802 SKIN_PART_LOOP_BUTTONS(part, sbutton)
803 Button* button = layout->buttons + n_buttons;
804 button_init( button, sbutton, loc, back, &layout->rect, slayout );
805 n_buttons += 1;
806 SKIN_PART_LOOP_END
807 SKIN_LAYOUT_LOOP_END
808
809 return 0;
810
811 Fail:
812 layout_done(layout);
813 return -1;
814 }
815
816 struct SkinWindow {
817 SDL_Surface* surface;
818 Layout layout;
819 SkinPos pos;
820 FingerState finger;
821 ButtonState button;
822 BallState ball;
823 char enabled;
824 char fullscreen;
825 char no_display;
826
827 char enable_touch;
828 char enable_trackball;
829 char enable_dpad;
830 char enable_qwerty;
831
832 SkinImage* onion;
833 SkinRotation onion_rotation;
834 int onion_alpha;
835
836 int x_pos;
837 int y_pos;
838
839 SkinScaler* scaler;
840 int shrink;
841 double shrink_scale;
842 unsigned* shrink_pixels;
843 SDL_Surface* shrink_surface;
844
845 double effective_scale;
846 double effective_x;
847 double effective_y;
848 };
849
850 static void
add_finger_event(unsigned x,unsigned y,unsigned state)851 add_finger_event(unsigned x, unsigned y, unsigned state)
852 {
853 //fprintf(stderr, "::: finger %d,%d %d\n", x, y, state);
854
855 /* NOTE: the 0 is used in hw/goldfish_events.c to differentiate
856 * between a touch-screen and a trackball event
857 */
858 user_event_mouse(x, y, 0, state);
859 }
860
861 static void
skin_window_find_finger(SkinWindow * window,int x,int y)862 skin_window_find_finger( SkinWindow* window,
863 int x,
864 int y )
865 {
866 FingerState* finger = &window->finger;
867
868 /* find the display that contains this movement */
869 finger->display = NULL;
870 finger->inside = 0;
871
872 if (!window->enable_touch)
873 return;
874
875 LAYOUT_LOOP_DISPLAYS(&window->layout,disp)
876 if ( skin_rect_contains( &disp->rect, x, y ) ) {
877 finger->inside = 1;
878 finger->display = disp;
879 finger->pos.x = x - disp->origin.x;
880 finger->pos.y = y - disp->origin.y;
881
882 skin_pos_rotate( &finger->pos, &finger->pos, -disp->rotation );
883 break;
884 }
885 LAYOUT_LOOP_END_DISPLAYS
886 }
887
888 static void
skin_window_move_mouse(SkinWindow * window,int x,int y)889 skin_window_move_mouse( SkinWindow* window,
890 int x,
891 int y )
892 {
893 FingerState* finger = &window->finger;
894 ButtonState* button = &window->button;
895
896 if (finger->tracking) {
897 ADisplay* disp = finger->display;
898 char inside = 1;
899 int dx = x - disp->rect.pos.x;
900 int dy = y - disp->rect.pos.y;
901
902 if (dx < 0) {
903 dx = 0;
904 inside = 0;
905 }
906 else if (dx >= disp->rect.size.w) {
907 dx = disp->rect.size.w - 1;
908 inside = 0;
909 }
910 if (dy < 0) {
911 dy = 0;
912 inside = 0;
913 } else if (dy >= disp->rect.size.h) {
914 dy = disp->rect.size.h-1;
915 inside = 0;
916 }
917 finger->inside = inside;
918 finger->pos.x = dx + (disp->rect.pos.x - disp->origin.x);
919 finger->pos.y = dy + (disp->rect.pos.y - disp->origin.y);
920
921 skin_pos_rotate( &finger->pos, &finger->pos, -disp->rotation );
922 }
923
924 {
925 Button* hover = button->hover;
926
927 if (hover) {
928 if ( skin_rect_contains( &hover->rect, x, y ) )
929 return;
930
931 hover->down = 0;
932 skin_window_redraw( window, &hover->rect );
933 button->hover = NULL;
934 }
935
936 hover = NULL;
937 LAYOUT_LOOP_BUTTONS( &window->layout, butt )
938 if ( skin_rect_contains( &butt->rect, x, y ) ) {
939 hover = butt;
940 break;
941 }
942 LAYOUT_LOOP_END_BUTTONS
943
944 /* filter DPAD and QWERTY buttons right here */
945 if (hover != NULL) {
946 switch (hover->keycode) {
947 /* these correspond to the DPad */
948 case kKeyCodeDpadUp:
949 case kKeyCodeDpadDown:
950 case kKeyCodeDpadLeft:
951 case kKeyCodeDpadRight:
952 case kKeyCodeDpadCenter:
953 if (!window->enable_dpad)
954 hover = NULL;
955 break;
956
957 /* these correspond to non-qwerty buttons */
958 case kKeyCodeSoftLeft:
959 case kKeyCodeSoftRight:
960 case kKeyCodeVolumeUp:
961 case kKeyCodeVolumeDown:
962 case kKeyCodePower:
963 case kKeyCodeHome:
964 case kKeyCodeBack:
965 case kKeyCodeCall:
966 case kKeyCodeEndCall:
967 break;
968
969 /* all the rest is assumed to be qwerty */
970 default:
971 if (!window->enable_qwerty)
972 hover = NULL;
973 }
974 }
975
976 if (hover != NULL) {
977 hover->down = 1;
978 skin_window_redraw( window, &hover->rect );
979 button->hover = hover;
980 }
981 }
982 }
983
984 static void
skin_window_trackball_press(SkinWindow * window,int down)985 skin_window_trackball_press( SkinWindow* window, int down )
986 {
987 user_event_key( BTN_MOUSE, down );
988 }
989
990 static void
skin_window_trackball_move(SkinWindow * window,int xrel,int yrel)991 skin_window_trackball_move( SkinWindow* window, int xrel, int yrel )
992 {
993 BallState* state = &window->ball;
994
995 if ( skin_trackball_move( state->ball, xrel, yrel ) ) {
996 skin_trackball_refresh( state->ball );
997 skin_window_redraw( window, &state->rect );
998 }
999 }
1000
1001 void
skin_window_set_trackball(SkinWindow * window,SkinTrackBall * ball)1002 skin_window_set_trackball( SkinWindow* window, SkinTrackBall* ball )
1003 {
1004 BallState* state = &window->ball;
1005
1006 ball_state_set( state, ball );
1007 }
1008
1009 void
skin_window_show_trackball(SkinWindow * window,int enable)1010 skin_window_show_trackball( SkinWindow* window, int enable )
1011 {
1012 BallState* state = &window->ball;
1013
1014 if (state->ball != NULL && window->enable_trackball) {
1015 ball_state_show(state, enable);
1016 }
1017 }
1018
1019
1020 static int skin_window_reset_internal (SkinWindow*, SkinLayout*);
1021
1022 SkinWindow*
skin_window_create(SkinLayout * slayout,int x,int y,double scale,int no_display)1023 skin_window_create( SkinLayout* slayout, int x, int y, double scale, int no_display )
1024 {
1025 SkinWindow* window;
1026
1027 ANEW0(window);
1028
1029 window->shrink_scale = scale;
1030 window->shrink = (scale != 1.0);
1031 window->scaler = skin_scaler_create();
1032 window->no_display = no_display;
1033
1034 /* enable everything by default */
1035 window->enable_touch = 1;
1036 window->enable_trackball = 1;
1037 window->enable_dpad = 1;
1038 window->enable_qwerty = 1;
1039
1040 window->x_pos = x;
1041 window->y_pos = y;
1042
1043 if (skin_window_reset_internal(window, slayout) < 0) {
1044 skin_window_free( window );
1045 return NULL;
1046 }
1047 //SDL_WM_SetCaption( "Android Emulator", "Android Emulator" );
1048
1049 SDL_WM_SetPos( x, y );
1050 if ( !SDL_WM_IsFullyVisible( 1 ) ) {
1051 dprint( "emulator window was out of view and was recentred\n" );
1052 }
1053
1054 return window;
1055 }
1056
1057 void
skin_window_enable_touch(SkinWindow * window,int enabled)1058 skin_window_enable_touch( SkinWindow* window, int enabled )
1059 {
1060 window->enable_touch = !!enabled;
1061 }
1062
1063 void
skin_window_enable_trackball(SkinWindow * window,int enabled)1064 skin_window_enable_trackball( SkinWindow* window, int enabled )
1065 {
1066 window->enable_trackball = !!enabled;
1067 }
1068
1069 void
skin_window_enable_dpad(SkinWindow * window,int enabled)1070 skin_window_enable_dpad( SkinWindow* window, int enabled )
1071 {
1072 window->enable_dpad = !!enabled;
1073 }
1074
1075 void
skin_window_enable_qwerty(SkinWindow * window,int enabled)1076 skin_window_enable_qwerty( SkinWindow* window, int enabled )
1077 {
1078 window->enable_qwerty = !!enabled;
1079 }
1080
1081 void
skin_window_set_title(SkinWindow * window,const char * title)1082 skin_window_set_title( SkinWindow* window, const char* title )
1083 {
1084 if (window && title)
1085 SDL_WM_SetCaption( title, title );
1086 }
1087
1088 static void
skin_window_resize(SkinWindow * window)1089 skin_window_resize( SkinWindow* window )
1090 {
1091 /* now resize window */
1092 if (window->surface) {
1093 SDL_FreeSurface(window->surface);
1094 window->surface = NULL;
1095 }
1096
1097 if (window->shrink_surface) {
1098 SDL_FreeSurface(window->shrink_surface);
1099 window->shrink_surface = NULL;
1100 }
1101
1102 if (window->shrink_pixels) {
1103 qemu_free(window->shrink_pixels);
1104 window->shrink_pixels = NULL;
1105 }
1106
1107 if ( !window->no_display ) {
1108 int layout_w = window->layout.rect.size.w;
1109 int layout_h = window->layout.rect.size.h;
1110 int window_w = layout_w;
1111 int window_h = layout_h;
1112 int window_x = window->x_pos;
1113 int window_y = window->y_pos;
1114 int flags;
1115 SDL_Surface* surface;
1116 double scale = 1.0;
1117 int fullscreen = window->fullscreen;
1118
1119 if (fullscreen) {
1120 SDL_Rect r;
1121 if (SDL_WM_GetMonitorRect(&r) < 0) {
1122 fullscreen = 0;
1123 } else {
1124 double x_scale, y_scale;
1125
1126 window_x = r.x;
1127 window_y = r.y;
1128 window_w = r.w;
1129 window_h = r.h;
1130
1131 x_scale = window_w * 1.0 / layout_w;
1132 y_scale = window_h * 1.0 / layout_h;
1133
1134 scale = (x_scale <= y_scale) ? x_scale : y_scale;
1135 }
1136 }
1137 else if (window->shrink) {
1138 scale = window->shrink_scale;
1139 window_w = (int) ceil(layout_w*scale);
1140 window_h = (int) ceil(layout_h*scale);
1141 }
1142
1143 {
1144 char temp[32];
1145 sprintf(temp,"SDL_VIDEO_WINDOW_POS=%d,%d",window_x,window_y);
1146 putenv(temp);
1147 putenv("SDL_VIDEO_WINDOW_FORCE_VISIBLE=1");
1148 }
1149
1150 flags = SDL_SWSURFACE;
1151 if (fullscreen) {
1152 flags |= SDL_FULLSCREEN;
1153 }
1154 surface = SDL_SetVideoMode( window_w, window_h, 32, flags );
1155 if (surface == NULL) {
1156 fprintf(stderr, "### Error: could not create or resize SDL window: %s\n", SDL_GetError() );
1157 exit(1);
1158 }
1159
1160 SDL_WM_SetPos( window_x, window_y );
1161
1162 window->effective_scale = scale;
1163 window->effective_x = 0;
1164 window->effective_y = 0;
1165
1166 if (fullscreen) {
1167 window->effective_x = (window_w - layout_w*scale)*0.5;
1168 window->effective_y = (window_h - layout_h*scale)*0.5;
1169 }
1170
1171 if (scale == 1.0)
1172 window->surface = surface;
1173 else
1174 {
1175 window_w = (int) ceil(window_w / scale );
1176 window_h = (int) ceil(window_h / scale );
1177
1178 window->shrink_surface = surface;
1179 AARRAY_NEW0(window->shrink_pixels, window_w * window_h * 4);
1180 if (window->shrink_pixels == NULL) {
1181 fprintf(stderr, "### Error: could not allocate memory for rescaling surface\n");
1182 exit(1);
1183 }
1184 window->surface = sdl_surface_from_argb32( window->shrink_pixels, window_w, window_h );
1185 if (window->surface == NULL) {
1186 fprintf(stderr, "### Error: could not create or resize SDL window: %s\n", SDL_GetError() );
1187 exit(1);
1188 }
1189 skin_scaler_set( window->scaler, scale, window->effective_x, window->effective_y );
1190 }
1191 }
1192 }
1193
1194 static int
skin_window_reset_internal(SkinWindow * window,SkinLayout * slayout)1195 skin_window_reset_internal ( SkinWindow* window, SkinLayout* slayout )
1196 {
1197 Layout layout;
1198 ADisplay* disp;
1199
1200 if ( layout_init( &layout, slayout ) < 0 )
1201 return -1;
1202
1203 disp = window->layout.displays;
1204
1205 layout_done( &window->layout );
1206 window->layout = layout;
1207
1208 disp = window->layout.displays;
1209 if (disp != NULL && window->onion)
1210 display_set_onion( disp,
1211 window->onion,
1212 window->onion_rotation,
1213 window->onion_alpha );
1214
1215 skin_window_resize(window);
1216
1217 finger_state_reset( &window->finger );
1218 button_state_reset( &window->button );
1219 ball_state_reset( &window->ball, window );
1220
1221 skin_window_redraw( window, NULL );
1222
1223 if (slayout->event_type != 0) {
1224 user_event_generic( slayout->event_type, slayout->event_code, slayout->event_value );
1225 /* XXX: hack, replace by better code here */
1226 if (slayout->event_value != 0)
1227 android_sensors_set_coarse_orientation( ANDROID_COARSE_PORTRAIT );
1228 else
1229 android_sensors_set_coarse_orientation( ANDROID_COARSE_LANDSCAPE );
1230 }
1231
1232 return 0;
1233 }
1234
1235 int
skin_window_reset(SkinWindow * window,SkinLayout * slayout)1236 skin_window_reset ( SkinWindow* window, SkinLayout* slayout )
1237 {
1238 if (!window->fullscreen) {
1239 SDL_WM_GetPos(&window->x_pos, &window->y_pos);
1240 }
1241 return skin_window_reset_internal( window, slayout );
1242 }
1243
1244 void
skin_window_set_lcd_brightness(SkinWindow * window,int brightness)1245 skin_window_set_lcd_brightness( SkinWindow* window, int brightness )
1246 {
1247 ADisplay* disp = window->layout.displays;
1248
1249 if (disp != NULL) {
1250 disp->brightness = brightness;
1251 skin_window_redraw( window, NULL );
1252 }
1253 }
1254
1255 void
skin_window_free(SkinWindow * window)1256 skin_window_free ( SkinWindow* window )
1257 {
1258 if (window) {
1259 if (window->surface) {
1260 SDL_FreeSurface(window->surface);
1261 window->surface = NULL;
1262 }
1263 if (window->shrink_surface) {
1264 SDL_FreeSurface(window->shrink_surface);
1265 window->shrink_surface = NULL;
1266 }
1267 if (window->shrink_pixels) {
1268 qemu_free(window->shrink_pixels);
1269 window->shrink_pixels = NULL;
1270 }
1271 if (window->onion) {
1272 skin_image_unref( &window->onion );
1273 window->onion_rotation = SKIN_ROTATION_0;
1274 }
1275 if (window->scaler) {
1276 skin_scaler_free(window->scaler);
1277 window->scaler = NULL;
1278 }
1279 layout_done( &window->layout );
1280 qemu_free(window);
1281 }
1282 }
1283
1284 void
skin_window_set_onion(SkinWindow * window,SkinImage * onion,SkinRotation onion_rotation,int onion_alpha)1285 skin_window_set_onion( SkinWindow* window,
1286 SkinImage* onion,
1287 SkinRotation onion_rotation,
1288 int onion_alpha )
1289 {
1290 ADisplay* disp;
1291 SkinImage* old = window->onion;
1292
1293 window->onion = skin_image_ref(onion);
1294 window->onion_rotation = onion_rotation;
1295 window->onion_alpha = onion_alpha;
1296
1297 skin_image_unref( &old );
1298
1299 disp = window->layout.displays;
1300
1301 if (disp != NULL)
1302 display_set_onion( disp, window->onion, onion_rotation, onion_alpha );
1303 }
1304
1305 static void
skin_window_update_shrink(SkinWindow * window,SkinRect * rect)1306 skin_window_update_shrink( SkinWindow* window, SkinRect* rect )
1307 {
1308 skin_scaler_scale( window->scaler, window->shrink_surface, window->surface,
1309 rect->pos.x, rect->pos.y, rect->size.w, rect->size.h );
1310 }
1311
1312 void
skin_window_set_scale(SkinWindow * window,double scale)1313 skin_window_set_scale( SkinWindow* window, double scale )
1314 {
1315 window->shrink = (scale != 1.0);
1316 window->shrink_scale = scale;
1317
1318 skin_window_resize( window );
1319 skin_window_redraw( window, NULL );
1320 }
1321
1322 void
skin_window_redraw(SkinWindow * window,SkinRect * rect)1323 skin_window_redraw( SkinWindow* window, SkinRect* rect )
1324 {
1325 if (window != NULL && window->surface != NULL) {
1326 Layout* layout = &window->layout;
1327
1328 if (rect == NULL)
1329 rect = &layout->rect;
1330
1331 {
1332 SkinRect r;
1333
1334 if ( skin_rect_intersect( &r, rect, &layout->rect ) ) {
1335 SDL_Rect rd;
1336 rd.x = r.pos.x;
1337 rd.y = r.pos.y;
1338 rd.w = r.size.w;
1339 rd.h = r.size.h;
1340
1341 SDL_FillRect( window->surface, &rd, layout->color );
1342 }
1343 }
1344
1345 {
1346 Background* back = layout->backgrounds;
1347 Background* end = back + layout->num_backgrounds;
1348 for ( ; back < end; back++ )
1349 background_redraw( back, rect, window->surface );
1350 }
1351
1352 {
1353 ADisplay* disp = layout->displays;
1354 ADisplay* end = disp + layout->num_displays;
1355 for ( ; disp < end; disp++ )
1356 display_redraw( disp, rect, window->surface );
1357 }
1358
1359 {
1360 Button* button = layout->buttons;
1361 Button* end = button + layout->num_buttons;
1362 for ( ; button < end; button++ )
1363 button_redraw( button, rect, window->surface );
1364 }
1365
1366 if ( window->ball.tracking )
1367 ball_state_redraw( &window->ball, rect, window->surface );
1368
1369 if (window->effective_scale != 1.0)
1370 skin_window_update_shrink( window, rect );
1371 else
1372 {
1373 SDL_Rect rd;
1374 rd.x = rect->pos.x;
1375 rd.y = rect->pos.y;
1376 rd.w = rect->size.w;
1377 rd.h = rect->size.h;
1378
1379 SDL_UpdateRects( window->surface, 1, &rd );
1380 }
1381 }
1382 }
1383
1384 void
skin_window_toggle_fullscreen(SkinWindow * window)1385 skin_window_toggle_fullscreen( SkinWindow* window )
1386 {
1387 if (window && window->surface) {
1388 if (!window->fullscreen)
1389 SDL_WM_GetPos( &window->x_pos, &window->y_pos );
1390
1391 window->fullscreen = !window->fullscreen;
1392 skin_window_resize( window );
1393 skin_window_redraw( window, NULL );
1394 }
1395 }
1396
1397 void
skin_window_get_display(SkinWindow * window,ADisplayInfo * info)1398 skin_window_get_display( SkinWindow* window, ADisplayInfo *info )
1399 {
1400 ADisplay* disp = window->layout.displays;
1401
1402 if (disp != NULL) {
1403 info->width = disp->datasize.w;
1404 info->height = disp->datasize.h;
1405 info->rotation = disp->rotation;
1406 info->data = disp->data;
1407 } else {
1408 info->width = 0;
1409 info->height = 0;
1410 info->rotation = SKIN_ROTATION_0;
1411 info->data = NULL;
1412 }
1413 }
1414
1415
1416 static void
skin_window_map_to_scale(SkinWindow * window,int * x,int * y)1417 skin_window_map_to_scale( SkinWindow* window, int *x, int *y )
1418 {
1419 *x = (*x - window->effective_x) / window->effective_scale;
1420 *y = (*y - window->effective_y) / window->effective_scale;
1421 }
1422
1423 void
skin_window_process_event(SkinWindow * window,SDL_Event * ev)1424 skin_window_process_event( SkinWindow* window, SDL_Event* ev )
1425 {
1426 Button* button;
1427 int mx, my;
1428
1429 if (!window->surface)
1430 return;
1431
1432 switch (ev->type) {
1433 case SDL_MOUSEBUTTONDOWN:
1434 if ( window->ball.tracking ) {
1435 skin_window_trackball_press( window, 1 );
1436 break;
1437 }
1438
1439 mx = ev->button.x;
1440 my = ev->button.y;
1441 skin_window_map_to_scale( window, &mx, &my );
1442 skin_window_move_mouse( window, mx, my );
1443 skin_window_find_finger( window, mx, my );
1444 #if 0
1445 printf("down: x=%d y=%d fx=%d fy=%d fis=%d\n",
1446 ev->button.x, ev->button.y, window->finger.pos.x,
1447 window->finger.pos.y, window->finger.inside);
1448 #endif
1449 if (window->finger.inside) {
1450 window->finger.tracking = 1;
1451 add_finger_event(window->finger.pos.x, window->finger.pos.y, 1);
1452 } else {
1453 window->button.pressed = NULL;
1454 button = window->button.hover;
1455 if(button) {
1456 button->down += 1;
1457 skin_window_redraw( window, &button->rect );
1458 window->button.pressed = button;
1459 if(button->keycode) {
1460 user_event_key(button->keycode, 1);
1461 }
1462 }
1463 }
1464 break;
1465
1466 case SDL_MOUSEBUTTONUP:
1467 if ( window->ball.tracking ) {
1468 skin_window_trackball_press( window, 0 );
1469 break;
1470 }
1471 button = window->button.pressed;
1472 mx = ev->button.x;
1473 my = ev->button.y;
1474 skin_window_map_to_scale( window, &mx, &my );
1475 if (button)
1476 {
1477 button->down = 0;
1478 skin_window_redraw( window, &button->rect );
1479 if(button->keycode) {
1480 user_event_key(button->keycode, 0);
1481 }
1482 window->button.pressed = NULL;
1483 window->button.hover = NULL;
1484 skin_window_move_mouse( window, mx, my );
1485 }
1486 else if (window->finger.tracking)
1487 {
1488 skin_window_move_mouse( window, mx, my );
1489 window->finger.tracking = 0;
1490 add_finger_event( window->finger.pos.x, window->finger.pos.y, 0);
1491 }
1492 break;
1493
1494 case SDL_MOUSEMOTION:
1495 if ( window->ball.tracking ) {
1496 skin_window_trackball_move( window, ev->motion.xrel, ev->motion.yrel );
1497 break;
1498 }
1499 mx = ev->button.x;
1500 my = ev->button.y;
1501 skin_window_map_to_scale( window, &mx, &my );
1502 if ( !window->button.pressed )
1503 {
1504 skin_window_move_mouse( window, mx, my );
1505 if ( window->finger.tracking ) {
1506 add_finger_event( window->finger.pos.x, window->finger.pos.y, 1 );
1507 }
1508 }
1509 break;
1510 }
1511 }
1512
1513 static ADisplay*
skin_window_display(SkinWindow * window)1514 skin_window_display( SkinWindow* window )
1515 {
1516 return window->layout.displays;
1517 }
1518
1519 void
skin_window_update_display(SkinWindow * window,int x,int y,int w,int h)1520 skin_window_update_display( SkinWindow* window, int x, int y, int w, int h )
1521 {
1522 ADisplay* disp = skin_window_display(window);
1523
1524 if ( !window->surface )
1525 return;
1526
1527 if (disp != NULL) {
1528 SkinRect r;
1529 r.pos.x = x;
1530 r.pos.y = y;
1531 r.size.w = w;
1532 r.size.h = h;
1533
1534 skin_rect_rotate( &r, &r, disp->rotation );
1535 r.pos.x += disp->origin.x;
1536 r.pos.y += disp->origin.y;
1537
1538 if (window->effective_scale != 1.0)
1539 skin_window_redraw( window, &r );
1540 else
1541 display_redraw( disp, &r, window->surface );
1542 }
1543 }
1544