aboutsummaryrefslogtreecommitdiffstats
path: root/android/skin/window.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:35 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:35 -0800
commitf721e3ac031f892af46f255a47d7f54a91317b30 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /android/skin/window.c
parentbae1bc39312d5019bd9a5b8d840a529213a69a17 (diff)
downloadexternal_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.zip
external_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.tar.gz
external_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'android/skin/window.c')
-rw-r--r--android/skin/window.c1516
1 files changed, 0 insertions, 1516 deletions
diff --git a/android/skin/window.c b/android/skin/window.c
deleted file mode 100644
index 6612ffe..0000000
--- a/android/skin/window.c
+++ /dev/null
@@ -1,1516 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#include "android/skin/window.h"
-#include "android/skin/image.h"
-#include "android/skin/scaler.h"
-#include "android/charmap.h"
-#include "android/utils/debug.h"
-#include "android/utils/display.h"
-#include <SDL_syswm.h>
-#include "qemu-common.h"
-#include <math.h>
-
-#include "framebuffer.h"
-
-/* when shrinking, we reduce the pixel ratio by this fixed amount */
-#define SHRINK_SCALE 0.6
-
-/* maximum value of LCD brighness */
-#define LCD_BRIGHTNESS_MIN 0
-#define LCD_BRIGHTNESS_DEFAULT 128
-#define LCD_BRIGHTNESS_MAX 255
-
-typedef struct Background {
- SkinImage* image;
- SkinRect rect;
- SkinPos origin;
-} Background;
-
-static void
-background_done( Background* back )
-{
- skin_image_unref( &back->image );
-}
-
-static void
-background_init( Background* back, SkinBackground* sback, SkinLocation* loc, SkinRect* frame )
-{
- SkinRect r;
-
- back->image = skin_image_rotate( sback->image, loc->rotation );
- skin_rect_rotate( &r, &sback->rect, loc->rotation );
- r.pos.x += loc->anchor.x;
- r.pos.y += loc->anchor.y;
-
- back->origin = r.pos;
- skin_rect_intersect( &back->rect, &r, frame );
-}
-
-static void
-background_redraw( Background* back, SkinRect* rect, SDL_Surface* surface )
-{
- SkinRect r;
-
- if (skin_rect_intersect( &r, rect, &back->rect ) )
- {
- SDL_Rect rd, rs;
-
- rd.x = r.pos.x;
- rd.y = r.pos.y;
- rd.w = r.size.w;
- rd.h = r.size.h;
-
- rs.x = r.pos.x - back->origin.x;
- rs.y = r.pos.y - back->origin.y;
- rs.w = r.size.w;
- rs.h = r.size.h;
-
- SDL_BlitSurface( skin_image_surface(back->image), &rs, surface, &rd );
- //SDL_UpdateRects( surface, 1, &rd );
- }
-}
-
-
-typedef struct ADisplay {
- SkinRect rect;
- SkinPos origin;
- SkinRotation rotation;
- SkinSize datasize; /* framebuffer size */
- void* data; /* framebuffer pixels */
- QFrameBuffer* qfbuff;
- SkinImage* onion; /* onion image */
- SkinRect onion_rect; /* onion rect, if any */
- int brightness;
-} ADisplay;
-
-static void
-display_done( ADisplay* disp )
-{
- disp->data = NULL;
- disp->qfbuff = NULL;
- skin_image_unref( &disp->onion );
-}
-
-static int
-display_init( ADisplay* disp, SkinDisplay* sdisp, SkinLocation* loc, SkinRect* frame )
-{
- skin_rect_rotate( &disp->rect, &sdisp->rect, loc->rotation );
- disp->rect.pos.x += loc->anchor.x;
- disp->rect.pos.y += loc->anchor.y;
-
- disp->rotation = (loc->rotation + sdisp->rotation) & 3;
- switch (disp->rotation) {
- case SKIN_ROTATION_0:
- disp->origin = disp->rect.pos;
- break;
-
- case SKIN_ROTATION_90:
- disp->origin.x = disp->rect.pos.x + disp->rect.size.w;
- disp->origin.y = disp->rect.pos.y;
- break;
-
- case SKIN_ROTATION_180:
- disp->origin.x = disp->rect.pos.x + disp->rect.size.w;
- disp->origin.y = disp->rect.pos.y + disp->rect.size.h;
- break;
-
- default:
- disp->origin.x = disp->rect.pos.x;
- disp->origin.y = disp->rect.pos.y + disp->rect.size.h;
- break;
- }
- skin_size_rotate( &disp->datasize, &sdisp->rect.size, sdisp->rotation );
- skin_rect_intersect( &disp->rect, &disp->rect, frame );
-#if 0
- fprintf(stderr, "... display_init rect.pos(%d,%d) rect.size(%d,%d) datasize(%d,%d)\n",
- disp->rect.pos.x, disp->rect.pos.y,
- disp->rect.size.w, disp->rect.size.h,
- disp->datasize.w, disp->datasize.h);
-#endif
- disp->qfbuff = sdisp->qfbuff;
- disp->data = sdisp->qfbuff->pixels;
- disp->onion = NULL;
-
- disp->brightness = LCD_BRIGHTNESS_DEFAULT;
-
- return (disp->data == NULL) ? -1 : 0;
-}
-
-static __inline__ uint32_t rgb565_to_argb32( uint32_t pix )
-{
- uint32_t r = ((pix & 0xf800) << 8) | ((pix & 0xe000) << 3);
- uint32_t g = ((pix & 0x07e0) << 5) | ((pix & 0x0600) >> 1);
- uint32_t b = ((pix & 0x001f) << 3) | ((pix & 0x001c) >> 2);
-
- return 0xff000000 | r | g | b;
-}
-
-
-static void
-display_set_onion( ADisplay* disp, SkinImage* onion, SkinRotation rotation, int blend )
-{
- int onion_w, onion_h;
- SkinRect* rect = &disp->rect;
- SkinRect* orect = &disp->onion_rect;
-
- rotation = (rotation + disp->rotation) & 3;
-
- skin_image_unref( &disp->onion );
- disp->onion = skin_image_clone_full( onion, rotation, blend );
-
- onion_w = skin_image_w(disp->onion);
- onion_h = skin_image_h(disp->onion);
-
- switch (rotation) {
- case SKIN_ROTATION_0:
- orect->pos = rect->pos;
- break;
-
- case SKIN_ROTATION_90:
- orect->pos.x = rect->pos.x + rect->size.w - onion_w;
- orect->pos.y = rect->pos.y;
- break;
-
- case SKIN_ROTATION_180:
- orect->pos.x = rect->pos.x + rect->size.w - onion_w;
- orect->pos.y = rect->pos.y + rect->size.h - onion_h;
- break;
-
- default:
- orect->pos.x = rect->pos.x;
- orect->pos.y = rect->pos.y + rect->size.h - onion_h;
- }
- orect->size.w = onion_w;
- orect->size.h = onion_h;
-}
-
-#define DOT_MATRIX 0
-
-#if DOT_MATRIX
-
-static void
-dotmatrix_dither_argb32( unsigned char* pixels, int x, int y, int w, int h, int pitch )
-{
- static const unsigned dotmatrix_argb32[16] = {
- 0x003f00, 0x00003f, 0x3f0000, 0x000000,
- 0x3f3f3f, 0x000000, 0x3f3f3f, 0x000000,
- 0x3f0000, 0x000000, 0x003f00, 0x00003f,
- 0x3f3f3f, 0x000000, 0x3f3f3f, 0x000000
- };
-
- int yy = y & 3;
-
- pixels += 4*x + y*pitch;
-
- for ( ; h > 0; h-- ) {
- unsigned* line = (unsigned*) pixels;
- int nn, xx = x & 3;
-
- for (nn = 0; nn < w; nn++) {
- unsigned c = line[nn];
-
- c = c - ((c >> 2) & dotmatrix_argb32[(yy << 2)|xx]);
-
- xx = (xx + 1) & 3;
- line[nn] = c;
- }
-
- yy = (yy + 1) & 3;
- pixels += pitch;
- }
-}
-
-#endif /* DOT_MATRIX */
-
-/* technical note about the lightness emulation
- *
- * we try to emulate something that looks like the Dream's
- * non-linear LCD lightness, without going too dark or bright.
- *
- * the default lightness is around 105 (about 40%) and we prefer
- * to keep full RGB colors at that setting, to not alleviate
- * developers who will not understand why the emulator's colors
- * look slightly too dark.
- *
- * we also want to implement a 'bright' mode by de-saturating
- * colors towards bright white.
- *
- * All of this leads to the implementation below that looks like
- * the following:
- *
- * if (level == MIN)
- * screen is off
- *
- * if (level > MIN && level < LOW)
- * interpolate towards black, with
- * MINALPHA = 0.2
- * alpha = MINALPHA + (1-MINALPHA)*(level-MIN)/(LOW-MIN)
- *
- * if (level >= LOW && level <= HIGH)
- * keep full RGB colors
- *
- * if (level > HIGH)
- * interpolate towards bright white, with
- * MAXALPHA = 0.6
- * alpha = MAXALPHA*(level-HIGH)/(MAX-HIGH)
- *
- * we probably want some sort of power law instead of interpolating
- * linearly, but frankly, this is sufficient for most uses.
- */
-
-#define LCD_BRIGHTNESS_LOW 80
-#define LCD_BRIGHTNESS_HIGH 180
-
-#define LCD_ALPHA_LOW_MIN 0.2
-#define LCD_ALPHA_HIGH_MAX 0.6
-
-/* treat as special value to turn screen off */
-#define LCD_BRIGHTNESS_OFF LCD_BRIGHTNESS_MIN
-
-static void
-lcd_brightness_argb32( unsigned char* pixels, SkinRect* r, int pitch, int brightness )
-{
- const unsigned b_min = LCD_BRIGHTNESS_MIN;
- const unsigned b_max = LCD_BRIGHTNESS_MAX;
- const unsigned b_low = LCD_BRIGHTNESS_LOW;
- const unsigned b_high = LCD_BRIGHTNESS_HIGH;
-
- unsigned alpha = brightness;
- int w = r->size.w;
- int h = r->size.h;
-
- if (alpha <= b_min)
- alpha = b_min;
- else if (alpha > b_max)
- alpha = b_max;
-
- pixels += 4*r->pos.x + r->pos.y*pitch;
-
- if (alpha < b_low)
- {
- const unsigned alpha_min = (255*LCD_ALPHA_LOW_MIN);
- const unsigned alpha_range = (255 - alpha_min);
-
- alpha = alpha_min + ((alpha - b_min)*alpha_range) / (b_low - b_min);
-
- for ( ; h > 0; h-- ) {
- unsigned* line = (unsigned*) pixels;
- int nn;
-
- for (nn = 0; nn < w; nn++) {
- unsigned c = line[nn];
- unsigned ag = (c >> 8) & 0x00ff00ff;
- unsigned rb = (c) & 0x00ff00ff;
-
- ag = (ag*alpha) & 0xff00ff00;
- rb = ((rb*alpha) >> 8) & 0x00ff00ff;
-
- line[nn] = (unsigned)(ag | rb);
- }
- pixels += pitch;
- }
- }
- else if (alpha > LCD_BRIGHTNESS_HIGH) /* 'superluminous' mode */
- {
- const unsigned alpha_max = (255*LCD_ALPHA_HIGH_MAX);
- const unsigned alpha_range = (255-alpha_max);
- unsigned ialpha;
-
- alpha = ((alpha - b_high)*alpha_range) / (b_max - b_high);
- ialpha = 255-alpha;
-
- for ( ; h > 0; h-- ) {
- unsigned* line = (unsigned*) pixels;
- int nn;
-
- for (nn = 0; nn < w; nn++) {
- unsigned c = line[nn];
- unsigned ag = (c >> 8) & 0x00ff00ff;
- unsigned rb = (c) & 0x00ff00ff;
-
- /* interpolate towards bright white, i.e. 0x00ffffff */
- ag = ((ag*ialpha + 0x00ff00ff*alpha)) & 0xff00ff00;
- rb = ((rb*ialpha + 0x00ff00ff*alpha) >> 8) & 0x00ff00ff;
-
- line[nn] = (unsigned)(ag | rb);
- }
- pixels += pitch;
- }
- }
-}
-
-
-/* this is called when the LCD framebuffer is off */
-static void
-lcd_off_argb32( unsigned char* pixels, SkinRect* r, int pitch )
-{
- int x = r->pos.x;
- int y = r->pos.y;
- int w = r->size.w;
- int h = r->size.h;
-
- pixels += 4*x + y*pitch;
- for ( ; h > 0; h-- ) {
- memset( pixels, 0, w*4 );
- pixels += pitch;
- }
-}
-
-
-static void
-display_redraw( ADisplay* disp, SkinRect* rect, SDL_Surface* surface )
-{
- SkinRect r;
-
- if (skin_rect_intersect( &r, rect, &disp->rect ))
- {
- int x = r.pos.x - disp->rect.pos.x;
- int y = r.pos.y - disp->rect.pos.y;
- int w = r.size.w;
- int h = r.size.h;
- int disp_w = disp->rect.size.w;
- int disp_h = disp->rect.size.h;
- int dst_pitch = surface->pitch;
- uint8_t* dst_line = (uint8_t*)surface->pixels + r.pos.x*4 + r.pos.y*dst_pitch;
- int src_pitch = disp->datasize.w*2;
- uint8_t* src_line = (uint8_t*)disp->data;
- int yy, xx;
-#if 0
- fprintf(stderr, "--- display redraw r.pos(%d,%d) r.size(%d,%d) "
- "disp.pos(%d,%d) disp.size(%d,%d) datasize(%d,%d) rect.pos(%d,%d) rect.size(%d,%d)\n",
- r.pos.x - disp->rect.pos.x, r.pos.y - disp->rect.pos.y, w, h, disp->rect.pos.x, disp->rect.pos.y,
- disp->rect.size.w, disp->rect.size.h, disp->datasize.w, disp->datasize.h,
- rect->pos.x, rect->pos.y, rect->size.w, rect->size.h );
-#endif
- SDL_LockSurface( surface );
-
- if (disp->brightness == LCD_BRIGHTNESS_OFF)
- {
- lcd_off_argb32( surface->pixels, &r, dst_pitch );
- }
- else
- {
- switch ( disp->rotation & 3 )
- {
- case ANDROID_ROTATION_0:
- src_line += x*2 + y*src_pitch;
-
- for (yy = h; yy > 0; yy--)
- {
- uint32_t* dst = (uint32_t*)dst_line;
- uint16_t* src = (uint16_t*)src_line;
-
- for (xx = 0; xx < w; xx++) {
- dst[xx] = rgb565_to_argb32(src[xx]);
- }
- src_line += src_pitch;
- dst_line += dst_pitch;
- }
- break;
-
- case ANDROID_ROTATION_90:
- src_line += y*2 + (disp_w - x - 1)*src_pitch;
-
- for (yy = h; yy > 0; yy--)
- {
- uint32_t* dst = (uint32_t*)dst_line;
- uint8_t* src = src_line;
-
- for (xx = w; xx > 0; xx--)
- {
- dst[0] = rgb565_to_argb32(((uint16_t*)src)[0]);
- src -= src_pitch;
- dst += 1;
- }
- src_line += 2;
- dst_line += dst_pitch;
- }
- break;
-
- case ANDROID_ROTATION_180:
- src_line += (disp_w -1 - x)*2 + (disp_h-1-y)*src_pitch;
-
- for (yy = h; yy > 0; yy--)
- {
- uint16_t* src = (uint16_t*)src_line;
- uint32_t* dst = (uint32_t*)dst_line;
-
- for (xx = w; xx > 0; xx--) {
- dst[0] = rgb565_to_argb32(src[0]);
- src -= 1;
- dst += 1;
- }
-
- src_line -= src_pitch;
- dst_line += dst_pitch;
- }
- break;
-
- default: /* ANDROID_ROTATION_270 */
- src_line += (disp_h-1-y)*2 + x*src_pitch;
-
- for (yy = h; yy > 0; yy--)
- {
- uint32_t* dst = (uint32_t*)dst_line;
- uint8_t* src = src_line;
-
- for (xx = w; xx > 0; xx--) {
- dst[0] = rgb565_to_argb32(((uint16_t*)src)[0]);
- dst += 1;
- src += src_pitch;
- }
- src_line -= 2;
- dst_line += dst_pitch;
- }
- }
-#if DOT_MATRIX
- dotmatrix_dither_argb32( surface->pixels, r.pos.x, r.pos.y, r.size.w, r.size.h, surface->pitch );
-#endif
- /* apply lightness */
- lcd_brightness_argb32( surface->pixels, &r, surface->pitch, disp->brightness );
- }
- SDL_UnlockSurface( surface );
-
- /* Apply onion skin */
- if (disp->onion != NULL) {
- SkinRect r2;
-
- if ( skin_rect_intersect( &r2, &r, &disp->onion_rect ) ) {
- SDL_Rect rs, rd;
-
- rd.x = r2.pos.x;
- rd.y = r2.pos.y;
- rd.w = r2.size.w;
- rd.h = r2.size.h;
-
- rs.x = rd.x - disp->onion_rect.pos.x;
- rs.y = rd.y - disp->onion_rect.pos.y;
- rs.w = rd.w;
- rs.h = rd.h;
-
- SDL_BlitSurface( skin_image_surface(disp->onion), &rs, surface, &rd );
- }
- }
-
- SDL_UpdateRect( surface, r.pos.x, r.pos.y, w, h );
- }
-}
-
-
-typedef struct Button {
- SkinImage* image;
- SkinRect rect;
- SkinPos origin;
- Background* background;
- unsigned keycode;
- int down;
-} Button;
-
-static void
-button_done( Button* button )
-{
- skin_image_unref( &button->image );
- button->background = NULL;
-}
-
-static void
-button_init( Button* button, SkinButton* sbutton, SkinLocation* loc, Background* back, SkinRect* frame )
-{
- SkinRect r;
-
- button->image = skin_image_rotate( sbutton->image, loc->rotation );
- button->background = back;
- button->keycode = sbutton->keycode;
- button->down = 0;
-
- skin_rect_rotate( &r, &sbutton->rect, loc->rotation );
- r.pos.x += loc->anchor.x;
- r.pos.y += loc->anchor.y;
- button->origin = r.pos;
- skin_rect_intersect( &button->rect, &r, frame );
-}
-
-static void
-button_redraw( Button* button, SkinRect* rect, SDL_Surface* surface )
-{
- SkinRect r;
-
- if (skin_rect_intersect( &r, rect, &button->rect ))
- {
- if ( button->down && button->image != SKIN_IMAGE_NONE )
- {
- SDL_Rect rs, rd;
-
- rs.x = r.pos.x - button->origin.x;
- rs.y = r.pos.y - button->origin.y;
- rs.w = r.size.w;
- rs.h = r.size.h;
-
- rd.x = r.pos.x;
- rd.y = r.pos.y;
- rd.w = r.size.w;
- rd.h = r.size.h;
-
- if (button->image != SKIN_IMAGE_NONE) {
- SDL_BlitSurface( skin_image_surface(button->image), &rs, surface, &rd );
- if (button->down > 1)
- SDL_BlitSurface( skin_image_surface(button->image), &rs, surface, &rd );
- }
- }
- }
-}
-
-
-typedef struct {
- char tracking;
- char inside;
- SkinPos pos;
- ADisplay* display;
-} FingerState;
-
-static void
-finger_state_reset( FingerState* finger )
-{
- finger->tracking = 0;
- finger->inside = 0;
-}
-
-typedef struct {
- Button* pressed;
- Button* hover;
-} ButtonState;
-
-static void
-button_state_reset( ButtonState* button )
-{
- button->pressed = NULL;
- button->hover = NULL;
-}
-
-typedef struct {
- char tracking;
- SkinTrackBall* ball;
- SkinRect rect;
- SkinWindow* window;
-} BallState;
-
-static void
-ball_state_reset( BallState* state, SkinWindow* window )
-{
- state->tracking = 0;
- state->ball = NULL;
-
- state->rect.pos.x = 0;
- state->rect.pos.y = 0;
- state->rect.size.w = 0;
- state->rect.size.h = 0;
- state->window = window;
-}
-
-static void
-ball_state_redraw( BallState* state, SkinRect* rect, SDL_Surface* surface )
-{
- SkinRect r;
-
- if (skin_rect_intersect( &r, rect, &state->rect ))
- skin_trackball_draw( state->ball, 0, 0, surface );
-}
-
-static void
-ball_state_show( BallState* state, int enable )
-{
- if (enable) {
- if ( !state->tracking ) {
- state->tracking = 1;
- SDL_ShowCursor(0);
- SDL_WM_GrabInput( SDL_GRAB_ON );
- skin_trackball_refresh( state->ball );
- skin_window_redraw( state->window, &state->rect );
- }
- } else {
- if ( state->tracking ) {
- state->tracking = 0;
- SDL_WM_GrabInput( SDL_GRAB_OFF );
- SDL_ShowCursor(1);
- skin_window_redraw( state->window, &state->rect );
- }
- }
-}
-
-
-static void
-ball_state_set( BallState* state, SkinTrackBall* ball )
-{
- ball_state_show( state, 0 );
-
- state->ball = ball;
- if (ball != NULL) {
- SDL_Rect sr;
-
- skin_trackball_rect( ball, &sr );
- state->rect.pos.x = sr.x;
- state->rect.pos.y = sr.y;
- state->rect.size.w = sr.w;
- state->rect.size.h = sr.h;
- }
-}
-
-typedef struct Layout {
- int num_buttons;
- int num_backgrounds;
- int num_displays;
- unsigned color;
- Button* buttons;
- Background* backgrounds;
- ADisplay* displays;
- SkinRect rect;
- SkinLayout* slayout;
-} Layout;
-
-#define LAYOUT_LOOP_BUTTONS(layout,button) \
- do { \
- Button* __button = (layout)->buttons; \
- Button* __button_end = __button + (layout)->num_buttons; \
- for ( ; __button < __button_end; __button ++ ) { \
- Button* button = __button;
-
-#define LAYOUT_LOOP_END_BUTTONS \
- } \
- } while (0);
-
-#define LAYOUT_LOOP_DISPLAYS(layout,display) \
- do { \
- ADisplay* __display = (layout)->displays; \
- ADisplay* __display_end = __display + (layout)->num_displays; \
- for ( ; __display < __display_end; __display ++ ) { \
- ADisplay* display = __display;
-
-#define LAYOUT_LOOP_END_DISPLAYS \
- } \
- } while (0);
-
-
-static void
-layout_done( Layout* layout )
-{
- int nn;
-
- for (nn = 0; nn < layout->num_buttons; nn++)
- button_done( &layout->buttons[nn] );
-
- for (nn = 0; nn < layout->num_backgrounds; nn++)
- background_done( &layout->backgrounds[nn] );
-
- for (nn = 0; nn < layout->num_displays; nn++)
- display_done( &layout->displays[nn] );
-
- qemu_free( layout->buttons );
- layout->buttons = NULL;
-
- qemu_free( layout->backgrounds );
- layout->backgrounds = NULL;
-
- qemu_free( layout->displays );
- layout->displays = NULL;
-
- layout->num_buttons = 0;
- layout->num_backgrounds = 0;
- layout->num_displays = 0;
-}
-
-static int
-layout_init( Layout* layout, SkinLayout* slayout )
-{
- int n_buttons, n_backgrounds, n_displays;
-
- /* first, count the number of elements of each kind */
- n_buttons = 0;
- n_backgrounds = 0;
- n_displays = 0;
-
- layout->color = slayout->color;
- layout->slayout = slayout;
-
- SKIN_LAYOUT_LOOP_LOCS(slayout,loc)
- SkinPart* part = loc->part;
-
- if ( part->background->valid )
- n_backgrounds += 1;
- if ( part->display->valid )
- n_displays += 1;
-
- SKIN_PART_LOOP_BUTTONS(part, sbutton)
- n_buttons += 1;
- sbutton=sbutton;
- SKIN_PART_LOOP_END
- SKIN_LAYOUT_LOOP_END
-
- layout->num_buttons = n_buttons;
- layout->num_backgrounds = n_backgrounds;
- layout->num_displays = n_displays;
-
- /* now allocate arrays, then populate them */
- layout->buttons = qemu_mallocz( sizeof(Button) * n_buttons );
- layout->backgrounds = qemu_mallocz( sizeof(Background) * n_backgrounds );
- layout->displays = qemu_mallocz( sizeof(ADisplay) * n_displays );
-
- if (layout->buttons == NULL && n_buttons > 0) goto Fail;
- if (layout->backgrounds == NULL && n_backgrounds > 0) goto Fail;
- if (layout->displays == NULL && n_displays > 0) goto Fail;
-
- n_buttons = 0;
- n_backgrounds = 0;
- n_displays = 0;
-
- layout->rect.pos.x = 0;
- layout->rect.pos.y = 0;
- layout->rect.size = slayout->size;
-
- SKIN_LAYOUT_LOOP_LOCS(slayout,loc)
- SkinPart* part = loc->part;
- Background* back = NULL;
-
- if ( part->background->valid ) {
- back = layout->backgrounds + n_backgrounds;
- background_init( back, part->background, loc, &layout->rect );
- n_backgrounds += 1;
- }
- if ( part->display->valid ) {
- ADisplay* disp = layout->displays + n_displays;
- display_init( disp, part->display, loc, &layout->rect );
- n_displays += 1;
- }
-
- SKIN_PART_LOOP_BUTTONS(part, sbutton)
- Button* button = layout->buttons + n_buttons;
- button_init( button, sbutton, loc, back, &layout->rect );
- n_buttons += 1;
- SKIN_PART_LOOP_END
- SKIN_LAYOUT_LOOP_END
-
- return 0;
-
-Fail:
- layout_done(layout);
- return -1;
-}
-
-struct SkinWindow {
- SDL_Surface* surface;
- Layout layout;
- SkinPos pos;
- FingerState finger;
- ButtonState button;
- BallState ball;
- char enabled;
- char fullscreen;
- char no_display;
-
- char enable_touch;
- char enable_trackball;
- char enable_dpad;
- char enable_qwerty;
-
- SkinImage* onion;
- SkinRotation onion_rotation;
- int onion_alpha;
-
- int x_pos;
- int y_pos;
-
- SkinScaler* scaler;
- int shrink;
- double shrink_scale;
- unsigned* shrink_pixels;
- SDL_Surface* shrink_surface;
-
- double effective_scale;
- double effective_x;
- double effective_y;
-};
-
-static void
-add_finger_event(unsigned x, unsigned y, unsigned state)
-{
- //fprintf(stderr, "::: finger %d,%d %d\n", x, y, state);
- kbd_mouse_event(x, y, 0, state);
-}
-
-static void
-skin_window_find_finger( SkinWindow* window,
- int x,
- int y )
-{
- FingerState* finger = &window->finger;
-
- /* find the display that contains this movement */
- finger->display = NULL;
- finger->inside = 0;
-
- if (!window->enable_touch)
- return;
-
- LAYOUT_LOOP_DISPLAYS(&window->layout,disp)
- if ( skin_rect_contains( &disp->rect, x, y ) ) {
- finger->inside = 1;
- finger->display = disp;
- finger->pos.x = x - disp->origin.x;
- finger->pos.y = y - disp->origin.y;
-
- skin_pos_rotate( &finger->pos, &finger->pos, -disp->rotation );
- break;
- }
- LAYOUT_LOOP_END_DISPLAYS
-}
-
-static void
-skin_window_move_mouse( SkinWindow* window,
- int x,
- int y )
-{
- FingerState* finger = &window->finger;
- ButtonState* button = &window->button;
-
- if (finger->tracking) {
- ADisplay* disp = finger->display;
- char inside = 1;
- int dx = x - disp->rect.pos.x;
- int dy = y - disp->rect.pos.y;
-
- if (dx < 0) {
- dx = 0;
- inside = 0;
- }
- else if (dx >= disp->rect.size.w) {
- dx = disp->rect.size.w - 1;
- inside = 0;
- }
- if (dy < 0) {
- dy = 0;
- inside = 0;
- } else if (dy >= disp->rect.size.h) {
- dy = disp->rect.size.h-1;
- inside = 0;
- }
- finger->inside = inside;
- finger->pos.x = dx + (disp->rect.pos.x - disp->origin.x);
- finger->pos.y = dy + (disp->rect.pos.y - disp->origin.y);
-
- skin_pos_rotate( &finger->pos, &finger->pos, -disp->rotation );
- }
-
- {
- Button* hover = button->hover;
-
- if (hover) {
- if ( skin_rect_contains( &hover->rect, x, y ) )
- return;
-
- hover->down = 0;
- skin_window_redraw( window, &hover->rect );
- button->hover = NULL;
- }
-
- hover = NULL;
- LAYOUT_LOOP_BUTTONS( &window->layout, butt )
- if ( skin_rect_contains( &butt->rect, x, y ) ) {
- hover = butt;
- break;
- }
- LAYOUT_LOOP_END_BUTTONS
-
- /* filter DPAD and QWERTY buttons right here */
- if (hover != NULL) {
- switch (hover->keycode) {
- /* these correspond to the DPad */
- case kKeyCodeDpadUp:
- case kKeyCodeDpadDown:
- case kKeyCodeDpadLeft:
- case kKeyCodeDpadRight:
- case kKeyCodeDpadCenter:
- if (!window->enable_dpad)
- hover = NULL;
- break;
-
- /* these correspond to non-qwerty buttons */
- case kKeyCodeSoftLeft:
- case kKeyCodeSoftRight:
- case kKeyCodeVolumeUp:
- case kKeyCodeVolumeDown:
- case kKeyCodePower:
- case kKeyCodeHome:
- case kKeyCodeBack:
- case kKeyCodeCall:
- case kKeyCodeEndCall:
- break;
-
- /* all the rest is assumed to be qwerty */
- default:
- if (!window->enable_qwerty)
- hover = NULL;
- }
- }
-
- if (hover != NULL) {
- hover->down = 1;
- skin_window_redraw( window, &hover->rect );
- button->hover = hover;
- }
- }
-}
-
-static void
-skin_window_trackball_press( SkinWindow* window, int down )
-{
- send_key_event( kKeyCodeBtnMouse, down );
-}
-
-static void
-skin_window_trackball_move( SkinWindow* window, int xrel, int yrel )
-{
- BallState* state = &window->ball;
-
- if ( skin_trackball_move( state->ball, xrel, yrel ) ) {
- skin_trackball_refresh( state->ball );
- skin_window_redraw( window, &state->rect );
- }
-}
-
-void
-skin_window_set_trackball( SkinWindow* window, SkinTrackBall* ball )
-{
- BallState* state = &window->ball;
-
- ball_state_set( state, ball );
-}
-
-void
-skin_window_show_trackball( SkinWindow* window, int enable )
-{
- BallState* state = &window->ball;
-
- if (state->ball != NULL && window->enable_trackball) {
- ball_state_show(state, enable);
- }
-}
-
-
-static int skin_window_reset_internal (SkinWindow*, SkinLayout*);
-
-SkinWindow*
-skin_window_create( SkinLayout* slayout, int x, int y, double scale, int no_display )
-{
- SkinWindow* window = qemu_mallocz(sizeof(*window));
-
- window->shrink_scale = scale;
- window->shrink = (scale != 1.0);
- window->scaler = skin_scaler_create();
- window->no_display = no_display;
-
- /* enable everything by default */
- window->enable_touch = 1;
- window->enable_trackball = 1;
- window->enable_dpad = 1;
- window->enable_qwerty = 1;
-
- window->x_pos = x;
- window->y_pos = y;
-
- if (skin_window_reset_internal(window, slayout) < 0) {
- skin_window_free( window );
- return NULL;
- }
- //SDL_WM_SetCaption( "Android Emulator", "Android Emulator" );
-
- SDL_WM_SetPos( x, y );
- if ( !SDL_WM_IsFullyVisible( 1 ) ) {
- dprint( "emulator window was out of view and was recentred\n" );
- }
-
- return window;
-}
-
-void
-skin_window_enable_touch( SkinWindow* window, int enabled )
-{
- window->enable_touch = !!enabled;
-}
-
-void
-skin_window_enable_trackball( SkinWindow* window, int enabled )
-{
- window->enable_trackball = !!enabled;
-}
-
-void
-skin_window_enable_dpad( SkinWindow* window, int enabled )
-{
- window->enable_dpad = !!enabled;
-}
-
-void
-skin_window_enable_qwerty( SkinWindow* window, int enabled )
-{
- window->enable_qwerty = !!enabled;
-}
-
-void
-skin_window_set_title( SkinWindow* window, const char* title )
-{
- if (window && title)
- SDL_WM_SetCaption( title, title );
-}
-
-static void
-skin_window_resize( SkinWindow* window )
-{
- /* now resize window */
- if (window->surface) {
- SDL_FreeSurface(window->surface);
- window->surface = NULL;
- }
-
- if (window->shrink_surface) {
- SDL_FreeSurface(window->shrink_surface);
- window->shrink_surface = NULL;
- }
-
- if (window->shrink_pixels) {
- qemu_free(window->shrink_pixels);
- window->shrink_pixels = NULL;
- }
-
- if ( !window->no_display ) {
- int layout_w = window->layout.rect.size.w;
- int layout_h = window->layout.rect.size.h;
- int window_w = layout_w;
- int window_h = layout_h;
- int window_x = window->x_pos;
- int window_y = window->y_pos;
- int flags;
- SDL_Surface* surface;
- double scale = 1.0;
- int fullscreen = window->fullscreen;
-
- if (fullscreen) {
- if (get_nearest_monitor_rect(&window_x, &window_y,
- &window_w, &window_h) < 0) {
- fullscreen = 0;
- } else {
- double x_scale = window_w * 1.0 / layout_w;
- double y_scale = window_h * 1.0 / layout_h;
-
- scale = (x_scale <= y_scale) ? x_scale : y_scale;
- }
- }
- else if (window->shrink) {
- scale = window->shrink_scale;
- window_w = (int) ceil(layout_w*scale);
- window_h = (int) ceil(layout_h*scale);
- }
-
- {
- char temp[32];
- sprintf(temp,"SDL_VIDEO_WINDOW_POS=%d,%d",window_x,window_y);
- putenv(temp);
- putenv("SDL_VIDEO_WINDOW_FORCE_VISIBLE=1");
- }
-
- flags = SDL_SWSURFACE;
- if (fullscreen) {
- flags |= SDL_FULLSCREEN;
- }
- surface = SDL_SetVideoMode( window_w, window_h, 32, flags );
- if (surface == NULL) {
- fprintf(stderr, "### Error: could not create or resize SDL window: %s\n", SDL_GetError() );
- exit(1);
- }
-
- SDL_WM_SetPos( window_x, window_y );
-
- window->effective_scale = scale;
- window->effective_x = 0;
- window->effective_y = 0;
-
- if (fullscreen) {
- window->effective_x = (window_w - layout_w*scale)*0.5;
- window->effective_y = (window_h - layout_h*scale)*0.5;
- }
-
- if (scale == 1.0)
- window->surface = surface;
- else
- {
- window_w = (int) ceil(window_w / scale );
- window_h = (int) ceil(window_h / scale );
-
- window->shrink_surface = surface;
- window->shrink_pixels = qemu_mallocz( window_w * window_h * 4 );
- if (window->shrink_pixels == NULL) {
- fprintf(stderr, "### Error: could not allocate memory for rescaling surface\n");
- exit(1);
- }
- window->surface = sdl_surface_from_argb32( window->shrink_pixels, window_w, window_h );
- if (window->surface == NULL) {
- fprintf(stderr, "### Error: could not create or resize SDL window: %s\n", SDL_GetError() );
- exit(1);
- }
- skin_scaler_set( window->scaler, scale, window->effective_x, window->effective_y );
- }
- }
-}
-
-static int
-skin_window_reset_internal ( SkinWindow* window, SkinLayout* slayout )
-{
- Layout layout;
- ADisplay* disp;
-
- if ( layout_init( &layout, slayout ) < 0 )
- return -1;
-
- disp = window->layout.displays;
-
- layout_done( &window->layout );
- window->layout = layout;
-
- disp = window->layout.displays;
- if (disp != NULL && window->onion)
- display_set_onion( disp,
- window->onion,
- window->onion_rotation,
- window->onion_alpha );
-
- skin_window_resize(window);
-
- finger_state_reset( &window->finger );
- button_state_reset( &window->button );
- ball_state_reset( &window->ball, window );
-
- skin_window_redraw( window, NULL );
-
- if (slayout->event_type != 0) {
- kbd_generic_event( slayout->event_type, slayout->event_code, slayout->event_value );
- }
-
- return 0;
-}
-
-int
-skin_window_reset ( SkinWindow* window, SkinLayout* slayout )
-{
- if (!window->fullscreen) {
- SDL_WM_GetPos(&window->x_pos, &window->y_pos);
- }
- return skin_window_reset_internal( window, slayout );
-}
-
-void
-skin_window_set_lcd_brightness( SkinWindow* window, int brightness )
-{
- ADisplay* disp = window->layout.displays;
-
- if (disp != NULL) {
- disp->brightness = brightness;
- skin_window_redraw( window, NULL );
- }
-}
-
-void
-skin_window_free ( SkinWindow* window )
-{
- if (window) {
- if (window->surface) {
- SDL_FreeSurface(window->surface);
- window->surface = NULL;
- }
- if (window->shrink_surface) {
- SDL_FreeSurface(window->shrink_surface);
- window->shrink_surface = NULL;
- }
- if (window->shrink_pixels) {
- qemu_free(window->shrink_pixels);
- window->shrink_pixels = NULL;
- }
- if (window->onion) {
- skin_image_unref( &window->onion );
- window->onion_rotation = SKIN_ROTATION_0;
- }
- if (window->scaler) {
- skin_scaler_free(window->scaler);
- window->scaler = NULL;
- }
- layout_done( &window->layout );
- qemu_free(window);
- }
-}
-
-void
-skin_window_set_onion( SkinWindow* window,
- SkinImage* onion,
- SkinRotation onion_rotation,
- int onion_alpha )
-{
- ADisplay* disp;
- SkinImage* old = window->onion;
-
- window->onion = skin_image_ref(onion);
- window->onion_rotation = onion_rotation;
- window->onion_alpha = onion_alpha;
-
- skin_image_unref( &old );
-
- disp = window->layout.displays;
-
- if (disp != NULL)
- display_set_onion( disp, window->onion, onion_rotation, onion_alpha );
-}
-
-static void
-skin_window_update_shrink( SkinWindow* window, SkinRect* rect )
-{
- skin_scaler_scale( window->scaler, window->shrink_surface, window->surface,
- rect->pos.x, rect->pos.y, rect->size.w, rect->size.h );
-}
-
-void
-skin_window_set_scale( SkinWindow* window, double scale )
-{
- window->shrink = (scale != 1.0);
- window->shrink_scale = scale;
-
- skin_window_resize( window );
- skin_window_redraw( window, NULL );
-}
-
-void
-skin_window_redraw( SkinWindow* window, SkinRect* rect )
-{
- if (window != NULL && window->surface != NULL) {
- Layout* layout = &window->layout;
-
- if (rect == NULL)
- rect = &layout->rect;
-
- {
- SkinRect r;
-
- if ( skin_rect_intersect( &r, rect, &layout->rect ) ) {
- SDL_Rect rd;
- rd.x = r.pos.x;
- rd.y = r.pos.y;
- rd.w = r.size.w;
- rd.h = r.size.h;
-
- SDL_FillRect( window->surface, &rd, layout->color );
- }
- }
-
- {
- Background* back = layout->backgrounds;
- Background* end = back + layout->num_backgrounds;
- for ( ; back < end; back++ )
- background_redraw( back, rect, window->surface );
- }
-
- {
- ADisplay* disp = layout->displays;
- ADisplay* end = disp + layout->num_displays;
- for ( ; disp < end; disp++ )
- display_redraw( disp, rect, window->surface );
- }
-
- {
- Button* button = layout->buttons;
- Button* end = button + layout->num_buttons;
- for ( ; button < end; button++ )
- button_redraw( button, rect, window->surface );
- }
-
- if ( window->ball.tracking )
- ball_state_redraw( &window->ball, rect, window->surface );
-
- if (window->effective_scale != 1.0)
- skin_window_update_shrink( window, rect );
- else
- {
- SDL_Rect rd;
- rd.x = rect->pos.x;
- rd.y = rect->pos.y;
- rd.w = rect->size.w;
- rd.h = rect->size.h;
-
- SDL_UpdateRects( window->surface, 1, &rd );
- }
- }
-}
-
-void
-skin_window_toggle_fullscreen( SkinWindow* window )
-{
- if (window && window->surface) {
- if (!window->fullscreen)
- SDL_WM_GetPos( &window->x_pos, &window->y_pos );
-
- window->fullscreen = !window->fullscreen;
- skin_window_resize( window );
- skin_window_redraw( window, NULL );
- }
-}
-
-void
-skin_window_get_display( SkinWindow* window, ADisplayInfo *info )
-{
- ADisplay* disp = window->layout.displays;
-
- if (disp != NULL) {
- info->width = disp->datasize.w;
- info->height = disp->datasize.h;
- info->rotation = disp->rotation;
- info->data = disp->data;
- } else {
- info->width = 0;
- info->height = 0;
- info->rotation = SKIN_ROTATION_0;
- info->data = NULL;
- }
-}
-
-
-static void
-skin_window_map_to_scale( SkinWindow* window, int *x, int *y )
-{
- *x = (*x - window->effective_x) / window->effective_scale;
- *y = (*y - window->effective_y) / window->effective_scale;
-}
-
-void
-skin_window_process_event( SkinWindow* window, SDL_Event* ev )
-{
- Button* button;
- int mx, my;
-
- if (!window->surface)
- return;
-
- switch (ev->type) {
- case SDL_MOUSEBUTTONDOWN:
- if ( window->ball.tracking ) {
- skin_window_trackball_press( window, 1 );
- break;
- }
-
- mx = ev->button.x;
- my = ev->button.y;
- skin_window_map_to_scale( window, &mx, &my );
- skin_window_move_mouse( window, mx, my );
- skin_window_find_finger( window, mx, my );
-#if 0
- printf("down: x=%d y=%d fx=%d fy=%d fis=%d\n",
- ev->button.x, ev->button.y, window->finger.pos.x,
- window->finger.pos.y, window->finger.inside);
-#endif
- if (window->finger.inside) {
- window->finger.tracking = 1;
- add_finger_event(window->finger.pos.x, window->finger.pos.y, 1);
- } else {
- window->button.pressed = NULL;
- button = window->button.hover;
- if(button) {
- button->down += 1;
- skin_window_redraw( window, &button->rect );
- window->button.pressed = button;
- if(button->keycode) {
- send_key_event(button->keycode, 1);
- }
- }
- }
- break;
-
- case SDL_MOUSEBUTTONUP:
- if ( window->ball.tracking ) {
- skin_window_trackball_press( window, 0 );
- break;
- }
- button = window->button.pressed;
- mx = ev->button.x;
- my = ev->button.y;
- skin_window_map_to_scale( window, &mx, &my );
- if (button)
- {
- button->down = 0;
- skin_window_redraw( window, &button->rect );
- if(button->keycode) {
- send_key_event(button->keycode, 0);
- }
- window->button.pressed = NULL;
- window->button.hover = NULL;
- skin_window_move_mouse( window, mx, my );
- }
- else if (window->finger.tracking)
- {
- skin_window_move_mouse( window, mx, my );
- window->finger.tracking = 0;
- add_finger_event( window->finger.pos.x, window->finger.pos.y, 0);
- }
- break;
-
- case SDL_MOUSEMOTION:
- if ( window->ball.tracking ) {
- skin_window_trackball_move( window, ev->motion.xrel, ev->motion.yrel );
- break;
- }
- mx = ev->button.x;
- my = ev->button.y;
- skin_window_map_to_scale( window, &mx, &my );
- if ( !window->button.pressed )
- {
- skin_window_move_mouse( window, mx, my );
- if ( window->finger.tracking ) {
- add_finger_event( window->finger.pos.x, window->finger.pos.y, 1 );
- }
- }
- break;
- }
-}
-
-static ADisplay*
-skin_window_display( SkinWindow* window )
-{
- return window->layout.displays;
-}
-
-void
-skin_window_update_display( SkinWindow* window, int x, int y, int w, int h )
-{
- ADisplay* disp = skin_window_display(window);
-
- if ( !window->surface )
- return;
-
- if (disp != NULL) {
- SkinRect r;
- r.pos.x = x;
- r.pos.y = y;
- r.size.w = w;
- r.size.h = h;
-
- skin_rect_rotate( &r, &r, disp->rotation );
- r.pos.x += disp->origin.x;
- r.pos.y += disp->origin.y;
-
- if (window->effective_scale != 1.0)
- skin_window_redraw( window, &r );
- else
- display_redraw( disp, &r, window->surface );
- }
-}