frontend: add minimize support
authornotaz <notasas@gmail.com>
Sun, 8 Jan 2012 17:23:52 +0000 (19:23 +0200)
committernotaz <notasas@gmail.com>
Sun, 8 Jan 2012 17:46:40 +0000 (19:46 +0200)
frontend/linux/xenv.c
frontend/linux/xenv.h
frontend/main.c
frontend/main.h
frontend/menu.c
frontend/plat.h
frontend/plat_dummy.c
frontend/plat_omap.c
frontend/plat_pandora.c
frontend/plat_pollux.c
maemo/hildon.c

index 3de7628..f54e57d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Gražvydas "notaz" Ignotas, 2009-2011
+ * (C) Gražvydas "notaz" Ignotas, 2009-2012
  *
  * This work is licensed under the terms of any of these licenses
  * (at your option):
@@ -38,6 +38,7 @@
 
 struct xstuff {
        Display *display;
+       Window window;
        FPTR(XCreateBitmapFromData);
        FPTR(XCreatePixmapCursor);
        FPTR(XFreePixmap);
@@ -50,11 +51,17 @@ struct xstuff {
        FPTR(XMapWindow);
        FPTR(XNextEvent);
        FPTR(XCheckTypedEvent);
-       FPTR(XUnmapWindow);
+       FPTR(XWithdrawWindow);
        FPTR(XGrabKeyboard);
        FPTR(XPending);
        FPTR(XLookupKeysym);
        FPTR(XkbSetDetectableAutoRepeat);
+       FPTR(XStoreName);
+       FPTR(XIconifyWindow);
+       FPTR(XMoveResizeWindow);
+       FPTR(XInternAtom);
+       FPTR(XSetWMHints);
+       FPTR(XSync);
 };
 
 static struct xstuff g_xstuff;
@@ -74,7 +81,7 @@ static Cursor transparent_cursor(struct xstuff *xf, Display *display, Window win
        return cursor;
 }
 
-static int x11h_init(void)
+static int x11h_init(const char *window_title)
 {
        unsigned int display_width, display_height;
        Display *display;
@@ -102,11 +109,17 @@ static int x11h_init(void)
        FPTR_LINK(g_xstuff, x11lib, XMapWindow);
        FPTR_LINK(g_xstuff, x11lib, XNextEvent);
        FPTR_LINK(g_xstuff, x11lib, XCheckTypedEvent);
-       FPTR_LINK(g_xstuff, x11lib, XUnmapWindow);
+       FPTR_LINK(g_xstuff, x11lib, XWithdrawWindow);
        FPTR_LINK(g_xstuff, x11lib, XGrabKeyboard);
        FPTR_LINK(g_xstuff, x11lib, XPending);
        FPTR_LINK(g_xstuff, x11lib, XLookupKeysym);
        FPTR_LINK(g_xstuff, x11lib, XkbSetDetectableAutoRepeat);
+       FPTR_LINK(g_xstuff, x11lib, XStoreName);
+       FPTR_LINK(g_xstuff, x11lib, XIconifyWindow);
+       FPTR_LINK(g_xstuff, x11lib, XMoveResizeWindow);
+       FPTR_LINK(g_xstuff, x11lib, XInternAtom);
+       FPTR_LINK(g_xstuff, x11lib, XSetWMHints);
+       FPTR_LINK(g_xstuff, x11lib, XSync);
 
        //XInitThreads();
 
@@ -132,22 +145,25 @@ static int x11h_init(void)
        display_height = DisplayHeight(display, screen);
        printf(PFX "display is %dx%d\n", display_width, display_height);
 
-       win = g_xstuff.pXCreateSimpleWindow(display,
-                       RootWindow(display, screen),
-                       0, 0, display_width, display_height, 0,
-                       BlackPixel(display, screen),
-                       BlackPixel(display, screen));
+       g_xstuff.window = win = g_xstuff.pXCreateSimpleWindow(display,
+               RootWindow(display, screen), 0, 0, display_width, display_height,
+               0, BlackPixel(display, screen), BlackPixel(display, screen));
 
        attributes.override_redirect = True;
        attributes.cursor = transparent_cursor(&g_xstuff, display, win);
        g_xstuff.pXChangeWindowAttributes(display, win, CWOverrideRedirect | CWCursor, &attributes);
 
-       g_xstuff.pXSelectInput(display, win, ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask);
+       g_xstuff.pXStoreName(display, win, window_title);
+       g_xstuff.pXSelectInput(display, win,
+               ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask | PropertyChangeMask);
        g_xstuff.pXMapWindow(display, win);
        g_xstuff.pXGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
        g_xstuff.pXkbSetDetectableAutoRepeat(display, 1, NULL);
        // XSetIOErrorHandler
 
+       // we don't know when event dispatch will be called, so sync now
+       g_xstuff.pXSync(display, False);
+
        return 0;
 fail2:
        dlclose(x11lib);
@@ -169,6 +185,8 @@ static int x11h_update(int *is_down)
                        case Expose:
                                while (g_xstuff.pXCheckTypedEvent(g_xstuff.display, Expose, &evt))
                                        ;
+                       default:
+                               // printf("event %d\n", evt.type);
                                break;
 
                        case KeyPress:
@@ -185,6 +203,86 @@ static int x11h_update(int *is_down)
        return NoSymbol;
 }
 
+static void x11h_wait_vmstate(void)
+{
+       Atom wm_state = g_xstuff.pXInternAtom(g_xstuff.display, "WM_STATE", False);
+       XEvent evt;
+       int i;
+
+       usleep(20000);
+
+       for (i = 0; i < 20; i++) {
+               while (g_xstuff.pXPending(g_xstuff.display)) {
+                       g_xstuff.pXNextEvent(g_xstuff.display, &evt);
+                       // printf("w event %d\n", evt.type);
+                       if (evt.type == PropertyNotify && evt.xproperty.atom == wm_state)
+                               return;
+               }
+               usleep(200000);
+       }
+
+       printf("timeout waiting for wm_state change\n");
+}
+
+static int x11h_minimize(void)
+{
+       XSetWindowAttributes attributes;
+       Display *display = g_xstuff.display;
+       Window window = g_xstuff.window;
+       int screen = DefaultScreen(g_xstuff.display);
+       int display_width, display_height;
+       XWMHints wm_hints;
+       XEvent evt;
+
+       g_xstuff.pXWithdrawWindow(display, window, screen);
+
+       attributes.override_redirect = False;
+       g_xstuff.pXChangeWindowAttributes(display, window,
+               CWOverrideRedirect, &attributes);
+
+       wm_hints.flags = StateHint;
+       wm_hints.initial_state = IconicState;
+       g_xstuff.pXSetWMHints(display, window, &wm_hints);
+
+       g_xstuff.pXMapWindow(display, window);
+
+       while (g_xstuff.pXNextEvent(display, &evt) == 0)
+       {
+               // printf("m event %d\n", evt.type);
+               switch (evt.type)
+               {
+                       case FocusIn:
+                               goto out;
+                       default:
+                               break;
+               }
+       }
+
+out:
+       g_xstuff.pXWithdrawWindow(display, window, screen);
+
+       // must wait for some magic vmstate property change before setting override_redirect
+       x11h_wait_vmstate();
+
+       attributes.override_redirect = True;
+       g_xstuff.pXChangeWindowAttributes(display, window,
+               CWOverrideRedirect, &attributes);
+
+       // fixup window after resize on override_redirect loss
+       display_width = DisplayWidth(display, screen);
+       display_height = DisplayHeight(display, screen);
+       g_xstuff.pXMoveResizeWindow(display, window, 0, 0, display_width, display_height);
+
+       g_xstuff.pXMapWindow(display, window);
+       g_xstuff.pXGrabKeyboard(display, window, False, GrabModeAsync, GrabModeAsync, CurrentTime);
+       g_xstuff.pXkbSetDetectableAutoRepeat(display, 1, NULL);
+
+       // we don't know when event dispatch will be called, so sync now
+       g_xstuff.pXSync(display, False);
+
+       return 0;
+}
+
 static struct termios g_kbd_termios_saved;
 static int g_kbdfd = -1;
 
@@ -249,11 +347,11 @@ static void tty_end(void)
        g_kbdfd = -1;
 }
 
