Index: CATEGORIES
===================================================================
--- CATEGORIES	(revision 15984)
+++ CATEGORIES	(working copy)
@@ -90,6 +91,7 @@
 wavplay,viewers
 wavrecord,apps
 wavview,viewers
+windowmanager,demos
 wormlet,games
 xobox,games
 zxbox,viewers
Index: windowmanager.c
===================================================================
--- windowmanager.c	(revision 0)
+++ windowmanager.c	(revision 0)
@@ -0,0 +1,289 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: helloworld.c 12807 2007-03-16 21:56:08Z amiconn $
+ *
+ * Copyright (C) 2002 Bj�rn Stenberg
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+
+PLUGIN_HEADER
+
+#define MAX_WINDOWS 8
+#define WINDOW_BUTTON_TIMEOUT HZ/5
+enum return_codes {
+    Redraw_Window = -1,
+    Status_OK = 1,
+};
+
+struct Window {
+    struct viewport vp;
+//    struct screen *display;
+    
+    void *data;
+    void (*draw_func)(struct viewport *vp,/* struct screen *display, */void *data);
+    int  (*button_func)(void *data);
+    
+    int refresh_ticks; /* # of ticks minimum between redraws, -1 means no refresh */
+    unsigned last_refresh;
+    bool force_refresh;
+};
+
+static struct Window *window_stack[MAX_WINDOWS];
+static int stacktop = 0;
+
+static struct plugin_api* rb;
+
+void push_window(struct Window *w)
+{
+    /* maybe check to make sure each window can only be there once? */
+    if (stacktop < MAX_WINDOWS)
+    {
+        window_stack[stacktop++] = w;
+        w->draw_func(&w->vp, /*w->display,*/ w->data);
+        w->last_refresh = *rb->current_tick;
+        w->force_refresh = false;
+    }
+}
+
+void remove_window(struct Window *w)
+{
+    int i;
+    bool found = false;
+    for (i=0; i<stacktop; i++)
+    {
+        if (w == window_stack[i] || found)
+        {
+            window_stack[i] = window_stack[i+1];
+        }
+    }
+    stacktop--;
+    /* redraw all windows in case the removed one overlapped */
+    for (i=0; i<stacktop; i++)
+    {
+        w = window_stack[i];
+        w->draw_func(&w->vp,/* w->display,*/ w->data);
+        w->last_refresh = *rb->current_tick;
+        w->force_refresh = false;
+    }
+}
+
+void main_loop(void)
+{
+    int i, ret;
+    struct Window *w;
+    while (1)
+    {
+        if (!stacktop)
+            rb->yield();
+        /* redraw windows */
+        for (i=0; i<stacktop; i++)
+        {
+            w = window_stack[i];
+            if (w->force_refresh || 
+                (w->refresh_ticks != -1 &&
+                 TIME_AFTER(*rb->current_tick, 
+                            w->last_refresh + w->refresh_ticks)))
+            {
+                w->draw_func(&w->vp,/* w->display,*/ w->data);
+                w->last_refresh = *rb->current_tick;
+                w->force_refresh = false;
+            }
+        }
+        /* find the top-mos window which acepts input */
+        i = stacktop-1;
+        while (i>=0 && window_stack[i]->button_func == NULL)
+            i--;
+        w = window_stack[i];
+        if (w->button_func)
+        {
+            ret = w->button_func(w->data);
+            switch (ret)
+            {
+                /* proper return codes will be added */
+                case Redraw_Window:
+                    w->force_refresh = true;
+                    break;
+                default:
+                    rb->sleep(ret);
+            }
+        }
+    }
+}
+
+/* SPLASH */
+void draw_splash(struct viewport *vp, /*struct screen *display,*/ void *data);
+static int remove_splash = 0;
+struct Window splash = {
+{
+    .x        = 2,
+    .y        = (LCD_HEIGHT-30)/2,
+    .width    = LCD_WIDTH-4,
+    .height   = 30,
+    .font     = FONT_UI,
+    .drawmode = DRMODE_SOLID,
+    .xmargin  = 0,
+    .ymargin  = 0,
+#if LCD_DEPTH > 1
+    .fg_pattern = LCD_DEFAULT_FG,
+    .bg_pattern = LCD_RGBPACK(255,0,0),
+#ifdef HAVE_LCD_COLOR
+    .lss_pattern = LCD_DEFAULT_BG,
+    .lse_pattern = LCD_DEFAULT_BG,
+    .lst_pattern = LCD_DEFAULT_BG,
+#endif
+#endif
+}, /*NULL,*/ &remove_splash, draw_splash,NULL, 5*HZ, 0, false};
+void draw_splash(struct viewport *vp, /*struct screen *display,*/ void *data)
+{
+    if (*(int*)data)
+    {
+        remove_window(&splash);
+    }
+    else
+    {
+        int *remove = (int*)data;
+        *remove = 1;
+        rb->lcd_set_viewport(vp);
+        rb->lcd_clear_display();
+        rb->lcd_puts_scroll(0,0,"Surprise!!!!");
+        rb->lcd_update_rect(vp->x, vp->y, vp->width, vp->height);
+        /* Restore the default viewport */
+        rb->lcd_set_viewport(NULL);
+    }
+}
+void show_splash(void)
+{
+    remove_splash = 0;
+    push_window(&splash);
+}
+/* "status bar" section */
+
+void draw_statusbar(struct viewport *vp, /*struct screen *display,*/ void *data)
+{
+    char msg[128];
+    rb->lcd_set_viewport(vp);
+    rb->lcd_clear_display();
+    rb->snprintf(msg, 128, "Statusbar: %d", *rb->current_tick);
+    rb->lcd_puts_scroll(0,0,msg);
+    rb->lcd_puts_scroll(0,1,"refresh every sec or so");
+    rb->lcd_update_rect(vp->x, vp->y, vp->width, vp->height);
+    /* Restore the default viewport */
+    rb->lcd_set_viewport(NULL);
+}
+struct Window statusbar = {
+{
+    .x        = 2,
+    .y        = 2,
+    .width    = LCD_WIDTH-4,
+    .height   = 20,
+    .font     = FONT_UI,
+    .drawmode = DRMODE_SOLID,
+    .xmargin  = 0,
+    .ymargin  = 0,
+#if LCD_DEPTH > 1
+    .fg_pattern = LCD_DEFAULT_FG,
+    .bg_pattern = LCD_RGBPACK(255,255,0),
+#ifdef HAVE_LCD_COLOR
+    .lss_pattern = LCD_DEFAULT_BG,
+    .lse_pattern = LCD_DEFAULT_BG,
+    .lst_pattern = LCD_DEFAULT_BG,
+#endif
+#endif
+}, /*NULL,*/ NULL, draw_statusbar,NULL, HZ, 0, false};
+
+/* browser/menu section */
+void draw_list(struct viewport *vp, /*struct screen *display,*/ void *data)
+{
+    char msg[128];
+    rb->lcd_set_viewport(vp);
+    rb->lcd_clear_display();
+    rb->snprintf(msg, 128, "List.. right pressed %d times", *(int*)data);
+    rb->lcd_puts_scroll(0,0,msg);
+    rb->lcd_puts_scroll(0,1,"refresh when >> pressed");
+    rb->lcd_puts_scroll(0,2,"press SELECT to pop up a splash");
+    rb->lcd_puts_scroll(0,3,"      which stays for 5 sec");
+    rb->lcd_update_rect(vp->x, vp->y, vp->width, vp->height);
+    /* Restore the default viewport */
+    rb->lcd_set_viewport(NULL);
+}
+
+int button_list(void *data)
+{
+    int button = rb->button_get_w_tmo(WINDOW_BUTTON_TIMEOUT);
+    int *count = (int*)data;
+    if (button & BUTTON_RIGHT)
+    {
+        (*count)++;
+        return Redraw_Window;
+    }
+    else if (button == BUTTON_SELECT)
+    {
+        show_splash();
+    }
+    else if (button == BUTTON_POWER)
+    {
+        toggle_statusbar();
+        return Redraw_Window;
+    }
+    return Status_OK;
+}
+static int up_count = 0;
+struct Window list = {
+{
+    .x        = 2,
+    .y        = 22,
+    .width    = LCD_WIDTH-4,
+    .height   = LCD_HEIGHT-24,
+    .font     = FONT_UI,
+    .drawmode = DRMODE_SOLID,
+    .xmargin  = 0,
+    .ymargin  = 0,
+#if LCD_DEPTH > 1
+    .fg_pattern = LCD_DEFAULT_FG,
+    .bg_pattern = LCD_RGBPACK(0xab,255,0xcd),
+#ifdef HAVE_LCD_COLOR
+    .lss_pattern = LCD_DEFAULT_BG,
+    .lse_pattern = LCD_DEFAULT_BG,
+    .lst_pattern = LCD_DEFAULT_BG,
+#endif
+#endif
+}, /*NULL,*/ &up_count, draw_list,button_list, -1, 0, false};
+void toggle_statusbar(void)
+{
+    static bool is_visible = true;
+    is_visible = !is_visible;
+    if (is_visible)
+    {
+        list.vp.height = LCD_HEIGHT-24;
+        list.vp.y = 22;
+        push_window(&statusbar);
+    }
+    else
+    {
+        list.vp.height = LCD_HEIGHT-4;
+        list.vp.y = 2;
+        remove_window(&statusbar);
+    }
+}
+/* this is the plugin entry point */
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
+{
+    (void)parameter;
+    rb = api;
+    push_window(&statusbar);
+    push_window(&list);
+    main_loop();
+    return PLUGIN_OK;
+}
Index: SOURCES
===================================================================
--- SOURCES	(revision 15984)
+++ SOURCES	(working copy)
@@ -7,6 +8,7 @@
 firmware_flash.c
 jackpot.c
 logo.c
+windowmanager.c
 mosaique.c
 properties.c
 random_folder_advance_config.c
