Allow skins to provide a "dpad-rotation" field for each layout.

This is used to deal with the fact that the framework *always* assumes that
the physical DPad is rotated in landscaped mode, while the default skin no
longer does that.

NOTE: tested on old skin files for backwards compatibility.

(Upcoming skin fixes coming in another patch)
diff --git a/Makefile.android b/Makefile.android
index 0cc5ed5..6a8e3fd 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -499,6 +499,7 @@
               android/hw-lcd.c \
               android/hw-qemud.c \
               android/hw-sensors.c \
+              android/keycode.c \
               android/main.c \
               android/resource.c \
               android/user-config.c \
diff --git a/android/charmap.h b/android/charmap.h
index 2b0d071..5ac1367 100644
--- a/android/charmap.h
+++ b/android/charmap.h
@@ -12,98 +12,7 @@
 #ifndef _android_charmap_h
 #define _android_charmap_h
 
-#include "linux_keycodes.h"
-
-/* Keep it consistent with linux/input.h */
-typedef enum {
-    kKeyCodeSoftLeft                = KEY_SOFT1,
-    kKeyCodeSoftRight               = KEY_SOFT2,
-    kKeyCodeHome                    = KEY_HOME,
-    kKeyCodeBack                    = KEY_BACK,
-    kKeyCodeCall                    = KEY_SEND,
-    kKeyCodeEndCall                 = KEY_END,
-    kKeyCode0                       = KEY_0,
-    kKeyCode1                       = KEY_1,
-    kKeyCode2                       = KEY_2,
-    kKeyCode3                       = KEY_3,
-    kKeyCode4                       = KEY_4,
-    kKeyCode5                       = KEY_5,
-    kKeyCode6                       = KEY_6,
-    kKeyCode7                       = KEY_7,
-    kKeyCode8                       = KEY_8,
-    kKeyCode9                       = KEY_9,
-    kKeyCodeStar                    = KEY_STAR,
-    kKeyCodePound                   = KEY_SHARP,
-    kKeyCodeDpadUp                  = KEY_UP,
-    kKeyCodeDpadDown                = KEY_DOWN,
-    kKeyCodeDpadLeft                = KEY_LEFT,
-    kKeyCodeDpadRight               = KEY_RIGHT,
-    kKeyCodeDpadCenter              = KEY_CENTER,
-    kKeyCodeVolumeUp                = KEY_VOLUMEUP,
-    kKeyCodeVolumeDown              = KEY_VOLUMEDOWN,
-    kKeyCodePower                   = KEY_POWER,
-    kKeyCodeCamera                  = KEY_CAMERA,
-    kKeyCodeClear                   = KEY_CLEAR,
-    kKeyCodeA                       = KEY_A,
-    kKeyCodeB                       = KEY_B,
-    kKeyCodeC                       = KEY_C,
-    kKeyCodeD                       = KEY_D,
-    kKeyCodeE                       = KEY_E,
-    kKeyCodeF                       = KEY_F,
-    kKeyCodeG                       = KEY_G,
-    kKeyCodeH                       = KEY_H,
-    kKeyCodeI                       = KEY_I,
-    kKeyCodeJ                       = KEY_J,
-    kKeyCodeK                       = KEY_K,
-    kKeyCodeL                       = KEY_L,
-    kKeyCodeM                       = KEY_M,
-    kKeyCodeN                       = KEY_N,
-    kKeyCodeO                       = KEY_O,
-    kKeyCodeP                       = KEY_P,
-    kKeyCodeQ                       = KEY_Q,
-    kKeyCodeR                       = KEY_R,
-    kKeyCodeS                       = KEY_S,
-    kKeyCodeT                       = KEY_T,
-    kKeyCodeU                       = KEY_U,
-    kKeyCodeV                       = KEY_V,
-    kKeyCodeW                       = KEY_W,
-    kKeyCodeX                       = KEY_X,
-    kKeyCodeY                       = KEY_Y,
-    kKeyCodeZ                       = KEY_Z,
-
-    kKeyCodeComma                   = KEY_COMMA,
-    kKeyCodePeriod                  = KEY_DOT,
-    kKeyCodeAltLeft                 = KEY_LEFTALT,
-    kKeyCodeAltRight                = KEY_RIGHTALT,
-    kKeyCodeCapLeft                 = KEY_LEFTSHIFT,
-    kKeyCodeCapRight                = KEY_RIGHTSHIFT,
-    kKeyCodeTab                     = KEY_TAB,
-    kKeyCodeSpace                   = KEY_SPACE,
-    kKeyCodeSym                     = KEY_COMPOSE,
-    kKeyCodeExplorer                = KEY_WWW,
-    kKeyCodeEnvelope                = KEY_MAIL,
-    kKeyCodeNewline                 = KEY_ENTER,
-    kKeyCodeDel                     = KEY_BACKSPACE,
-    kKeyCodeGrave                   = 399,
-    kKeyCodeMinus                   = KEY_MINUS,
-    kKeyCodeEquals                  = KEY_EQUAL,
-    kKeyCodeLeftBracket             = KEY_LEFTBRACE,
-    kKeyCodeRightBracket            = KEY_RIGHTBRACE,
-    kKeyCodeBackslash               = KEY_BACKSLASH,
-    kKeyCodeSemicolon               = KEY_SEMICOLON,
-    kKeyCodeApostrophe              = KEY_APOSTROPHE,
-    kKeyCodeSlash                   = KEY_SLASH,
-    kKeyCodeAt                      = KEY_EMAIL,
-    kKeyCodeNum                     = KEY_NUM,
-    kKeyCodeHeadsetHook             = KEY_HEADSETHOOK,
-    kKeyCodeFocus                   = KEY_FOCUS,
-    kKeyCodePlus                    = KEY_PLUS,
-    kKeyCodeMenu                    = KEY_SOFT1,
-    kKeyCodeNotification            = KEY_NOTIFICATION,
-    kKeyCodeSearch                  = KEY_SEARCH,
-
-} AndroidKeyCode;
-
+#include "android/keycode.h"
 
 /* this defines a structure used to describe an Android keyboard charmap */
 typedef struct AKeyEntry {
diff --git a/android/keycode.c b/android/keycode.c
new file mode 100644
index 0000000..7364427
--- /dev/null
+++ b/android/keycode.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2009 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/keycode.h"
+
+AndroidKeyCode
+android_keycode_rotate( AndroidKeyCode  code, int  rotation )
+{
+    static const AndroidKeyCode  wheel[4] = { kKeyCodeDpadUp,
+                                              kKeyCodeDpadRight,
+                                              kKeyCodeDpadDown,
+                                              kKeyCodeDpadLeft };
+
+    int  index;
+
+    for (index = 0; index < 4; index++) {
+        if (code == wheel[index]) {
+            index = (index + rotation) & 3;
+            code  = wheel[index];
+            break;
+        }
+    }
+    return code;
+}
+
diff --git a/android/keycode.h b/android/keycode.h
new file mode 100644
index 0000000..a32ac0d
--- /dev/null
+++ b/android/keycode.h
@@ -0,0 +1,120 @@
+/* Copyright (C) 2009 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.
+*/
+#ifndef ANDROID_KEYCODE_H
+#define ANDROID_KEYCODE_H
+
+#include "linux_keycodes.h"
+
+/* Keep it consistent with linux/input.h */
+typedef enum {
+    kKeyCodeSoftLeft                = KEY_SOFT1,
+    kKeyCodeSoftRight               = KEY_SOFT2,
+    kKeyCodeHome                    = KEY_HOME,
+    kKeyCodeBack                    = KEY_BACK,
+    kKeyCodeCall                    = KEY_SEND,
+    kKeyCodeEndCall                 = KEY_END,
+    kKeyCode0                       = KEY_0,
+    kKeyCode1                       = KEY_1,
+    kKeyCode2                       = KEY_2,
+    kKeyCode3                       = KEY_3,
+    kKeyCode4                       = KEY_4,
+    kKeyCode5                       = KEY_5,
+    kKeyCode6                       = KEY_6,
+    kKeyCode7                       = KEY_7,
+    kKeyCode8                       = KEY_8,
+    kKeyCode9                       = KEY_9,
+    kKeyCodeStar                    = KEY_STAR,
+    kKeyCodePound                   = KEY_SHARP,
+    kKeyCodeDpadUp                  = KEY_UP,
+    kKeyCodeDpadDown                = KEY_DOWN,
+    kKeyCodeDpadLeft                = KEY_LEFT,
+    kKeyCodeDpadRight               = KEY_RIGHT,
+    kKeyCodeDpadCenter              = KEY_CENTER,
+    kKeyCodeVolumeUp                = KEY_VOLUMEUP,
+    kKeyCodeVolumeDown              = KEY_VOLUMEDOWN,
+    kKeyCodePower                   = KEY_POWER,
+    kKeyCodeCamera                  = KEY_CAMERA,
+    kKeyCodeClear                   = KEY_CLEAR,
+    kKeyCodeA                       = KEY_A,
+    kKeyCodeB                       = KEY_B,
+    kKeyCodeC                       = KEY_C,
+    kKeyCodeD                       = KEY_D,
+    kKeyCodeE                       = KEY_E,
+    kKeyCodeF                       = KEY_F,
+    kKeyCodeG                       = KEY_G,
+    kKeyCodeH                       = KEY_H,
+    kKeyCodeI                       = KEY_I,
+    kKeyCodeJ                       = KEY_J,
+    kKeyCodeK                       = KEY_K,
+    kKeyCodeL                       = KEY_L,
+    kKeyCodeM                       = KEY_M,
+    kKeyCodeN                       = KEY_N,
+    kKeyCodeO                       = KEY_O,
+    kKeyCodeP                       = KEY_P,
+    kKeyCodeQ                       = KEY_Q,
+    kKeyCodeR                       = KEY_R,
+    kKeyCodeS                       = KEY_S,
+    kKeyCodeT                       = KEY_T,
+    kKeyCodeU                       = KEY_U,
+    kKeyCodeV                       = KEY_V,
+    kKeyCodeW                       = KEY_W,
+    kKeyCodeX                       = KEY_X,
+    kKeyCodeY                       = KEY_Y,
+    kKeyCodeZ                       = KEY_Z,
+
+    kKeyCodeComma                   = KEY_COMMA,
+    kKeyCodePeriod                  = KEY_DOT,
+    kKeyCodeAltLeft                 = KEY_LEFTALT,
+    kKeyCodeAltRight                = KEY_RIGHTALT,
+    kKeyCodeCapLeft                 = KEY_LEFTSHIFT,
+    kKeyCodeCapRight                = KEY_RIGHTSHIFT,
+    kKeyCodeTab                     = KEY_TAB,
+    kKeyCodeSpace                   = KEY_SPACE,
+    kKeyCodeSym                     = KEY_COMPOSE,
+    kKeyCodeExplorer                = KEY_WWW,
+    kKeyCodeEnvelope                = KEY_MAIL,
+    kKeyCodeNewline                 = KEY_ENTER,
+    kKeyCodeDel                     = KEY_BACKSPACE,
+    kKeyCodeGrave                   = 399,
+    kKeyCodeMinus                   = KEY_MINUS,
+    kKeyCodeEquals                  = KEY_EQUAL,
+    kKeyCodeLeftBracket             = KEY_LEFTBRACE,
+    kKeyCodeRightBracket            = KEY_RIGHTBRACE,
+    kKeyCodeBackslash               = KEY_BACKSLASH,
+    kKeyCodeSemicolon               = KEY_SEMICOLON,
+    kKeyCodeApostrophe              = KEY_APOSTROPHE,
+    kKeyCodeSlash                   = KEY_SLASH,
+    kKeyCodeAt                      = KEY_EMAIL,
+    kKeyCodeNum                     = KEY_NUM,
+    kKeyCodeHeadsetHook             = KEY_HEADSETHOOK,
+    kKeyCodeFocus                   = KEY_FOCUS,
+    kKeyCodePlus                    = KEY_PLUS,
+    kKeyCodeMenu                    = KEY_SOFT1,
+    kKeyCodeNotification            = KEY_NOTIFICATION,
+    kKeyCodeSearch                  = KEY_SEARCH,
+
+} AndroidKeyCode;
+
+/* This function is used to rotate D-Pad keycodes, while leaving other ones
+ * untouched. 'code' is the input keycode, which will be returned as is if
+ * it doesn't correspond to a D-Pad arrow. 'rotation' is the number of
+ * *clockwise* 90 degrees rotations to perform on D-Pad keys.
+ *
+ * Here are examples:
+ *    android_keycode_rotate( kKeyCodeDpadUp, 1 )  => kKeyCodeDpadRight
+ *    android_keycode_rotate( kKeyCodeDpadRight, 2 ) => kKeyCodeDpadLeft
+ *    android_keycode_rotate( kKeyCodeDpadDown, 3 ) => kKeyCodeDpadRight
+ *    android_keycode_rotate( kKeyCodeSpace, n ) => kKeyCodeSpace independent of n
+ */
+extern AndroidKeyCode   android_keycode_rotate( AndroidKeyCode  code, int  rotation );
+
+#endif /* ANDROID_KEYCODE_H */
diff --git a/android/main.c b/android/main.c
index 70c13b8..35f236f 100644
--- a/android/main.c
+++ b/android/main.c
@@ -397,40 +397,8 @@
 qemulator_rotate_keycode( QEmulator*      emulator,
                           AndroidKeyCode  sym )
 {
-    switch (skin_layout_get_dpad_rotation(emulator->layout)) {
-        case SKIN_ROTATION_90:
-            switch (sym) {
-                case kKeyCodeDpadLeft:  sym = kKeyCodeDpadDown; break;
-                case kKeyCodeDpadRight: sym = kKeyCodeDpadUp; break;
-                case kKeyCodeDpadUp:    sym = kKeyCodeDpadLeft; break;
-                case kKeyCodeDpadDown:  sym = kKeyCodeDpadRight; break;
-                default: ;
-            }
-            break;
-
-        case SKIN_ROTATION_180:
-            switch (sym) {
-                case kKeyCodeDpadLeft:  sym = kKeyCodeDpadRight; break;
-                case kKeyCodeDpadRight: sym = kKeyCodeDpadLeft; break;
-                case kKeyCodeDpadUp:    sym = kKeyCodeDpadDown; break;
-                case kKeyCodeDpadDown:  sym = kKeyCodeDpadUp; break;
-                default: ;
-            }
-            break;
-
-        case SKIN_ROTATION_270:
-            switch (sym) {
-                case kKeyCodeDpadLeft:  sym = kKeyCodeDpadUp; break;
-                case kKeyCodeDpadRight: sym = kKeyCodeDpadDown; break;
-                case kKeyCodeDpadUp:    sym = kKeyCodeDpadRight; break;
-                case kKeyCodeDpadDown:  sym = kKeyCodeDpadLeft; break;
-                default: ;
-            }
-            break;
-
-        default: ;
-    }
-    return sym;
+    return android_keycode_rotate( sym,
+                                   skin_layout_get_dpad_rotation(emulator->layout) );
 }
 
 static int
diff --git a/android/skin/file.c b/android/skin/file.c
index 3d5ea7f..f7f0be9 100644
--- a/android/skin/file.c
+++ b/android/skin/file.c
@@ -424,6 +424,9 @@
 SkinRotation
 skin_layout_get_dpad_rotation( SkinLayout*  layout )
 {
+    if (layout->has_dpad_rotation)
+        return layout->dpad_rotation;
+
     SKIN_LAYOUT_LOOP_LOCS(layout, loc)
         SkinPart*  part = loc->part;
         SKIN_PART_LOOP_BUTTONS(part,button)
@@ -505,6 +508,12 @@
     layout->color = aconfig_unsigned( root, "color", 0x808080 ) | 0xff000000;
     ptail         = &layout->locations;
 
+    node = aconfig_find( root, "dpad-rotation" );
+    if (node != NULL) {
+        layout->dpad_rotation     = aconfig_int( root, "dpad-rotation", 0 );
+        layout->has_dpad_rotation = 1;
+    }
+
     for (node = root->first_child; node; node = node->next)
     {
         if (!memcmp(node->name, "part", 4)) {
diff --git a/android/skin/file.h b/android/skin/file.h
index 8f95368..9f188b9 100644
--- a/android/skin/file.h
+++ b/android/skin/file.h
@@ -75,6 +75,8 @@
     int                 event_type;
     int                 event_code;
     int                 event_value;
+    char                has_dpad_rotation;
+    SkinRotation        dpad_rotation;
     SkinSize            size;
     SkinLocation*       locations;
 } SkinLayout;
diff --git a/android/skin/keyboard.h b/android/skin/keyboard.h
index 45efd18..f583298 100644
--- a/android/skin/keyboard.h
+++ b/android/skin/keyboard.h
@@ -42,6 +42,9 @@
 extern void           skin_keyboard_set_rotation( SkinKeyboard*     keyboard,
                                                   SkinRotation      rotation );
 
+extern AndroidKeyCode skin_keyboard_rotate_keycode( SkinKeyboard*   keyboard,
+                                                    AndroidKeyCode  keycode );
+
 extern void           skin_keyboard_on_key_press( SkinKeyboard*     keyboard,
                                                   SkinKeyEventFunc  press_func,
                                                   void*             press_opaque );
diff --git a/android/skin/window.c b/android/skin/window.c
index 674b594..156ac56 100644
--- a/android/skin/window.c
+++ b/android/skin/window.c
@@ -523,7 +523,7 @@
 }
 
 static void
-button_init( Button*  button, SkinButton*  sbutton, SkinLocation*  loc, Background*  back, SkinRect*  frame )
+button_init( Button*  button, SkinButton*  sbutton, SkinLocation*  loc, Background*  back, SkinRect*  frame, SkinLayout*  slayout )
 {
     SkinRect  r;
 
@@ -532,6 +532,14 @@
     button->keycode    = sbutton->keycode;
     button->down       = 0;
 
+    if (slayout->has_dpad_rotation) {
+        /* Dpad keys must be rotated if the skin provides a 'dpad-rotation' field.
+         * this is used as a counter-measure to the fact that the framework always assumes
+         * that the physical D-Pad has been rotated when in landscape mode.
+         */
+        button->keycode = android_keycode_rotate( button->keycode, -slayout->dpad_rotation );
+    }
+
     skin_rect_rotate( &r, &sbutton->rect, loc->rotation );
     r.pos.x += loc->anchor.x;
     r.pos.y += loc->anchor.y;
@@ -792,7 +800,7 @@
 
         SKIN_PART_LOOP_BUTTONS(part, sbutton)
             Button*  button = layout->buttons + n_buttons;
-            button_init( button, sbutton, loc, back, &layout->rect );
+            button_init( button, sbutton, loc, back, &layout->rect, slayout );
             n_buttons += 1;
         SKIN_PART_LOOP_END
     SKIN_LAYOUT_LOOP_END