-int xenv_init(void)
+int xenv_init(const char *window_title)
 {
        int ret;
 
-       ret = x11h_init();
+       ret = x11h_init(window_title);
        if (ret == 0)
                return 0;
 
@@ -274,8 +372,47 @@ int xenv_update(int *is_down)
        return -1;
 }
 
+/* blocking minimize until user maximazes again */
+int xenv_minimize(void)
+{
+       int ret, dummy;
+
+       if (g_xstuff.display) {
+               xenv_update(&dummy);
+               ret = x11h_minimize();
+               xenv_update(&dummy);
+               return ret;
+       }
+
+       return -1;
+}
+
 void xenv_finish(void)
 {
        // TODO: cleanup X?
        tty_end();
 }
+
+#if 0
+int main()
+{
+       int i, r, d;
+
+       xenv_init("just a test");
+
+       for (i = 0; i < 5; i++) {
+               while ((r = xenv_update(&d)) > 0)
+                       printf("%d %x %d\n", d, r, r);
+               sleep(1);
+
+               if (i == 1)
+                       xenv_minimize();
+               printf("ll %d\n", i);
+       }
+
+       printf("xenv_finish..\n");
+       xenv_finish();
+
+       return 0;
+}
+#endif
index 948381e..1afad9d 100644 (file)
@@ -1,5 +1,6 @@
 
