diff options
author | Siva Velusamy <vsiva@google.com> | 2012-10-04 17:44:27 -0700 |
---|---|---|
committer | Chirayu Desai <cdesai@cyanogenmod.org> | 2013-03-28 20:11:22 +0530 |
commit | 2ed75275928cbccd3c30b12856866a61442363ff (patch) | |
tree | 19fb4b7bccc165f4071bd1d69a0f69451a1f38f8 /android | |
parent | a546c7006355a7bd1df4267ee53d0bfa2c017c8c (diff) | |
download | external_qemu-2ed75275928cbccd3c30b12856866a61442363ff.zip external_qemu-2ed75275928cbccd3c30b12856866a61442363ff.tar.gz external_qemu-2ed75275928cbccd3c30b12856866a61442363ff.tar.bz2 |
Support dynamic skin layout
This CL adds support for a skin whose layout section is
generated at runtime based on the hardware configuration.
Change-Id: I5f81f665b49ce0f3ec5795d922a08b30c1f34b98
Diffstat (limited to 'android')
-rw-r--r-- | android/cmdline-options.h | 1 | ||||
-rw-r--r-- | android/help.c | 9 | ||||
-rw-r--r-- | android/main-common.c | 215 |
3 files changed, 223 insertions, 2 deletions
diff --git a/android/cmdline-options.h b/android/cmdline-options.h index 5e8d59f..16edeac 100644 --- a/android/cmdline-options.h +++ b/android/cmdline-options.h @@ -90,6 +90,7 @@ CFG_PARAM( skindir, "<dir>", "search skins in <dir> (default <system>/skins)" ) CFG_PARAM( skin, "<name>", "select a given skin" ) CFG_FLAG ( no_skin, "don't use any emulator skin" ) CFG_FLAG ( noskin, "same as -no-skin" ) +CFG_FLAG ( dynamic_skin, "dynamically construct a skin of given size, requires -skin WxH option" ) CFG_PARAM( memory, "<size>", "physical RAM size in MBs" ) OPT_PARAM( netspeed, "<speed>", "maximum network download/upload speeds" ) diff --git a/android/help.c b/android/help.c index 1570160..0a9eed8 100644 --- a/android/help.c +++ b/android/help.c @@ -759,6 +759,15 @@ help_skin(stralloc_t* out) " specify an exact framebuffer size, without any visual ornaments.\n\n" ); } +static void +help_dynamic_skin(stralloc_t* out) +{ + PRINTF( + " use '-dynamic_skin' to dynamically generate a skin based on the settings\n" + " in the AVD. This option only has effect if the -skin WxH option is used\n" + " to specify the width and height of the framebuffer\n"); +} + /* default network settings for emulator */ #define DEFAULT_NETSPEED "full" #define DEFAULT_NETDELAY "none" diff --git a/android/main-common.c b/android/main-common.c index 2d535c7..5c82005 100644 --- a/android/main-common.c +++ b/android/main-common.c @@ -321,6 +321,207 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) #endif } +typedef struct part_properties part_properties; +struct part_properties { + const char* name; + int width; + int height; + part_properties* next; +}; + +part_properties* +read_all_part_properties(AConfig* parts) +{ + part_properties* head = NULL; + part_properties* prev = NULL; + + AConfig *node = parts->first_child; + while (node) { + part_properties* t = calloc(1, sizeof(part_properties)); + t->name = node->name; + + AConfig* bg = aconfig_find(node, "background"); + if (bg != NULL) { + t->width = aconfig_int(bg, "width", 0); + t->height = aconfig_int(bg, "height", 0); + } + + if (prev == NULL) { + head = t; + } else { + prev->next = t; + } + prev = t; + node = node->next; + } + + return head; +} + +void +free_all_part_properties(part_properties* head) +{ + part_properties* prev = head; + while (head) { + prev = head; + head = head->next; + free(prev); + } +} + +part_properties* +get_part_properties(part_properties* allparts, char *partname) +{ + part_properties* p; + for (p = allparts; p != NULL; p = p->next) { + if (!strcmp(partname, p->name)) + return p; + } + + return NULL; +} + +void +add_parts_to_layout(AConfig* layout, + char* parts[], + int n_parts, + part_properties *props, + int xoffset, + int x_margin, + int y_margin) +{ + int i; + int y = 10; + char tmp[512]; + for (i = 0; i < n_parts; i++) { + part_properties *p = get_part_properties(props, parts[i]); + snprintf(tmp, sizeof tmp, + "part%d {\n \ + name %s\n \ + x %d\n \ + y %d\n \ + }", + i + 2, // layout already has the device part as part1, so start from part2 + p->name, + xoffset + x_margin, + y + ); + y += p->height + y_margin; + aconfig_load(layout, strdup(tmp)); + } +} + +int +load_dynamic_skin(AndroidHwConfig* hwConfig, + const char* skinDirPath, + int width, + int height, + AConfig* root) +{ + char tmp[1024]; + AConfig* node; + int i; + int max_part_width; + + if (skinDirPath == NULL) + return 0; + + snprintf(tmp, sizeof(tmp), "%s/dynamic", skinDirPath); + if (!path_exists(tmp)) + return 0; + + snprintf(tmp, sizeof(tmp), "%s/dynamic/layout", skinDirPath); + D("trying to load skin file '%s'", tmp); + + if(aconfig_load_file(root, tmp) < 0) { + dwarning("could not load skin file '%s', won't use a skin\n", tmp); + return 0; + } + + /* Fix the width and height specified for the "device" part in the layout */ + node = aconfig_find(root, "parts"); + if (node != NULL) { + node = aconfig_find(node, "device"); + if (node != NULL) { + node = aconfig_find(node, "display"); + if (node != NULL) { + snprintf(tmp, sizeof tmp, "%d", width); + aconfig_set(node, "width", strdup(tmp)); + snprintf(tmp, sizeof tmp, "%d", height); + aconfig_set(node, "height", strdup(tmp)); + } + } + } + + /* The dynamic layout declares all the parts that are available statically + in the layout file. Now we need to dynamically generate the + appropriate layout based on the hardware config */ + + part_properties* props = read_all_part_properties(aconfig_find(root, "parts")); + + const int N_PARTS = 3; + char* parts[N_PARTS]; + parts[0] = hwConfig->hw_mainKeys ? "hwkeys_on" : "hwkeys_off"; + parts[1] = hwConfig->hw_dPad ? "dpad_on" : "dpad_off"; + parts[2] = hwConfig->hw_keyboard ? "keyboard_on" : "keyboard_off"; + + for (i = 0, max_part_width = 0; i < N_PARTS; i++) { + part_properties *p = get_part_properties(props, parts[i]); + if (p != NULL && p->width > max_part_width) + max_part_width = p->width; + } + + int x_margin = 10; + int y_margin = 10; + snprintf(tmp, sizeof tmp, + "layouts {\n \ + portrait {\n \ + width %d\n \ + height %d\n \ + color 0x404040\n \ + event EV_SW:0:1\n \ + part1 {\n name device\n x 0\n y 0\n}\n \ + }\n \ + landscape {\n \ + width %d\n \ + height %d\n \ + color 0x404040\n \ + event EV_SW:0:0\n \ + dpad-rotation 3\n \ + part1 {\n name device\n x 0\n y %d\n rotation 3\n }\n \ + }\n \ + }\n \ + }\n", + width + max_part_width + 2 * x_margin, + height, + height + max_part_width + 2 * x_margin, + width, + width); + aconfig_load(root, strdup(tmp)); + + /* Add parts to portrait orientation */ + node = aconfig_find(root, "layouts"); + if (node != NULL) { + node = aconfig_find(node, "portrait"); + if (node != NULL) { + add_parts_to_layout(node, parts, N_PARTS, props, width, x_margin, y_margin); + } + } + + /* Add parts to landscape orientation */ + node = aconfig_find(root, "layouts"); + if (node != NULL) { + node = aconfig_find(node, "landscape"); + if (node != NULL) { + add_parts_to_layout(node, parts, N_PARTS, props, height, x_margin, y_margin); + } + } + + free_all_part_properties(props); + + return 1; +} + /* list of skin aliases */ static const struct { const char* name; @@ -396,9 +597,19 @@ parse_skin_files(const char* skinDirPath, if (y && isdigit(y[1])) { bpp = atoi(y+1); } + + if (opts->dynamic_skin) { + if (load_dynamic_skin(hwConfig, skinDirPath, width, height, root)) { + snprintf(tmp, sizeof tmp, "%s/dynamic/", skinDirPath); + path = tmp; + D("loaded dynamic skin width=%d height=%d bpp=%d\n", width, height, bpp); + goto FOUND_SKIN; + } + } + snprintf(tmp, sizeof tmp, - "display {\n width %d\n height %d\n bpp %d}\n", - width, height,bpp); + "display {\n width %d\n height %d\n bpp %d}\n", + width, height,bpp); aconfig_load(root, strdup(tmp)); path = ":"; D("found magic skin width=%d height=%d bpp=%d\n", width, height, bpp); |