-int  xenv_init(void);
+int  xenv_init(const char *window_title);
 int  xenv_update(int *is_down);
+int  xenv_minimize(void);
 void xenv_finish(void);
 
index 7b3aac5..d7f23ed 100644 (file)
@@ -250,6 +250,9 @@ void do_emu_action(void)
        case SACTION_VOLUME_DOWN:
                plat_step_volume(emu_action == SACTION_VOLUME_UP);
                return;
+       case SACTION_MINIMIZE:
+               plat_minimize();
+               return;
        default:
                return;
        }
index bc6c267..22a42f6 100644 (file)
@@ -60,6 +60,7 @@ enum sched_action {
        SACTION_SCREENSHOT,
        SACTION_VOLUME_UP,
        SACTION_VOLUME_DOWN,
+       SACTION_MINIMIZE,
        SACTION_GUN_TRIGGER = 16,
        SACTION_GUN_A,
        SACTION_GUN_B,
index c6a52de..1e64718 100644 (file)
@@ -756,6 +756,9 @@ me_bind_action emuctrl_actions[] =
        { "Toggle Frameskip ", 1 << SACTION_TOGGLE_FSKIP },
        { "Take Screenshot  ", 1 << SACTION_SCREENSHOT },
        { "Enter Menu       ", 1 << SACTION_ENTER_MENU },
+#ifdef __ARM_ARCH_7A__ /* XXX */
+       { "Minimize         ", 1 << SACTION_MINIMIZE },
+#endif
        { "Gun Trigger      ", 1 << SACTION_GUN_TRIGGER },
        { "Gun A button     ", 1 << SACTION_GUN_A },
        { "Gun B button     ", 1 << SACTION_GUN_B },
index 185ee98..6a22035 100644 (file)
@@ -1,3 +1,4 @@
+void plat_minimize(void);
 void *plat_prepare_screenshot(int *w, int *h, int *bpp);
 void plat_step_volume(int is_up);
 int  plat_cpu_clock_get(void);
index e768946..7929015 100644 (file)
@@ -71,3 +71,7 @@ void plat_step_volume(int is_up)
 void plat_trigger_vibrate(void)
 {
 }
+
+void plat_minimize(void)
+{
+}
index b529cfa..62f198b 100644 (file)
@@ -121,6 +121,13 @@ void plat_video_menu_leave(void)
                fprintf(stderr, "warning: vout_fbdev_resize failed\n");
 }
 
+void plat_minimize(void)
+{
+       omap_enable_layer(0);
+       xenv_minimize();
+       omap_enable_layer(1);
+}
+
 void plat_step_volume(int is_up)
 {
 }
@@ -158,7 +165,7 @@ void plat_init(void)
                exit(1);
        }
 
-       xenv_init();
+       xenv_init("PCSX-ReARMed");
 
        w = h = 0;
        main_fb = vout_fbdev_init(main_fb_name, &w, &h, 16, 2);
index d869d24..1c07924 100644 (file)
@@ -53,6 +53,7 @@ struct in_default_bind in_evdev_defbinds[] = {
        { KEY_RIGHTCTRL, IN_BINDTYPE_PLAYER12, DKEY_R1 },
        { KEY_Q,        IN_BINDTYPE_PLAYER12, DKEY_L2 },
        { KEY_P,        IN_BINDTYPE_PLAYER12, DKEY_R2 },
+       { KEY_TAB,      IN_BINDTYPE_EMU, SACTION_MINIMIZE },
        { KEY_SPACE,    IN_BINDTYPE_EMU, SACTION_ENTER_MENU },
        { KEY_1,        IN_BINDTYPE_EMU, SACTION_SAVE_STATE },
        { KEY_2,        IN_BINDTYPE_EMU, SACTION_LOAD_STATE },
index af91066..af5b81a 100644 (file)
@@ -262,6 +262,10 @@ void *plat_prepare_screenshot(int *w, int *h, int *bpp)
        return pl_vout_buf;
 }
 
+void plat_minimize(void)
+{
+}
+
 static void pl_vout_set_raw_vram(void *vram)
 {
        int i;
index a5f151e..0399909 100644 (file)
@@ -265,3 +265,7 @@ void plat_step_volume(int is_up)
 void plat_trigger_vibrate(void)
 {
 }
+
+void plat_minimize(void)
+{
+}