Usermode/AxWin3 - Splitting widget types out into separate files
authorJohn Hodge <[email protected]>
Thu, 17 Nov 2011 14:15:27 +0000 (22:15 +0800)
committerJohn Hodge <[email protected]>
Thu, 17 Nov 2011 14:15:27 +0000 (22:15 +0800)
27 files changed:
Usermode/Applications/axwin3_src/Interface/main.c
Usermode/Applications/axwin3_src/WM/Makefile
Usermode/Applications/axwin3_src/WM/decorator.c
Usermode/Applications/axwin3_src/WM/include/decorator.h
Usermode/Applications/axwin3_src/WM/include/wm.h
Usermode/Applications/axwin3_src/WM/include/wm_messages.h
Usermode/Applications/axwin3_src/WM/include/wm_renderer.h
Usermode/Applications/axwin3_src/WM/renderer_background.c [deleted file]
Usermode/Applications/axwin3_src/WM/renderer_classes.c [deleted file]
Usermode/Applications/axwin3_src/WM/renderer_menu.c [deleted file]
Usermode/Applications/axwin3_src/WM/renderer_passthru.c [deleted file]
Usermode/Applications/axwin3_src/WM/renderer_widget.c [deleted file]
Usermode/Applications/axwin3_src/WM/renderer_widget_decorator.c [deleted file]
Usermode/Applications/axwin3_src/WM/renderers/background.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/renderers/classes.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/renderers/menu.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/renderers/passthru.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/renderers/widget.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/renderers/widget/button.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/renderers/widget/colours.h [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/renderers/widget/common.h [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/renderers/widget/disptext.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/renderers/widget/image.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/renderers/widget/widget_decorator.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/wm.c
Usermode/Applications/axwin3_src/WM/wm_input.c

index 61ba4ac..d43845b 100644 (file)
@@ -11,7 +11,7 @@
 #include <axwin3/widget.h>
 #include <axwin3/menu.h>
 
-#define SIDEBAR_WIDTH  36
+#define SIDEBAR_WIDTH  40
 #define RUN_WIDTH      200
 #define RUN_HEIGHT     70
 
index 0e501e0..60669b7 100644 (file)
@@ -9,10 +9,15 @@ BIN := AxWinWM
 OBJ := main.o input.o video.o ipc.o image.o
 OBJ += wm.o wm_input.o wm_render.o wm_render_text.o
 OBJ += decorator.o
-OBJ += renderer_passthru.o
-OBJ += renderer_background.o
-OBJ += renderer_widget.o renderer_widget_decorator.o
-OBJ += renderer_menu.o
+OBJ += renderers/passthru.o
+OBJ += renderers/background.o
+OBJ += renderers/menu.o
+# TODO: Move to a lower makefile
+OBJ += renderers/widget.o renderers/widget/widget_decorator.o
+OBJ += renderers/widget/button.o
+OBJ += renderers/widget/image.o
+OBJ += renderers/widget/disptext.o
+OBJ += renderers/widget/textinput.o
 
 LDFLAGS += -limage_sif -luri -lnet
 
index 52ffbfb..d1e2461 100644 (file)
@@ -8,17 +8,19 @@
 #include <common.h>
 #include <wm.h>
 #include <decorator.h>
+#include <wm_messages.h>
 
 // === PROTOTYPES ===
 void   Decorator_UpdateBorderSize(tWindow *Window);
 void   Decorator_Redraw(tWindow *Window);
- int   Decorator_HandleMessage(tWindow *Window, int Message, int Length, void *Data);
+ int   Decorator_HandleMessage(tWindow *Window, int Message, int Length, const void *Data);
 
 // === CONSTANTS ===
 tColour        cColourActive_Titlebar   = 0xFF8800;
 tColour        cColourActive_TitleText  = 0x000000;
 tColour        cColourInactive_Titlebar = 0xD0D0D0;
 tColour        cColourInactive_TitleText= 0x000000;
+tColour        cColour_TitleTopBorder   = 0xFFFFFF;
 tColour        cColour_SideBorder       = 0xD0D0D0;
 tColour        cColour_BottomBorder     = 0xD0D0D0;
  int   ciTitlebarHeight        = 18;
@@ -54,6 +56,18 @@ void Decorator_Redraw(tWindow *Window)
                0, -ciTitlebarHeight, Window->W, ciTitlebarHeight,
                (bActive ? cColourActive_Titlebar : cColourInactive_Titlebar)
                );
+       WM_Render_FillRect(Window,
+               0, -ciTitlebarHeight, Window->W, 1,
+               cColour_TitleTopBorder
+               );
+       WM_Render_FillRect(Window,
+               0, -ciTitlebarHeight, 1, ciTitlebarHeight,
+               cColour_SideBorder
+               );
+       WM_Render_FillRect(Window,
+               Window->W, -ciTitlebarHeight, 1, ciTitlebarHeight,
+               cColour_SideBorder
+               );
 
        WM_Render_GetTextDims(
                NULL,   // TODO: Select font
@@ -92,10 +106,22 @@ void Decorator_Redraw(tWindow *Window)
                );
 }
 
-int Decorator_HandleMessage(tWindow *Window, int Message, int Length, void *Data)
+int Decorator_HandleMessage(tWindow *Window, int Message, int Length, const void *Data)
 {
        switch(Message)
        {
+       case WNDMSG_MOUSEMOVE: {
+               const struct sWndMsg_MouseMove  *msg = Data;
+               if(msg->Y >= 0) return 1;       // Pass
+               
+               // TODO: Handle
+               return 0; }
+       case WNDMSG_MOUSEBTN: {
+               const struct sWndMsg_MouseButton        *msg = Data;
+               if(msg->Y >= 0) return 1;       // Pass
+               
+               // TODO: Handle
+               return 0; }
        default:        // Anything unhandled is passed on
                return 1;
        }
index ae84cdb..2650584 100644 (file)
@@ -12,7 +12,7 @@
 
 extern void    Decorator_UpdateBorderSize(tWindow *Window);
 extern void    Decorator_Redraw(tWindow *Window);
-extern int     Decorator_HandleMessage(tWindow *Window, int Message, int Length, void *Data);
+extern int     Decorator_HandleMessage(tWindow *Window, int Message, int Length, const void *Data);
 
 #endif
 
index d35a462..1c0671f 100644 (file)
@@ -53,7 +53,7 @@ extern void   WM_ShowWindow(tWindow *Window, int bShow);
 extern void    WM_DecorateWindow(tWindow *Window, int bDecorate);
 extern int     WM_ResizeWindow(tWindow *Window, int W, int H);
 extern int     WM_MoveWindow(tWindow *Window, int X, int Y);
-extern int     WM_SendMessage(tWindow *Source, tWindow *Dest, int MessageID, int Length, void *Data);
+extern int     WM_SendMessage(tWindow *Source, tWindow *Dest, int MessageID, int Length, const void *Data);
 // --- Rendering
 extern void    WM_Render_FillRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour);
 extern void    WM_Render_DrawRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour);
index df20d77..a64ac99 100644 (file)
@@ -50,7 +50,7 @@ struct sWndMsg_MouseMove
 
 struct sWndMsg_MouseButton
 {
-       uint16_t        X, Y;
+        int16_t        X, Y;
        uint8_t         Button;
        uint8_t         bPressed;
 };
index b734348..5882549 100644 (file)
@@ -51,7 +51,7 @@ struct sWMRenderer
         * \param Data          Implementation defined data buffer
         * \return Boolean failure (0: Handled, 1: Unhandled)
         */
-        int    (*HandleMessage)(tWindow *Window, int MessageID, int Length, void *Data);
+        int    (*HandleMessage)(tWindow *Window, int MessageID, int Length, const void *Data);
 };
 
 extern void    WM_RegisterRenderer(tWMRenderer *Renderer);
diff --git a/Usermode/Applications/axwin3_src/WM/renderer_background.c b/Usermode/Applications/axwin3_src/WM/renderer_background.c
deleted file mode 100644 (file)
index 7772cdd..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Acess2 Window Manager v3
- * - By John Hodge (thePowersGang)
- *
- * render_widget.c
- * - AxWin2 Background port
- */
-#include <common.h>
-#include <wm_renderer.h>
-
-// === TYPES ===
-
-// === STRUCTURES ===
-struct sBgWin
-{
-       uint32_t        Colour;
-};
-
-// === PROTOTYPES ===
-tWindow        *Renderer_Background_Create(int Flags);
-void   Renderer_Background_Redraw(tWindow *Window);
-int    Renderer_Background_HandleMessage(tWindow *Target, int Msg, int Len, void *Data);
-
-// === GLOBALS ===
-tWMRenderer    gRenderer_Background = {
-       .Name = "Background",
-       .CreateWindow = Renderer_Background_Create,
-       .Redraw = Renderer_Background_Redraw,
-       .HandleMessage = Renderer_Background_HandleMessage
-};
-
-// === CODE ===
-int Renderer_Background_Init(void)
-{
-       WM_RegisterRenderer(&gRenderer_Background);     
-
-       return 0;
-}
-
-tWindow        *Renderer_Background_Create(int Arg)
-{
-       tWindow *ret;
-       ret = WM_CreateWindowStruct( sizeof(struct sBgWin) );
-       
-       ((struct sBgWin*)ret->RendererInfo)->Colour = Arg;
-       
-       return ret;
-}
-
-void Renderer_Background_Redraw(tWindow *Window)
-{
-       struct sBgWin   *info = Window->RendererInfo;
-       
-       WM_Render_FillRect(Window, 0, 0, 0xFFFF, 0xFFFF, info->Colour);
-}
-
-int Renderer_Background_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
-{
-       switch(Msg)
-       {
-       // TODO: Handle resize
-       
-       default:
-               break;
-       }
-       return 0;
-}
-
-
-
-
diff --git a/Usermode/Applications/axwin3_src/WM/renderer_classes.c b/Usermode/Applications/axwin3_src/WM/renderer_classes.c
deleted file mode 100644 (file)
index 4b0f3c6..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Acess2 Window Manager v3
- * - By John Hodge (thePowersGang)
- *
- * render_classes.c
- * - Simple class based window renderer
- */
-#include <common.h>
-#include <wm_renderer.h>
-#include <renderer_classful.h>
-
-// === TYPES ===
-typedef struct sClassfulInfo
-{
-       tColour BGColour;
-} tClassfulInfo;
-
-// === PROTOTYPES ===
-tWindow        *Renderer_Class_Create(int Flags);
-void   Renderer_Class_Redraw(tWindow *Window);
-int    Renderer_Class_HandleMessage(tWindow *Target, int Msg, int Len, void *Data);
-
-// === GLOBALS ===
-tWMRenderer    gRenderer_Class = {
-       .Name = "Classful",
-       .CreateWindow = Renderer_Class_Create,
-       .Redraw = Renderer_Class_Redraw,
-       .HandleMessage = Renderer_Class_HandleMessage
-};
-
-// === CODE ===
-int Renderer_Class_Init(void)
-{
-       WM_RegisterRenderer(&gRenderer_Class);  
-
-       return 0;
-}
-
-tWindow        *Renderer_Class_Create(int Flags)
-{
-       return WM_CreateWindowStruct(sizeof(tClassfulInfo));
-}
-
-void Renderer_Class_Redraw(tWindow *Window)
-{
-       tClassfulInfo   *info = Window->RendererInfo;
-       WM_Render_FillRect(Window, 0, 0, Window->W, Window->H, info->BGColour);
-}
-
-int Renderer_Class_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
-{
-       tClassfulInfo   *info = Target->RendererInfo;
-       switch(Msg)
-       {
-       case MSG_CLASSFUL_SETBGCOLOUR:
-               if( Len != sizeof(uint32_t) ) return -1;
-               info->BGColour = *(uint32_t*)Data;
-               return 0;
-
-       case MSG_CLASSFUL_SETTEXT:
-               
-               return -1;
-       
-       // Anything else is unhandled
-       default:
-               return 1;
-       }
-}
-
diff --git a/Usermode/Applications/axwin3_src/WM/renderer_menu.c b/Usermode/Applications/axwin3_src/WM/renderer_menu.c
deleted file mode 100644 (file)
index 45c6a24..0000000
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Acess2 Window Manager v3
- * - By John Hodge (thePowersGang)
- *
- * render_menu.c
- * - Pop-up menu window class/renderer
- */
-#include <common.h>
-#include <wm_renderer.h>
-#include <menu_messages.h>
-#include <wm_messages.h>
-#include <stdlib.h>
-#include <string.h>
-
-// === STRUCTURES ===
-typedef struct sMenuItem
-{
-       // Settings
-       char    *Label;
-       char    *Shortcut;
-        int    KeyOffset;
-        int    Flags;
-       
-       // Cached values
-        int    LabelWidth;     
-        int    ShortcutWidth;
-        int    UnderlineX;
-        int    UnderlineW;
-
-       char    Data[];
-} tMenuItem;
-
-typedef struct sMenuWindowInfo
-{
-        int    MaxLabelWidth;
-        int    MaxShortcutWidth;
-        int    CachedW;
-
-        int    HilightedItem;  
-
-        int    MaxItems;
-        int    nItems;
-       tMenuItem       *Items[];
-} tMenuWindowInfo;
-
-// === PROTOTYPES ===
-void   Renderer_Menu_Init(void);
-tWindow        *Renderer_Menu_Create(int Argument);
-void   Renderer_Menu_Redraw(tWindow *Window);
- int   Renderer_Menu_HandleMessage(tWindow *Window, int Msg, int Length, void *Data);
-
-// === CONSTANTS ===
-const int      ciMenu_Gap = 10;        // Gap between label and shortcut
-const int      ciMenu_TopPadding = 2;
-const int      ciMenu_BottomPadding = 2;
-const int      ciMenu_LeftPadding = 2;
-const int      ciMenu_RightPadding = 2;
-const int      ciMenu_FontHeight = 16;
-const int      ciMenu_ItemHeight = 20;
-const int      ciMenu_SpacerHeight = 5;
-const tColour  cMenu_BackgroundColour = 0xCCCCCC;
-const tColour  cMenu_BorderColour   = 0x000000;
-const tColour  cMenu_SpacerColour   = 0x404040;
-const tColour  cMenu_LabelColour    = 0x000000;
-const tColour  cMenu_ShortcutColour = 0x404040;
-const tColour  cMenu_HilightColour  = 0xE0E0E0;
-
-// === GLOBALS ===
-tWMRenderer    gRenderer_Menu = {
-       .Name = "Menu",
-       .CreateWindow = Renderer_Menu_Create,
-       .Redraw = Renderer_Menu_Redraw,
-       .HandleMessage = Renderer_Menu_HandleMessage
-};
-tFont  *gMenu_Font = NULL;     // System monospace
-
-// === CODE ===
-void Renderer_Menu_Init(void)
-{
-       WM_RegisterRenderer(&gRenderer_Menu);
-}
-
-tWindow        *Renderer_Menu_Create(int Argument)
-{
-       tWindow *ret;
-       tMenuWindowInfo *info;
-
-       if(Argument < 5)        Argument = 5;
-       if(Argument > 200)      Argument = 200; 
-
-       ret = WM_CreateWindowStruct(sizeof(*info) + Argument*sizeof(info->Items[0]));
-       info = ret->RendererInfo;
-       info->MaxItems = Argument;
-       info->HilightedItem = -1;
-
-       ret->Flags |= WINFLAG_NODECORATE;
-       ret->H = ciMenu_TopPadding + ciMenu_BottomPadding;
-
-//     _SysDebug("Renderer_Menu_Create: ->MaxItems = %i", info->MaxItems);
-       
-       return ret;
-}
-
-void Renderer_Menu_Redraw(tWindow *Window)
-{
-       tMenuWindowInfo *info = Window->RendererInfo;
-        int    w, h, y, i;
-
-       w = info->CachedW;
-       #if 0
-       h = ciMenu_TopPadding + ciMenu_BottomPadding;
-       for( i = 0; i < info->nItems; i ++ )
-       {
-               if( !info->Items[i] )   continue;
-               
-               if(info->Items[i]->Label)
-                       h += ciMenu_ItemHeight;
-               else
-                       h += ciMenu_SpacerHeight;
-       }
-       #else
-       h = Window->H;
-       #endif
-
-//     _SysDebug("w = %i, h = %i", w, h);
-
-       // - Move the window such that it is on screen
-       //  > Make sure to catch if the menu can't fit fully onscreen
-
-       // - Clear
-       WM_Render_FillRect(Window, 0, 0, w, h, cMenu_BackgroundColour);
-       WM_Render_DrawRect(Window, 0, 0, w, h, cMenu_BorderColour);
-
-       // - Render each item
-       y = ciMenu_TopPadding;
-       for( i = 0; i < info->nItems; i ++ )
-       {
-               tMenuItem       *item = info->Items[i];
-               
-               // Unused slot
-               if(!item)       continue;
-               
-               // Spacer
-               if(!item->Label)
-               {
-                       WM_Render_FillRect(Window,
-                               1, y + ciMenu_SpacerHeight/2,
-                               w-2, 1,
-                               cMenu_SpacerColour
-                               );
-                       y += ciMenu_SpacerHeight;
-                       continue ;
-               }
-       
-               // Hilight
-               if( info->HilightedItem == i )
-               {
-                       WM_Render_FillRect(Window,
-                               1, y,
-                               w-2, ciMenu_ItemHeight,
-                               cMenu_HilightColour
-                               );
-               }
-       
-               // Text
-               WM_Render_DrawText(Window,
-                       ciMenu_LeftPadding, y,
-                       w, ciMenu_ItemHeight,
-                       gMenu_Font,
-                       cMenu_LabelColour,
-                       item->Label
-                       );
-               // Underline
-               if(item->UnderlineW)
-               {
-                       WM_Render_FillRect(Window,
-                               ciMenu_LeftPadding + item->UnderlineX, y + ciMenu_FontHeight,
-                               item->UnderlineW, 1,
-                               cMenu_LabelColour
-                               );
-               }
-               
-               // Shortcut key
-               if(item->Shortcut)
-               {
-                       WM_Render_DrawText(Window,
-                               w - item->ShortcutWidth - ciMenu_RightPadding, y,
-                               w, ciMenu_ItemHeight,
-                               gMenu_Font,
-                               cMenu_ShortcutColour,
-                               item->Shortcut
-                               );
-               }
-               
-               y += ciMenu_ItemHeight;
-       }
-}
-
-int Renderer_Menu_int_AddItem(tWindow *Window, int Length, void *Data)
-{
-       tMenuWindowInfo *info = Window->RendererInfo;
-       tMenuMsg_AddItem        *req = Data;
-       tMenuItem       *item;
-       
-       // Sanity checking
-       // - Message length
-       if(Length < sizeof(*req) + 1 || req->Label[Length-sizeof(*req)-1] != '\0') {
-               _SysDebug("Renderer_Menu_int_AddItem: Size checks failed");
-               return -1;
-       }
-       // - ID Number
-       if(req->ID >= info->MaxItems) {
-               _SysDebug("Renderer_Menu_int_AddItem: ID (%i) >= MaxItems (%i)",
-                       req->ID, info->MaxItems);
-               return -1;
-       }
-       
-       // Don't overwrite
-       if(info->Items[req->ID]) {
-               _SysDebug("- Caught overwrite of %i", req->ID);
-               return 0;
-       }
-       // Bookkeeping
-       if(req->ID >= info->nItems)     info->nItems = req->ID + 1;
-       // Allocate
-       item = malloc(sizeof(tMenuItem)+strlen(req->Label));
-       info->Items[req->ID] = item;
-       
-       if(req->Label[0] == '\0')
-       {
-               // Spacer
-               item->Label = NULL;
-               WM_ResizeWindow(Window, info->CachedW, Window->H+ciMenu_SpacerHeight);
-               
-               return 0;
-       }
-       
-       // Actual item
-       char    *dest = item->Data;
-       char    *src = req->Label;
-        int    ofs = 0;
-
-       // - Main label
-       item->KeyOffset = -1;
-       item->Label = dest;
-       for(ofs = 0; *src && *src != '\t'; ofs ++)
-       {
-               if(*src == '&') {
-                       *dest = '\0';
-                       item->KeyOffset = ofs;
-                       src ++;
-               }
-               else {
-                       *dest++ = *src++;
-               }
-       }
-       *dest++ = '\0';
-       // - Key combo / Shortcut
-       if(*src)
-       {
-               src ++;
-               item->Shortcut = dest;
-               strcpy(item->Shortcut, src);
-       }
-       else
-       {
-               item->Shortcut = NULL;
-       }
-       
-       // Get dimensions
-       // - Underline (hotkey)
-       if(item->KeyOffset == -1)
-       {
-               item->UnderlineX = 0;
-               item->UnderlineW = 0;
-       }
-       else
-       {
-               char    tmp = item->Label[item->KeyOffset];
-               // Get width of preceding substring
-               item->Label[item->KeyOffset] = '\0';
-               WM_Render_GetTextDims(NULL, item->Label, &item->UnderlineX, NULL);
-               // Get the width of the underlined character
-               // TODO: Fix for high UTF-8 characters
-               item->Label[item->KeyOffset] = tmp;
-               tmp = item->Label[item->KeyOffset+1];
-               item->Label[item->KeyOffset+1] = '\0';
-               WM_Render_GetTextDims(
-                       NULL, item->Label+item->KeyOffset,
-                       &item->UnderlineW, NULL
-                       );
-               item->Label[item->KeyOffset+1] = tmp;
-       }
-       // - Labels
-       WM_Render_GetTextDims(NULL, item->Label, &item->LabelWidth, NULL);
-       if(item->Shortcut)
-               WM_Render_GetTextDims(NULL, item->Shortcut, &item->ShortcutWidth, NULL);
-       else
-               item->ShortcutWidth = 0;
-       
-       if( item->LabelWidth > info->MaxLabelWidth )
-               info->MaxLabelWidth = item->LabelWidth;
-       if( item->ShortcutWidth > info->MaxShortcutWidth )
-               info->MaxShortcutWidth = item->ShortcutWidth;
-       
-       if( info->MaxLabelWidth + info->MaxShortcutWidth + ciMenu_Gap > info->CachedW )
-       {
-               info->CachedW = ciMenu_LeftPadding + info->MaxLabelWidth
-                       + ciMenu_Gap + info->MaxShortcutWidth
-                       + ciMenu_RightPadding;
-       }
-       WM_ResizeWindow(Window, info->CachedW, Window->H+ciMenu_ItemHeight);
-       
-       return 0;
-}
-
-int Renderer_Menu_int_GetItemByPos(tWindow *Window, tMenuWindowInfo *Info, int X, int Y)
-{
-        int    i;
-
-       if( X < 0 || X >= Window->W )
-               return -1;
-       
-       for( i = 0; i < Info->nItems; i ++ )
-       {
-               if( !Info->Items[i] )   continue;
-                       
-               if( !Info->Items[i]->Label )
-               {
-                       // Spacer - not selectable
-                       if(Y < ciMenu_SpacerHeight) {
-                               return -1;
-                       }
-                       Y -= ciMenu_SpacerHeight;
-               }
-               else
-               {
-                       // Normal item, can be selected/hilighted
-                       if(Y < ciMenu_ItemHeight) {
-                               return i;
-                       }
-                       Y -= ciMenu_ItemHeight;
-               }
-       }
-       return -1;
-}
-
-int Renderer_Menu_HandleMessage(tWindow *Window, int Msg, int Length, void *Data)
-{
-       tMenuWindowInfo *info = Window->RendererInfo;
-       switch(Msg)
-       {
-       case WNDMSG_SHOW: {
-               struct sWndMsg_Bool     *msg = Data;
-               if(Length < sizeof(*msg))       return -1;
-               if(msg->Val)
-               {
-//                     _SysDebug(" - Shown, take focus");
-                       // TODO: This shouldn't really be done, instead focus should be given
-                       //       when the menu is shown.
-//                     WM_FocusWindow(Window);
-               }
-               else
-               {
-                       // Hide Children
-                       _SysDebug("- Hidden, hide the children!");
-               }
-               return 0; }
-       case WNDMSG_FOCUS: {
-               struct sWndMsg_Bool     *msg = Data;
-               if(Length < sizeof(*msg))       return -1;
-               if(!msg->Val) {
-                       // TODO: Catch if focus was given away to a child
-                       _SysDebug("- Lost focus");
-                       WM_ShowWindow(Window, 0);       // Hide!
-               }
-               else {
-                       _SysDebug("- Focus gained, TODO: Show accel keys");
-               }
-               return 0; }
-
-       case WNDMSG_MOUSEBTN: {
-               struct sWndMsg_MouseButton      *msg = Data;
-                int    item;
-               
-               if(Length < sizeof(*msg))       return -1;
-
-               if(msg->Button == 0 && msg->bPressed == 0)
-               {
-                       item = Renderer_Menu_int_GetItemByPos(Window, info, msg->X, msg->Y);
-                       if(item != -1)
-                       {
-                               tMenuMsg_Select _msg;
-                               // TODO: Ignore sub-menus too
-                               _msg.ID = item;
-                               WM_SendMessage(Window, Window, MSG_MENU_SELECT, sizeof(_msg), &_msg);
-                               WM_ShowWindow(Window, 0);
-                       }
-               }
-                               
-
-               return 0; }     
-
-       case WNDMSG_MOUSEMOVE: {
-               struct sWndMsg_MouseMove        *msg = Data;
-                int    new_hilight;
-
-               if(Length < sizeof(*msg))       return -1;
-
-               new_hilight = Renderer_Menu_int_GetItemByPos(Window, info, msg->X, msg->Y);
-
-               if( new_hilight != info->HilightedItem )
-               {
-                       info->HilightedItem = new_hilight;
-                       // TODO: Change sub-menu
-                       WM_Invalidate(Window);
-               }
-
-               return 0; }
-
-       // Manipulation messages
-       case MSG_MENU_ADDITEM:
-//             _SysDebug("MSG_MENU_ADDITEM");
-               return Renderer_Menu_int_AddItem(Window, Length, Data);
-       
-       // Only message to pass to client
-       case MSG_MENU_SELECT:
-               return 1;
-       }
-       return 0;
-}
-
diff --git a/Usermode/Applications/axwin3_src/WM/renderer_passthru.c b/Usermode/Applications/axwin3_src/WM/renderer_passthru.c
deleted file mode 100644 (file)
index 6e16e6a..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Acess2 Window Manager v3
- * - By John Hodge (thePowersGang)
- *
- * renderer_passthru.c
- * - Passthrough window render (framebuffer essentially)
- */
-#include <common.h>
-#include <wm_renderer.h>
-
-// === PROTOTYPES ===
-tWindow        *Renderer_Passthru_Create(int Flags);
-void   Renderer_Passthru_Redraw(tWindow *Window);
- int   Renderer_Passthru_HandleMessage(tWindow *Target, int Msg, int Len, void *Data);
-
-// === GLOBALS ===
-tWMRenderer    gRenderer_Passthru = {
-       .Name = "Passthru",
-       .CreateWindow = Renderer_Passthru_Create,
-       .Redraw = Renderer_Passthru_Redraw,
-       .HandleMessage = Renderer_Passthru_HandleMessage
-};
-
-// === CODE ===
-int Renderer_Passthru_Init(void)
-{
-       return 0;
-}
-
-tWindow        *Renderer_Passthru_Create(int Flags)
-{
-       return NULL;
-}
-
-void Renderer_Passthru_Redraw(tWindow *Window)
-{
-       
-}
-
-int Renderer_Passthru_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
-{
-       return 1;
-}
-
-
diff --git a/Usermode/Applications/axwin3_src/WM/renderer_widget.c b/Usermode/Applications/axwin3_src/WM/renderer_widget.c
deleted file mode 100644 (file)
index c4799e9..0000000
+++ /dev/null
@@ -1,680 +0,0 @@
-/*
- * Acess2 Window Manager v3
- * - By John Hodge (thePowersGang)
- *
- * render_widget.c
- * - AxWin2 Widget port
- */
-#include <common.h>
-#include <wm_renderer.h>
-#include <renderer_widget.h>
-#include <string.h>
-#include <wm_messages.h>
-#include <stdlib.h>
-#include "include/image.h"
-
-#define DEFAULT_ELETABLE_SIZE  64
-
-// === PROTOTYPES ===
- int   Renderer_Widget_Init(void);
-tWindow        *Renderer_Widget_Create(int Flags);
-void   Renderer_Widget_Redraw(tWindow *Window);
-
-void   Widget_RenderWidget(tWindow *Window, tElement *Element);
-void   Widget_UpdateDimensions(tElement *Element);
-void   Widget_UpdatePosition(tElement *Element);
-// --- Messages
-tElement       *Widget_GetElementById(tWidgetWin *Info, uint32_t ID);
-void   Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg);
-void   Widget_SetFlags(tWidgetWin *Info, int Len, tWidgetMsg_SetFlags *Msg);
-void   Widget_SetSize(tWidgetWin *Info, int Len, tWidgetMsg_SetSize *Msg);
-void   Widget_SetText(tWidgetWin *Info, int Len, tWidgetMsg_SetText *Msg);
- int   Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data);
-// --- Type helpers
-void   Widget_DispText_UpdateText(tElement *Element, const char *Text);
-void   Widget_Image_UpdateText(tElement *Element, const char *Text);
- int   Widget_Button_MouseButton(tElement *Element, int X, int Y, int Button, int bPress);
-void   Widget_TextInput_Init(tElement *Element);
-
-// === GLOBALS ===
-tWMRenderer    gRenderer_Widget = {
-       .Name = "Widget",
-       .CreateWindow = Renderer_Widget_Create,
-       .Redraw = Renderer_Widget_Redraw,
-       .HandleMessage = Renderer_Widget_HandleMessage
-};
-       
-// --- Element callbacks
-struct {
-       void    (*Init)(tElement *Ele);
-       void    (*Delete)(tElement *Ele);
-       
-       void    (*UpdateFlags)(tElement *Ele);
-       void    (*UpdateSize)(tElement *Ele);
-       void    (*UpdateText)(tElement *Ele, const char *Text); // This should update Ele->Text
-
-       /**
-        * \name Input handlers
-        * \note Returns boolean unhandled
-        * \{
-        */     
-        int    (*MouseButton)(tElement *Ele, int X, int Y, int Button, int bPressed);
-        int    (*MouseMove)(tElement *Ele, int X, int Y);
-        int    (*KeyDown)(tElement *Ele, int KeySym, int Character);
-        int    (*KeyUp)(tElement *Ele, int KeySym);
-        int    (*KeyFire)(tElement *Ele, int KeySym, int Character);
-       /**
-        * \}
-        */
-}      gaWM_WidgetTypes[NUM_ELETYPES] = {
-       {0},    // NULL
-       {0},    // Box
-       {.UpdateText = Widget_DispText_UpdateText},     // Text
-       {.UpdateText = Widget_Image_UpdateText},        // Image
-       {.MouseButton = Widget_Button_MouseButton},     // Button
-       {0},    // Spacer
-       {.Init = Widget_TextInput_Init},        // Text Box (Single Line)
-};
-const int      ciWM_NumWidgetTypes = sizeof(gaWM_WidgetTypes)/sizeof(gaWM_WidgetTypes[0]);
-
-// === CODE ===
-int Renderer_Widget_Init(void)
-{
-       WM_RegisterRenderer(&gRenderer_Widget); 
-
-       return 0;
-}
-
-tWindow        *Renderer_Widget_Create(int Flags)
-{
-       tWindow *ret;
-       tWidgetWin      *info;
-        int    eletable_size = DEFAULT_ELETABLE_SIZE;
-
-       _SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
-
-       // TODO: Use `Flags` as default element count?
-       // - Actaully, it's taken by the root ele flags
-       // - Use the upper bits?
-
-       ret = WM_CreateWindowStruct( sizeof(tWidgetWin) + sizeof(tElement*)*eletable_size );
-       info = ret->RendererInfo;
-       
-       info->TableSize = eletable_size;
-       info->RootElement.Window = ret;
-       info->RootElement.ID = -1;
-       info->RootElement.BackgroundColour = 0xCCCCCC;
-       info->RootElement.Flags = Flags;
-       
-       return ret;
-}
-
-void Renderer_Widget_Redraw(tWindow *Window)
-{
-       tWidgetWin      *info = Window->RendererInfo;
-       WM_Render_FillRect(Window, 0, 0, 0xFFF, 0xFFF, info->RootElement.BackgroundColour);
-
-       Widget_UpdateDimensions(&info->RootElement);
-       Widget_UpdatePosition(&info->RootElement);
-
-       Widget_RenderWidget(Window, &info->RootElement);
-}
-
-// --- Render / Resize ---
-void Widget_RenderWidget(tWindow *Window, tElement *Element)
-{
-       tElement        *child;
-       
-       if( Element->Flags & ELEFLAG_NORENDER ) return ;
-       if( Element->Flags & ELEFLAG_INVISIBLE )        return ;
-       
-       Widget_Decorator_RenderWidget(Window, Element);
-       
-       for(child = Element->FirstChild; child; child = child->NextSibling)
-       {
-               Widget_RenderWidget(Window, child);
-       }
-}
-
-void Widget_UpdateDimensions(tElement *Element)
-{
-       tElement        *child;
-        int    nChildren = 0;
-        int    nFixed = 0;
-        int    maxCross = 0;
-        int    fixedSize = 0;
-        int    fullCross, dynWith;
-       
-       // Pass 1
-       // - Get the fixed and minimum sizes of the element
-       for( child = Element->FirstChild; child; child = child->NextSibling )
-       {
-               // Ignore elements that will not be rendered
-               if( child->Flags & ELEFLAG_NORENDER )   continue ;
-               
-               // Absolutely positioned elements don't affect dimensions
-               if( child->Flags & ELEFLAG_ABSOLUTEPOS )        continue ;
-       
-               // Fixed width elements 
-               if( child->FixedWith )
-               {
-                       nFixed ++;
-                       fixedSize += child->FixedWith;
-               }
-               else if( child->Flags & ELEFLAG_NOSTRETCH )
-               {
-                       nFixed ++;
-                       fixedSize += child->MinWith;
-               }
-               
-               if( child->FixedCross && maxCross < child->FixedCross )
-                       maxCross = child->FixedCross;
-               if( child->MinCross && maxCross < child->MinCross )
-                       maxCross = child->MinCross;
-               nChildren ++;
-       }
-
-       // Get the dynamic with size from the unused space in the element
-       if( nChildren > nFixed ) {
-               if( Element->Flags & ELEFLAG_VERTICAL )
-                       dynWith = Element->CachedH - Element->PaddingT - Element->PaddingB;
-               else
-                       dynWith = Element->CachedW - Element->PaddingL - Element->PaddingR;
-               dynWith -= fixedSize;
-               if( dynWith < 0 )       return ;
-               dynWith /= nChildren - nFixed;
-       }
-       
-//     _SysDebug("%i - nChildren = %i, nFixed = %i, dynWith = %i, fixedSize = %i",
-//             Element->ID, nChildren, nFixed, dynWith, fixedSize);
-
-       // Get the cross size
-       if( Element->Flags & ELEFLAG_VERTICAL )
-               fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
-       else
-               fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
-       
-       // Pass 2 - Set sizes and recurse
-       for( child = Element->FirstChild; child; child = child->NextSibling )
-       {
-                int    cross, with;
-
-               // Ignore elements that will not be rendered
-               if( child->Flags & ELEFLAG_NORENDER )   continue ;
-               
-               // --- Cross Size ---
-               // TODO: Expand to fill?
-               // TODO: Extra flag so options are (Expand, Equal, Wrap)
-               if( child->FixedCross )
-                       cross = child->FixedCross;
-               else if( child->Flags & ELEFLAG_NOEXPAND )
-                       cross = child->MinCross;
-               else
-                       cross = fullCross;
-               
-               // --- With Size ---
-               if( child->FixedWith )
-                       with = child->FixedWith;
-               else if( child->Flags & ELEFLAG_NOSTRETCH )
-                       with = child->MinWith;
-               else
-                       with = dynWith;
-       
-
-               if(with < child->MinWith)       with = child->MinWith;
-               if(cross < child->MinCross)     cross = child->MinCross;
-               
-               // Update the dimensions if they have changed
-               if( Element->Flags & ELEFLAG_VERTICAL ) {
-                       // If no change, don't recurse
-                       if( child->CachedW == cross && child->CachedH == with )
-                               continue ;
-                       child->CachedW = cross;
-                       child->CachedH = with;
-               }
-               else {
-                       // If no change, don't recurse
-                       if( child->CachedW == with && child->CachedH == cross )
-                               continue ;
-                       child->CachedW = with;
-                       child->CachedH = cross;
-               }
-               
-               // Force the positions of child elements to be recalculated
-               child->CachedX = -1;
-       
-               // Recurse down so the child elements can be updated    
-               Widget_UpdateDimensions(child);
-       }
-       
-}
-
-/**
- * \brief Update the position of child elements
- */
-void Widget_UpdatePosition(tElement *Element)
-{
-       tElement        *child;
-        int    x, y;
-       
-       if( Element->Flags & ELEFLAG_NORENDER ) return ;
-
-//     _SysDebug("Widget_UpdatePosition: (Element=%p(%i Type=%i Flags=0x%x))",
-//             Element, Element->ID, Element->Type, Element->Flags);
-       
-       // Initialise
-       x = Element->CachedX + Element->PaddingL;
-       y = Element->CachedY + Element->PaddingT;
-       
-       // Update each child
-       for(child = Element->FirstChild; child; child = child->NextSibling)
-       {
-                int    newX, newY;
-               // Ignore elements that will not be rendered
-               if( child->Flags & ELEFLAG_NORENDER )   continue ;
-
-               newX = x; newY = y;
-               
-               // Handle alignment
-               if( Element->Flags & ELEFLAG_ALIGN_CENTER ) {
-                       if(Element->Flags & ELEFLAG_VERTICAL)
-                               newX += Element->CachedW/2 - child->CachedW/2;
-                       else
-                               newY += Element->CachedH/2 - child->CachedH/2;
-               }
-               else if( Element->Flags & ELEFLAG_ALIGN_END ) {
-                       if(Element->Flags & ELEFLAG_VERTICAL )
-                               newX += Element->CachedW - child->CachedW
-                                       - Element->PaddingL - Element->PaddingR;
-                       else
-                               newY += Element->CachedH - child->CachedH
-                                       - Element->PaddingT - Element->PaddingB;
-               }
-
-//             _SysDebug(" Widget_UpdatePosition[%i]: newX = %i, newY = %i", Element->ID, newX, newY);
-
-               // Check for changes, and don't update if there was no change
-               if( newX != child->CachedX || newY != child->CachedY )
-               {
-                       child->CachedX = newX;
-                       child->CachedY = newY;
-                       // Update child's children positions
-                       Widget_UpdatePosition(child);
-               }
-               
-               // Increment
-               if(Element->Flags & ELEFLAG_VERTICAL ) {
-                       y += child->CachedH + Element->GapSize;
-               }
-               else {
-                       x += child->CachedW + Element->GapSize;
-               }
-       }
-}
-
-/**
- * \brief Update the minimum dimensions of the element
- * \note Called after a child's minimum dimensions have changed
- */
-void Widget_UpdateMinDims(tElement *Element)
-{
-       tElement        *child;
-       
-       if(!Element)    return;
-       
-       Element->MinCross = 0;
-       Element->MinWith = 0;
-       
-       for(child = Element->FirstChild; child; child = child->NextSibling)
-       {
-               if( Element->Parent &&
-                       (Element->Flags & ELEFLAG_VERTICAL) == (Element->Parent->Flags & ELEFLAG_VERTICAL)
-                       )
-               {
-                       if(child->FixedCross)
-                               Element->MinCross += child->FixedCross;
-                       else
-                               Element->MinCross += child->MinCross;
-                       if(child->FixedWith)
-                               Element->MinWith += child->FixedWith;
-                       else
-                               Element->MinWith += child->MinWith;
-               }
-               else
-               {
-                       if(child->FixedCross)
-                               Element->MinWith += child->FixedCross;
-                       else
-                               Element->MinWith += child->MinCross;
-                       if(child->FixedWith)
-                               Element->MinCross += child->FixedWith;
-                       else
-                               Element->MinCross += child->MinWith;
-               }
-       }
-       
-       // Recurse upwards
-       Widget_UpdateMinDims(Element->Parent);
-}
-
-tElement *Widget_GetElementByPos(tWidgetWin *Info, int X, int Y)
-{
-       tElement        *ret, *next, *ele;
-       
-       next = &Info->RootElement;
-       while(next)
-       {
-               ret = next;
-               next = NULL;
-               for(ele = ret->FirstChild; ele; ele = ele->NextSibling)
-               {
-                       if(ele->Flags & ELEFLAG_NORENDER)       continue;
-                       if(X < ele->CachedX)    continue;
-                       if(Y < ele->CachedY)    continue;
-                       if(X >= ele->CachedX + ele->CachedW)    continue;
-                       if(Y >= ele->CachedY + ele->CachedH)    continue;
-                       next = ele;
-               }
-       }
-       return ret;
-}
-
-// --- Helpers ---
-tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID)
-{
-       tElement        *ele;
-
-       if( ID == -1 )  return &Info->RootElement;
-       
-       if( ID < Info->TableSize )      return Info->ElementTable[ID];
-
-       ele = Info->ElementTable[ID % Info->TableSize];
-       while(ele && ele->ID != ID)     ele = ele->ListNext;
-       return ele;
-}
-
-// --- Message Handlers ---
-void Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg)
-{
-       const int       max_debugname_len = Len - sizeof(tWidgetMsg_Create);
-       tElement        *parent, *new;
-
-       // Sanity check
-       if( Len < sizeof(tWidgetMsg_Create) )
-               return ;
-       if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
-               return ;
-       
-       _SysDebug("Widget_NewWidget (%i %i Type %i Flags 0x%x)",
-               Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags);
-       
-       // Create
-       parent = Widget_GetElementById(Info, Msg->Parent);
-       if(!parent)
-       {
-               _SysDebug("Widget_NewWidget - Bad parent ID %i", Msg->Parent);
-               return ;
-       }
-
-       // Check if the ID is already in use
-       if( Widget_GetElementById(Info, Msg->NewID) )
-               return ;
-
-       // Create new element
-       new = calloc(sizeof(tElement), 1);
-       new->Window = parent->Window;
-       new->ID = Msg->NewID;
-       new->Type = Msg->Type;
-       new->Parent = parent;
-       new->Flags = Msg->Flags;
-       new->PaddingT = 2;
-       new->PaddingB = 2;
-       new->PaddingL = 2;
-       new->PaddingR = 2;
-       new->CachedX = -1;
-       
-       if( new->Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[new->Type].Init )
-               gaWM_WidgetTypes[new->Type].Init(new);
-       
-       // Add to parent's list
-       if(parent->LastChild)
-               parent->LastChild->NextSibling = new;
-       else
-               parent->FirstChild = new;
-       parent->LastChild = new;
-
-       // Add to info
-       {
-               tElement        *ele, *prev = NULL;
-               for(ele = Info->ElementTable[new->ID % Info->TableSize]; ele; prev = ele, ele = ele->ListNext);
-               if(prev)
-                       prev->ListNext = new;
-               else
-                       Info->ElementTable[new->ID % Info->TableSize] = new;
-       }
-
-       Widget_UpdateMinDims(parent);
-}
-
-void Widget_SetFlags(tWidgetWin *Info, int Len, tWidgetMsg_SetFlags *Msg)
-{
-       tElement        *ele;
-       
-       if( Len < sizeof(tWidgetMsg_SetFlags) )
-               return ;
-
-       _SysDebug("Widget_SetFlags: (%i 0x%x 0x%x)", Msg->WidgetID, Msg->Value, Msg->Mask);
-       
-       ele = Widget_GetElementById(Info, Msg->WidgetID);
-       if(!ele)        return;
-
-       Msg->Value &= Msg->Mask;
-       
-       ele->Flags &= ~Msg->Mask;
-       ele->Flags |= Msg->Value;
-}
-
-void Widget_SetSize(tWidgetWin *Info, int Len, tWidgetMsg_SetSize *Msg)
-{
-       tElement        *ele;
-       
-       if( Len < sizeof(tWidgetMsg_SetSize) )
-               return ;
-       
-       ele = Widget_GetElementById(Info, Msg->WidgetID);
-       if(!ele)        return ;
-       
-       ele->FixedWith = Msg->Value;
-}
-
-void Widget_SetText(tWidgetWin *Info, int Len, tWidgetMsg_SetText *Msg)
-{
-       tElement        *ele;
-       
-       if( Len < sizeof(tWidgetMsg_SetText) + 1 )
-               return ;
-       if( Msg->Text[Len - sizeof(tWidgetMsg_SetText) - 1] != '\0' )
-               return ;
-
-       ele = Widget_GetElementById(Info, Msg->WidgetID);
-       if(!ele)        return ;
-
-
-       if( ele->Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[ele->Type].UpdateText )
-       {
-               gaWM_WidgetTypes[ele->Type].UpdateText( ele, Msg->Text );
-       }
-//     else
-//     {
-//             if(ele->Text)   free(ele->Text);
-//             ele->Text = strdup(Msg->Text);
-//     }
-}
-
-int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
-{
-       tWidgetWin      *info = Target->RendererInfo;
-       switch(Msg)
-       {
-       case WNDMSG_RESIZE: {
-               struct sWndMsg_Resize   *msg = Data;
-               if(Len < sizeof(*msg))  return -1;              
-
-               info->RootElement.CachedW = msg->W;             
-               info->RootElement.CachedH = msg->H;
-               
-               // TODO: Update dimensions of all child elements?
-               
-               return 0; }
-
-       case WNDMSG_MOUSEMOVE: {
-               _SysDebug("TODO: Support widget mouse move events");
-               return 0; }
-
-       case WNDMSG_MOUSEBTN: {
-               struct sWndMsg_MouseButton      *msg = Data;
-               tWidgetMsg_MouseBtn     client_msg;
-               tElement        *ele;
-                int    x, y;
-                int    rv;
-               
-               if(Len < sizeof(*msg))  return -1;
-
-               x = msg->X; y = msg->Y;
-               client_msg.Button = msg->Button;
-               client_msg.bPressed = msg->bPressed;
-
-               ele = Widget_GetElementByPos(info, x, y);
-               // Send event to all elements from `ele` upwards
-               for( ; ele; ele = ele->Parent )
-               {
-                       if(ele->Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[ele->Type].MouseButton)
-                       {
-                               rv = gaWM_WidgetTypes[ele->Type].MouseButton(
-                                       ele,
-                                       x - ele->CachedX, y - ele->CachedY,
-                                       msg->Button, msg->bPressed
-                                       );
-                               // Allow a type to trap the input from going any higher
-                               if(rv == 0)     break;
-                       }
-                       else
-                       {
-                               // Pass to user
-                               client_msg.X = x - ele->CachedX;
-                               client_msg.Y = y - ele->CachedY;
-                               client_msg.WidgetID = ele->ID;
-                               WM_SendMessage(Target, Target, MSG_WIDGET_MOUSEBTN, sizeof(client_msg), &client_msg);
-                       }
-               }
-               return 0; }
-
-       // New Widget
-       case MSG_WIDGET_CREATE:
-               Widget_NewWidget(info, Len, Data);
-               return 0;
-
-       case MSG_WIDGET_DELETE:
-               _SysDebug("TODO: Implement MSG_WIDGET_DELETE");
-               return 0;
-
-       // Set Flags
-       case MSG_WIDGET_SETFLAGS:
-               Widget_SetFlags(info, Len, Data);
-               return 0;
-       
-       // Set length
-       case MSG_WIDGET_SETSIZE:
-               Widget_SetSize(info, Len, Data);
-               return 0;
-       
-       // Set text
-       case MSG_WIDGET_SETTEXT:
-               Widget_SetText(info, Len, Data);
-               return 0;
-       
-       // 
-       default:
-               return 1;       // Unhandled, pass to user
-       }
-}
-
-void Widget_Fire(tElement *Element)
-{
-       tWidgetMsg_Fire msg;
-       msg.WidgetID = Element->ID;
-       WM_SendMessage(Element->Window, Element->Window, MSG_WIDGET_FIRE, sizeof(msg), &msg);
-}
-
-// --- Type Helpers
-void Widget_DispText_UpdateText(tElement *Element, const char *Text)
-{
-        int    w=0, h=0;
-
-       if(Element->Text)       free(Element->Text);
-       Element->Text = strdup(Text);
-
-       WM_Render_GetTextDims(NULL, Element->Text, &w, &h);
-       if(Element->Parent && (Element->Parent->Flags & ELEFLAG_VERTICAL)) {
-               Element->MinCross = w;
-               Element->MinWith = h;
-       }
-       else {
-               Element->MinWith = w;
-               Element->MinCross = h;
-       }
-
-       Widget_UpdateMinDims(Element->Parent);
-}
-
-void Widget_Image_UpdateText(tElement *Element, const char *Text)
-{
-       if(Element->Data)       free(Element->Data);
-       Element->Data = Image_Load( Text );
-       if(!Element->Data) {
-//             Element->Flags &= ~ELEFLAG_FIXEDSIZE;
-               return ;
-       }
-       
-       Element->CachedW = ((tImage*)Element->Data)->Width;
-       Element->CachedH = ((tImage*)Element->Data)->Height;
-       
-       if(Element->Parent && (Element->Parent->Flags & ELEFLAG_VERTICAL) ) {
-               Element->MinCross = ((tImage*)Element->Data)->Width;
-               Element->MinWith = ((tImage*)Element->Data)->Height;
-       }
-       else {
-               Element->MinWith = ((tImage*)Element->Data)->Width;
-               Element->MinCross = ((tImage*)Element->Data)->Height;
-       }
-
-       Widget_UpdateMinDims(Element->Parent);
-       
-       // NOTE: Doesn't update Element->Text because it's useless
-}
-
-int Widget_Button_MouseButton(tElement *Element, int X, int Y, int Button, int bPress)
-{
-       _SysDebug("Ele %i - Button %i %s",
-               Element->ID, Button,
-               (bPress ? "pressed" : "released")
-               );
-       if(!bPress)     Widget_Fire(Element);
-       return 0;       // Handled
-}
-
-void Widget_TextInput_Init(tElement *Element)
-{
-        int    h;
-
-       // TODO: Select font correctly  
-       WM_Render_GetTextDims(NULL, "jJ", NULL, &h);
-       
-       if( Element->Parent && (Element->Parent->Flags & ELEFLAG_VERTICAL) )
-               Element->MinWith = h;
-       else
-               Element->MinCross = h;
-
-       // No need to explicitly update parent min dims, as the AddElement routine does that    
-}
-
diff --git a/Usermode/Applications/axwin3_src/WM/renderer_widget_decorator.c b/Usermode/Applications/axwin3_src/WM/renderer_widget_decorator.c
deleted file mode 100644 (file)
index 8f6309f..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Acess2 Window Manager v3
- * - By John Hodge (thePowersGang)
- * 
- * renderer_widget_decorator.c
- * - Widget Decorator
- */
-#include <common.h>
-#include <wm.h>
-#include <renderer_widget.h>
-
-#define BORDER_EVERYTHING      1
-
-#define BOX_BGCOLOUR    0xC0C0C0
-#define BOX_BORDER      0xA0A0A0
-#define BUTTON_BGCOLOUR 0xD0D0D0
-#define BUTTON_BORDER   0xF0F0F0
-#define        TEXT_COLOUR     0x000000
-#define TEXTINPUT_BACKGROUND   0xFFFFFF
-#define TEXTINPUT_BORDER_OUT   0x404040
-
-// === CODE ===
-void Widget_Decorator_RenderWidget(tWindow *Window, tElement *Element)
-{
-//     _SysDebug("Widget_Decorator_RenderWidget: (Element={Type:%i,(%i,%i) %ix%i})",
-//             Element->Type,
-//             Element->CachedX, Element->CachedY,
-//             Element->CachedW, Element->CachedH
-//             );
-       
-       #if BORDER_EVERYTHING
-       WM_Render_DrawRect(
-               Window,
-               Element->CachedX, Element->CachedY,
-               Element->CachedW, Element->CachedH,
-               0
-               );
-       #endif
-       
-       switch(Element->Type)
-       {
-       case ELETYPE_NONE:
-       case ELETYPE_BOX:       break;  // Box is a meta-element
-       
-       case ELETYPE_TABBAR:    // Tab Bar
-               WM_Render_DrawRect(
-                       Window,
-                       Element->CachedX, Element->CachedY,
-                       Element->CachedW, Element->CachedH,
-                       BOX_BORDER
-                       );
-               WM_Render_FillRect(
-                       Window,
-                       Element->CachedX+1, Element->CachedY+1,
-                       Element->CachedW-2, Element->CachedH-2,
-                       BOX_BGCOLOUR
-                       );
-               // Enumerate Items.
-               break;
-       case ELETYPE_TOOLBAR:   // Tool Bar
-               WM_Render_DrawRect(
-                       Window,
-                       Element->CachedX, Element->CachedY,
-                       Element->CachedW, Element->CachedH,
-                       BOX_BORDER
-                       );
-               WM_Render_FillRect(
-                       Window,
-                       Element->CachedX+1, Element->CachedY+1,
-                       Element->CachedW-2, Element->CachedH-2,
-                       BOX_BGCOLOUR
-                       );
-               break;
-       
-       case ELETYPE_SPACER:    // Spacer (subtle line)
-               WM_Render_FillRect(
-                       Window,
-                       Element->CachedX+3, Element->CachedY+3,
-                       Element->CachedW-6, Element->CachedH-6,
-                       BOX_BORDER
-                       );
-               break;
-       
-       case ELETYPE_BUTTON:    // Button
-               WM_Render_FillRect(
-                       Window,
-                       Element->CachedX+1, Element->CachedY+1,
-                       Element->CachedW-2, Element->CachedH-2,
-                       BUTTON_BGCOLOUR
-                       );
-               WM_Render_DrawRect(
-                       Window,
-                       Element->CachedX, Element->CachedY,
-                       Element->CachedW-1, Element->CachedH-1,
-                       BUTTON_BORDER
-                       );
-               break;
-
-       // Text input field / Text Box
-       case ELETYPE_TEXTINPUT:
-       case ELETYPE_TEXTBOX:
-               WM_Render_FillRect(
-                       Window, 
-                       Element->CachedX, Element->CachedY,
-                       Element->CachedW, Element->CachedH,
-                       TEXTINPUT_BACKGROUND
-                       );
-               WM_Render_DrawRect(
-                       Window, 
-                       Element->CachedX, Element->CachedY,
-                       Element->CachedW, Element->CachedH,
-                       TEXTINPUT_BORDER_OUT
-                       );
-//             WM_Render_DrawRect(
-//                     Window, 
-//                     Element->CachedX+1, Element->CachedY+1,
-//                     Element->CachedW-2, Element->CachedH-2,
-//                     TEXTINPUT_BORDER_IN
-//                     );
-               break;
-       
-       case ELETYPE_TEXT:
-               WM_Render_DrawText(
-                       Window,
-                       Element->CachedX+1, Element->CachedY+1,
-                       Element->CachedW-2, Element->CachedH-2,
-                       NULL,
-                       TEXT_COLOUR,
-                       Element->Text
-                       );
-               break;
-       
-       case ELETYPE_IMAGE:
-               WM_Render_DrawImage(
-                       Window,
-                       Element->CachedX, Element->CachedY,
-                       Element->CachedW, Element->CachedH,
-                       Element->Data
-                       );
-               break;
-               
-       default:
-               _SysDebug(" ERROR: Unknown type %i", Element->Type);
-               break;
-       }
-}
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/background.c b/Usermode/Applications/axwin3_src/WM/renderers/background.c
new file mode 100644 (file)
index 0000000..d67ca74
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * render_widget.c
+ * - AxWin2 Background port
+ */
+#include <common.h>
+#include <wm_renderer.h>
+
+// === TYPES ===
+
+// === STRUCTURES ===
+struct sBgWin
+{
+       uint32_t        Colour;
+};
+
+// === PROTOTYPES ===
+tWindow        *Renderer_Background_Create(int Flags);
+void   Renderer_Background_Redraw(tWindow *Window);
+int    Renderer_Background_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
+
+// === GLOBALS ===
+tWMRenderer    gRenderer_Background = {
+       .Name = "Background",
+       .CreateWindow = Renderer_Background_Create,
+       .Redraw = Renderer_Background_Redraw,
+       .HandleMessage = Renderer_Background_HandleMessage
+};
+
+// === CODE ===
+int Renderer_Background_Init(void)
+{
+       WM_RegisterRenderer(&gRenderer_Background);     
+
+       return 0;
+}
+
+tWindow        *Renderer_Background_Create(int Arg)
+{
+       tWindow *ret;
+       ret = WM_CreateWindowStruct( sizeof(struct sBgWin) );
+       
+       ((struct sBgWin*)ret->RendererInfo)->Colour = Arg;
+       
+       return ret;
+}
+
+void Renderer_Background_Redraw(tWindow *Window)
+{
+       struct sBgWin   *info = Window->RendererInfo;
+       
+       WM_Render_FillRect(Window, 0, 0, 0xFFFF, 0xFFFF, info->Colour);
+}
+
+int Renderer_Background_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
+{
+       switch(Msg)
+       {
+       // TODO: Handle resize
+       
+       default:
+               break;
+       }
+       return 0;
+}
+
+
+
+
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/classes.c b/Usermode/Applications/axwin3_src/WM/renderers/classes.c
new file mode 100644 (file)
index 0000000..4b0f3c6
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * render_classes.c
+ * - Simple class based window renderer
+ */
+#include <common.h>
+#include <wm_renderer.h>
+#include <renderer_classful.h>
+
+// === TYPES ===
+typedef struct sClassfulInfo
+{
+       tColour BGColour;
+} tClassfulInfo;
+
+// === PROTOTYPES ===
+tWindow        *Renderer_Class_Create(int Flags);
+void   Renderer_Class_Redraw(tWindow *Window);
+int    Renderer_Class_HandleMessage(tWindow *Target, int Msg, int Len, void *Data);
+
+// === GLOBALS ===
+tWMRenderer    gRenderer_Class = {
+       .Name = "Classful",
+       .CreateWindow = Renderer_Class_Create,
+       .Redraw = Renderer_Class_Redraw,
+       .HandleMessage = Renderer_Class_HandleMessage
+};
+
+// === CODE ===
+int Renderer_Class_Init(void)
+{
+       WM_RegisterRenderer(&gRenderer_Class);  
+
+       return 0;
+}
+
+tWindow        *Renderer_Class_Create(int Flags)
+{
+       return WM_CreateWindowStruct(sizeof(tClassfulInfo));
+}
+
+void Renderer_Class_Redraw(tWindow *Window)
+{
+       tClassfulInfo   *info = Window->RendererInfo;
+       WM_Render_FillRect(Window, 0, 0, Window->W, Window->H, info->BGColour);
+}
+
+int Renderer_Class_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
+{
+       tClassfulInfo   *info = Target->RendererInfo;
+       switch(Msg)
+       {
+       case MSG_CLASSFUL_SETBGCOLOUR:
+               if( Len != sizeof(uint32_t) ) return -1;
+               info->BGColour = *(uint32_t*)Data;
+               return 0;
+
+       case MSG_CLASSFUL_SETTEXT:
+               
+               return -1;
+       
+       // Anything else is unhandled
+       default:
+               return 1;
+       }
+}
+
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/menu.c b/Usermode/Applications/axwin3_src/WM/renderers/menu.c
new file mode 100644 (file)
index 0000000..4506ad2
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * render_menu.c
+ * - Pop-up menu window class/renderer
+ */
+#include <common.h>
+#include <wm_renderer.h>
+#include <menu_messages.h>
+#include <wm_messages.h>
+#include <stdlib.h>
+#include <string.h>
+
+// === STRUCTURES ===
+typedef struct sMenuItem
+{
+       // Settings
+       char    *Label;
+       char    *Shortcut;
+        int    KeyOffset;
+        int    Flags;
+       
+       // Cached values
+        int    LabelWidth;     
+        int    ShortcutWidth;
+        int    UnderlineX;
+        int    UnderlineW;
+
+       char    Data[];
+} tMenuItem;
+
+typedef struct sMenuWindowInfo
+{
+        int    MaxLabelWidth;
+        int    MaxShortcutWidth;
+        int    CachedW;
+
+        int    HilightedItem;  
+
+        int    MaxItems;
+        int    nItems;
+       tMenuItem       *Items[];
+} tMenuWindowInfo;
+
+// === PROTOTYPES ===
+void   Renderer_Menu_Init(void);
+tWindow        *Renderer_Menu_Create(int Argument);
+void   Renderer_Menu_Redraw(tWindow *Window);
+ int   Renderer_Menu_HandleMessage(tWindow *Window, int Msg, int Length, const void *Data);
+
+// === CONSTANTS ===
+const int      ciMenu_Gap = 10;        // Gap between label and shortcut
+const int      ciMenu_TopPadding = 2;
+const int      ciMenu_BottomPadding = 2;
+const int      ciMenu_LeftPadding = 2;
+const int      ciMenu_RightPadding = 2;
+const int      ciMenu_FontHeight = 16;
+const int      ciMenu_ItemHeight = 20;
+const int      ciMenu_SpacerHeight = 5;
+const tColour  cMenu_BackgroundColour = 0xCCCCCC;
+const tColour  cMenu_BorderColour   = 0x000000;
+const tColour  cMenu_SpacerColour   = 0x404040;
+const tColour  cMenu_LabelColour    = 0x000000;
+const tColour  cMenu_ShortcutColour = 0x404040;
+const tColour  cMenu_HilightColour  = 0xE0E0E0;
+
+// === GLOBALS ===
+tWMRenderer    gRenderer_Menu = {
+       .Name = "Menu",
+       .CreateWindow = Renderer_Menu_Create,
+       .Redraw = Renderer_Menu_Redraw,
+       .HandleMessage = Renderer_Menu_HandleMessage
+};
+tFont  *gMenu_Font = NULL;     // System monospace
+
+// === CODE ===
+void Renderer_Menu_Init(void)
+{
+       WM_RegisterRenderer(&gRenderer_Menu);
+}
+
+tWindow        *Renderer_Menu_Create(int Argument)
+{
+       tWindow *ret;
+       tMenuWindowInfo *info;
+
+       if(Argument < 5)        Argument = 5;
+       if(Argument > 200)      Argument = 200; 
+
+       ret = WM_CreateWindowStruct(sizeof(*info) + Argument*sizeof(info->Items[0]));
+       info = ret->RendererInfo;
+       info->MaxItems = Argument;
+       info->HilightedItem = -1;
+
+       ret->Flags |= WINFLAG_NODECORATE;
+       ret->H = ciMenu_TopPadding + ciMenu_BottomPadding;
+
+//     _SysDebug("Renderer_Menu_Create: ->MaxItems = %i", info->MaxItems);
+       
+       return ret;
+}
+
+void Renderer_Menu_Redraw(tWindow *Window)
+{
+       tMenuWindowInfo *info = Window->RendererInfo;
+        int    w, h, y, i;
+
+       w = info->CachedW;
+       #if 0
+       h = ciMenu_TopPadding + ciMenu_BottomPadding;
+       for( i = 0; i < info->nItems; i ++ )
+       {
+               if( !info->Items[i] )   continue;
+               
+               if(info->Items[i]->Label)
+                       h += ciMenu_ItemHeight;
+               else
+                       h += ciMenu_SpacerHeight;
+       }
+       #else
+       h = Window->H;
+       #endif
+
+//     _SysDebug("w = %i, h = %i", w, h);
+
+       // - Move the window such that it is on screen
+       //  > Make sure to catch if the menu can't fit fully onscreen
+
+       // - Clear
+       WM_Render_FillRect(Window, 0, 0, w, h, cMenu_BackgroundColour);
+       WM_Render_DrawRect(Window, 0, 0, w, h, cMenu_BorderColour);
+
+       // - Render each item
+       y = ciMenu_TopPadding;
+       for( i = 0; i < info->nItems; i ++ )
+       {
+               tMenuItem       *item = info->Items[i];
+               
+               // Unused slot
+               if(!item)       continue;
+               
+               // Spacer
+               if(!item->Label)
+               {
+                       WM_Render_FillRect(Window,
+                               1, y + ciMenu_SpacerHeight/2,
+                               w-2, 1,
+                               cMenu_SpacerColour
+                               );
+                       y += ciMenu_SpacerHeight;
+                       continue ;
+               }
+       
+               // Hilight
+               if( info->HilightedItem == i )
+               {
+                       WM_Render_FillRect(Window,
+                               1, y,
+                               w-2, ciMenu_ItemHeight,
+                               cMenu_HilightColour
+                               );
+               }
+       
+               // Text
+               WM_Render_DrawText(Window,
+                       ciMenu_LeftPadding, y,
+                       w, ciMenu_ItemHeight,
+                       gMenu_Font,
+                       cMenu_LabelColour,
+                       item->Label
+                       );
+               // Underline
+               if(item->UnderlineW)
+               {
+                       WM_Render_FillRect(Window,
+                               ciMenu_LeftPadding + item->UnderlineX, y + ciMenu_FontHeight,
+                               item->UnderlineW, 1,
+                               cMenu_LabelColour
+                               );
+               }
+               
+               // Shortcut key
+               if(item->Shortcut)
+               {
+                       WM_Render_DrawText(Window,
+                               w - item->ShortcutWidth - ciMenu_RightPadding, y,
+                               w, ciMenu_ItemHeight,
+                               gMenu_Font,
+                               cMenu_ShortcutColour,
+                               item->Shortcut
+                               );
+               }
+               
+               y += ciMenu_ItemHeight;
+       }
+}
+
+int Renderer_Menu_int_AddItem(tWindow *Window, int Length, const tMenuMsg_AddItem *Msg)
+{
+       tMenuWindowInfo *info = Window->RendererInfo;
+       tMenuItem       *item;
+       
+       // Sanity checking
+       // - Message length
+       if(Length < sizeof(*Msg) + 1 || Msg->Label[Length-sizeof(*Msg)-1] != '\0') {
+               _SysDebug("Renderer_Menu_int_AddItem: Size checks failed");
+               return -1;
+       }
+       // - ID Number
+       if(Msg->ID >= info->MaxItems) {
+               _SysDebug("Renderer_Menu_int_AddItem: ID (%i) >= MaxItems (%i)",
+                       Msg->ID, info->MaxItems);
+               return -1;
+       }
+       
+       // Don't overwrite
+       if(info->Items[Msg->ID]) {
+               _SysDebug("- Caught overwrite of %i", Msg->ID);
+               return 0;
+       }
+       // Bookkeeping
+       if(Msg->ID >= info->nItems)     info->nItems = Msg->ID + 1;
+       // Allocate
+       item = malloc(sizeof(tMenuItem)+strlen(Msg->Label)+1);
+       info->Items[Msg->ID] = item;
+       
+       if(Msg->Label[0] == '\0')
+       {
+               // Spacer
+               item->Label = NULL;
+               WM_ResizeWindow(Window, info->CachedW, Window->H+ciMenu_SpacerHeight);
+               
+               return 0;
+       }
+       
+       // Actual item
+       char    *dest = item->Data;
+       const char      *src = Msg->Label;
+        int    ofs = 0;
+
+       // - Main label
+       item->KeyOffset = -1;
+       item->Label = dest;
+       for(ofs = 0; *src && *src != '\t'; ofs ++)
+       {
+               if(*src == '&') {
+                       *dest = '\0';
+                       item->KeyOffset = ofs;
+                       src ++;
+               }
+               else {
+                       *dest++ = *src++;
+               }
+       }
+       *dest++ = '\0';
+       // - Key combo / Shortcut
+       if(*src)
+       {
+               src ++;
+               item->Shortcut = dest;
+               strcpy(item->Shortcut, src);
+       }
+       else
+       {
+               item->Shortcut = NULL;
+       }
+       
+       // Get dimensions
+       // - Underline (hotkey)
+       if(item->KeyOffset == -1)
+       {
+               item->UnderlineX = 0;
+               item->UnderlineW = 0;
+       }
+       else
+       {
+               char    tmp = item->Label[item->KeyOffset];
+               // Get width of preceding substring
+               item->Label[item->KeyOffset] = '\0';
+               WM_Render_GetTextDims(NULL, item->Label, &item->UnderlineX, NULL);
+               // Get the width of the underlined character
+               // TODO: Fix for high UTF-8 characters
+               item->Label[item->KeyOffset] = tmp;
+               tmp = item->Label[item->KeyOffset+1];
+               item->Label[item->KeyOffset+1] = '\0';
+               WM_Render_GetTextDims(
+                       NULL, item->Label+item->KeyOffset,
+                       &item->UnderlineW, NULL
+                       );
+               item->Label[item->KeyOffset+1] = tmp;
+       }
+       // - Labels
+       WM_Render_GetTextDims(NULL, item->Label, &item->LabelWidth, NULL);
+       if(item->Shortcut)
+               WM_Render_GetTextDims(NULL, item->Shortcut, &item->ShortcutWidth, NULL);
+       else
+               item->ShortcutWidth = 0;
+       
+       if( item->LabelWidth > info->MaxLabelWidth )
+               info->MaxLabelWidth = item->LabelWidth;
+       if( item->ShortcutWidth > info->MaxShortcutWidth )
+               info->MaxShortcutWidth = item->ShortcutWidth;
+       
+       if( info->MaxLabelWidth + info->MaxShortcutWidth + ciMenu_Gap > info->CachedW )
+       {
+               info->CachedW = ciMenu_LeftPadding + info->MaxLabelWidth
+                       + ciMenu_Gap + info->MaxShortcutWidth
+                       + ciMenu_RightPadding;
+       }
+       WM_ResizeWindow(Window, info->CachedW, Window->H+ciMenu_ItemHeight);
+       
+       return 0;
+}
+
+int Renderer_Menu_int_GetItemByPos(tWindow *Window, tMenuWindowInfo *Info, int X, int Y)
+{
+        int    i;
+
+       if( X < 0 || X >= Window->W )
+               return -1;
+       
+       for( i = 0; i < Info->nItems; i ++ )
+       {
+               if( !Info->Items[i] )   continue;
+                       
+               if( !Info->Items[i]->Label )
+               {
+                       // Spacer - not selectable
+                       if(Y < ciMenu_SpacerHeight) {
+                               return -1;
+                       }
+                       Y -= ciMenu_SpacerHeight;
+               }
+               else
+               {
+                       // Normal item, can be selected/hilighted
+                       if(Y < ciMenu_ItemHeight) {
+                               return i;
+                       }
+                       Y -= ciMenu_ItemHeight;
+               }
+       }
+       return -1;
+}
+
+int Renderer_Menu_HandleMessage(tWindow *Window, int Msg, int Length, const void *Data)
+{
+       tMenuWindowInfo *info = Window->RendererInfo;
+       switch(Msg)
+       {
+       case WNDMSG_SHOW: {
+               const struct sWndMsg_Bool       *msg = Data;
+               if(Length < sizeof(*msg))       return -1;
+               if(msg->Val)
+               {
+//                     _SysDebug(" - Shown, take focus");
+                       // TODO: This shouldn't really be done, instead focus should be given
+                       //       when the menu is shown.
+//                     WM_FocusWindow(Window);
+               }
+               else
+               {
+                       // Hide Children
+                       _SysDebug("- Hidden, hide the children!");
+               }
+               return 0; }
+       case WNDMSG_FOCUS: {
+               const struct sWndMsg_Bool       *msg = Data;
+               if(Length < sizeof(*msg))       return -1;
+               if(!msg->Val) {
+                       // TODO: Catch if focus was given away to a child
+                       _SysDebug("- Lost focus");
+                       WM_ShowWindow(Window, 0);       // Hide!
+               }
+               else {
+                       _SysDebug("- Focus gained, TODO: Show accel keys");
+               }
+               return 0; }
+
+       case WNDMSG_MOUSEBTN: {
+               const struct sWndMsg_MouseButton        *msg = Data;
+                int    item;
+               
+               if(Length < sizeof(*msg))       return -1;
+
+               if(msg->Button == 0 && msg->bPressed == 0)
+               {
+                       item = Renderer_Menu_int_GetItemByPos(Window, info, msg->X, msg->Y);
+                       if(item != -1)
+                       {
+                               tMenuMsg_Select _msg;
+                               // TODO: Ignore sub-menus too
+                               _msg.ID = item;
+                               WM_SendMessage(Window, Window, MSG_MENU_SELECT, sizeof(_msg), &_msg);
+                               WM_ShowWindow(Window, 0);
+                       }
+               }
+                               
+
+               return 0; }     
+
+       case WNDMSG_MOUSEMOVE: {
+               const struct sWndMsg_MouseMove  *msg = Data;
+                int    new_hilight;
+
+               if(Length < sizeof(*msg))       return -1;
+
+               new_hilight = Renderer_Menu_int_GetItemByPos(Window, info, msg->X, msg->Y);
+
+               if( new_hilight != info->HilightedItem )
+               {
+                       info->HilightedItem = new_hilight;
+                       // TODO: Change sub-menu
+                       WM_Invalidate(Window);
+               }
+
+               return 0; }
+
+       // Manipulation messages
+       case MSG_MENU_ADDITEM:
+//             _SysDebug("MSG_MENU_ADDITEM");
+               return Renderer_Menu_int_AddItem(Window, Length, Data);
+       
+       // Only message to pass to client
+       case MSG_MENU_SELECT:
+               return 1;
+       }
+       return 0;
+}
+
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/passthru.c b/Usermode/Applications/axwin3_src/WM/renderers/passthru.c
new file mode 100644 (file)
index 0000000..9cd112c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * renderer_passthru.c
+ * - Passthrough window render (framebuffer essentially)
+ */
+#include <common.h>
+#include <wm_renderer.h>
+
+// === PROTOTYPES ===
+tWindow        *Renderer_Passthru_Create(int Flags);
+void   Renderer_Passthru_Redraw(tWindow *Window);
+ int   Renderer_Passthru_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
+
+// === GLOBALS ===
+tWMRenderer    gRenderer_Passthru = {
+       .Name = "Passthru",
+       .CreateWindow = Renderer_Passthru_Create,
+       .Redraw = Renderer_Passthru_Redraw,
+       .HandleMessage = Renderer_Passthru_HandleMessage
+};
+
+// === CODE ===
+int Renderer_Passthru_Init(void)
+{
+       return 0;
+}
+
+tWindow        *Renderer_Passthru_Create(int Flags)
+{
+       return NULL;
+}
+
+void Renderer_Passthru_Redraw(tWindow *Window)
+{
+       
+}
+
+int Renderer_Passthru_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
+{
+       return 1;
+}
+
+
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget.c b/Usermode/Applications/axwin3_src/WM/renderers/widget.c
new file mode 100644 (file)
index 0000000..1bd437d
--- /dev/null
@@ -0,0 +1,610 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * render_widget.c
+ * - AxWin2 Widget port
+ */
+#include <common.h>
+#include <wm_renderer.h>
+#include <renderer_widget.h>
+#include <string.h>
+#include <wm_messages.h>
+#include <stdlib.h>
+#include "widget/common.h"
+
+#define DEFAULT_ELETABLE_SIZE  64
+
+// === PROTOTYPES ===
+ int   Renderer_Widget_Init(void);
+tWindow        *Renderer_Widget_Create(int Flags);
+void   Renderer_Widget_Redraw(tWindow *Window);
+
+void   Widget_RenderWidget(tWindow *Window, tElement *Element);
+void   Widget_UpdateDimensions(tElement *Element);
+void   Widget_UpdatePosition(tElement *Element);
+// --- Messages
+tElement       *Widget_GetElementById(tWidgetWin *Info, uint32_t ID);
+void   Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg);
+void   Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg);
+void   Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg);
+void   Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg);
+ int   Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
+
+// === GLOBALS ===
+tWMRenderer    gRenderer_Widget = {
+       .Name = "Widget",
+       .CreateWindow = Renderer_Widget_Create,
+       .Redraw = Renderer_Widget_Redraw,
+       .HandleMessage = Renderer_Widget_HandleMessage
+};
+       
+// --- Element callbacks
+tWidgetDef     *gaWM_WidgetTypes[NUM_ELETYPES];
+const int      ciWM_NumWidgetTypes = sizeof(gaWM_WidgetTypes)/sizeof(gaWM_WidgetTypes[0]);
+
+// === CODE ===
+int Renderer_Widget_Init(void)
+{
+       WM_RegisterRenderer(&gRenderer_Widget); 
+
+       return 0;
+}
+
+void Widget_int_SetTypeDef(int Type, tWidgetDef *Ptr)
+{
+       if( Type < 0 || Type >= ciWM_NumWidgetTypes ) {
+               _SysDebug("ERROR - Widget ID %i out of range (from %p)",
+                       Type, __builtin_return_address(0)
+                       );
+               return ;
+       }
+       
+       if( gaWM_WidgetTypes[Type] ) {
+               _SysDebug("ERROR - Widget ID %i redefined by %p",
+                       Type, __builtin_return_address(0)
+                       );
+               return ;
+       }
+       
+       gaWM_WidgetTypes[Type] = Ptr;
+       _SysDebug("Registered type %i to %p", Type, Ptr);
+}
+
+tWindow        *Renderer_Widget_Create(int Flags)
+{
+       tWindow *ret;
+       tWidgetWin      *info;
+        int    eletable_size = DEFAULT_ELETABLE_SIZE;
+
+       _SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
+
+       // TODO: Use `Flags` as default element count?
+       // - Actaully, it's taken by the root ele flags
+       // - Use the upper bits?
+
+       ret = WM_CreateWindowStruct( sizeof(tWidgetWin) + sizeof(tElement*)*eletable_size );
+       info = ret->RendererInfo;
+       
+       info->TableSize = eletable_size;
+       info->RootElement.Window = ret;
+       info->RootElement.ID = -1;
+       info->RootElement.BackgroundColour = 0xCCCCCC;
+       info->RootElement.Flags = Flags;
+       info->RootElement.PaddingT = 2;
+       info->RootElement.PaddingB = 2;
+       info->RootElement.PaddingL = 2;
+       info->RootElement.PaddingR = 2;
+       
+       return ret;
+}
+
+void Renderer_Widget_Redraw(tWindow *Window)
+{
+       tWidgetWin      *info = Window->RendererInfo;
+       WM_Render_FillRect(Window, 0, 0, 0xFFF, 0xFFF, info->RootElement.BackgroundColour);
+
+       Widget_UpdateDimensions(&info->RootElement);
+       Widget_UpdatePosition(&info->RootElement);
+
+       Widget_RenderWidget(Window, &info->RootElement);
+}
+
+// --- Render / Resize ---
+void Widget_RenderWidget(tWindow *Window, tElement *Element)
+{
+       tElement        *child;
+       
+       if( Element->Flags & ELEFLAG_NORENDER ) return ;
+       if( Element->Flags & ELEFLAG_INVISIBLE )        return ;
+
+       if( Element->Type < ciWM_NumWidgetTypes
+        && gaWM_WidgetTypes[Element->Type]
+        && gaWM_WidgetTypes[Element->Type]->Render
+           )
+       {
+               gaWM_WidgetTypes[Element->Type]->Render(Window, Element);
+       }
+       else
+       {
+               Widget_Decorator_RenderWidget(Window, Element);
+       }
+       
+       for(child = Element->FirstChild; child; child = child->NextSibling)
+       {
+               Widget_RenderWidget(Window, child);
+       }
+}
+
+void Widget_UpdateDimensions(tElement *Element)
+{
+       tElement        *child;
+        int    nChildren = 0;
+        int    nFixed = 0;
+        int    maxCross = 0;
+        int    fixedSize = 0;
+        int    fullCross, dynWith;
+       
+       // Pass 1
+       // - Get the fixed and minimum sizes of the element
+       for( child = Element->FirstChild; child; child = child->NextSibling )
+       {
+               // Ignore elements that will not be rendered
+               if( child->Flags & ELEFLAG_NORENDER )   continue ;
+               
+               // Absolutely positioned elements don't affect dimensions
+               if( child->Flags & ELEFLAG_ABSOLUTEPOS )        continue ;
+       
+               // Fixed width elements 
+               if( child->FixedWith )
+               {
+                       nFixed ++;
+                       fixedSize += child->FixedWith;
+               }
+               else if( child->Flags & ELEFLAG_NOSTRETCH )
+               {
+                       nFixed ++;
+                       fixedSize += child->MinWith;
+               }
+               
+               if( child->FixedCross && maxCross < child->FixedCross )
+                       maxCross = child->FixedCross;
+               if( child->MinCross && maxCross < child->MinCross )
+                       maxCross = child->MinCross;
+               nChildren ++;
+       }
+
+       // Get the dynamic with size from the unused space in the element
+       if( nChildren > nFixed ) {
+               if( Element->Flags & ELEFLAG_VERTICAL )
+                       dynWith = Element->CachedH - Element->PaddingT - Element->PaddingB;
+               else
+                       dynWith = Element->CachedW - Element->PaddingL - Element->PaddingR;
+               dynWith -= fixedSize;
+               if( dynWith < 0 )       return ;
+               dynWith /= nChildren - nFixed;
+       }
+       
+//     _SysDebug("%i - nChildren = %i, nFixed = %i, dynWith = %i, fixedSize = %i",
+//             Element->ID, nChildren, nFixed, dynWith, fixedSize);
+
+       // Get the cross size
+       if( Element->Flags & ELEFLAG_VERTICAL )
+               fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
+       else
+               fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
+       
+       // Pass 2 - Set sizes and recurse
+       for( child = Element->FirstChild; child; child = child->NextSibling )
+       {
+                int    cross, with;
+
+               // Ignore elements that will not be rendered
+               if( child->Flags & ELEFLAG_NORENDER )   continue ;
+               
+               // --- Cross Size ---
+               // TODO: Expand to fill?
+               // TODO: Extra flag so options are (Expand, Equal, Wrap)
+               if( child->FixedCross )
+                       cross = child->FixedCross;
+               else if( child->Flags & ELEFLAG_NOEXPAND )
+                       cross = child->MinCross;
+               else
+                       cross = fullCross;
+               
+               // --- With Size ---
+               if( child->FixedWith )
+                       with = child->FixedWith;
+               else if( child->Flags & ELEFLAG_NOSTRETCH )
+                       with = child->MinWith;
+               else
+                       with = dynWith;
+       
+
+               if(with < child->MinWith)       with = child->MinWith;
+               if(cross < child->MinCross)     cross = child->MinCross;
+               
+               // Update the dimensions if they have changed
+               if( Element->Flags & ELEFLAG_VERTICAL ) {
+                       // If no change, don't recurse
+                       if( child->CachedW == cross && child->CachedH == with )
+                               continue ;
+                       child->CachedW = cross;
+                       child->CachedH = with;
+               }
+               else {
+                       // If no change, don't recurse
+                       if( child->CachedW == with && child->CachedH == cross )
+                               continue ;
+                       child->CachedW = with;
+                       child->CachedH = cross;
+               }
+               
+               // Force the positions of child elements to be recalculated
+               child->CachedX = -1;
+       
+               // Recurse down so the child elements can be updated    
+               Widget_UpdateDimensions(child);
+       }
+       
+}
+
+/**
+ * \brief Update the position of child elements
+ */
+void Widget_UpdatePosition(tElement *Element)
+{
+       tElement        *child;
+        int    x, y;
+       
+       if( Element->Flags & ELEFLAG_NORENDER ) return ;
+
+//     _SysDebug("Widget_UpdatePosition: (Element=%p(%i Type=%i Flags=0x%x))",
+//             Element, Element->ID, Element->Type, Element->Flags);
+       
+       // Initialise
+       x = Element->CachedX + Element->PaddingL;
+       y = Element->CachedY + Element->PaddingT;
+       
+       // Update each child
+       for(child = Element->FirstChild; child; child = child->NextSibling)
+       {
+                int    newX, newY;
+               // Ignore elements that will not be rendered
+               if( child->Flags & ELEFLAG_NORENDER )   continue ;
+
+               newX = x; newY = y;
+               
+               // Handle alignment
+               if( Element->Flags & ELEFLAG_ALIGN_CENTER ) {
+                       if(Element->Flags & ELEFLAG_VERTICAL)
+                               newX += Element->CachedW/2 - child->CachedW/2;
+                       else
+                               newY += Element->CachedH/2 - child->CachedH/2;
+               }
+               else if( Element->Flags & ELEFLAG_ALIGN_END ) {
+                       if(Element->Flags & ELEFLAG_VERTICAL )
+                               newX += Element->CachedW - child->CachedW
+                                       - Element->PaddingL - Element->PaddingR;
+                       else
+                               newY += Element->CachedH - child->CachedH
+                                       - Element->PaddingT - Element->PaddingB;
+               }
+
+//             _SysDebug(" Widget_UpdatePosition[%i]: newX = %i, newY = %i", Element->ID, newX, newY);
+
+               // Check for changes, and don't update if there was no change
+               if( newX != child->CachedX || newY != child->CachedY )
+               {
+                       child->CachedX = newX;
+                       child->CachedY = newY;
+                       // Update child's children positions
+                       Widget_UpdatePosition(child);
+               }
+               
+               // Increment
+               if(Element->Flags & ELEFLAG_VERTICAL ) {
+                       y += child->CachedH + Element->GapSize;
+               }
+               else {
+                       x += child->CachedW + Element->GapSize;
+               }
+       }
+}
+
+/**
+ * \brief Update the minimum dimensions of the element
+ * \note Called after a child's minimum dimensions have changed
+ */
+void Widget_UpdateMinDims(tElement *Element)
+{
+       tElement        *child;
+       
+       if(!Element)    return;
+       
+       Element->MinCross = 0;
+       Element->MinWith = 0;
+       
+       for(child = Element->FirstChild; child; child = child->NextSibling)
+       {
+               if( Element->Parent &&
+                       (Element->Flags & ELEFLAG_VERTICAL) == (Element->Parent->Flags & ELEFLAG_VERTICAL)
+                       )
+               {
+                       if(child->FixedCross)
+                               Element->MinCross += child->FixedCross;
+                       else
+                               Element->MinCross += child->MinCross;
+                       if(child->FixedWith)
+                               Element->MinWith += child->FixedWith;
+                       else
+                               Element->MinWith += child->MinWith;
+               }
+               else
+               {
+                       if(child->FixedCross)
+                               Element->MinWith += child->FixedCross;
+                       else
+                               Element->MinWith += child->MinCross;
+                       if(child->FixedWith)
+                               Element->MinCross += child->FixedWith;
+                       else
+                               Element->MinCross += child->MinWith;
+               }
+       }
+       
+       // Recurse upwards
+       Widget_UpdateMinDims(Element->Parent);
+}
+
+tElement *Widget_GetElementByPos(tWidgetWin *Info, int X, int Y)
+{
+       tElement        *ret, *next, *ele;
+       
+       next = &Info->RootElement;
+       while(next)
+       {
+               ret = next;
+               next = NULL;
+               for(ele = ret->FirstChild; ele; ele = ele->NextSibling)
+               {
+                       if(ele->Flags & ELEFLAG_NORENDER)       continue;
+                       if(X < ele->CachedX)    continue;
+                       if(Y < ele->CachedY)    continue;
+                       if(X >= ele->CachedX + ele->CachedW)    continue;
+                       if(Y >= ele->CachedY + ele->CachedH)    continue;
+                       next = ele;
+               }
+       }
+       return ret;
+}
+
+// --- Helpers ---
+tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID)
+{
+       tElement        *ele;
+
+       if( ID == -1 )  return &Info->RootElement;
+       
+       if( ID < Info->TableSize )      return Info->ElementTable[ID];
+
+       ele = Info->ElementTable[ID % Info->TableSize];
+       while(ele && ele->ID != ID)     ele = ele->ListNext;
+       return ele;
+}
+
+// --- Message Handlers ---
+void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg)
+{
+       const int       max_debugname_len = Len - sizeof(tWidgetMsg_Create);
+       tElement        *parent, *new;
+
+       // Sanity check
+       if( Len < sizeof(*Msg) )
+               return ;
+       if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
+               return ;
+       
+       _SysDebug("Widget_NewWidget (%i %i Type %i Flags 0x%x)",
+               Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags);
+       
+       // Create
+       parent = Widget_GetElementById(Info, Msg->Parent);
+       if(!parent)
+       {
+               _SysDebug("Widget_NewWidget - Bad parent ID %i", Msg->Parent);
+               return ;
+       }
+
+       // Check if the ID is already in use
+       if( Widget_GetElementById(Info, Msg->NewID) )
+               return ;
+
+       // Create new element
+       new = calloc(sizeof(tElement), 1);
+       new->Window = parent->Window;
+       new->ID = Msg->NewID;
+       new->Type = Msg->Type;
+       new->Parent = parent;
+       new->Flags = Msg->Flags;
+       new->PaddingT = 2;
+       new->PaddingB = 2;
+       new->PaddingL = 2;
+       new->PaddingR = 2;
+       new->CachedX = -1;
+       
+       if( new->Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[new->Type] && gaWM_WidgetTypes[new->Type]->Init )
+               gaWM_WidgetTypes[new->Type]->Init(new);
+       
+       // Add to parent's list
+       if(parent->LastChild)
+               parent->LastChild->NextSibling = new;
+       else
+               parent->FirstChild = new;
+       parent->LastChild = new;
+
+       // Add to info
+       {
+               tElement        *ele, *prev = NULL;
+               for(ele = Info->ElementTable[new->ID % Info->TableSize]; ele; prev = ele, ele = ele->ListNext);
+               if(prev)
+                       prev->ListNext = new;
+               else
+                       Info->ElementTable[new->ID % Info->TableSize] = new;
+       }
+
+       Widget_UpdateMinDims(parent);
+}
+
+void Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg)
+{
+       tElement        *ele;
+       
+       if( Len < sizeof(*Msg) )
+               return ;
+
+       _SysDebug("Widget_SetFlags: (%i 0x%x 0x%x)", Msg->WidgetID, Msg->Value, Msg->Mask);
+       
+       ele = Widget_GetElementById(Info, Msg->WidgetID);
+       if(!ele)        return;
+
+       ele->Flags &= ~Msg->Mask;
+       ele->Flags |= Msg->Value & Msg->Mask;
+}
+
+void Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg)
+{
+       tElement        *ele;
+       
+       if( Len < sizeof(*Msg) )
+               return ;
+       
+       ele = Widget_GetElementById(Info, Msg->WidgetID);
+       if(!ele)        return ;
+       
+       ele->FixedWith = Msg->Value;
+}
+
+void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg)
+{
+       tElement        *ele;
+       
+       if( Len < sizeof(*Msg) + 1 )
+               return ;
+       if( Msg->Text[Len - sizeof(*Msg) - 1] != '\0' )
+               return ;
+
+       ele = Widget_GetElementById(Info, Msg->WidgetID);
+       if(!ele)        return ;
+
+
+       if( ele->Type < ciWM_NumWidgetTypes
+        && gaWM_WidgetTypes[ele->Type]
+        && gaWM_WidgetTypes[ele->Type]->UpdateText )
+       {
+               gaWM_WidgetTypes[ele->Type]->UpdateText( ele, Msg->Text );
+       }
+//     else
+//     {
+//             if(ele->Text)   free(ele->Text);
+//             ele->Text = strdup(Msg->Text);
+//     }
+}
+
+int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
+{
+       tWidgetWin      *info = Target->RendererInfo;
+       switch(Msg)
+       {
+       case WNDMSG_RESIZE: {
+               const struct sWndMsg_Resize     *msg = Data;
+               if(Len < sizeof(*msg))  return -1;              
+
+               info->RootElement.CachedW = msg->W;             
+               info->RootElement.CachedH = msg->H;
+               
+               // TODO: Update dimensions of all child elements?
+               
+               return 0; }
+
+       case WNDMSG_MOUSEMOVE: {
+//             _SysDebug("TODO: Support widget mouse move events");
+               return 0; }
+
+       case WNDMSG_MOUSEBTN: {
+               const struct sWndMsg_MouseButton        *msg = Data;
+               tWidgetMsg_MouseBtn     client_msg;
+               tElement        *ele;
+                int    x, y;
+                int    rv;
+               
+               if(Len < sizeof(*msg))  return -1;
+
+               x = msg->X; y = msg->Y;
+               client_msg.Button = msg->Button;
+               client_msg.bPressed = msg->bPressed;
+
+               ele = Widget_GetElementByPos(info, x, y);
+               // Send event to all elements from `ele` upwards
+               for( ; ele; ele = ele->Parent )
+               {
+                       if(ele->Type < ciWM_NumWidgetTypes
+                        && gaWM_WidgetTypes[ele->Type]
+                        && gaWM_WidgetTypes[ele->Type]->MouseButton)
+                       {
+                               rv = gaWM_WidgetTypes[ele->Type]->MouseButton(
+                                       ele,
+                                       x - ele->CachedX, y - ele->CachedY,
+                                       msg->Button, msg->bPressed
+                                       );
+                               // Allow a type to trap the input from going any higher
+                               if(rv == 0)     break;
+                       }
+                       else
+                       {
+                               // Pass to user
+                               client_msg.X = x - ele->CachedX;
+                               client_msg.Y = y - ele->CachedY;
+                               client_msg.WidgetID = ele->ID;
+                               WM_SendMessage(Target, Target, MSG_WIDGET_MOUSEBTN, sizeof(client_msg), &client_msg);
+                       }
+               }
+               return 0; }
+
+       // New Widget
+       case MSG_WIDGET_CREATE:
+               Widget_NewWidget(info, Len, Data);
+               return 0;
+
+       case MSG_WIDGET_DELETE:
+               _SysDebug("TODO: Implement MSG_WIDGET_DELETE");
+               return 0;
+
+       // Set Flags
+       case MSG_WIDGET_SETFLAGS:
+               Widget_SetFlags(info, Len, Data);
+               return 0;
+       
+       // Set length
+       case MSG_WIDGET_SETSIZE:
+               Widget_SetSize(info, Len, Data);
+               return 0;
+       
+       // Set text
+       case MSG_WIDGET_SETTEXT:
+               Widget_SetText(info, Len, Data);
+               return 0;
+       
+       // 
+       default:
+               return 1;       // Unhandled, pass to user
+       }
+}
+
+void Widget_Fire(tElement *Element)
+{
+       tWidgetMsg_Fire msg;
+       msg.WidgetID = Element->ID;
+       WM_SendMessage(Element->Window, Element->Window, MSG_WIDGET_FIRE, sizeof(msg), &msg);
+}
+
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget/button.c b/Usermode/Applications/axwin3_src/WM/renderers/widget/button.c
new file mode 100644 (file)
index 0000000..e4b252c
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ * 
+ * renderer/widget/button.c
+ * - Button Widget Type
+ */
+#include <common.h>
+#include "./common.h"
+#include "./colours.h"
+
+void Widget_Button_Render(tWindow *Window, tElement *Element)
+{
+       WM_Render_FillRect(
+               Window,
+               Element->CachedX+1, Element->CachedY+1,
+               Element->CachedW-2, Element->CachedH-2,
+               BUTTON_BGCOLOUR
+               );
+       WM_Render_DrawRect(
+               Window,
+               Element->CachedX, Element->CachedY,
+               Element->CachedW-1, Element->CachedH-1,
+               BUTTON_BORDER
+               );
+}
+
+int Widget_Button_MouseButton(tElement *Element, int X, int Y, int Button, int bPress)
+{
+       _SysDebug("Ele %i - Button %i %s",
+               Element->ID, Button,
+               (bPress ? "pressed" : "released")
+               );
+       if(!bPress)     Widget_Fire(Element);
+       return 0;       // Handled
+}
+
+DEFWIDGETTYPE(ELETYPE_BUTTON,
+       .Render = Widget_Button_Render,
+       .MouseButton = Widget_Button_MouseButton
+       )
+
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget/colours.h b/Usermode/Applications/axwin3_src/WM/renderers/widget/colours.h
new file mode 100644 (file)
index 0000000..7550022
--- /dev/null
@@ -0,0 +1,21 @@
+/**
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * renderer/widget/colours.h
+ * - Widget style definitions
+ */
+#ifndef _RENDERER_WIDGET_COLOURS_H
+#define _RENDERER_WIDGET_COLOURS_H
+
+#define BOX_BGCOLOUR    0xC0C0C0
+#define BOX_BORDER      0xA0A0A0
+#define BUTTON_BGCOLOUR 0xD0D0D0
+#define BUTTON_BORDER   0xF0F0F0
+#define        TEXT_COLOUR     0x000000
+#define TEXTINPUT_BACKGROUND   0xFFFFFF
+#define TEXTINPUT_BORDER_OUT   0x404040
+#define TEXTINPUT_BORDER_IN    0x808080
+
+#endif
+
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget/common.h b/Usermode/Applications/axwin3_src/WM/renderers/widget/common.h
new file mode 100644 (file)
index 0000000..b491333
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * renderer/widget/common.h
+ * - Widget common definitions
+ */
+#ifndef _RENDERER_WIDGET_COMMON_H
+#define _RENDERER_WIDGET_COMMON_H
+
+#include <renderer_widget.h>   // Widget types
+
+typedef struct sWidgetDef      tWidgetDef;
+
+struct sWidgetDef
+{
+       void    (*Init)(tElement *Ele);
+       void    (*Delete)(tElement *Ele);
+
+       void    (*Render)(tWindow *Window, tElement *Ele);
+       
+       void    (*UpdateFlags)(tElement *Ele);
+       void    (*UpdateSize)(tElement *Ele);
+       void    (*UpdateText)(tElement *Ele, const char *Text); // This should update Ele->Text
+
+       /**
+        * \name Input handlers
+        * \note Returns boolean unhandled
+        * \{
+        */     
+        int    (*MouseButton)(tElement *Ele, int X, int Y, int Button, int bPressed);
+        int    (*MouseMove)(tElement *Ele, int X, int Y);
+        int    (*KeyDown)(tElement *Ele, int KeySym, int Character);
+        int    (*KeyUp)(tElement *Ele, int KeySym);
+        int    (*KeyFire)(tElement *Ele, int KeySym, int Character);
+       /**
+        * \}
+        */
+};
+
+extern void    Widget_int_SetTypeDef(int Type, tWidgetDef *Def);
+extern void    Widget_UpdateMinDims(tElement *Element);
+extern void    Widget_Fire(tElement *Element);
+
+#define DEFWIDGETTYPE(_type, _attribs...) \
+tWidgetDef     _widget_typedef_##_type = {_attribs};\
+void _widget_set_##_type(void) __attribute__((constructor));\
+void _widget_set_##_type(void) { Widget_int_SetTypeDef(_type, &_widget_typedef_##_type);}
+
+#endif
+
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget/disptext.c b/Usermode/Applications/axwin3_src/WM/renderers/widget/disptext.c
new file mode 100644 (file)
index 0000000..4a091de
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ * 
+ * renderer/widget/button.c
+ * - Button Widget Type
+ */
+#include <common.h>
+#include "./common.h"
+#include "./colours.h"
+#include <string.h>
+
+void Widget_DispText_Render(tWindow *Window, tElement *Element)
+{
+       WM_Render_DrawText(
+               Window,
+               Element->CachedX+1, Element->CachedY+1,
+               Element->CachedW-2, Element->CachedH-2,
+               NULL, TEXT_COLOUR,
+               Element->Text
+               );
+}
+
+void Widget_DispText_UpdateText(tElement *Element, const char *Text)
+{
+        int    w=0, h=0;
+
+       if(Element->Text)       free(Element->Text);
+       Element->Text = strdup(Text);
+
+       WM_Render_GetTextDims(NULL, Element->Text, &w, &h);
+       if(Element->Parent && (Element->Parent->Flags & ELEFLAG_VERTICAL)) {
+               Element->MinCross = w;
+               Element->MinWith = h;
+       }
+       else {
+               Element->MinWith = w;
+               Element->MinCross = h;
+       }
+
+       Widget_UpdateMinDims(Element->Parent);
+}
+
+DEFWIDGETTYPE(ELETYPE_TEXT,
+       .Render = Widget_DispText_Render,
+       .UpdateText = Widget_DispText_UpdateText
+       );
+
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget/image.c b/Usermode/Applications/axwin3_src/WM/renderers/widget/image.c
new file mode 100644 (file)
index 0000000..f1f3155
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ * 
+ * renderer/widget/image.c
+ * - Image Widget Type
+ */
+#include <common.h>
+#include "./common.h"
+#include "./colours.h"
+#include "../../include/image.h"
+
+void Widget_Image_Render(tWindow *Window, tElement *Element)
+{
+       WM_Render_DrawImage(
+               Window,
+               Element->CachedX, Element->CachedY,
+               Element->CachedW, Element->CachedH,
+               Element->Data
+               );
+}
+
+void Widget_Image_UpdateText(tElement *Element, const char *Text)
+{
+       if(Element->Data)       free(Element->Data);
+       Element->Data = Image_Load( Text );
+       if(!Element->Data) {
+//             Element->Flags &= ~ELEFLAG_FIXEDSIZE;
+               return ;
+       }
+       
+       Element->CachedW = ((tImage*)Element->Data)->Width;
+       Element->CachedH = ((tImage*)Element->Data)->Height;
+       
+       if(Element->Parent && (Element->Parent->Flags & ELEFLAG_VERTICAL) ) {
+               Element->MinCross = ((tImage*)Element->Data)->Width;
+               Element->MinWith = ((tImage*)Element->Data)->Height;
+       }
+       else {
+               Element->MinWith = ((tImage*)Element->Data)->Width;
+               Element->MinCross = ((tImage*)Element->Data)->Height;
+       }
+
+       Widget_UpdateMinDims(Element->Parent);
+       
+       // NOTE: Doesn't update Element->Text because it's useless
+}
+
+DEFWIDGETTYPE(ELETYPE_IMAGE,
+       .Render = Widget_Image_Render,
+       .UpdateText = Widget_Image_UpdateText
+       );
+
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c b/Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c
new file mode 100644 (file)
index 0000000..c2eea82
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ * 
+ * renderer/widget/textinput.c
+ * - Single line text box
+ */
+#include <common.h>
+#include "./common.h"
+#include "./colours.h"
+
+void Widget_TextInput_Render(tWindow *Window, tElement *Element)
+{
+       WM_Render_FillRect(
+               Window, 
+               Element->CachedX, Element->CachedY,
+               Element->CachedW, Element->CachedH,
+               TEXTINPUT_BACKGROUND
+               );
+       WM_Render_DrawRect(
+               Window, 
+               Element->CachedX, Element->CachedY,
+               Element->CachedW, Element->CachedH,
+               TEXTINPUT_BORDER_OUT
+               );
+       WM_Render_DrawRect(
+               Window, 
+               Element->CachedX+1, Element->CachedY+1,
+               Element->CachedW-2, Element->CachedH-2,
+               TEXTINPUT_BORDER_IN
+               );
+       // TODO: Cursor?
+}
+
+void Widget_TextInput_Init(tElement *Element)
+{
+        int    h;
+
+       // TODO: Select font correctly  
+       WM_Render_GetTextDims(NULL, "jJ", NULL, &h);
+       
+       if( Element->Parent && (Element->Parent->Flags & ELEFLAG_VERTICAL) )
+               Element->MinWith = h;
+       else
+               Element->MinCross = h;
+
+       // No need to explicitly update parent min dims, as the AddElement routine does that    
+}
+
+DEFWIDGETTYPE(ELETYPE_TEXTINPUT,
+       .Render = Widget_TextInput_Render,
+       .Init = Widget_TextInput_Init
+       );
+
+
diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget/widget_decorator.c b/Usermode/Applications/axwin3_src/WM/renderers/widget/widget_decorator.c
new file mode 100644 (file)
index 0000000..442e9fc
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ * 
+ * renderer_widget_decorator.c
+ * - Widget Decorator
+ */
+#include <common.h>
+#include <wm.h>
+#include <renderer_widget.h>
+
+#define BORDER_EVERYTHING      1
+
+#include "./colours.h"
+
+// === CODE ===
+void Widget_Decorator_RenderWidget(tWindow *Window, tElement *Element)
+{
+//     _SysDebug("Widget_Decorator_RenderWidget: (Element={Type:%i,(%i,%i) %ix%i})",
+//             Element->Type,
+//             Element->CachedX, Element->CachedY,
+//             Element->CachedW, Element->CachedH
+//             );
+       
+       #if BORDER_EVERYTHING
+       WM_Render_DrawRect(
+               Window,
+               Element->CachedX, Element->CachedY,
+               Element->CachedW, Element->CachedH,
+               0
+               );
+       #endif
+       
+       switch(Element->Type)
+       {
+       case ELETYPE_NONE:
+       case ELETYPE_BOX:       break;  // Box is a meta-element
+       
+       case ELETYPE_TABBAR:    // Tab Bar
+               WM_Render_DrawRect(
+                       Window,
+                       Element->CachedX, Element->CachedY,
+                       Element->CachedW, Element->CachedH,
+                       BOX_BORDER
+                       );
+               WM_Render_FillRect(
+                       Window,
+                       Element->CachedX+1, Element->CachedY+1,
+                       Element->CachedW-2, Element->CachedH-2,
+                       BOX_BGCOLOUR
+                       );
+               // Enumerate Items.
+               break;
+       case ELETYPE_TOOLBAR:   // Tool Bar
+               WM_Render_DrawRect(
+                       Window,
+                       Element->CachedX, Element->CachedY,
+                       Element->CachedW, Element->CachedH,
+                       BOX_BORDER
+                       );
+               WM_Render_FillRect(
+                       Window,
+                       Element->CachedX+1, Element->CachedY+1,
+                       Element->CachedW-2, Element->CachedH-2,
+                       BOX_BGCOLOUR
+                       );
+               break;
+       
+       case ELETYPE_SPACER:    // Spacer (subtle line)
+               WM_Render_FillRect(
+                       Window,
+                       Element->CachedX+3, Element->CachedY+3,
+                       Element->CachedW-6, Element->CachedH-6,
+                       BOX_BORDER
+                       );
+               break;
+       
+       case ELETYPE_BUTTON:    // Button
+               break;
+
+       // Text input field / Text Box
+       case ELETYPE_TEXTINPUT:
+       case ELETYPE_TEXTBOX:
+               break;
+       
+       case ELETYPE_TEXT:
+               break;
+       
+       case ELETYPE_IMAGE:
+               break;
+               
+       default:
+               _SysDebug(" ERROR: Unknown type %i", Element->Type);
+               break;
+       }
+}
index a056a52..dad3b6e 100644 (file)
@@ -14,7 +14,7 @@
 #include <decorator.h>
 
 // === IMPORTS ===
-extern void    IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int Msg, int Len, void *Data);
+extern void    IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int Msg, int Len, const void *Data);
 
 // === GLOBALS ===
 tWMRenderer    *gpWM_Renderers;
@@ -230,10 +230,16 @@ int WM_ResizeWindow(tWindow *Window, int W, int H)
        return 0;
 }
 
-int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, void *Data)
+int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, const void *Data)
 {
        if(Dest == NULL)        return -2;
        if(Length > 0 && Data == NULL)  return -1;
+
+       if( Decorator_HandleMessage(Dest, Message, Length, Data) != 1 )
+       {
+               // TODO: Catch errors from ->HandleMessage
+               return 0;
+       }
        
        // ->HandleMessage returns 1 when the message was not handled
        if( Dest->Renderer->HandleMessage(Dest, Message, Length, Data) != 1 )
index 66088f9..f15d25a 100644 (file)
@@ -47,8 +47,8 @@ void WM_Input_MouseMoved(int OldX, int OldY, int NewX, int NewY)
        struct sWndMsg_MouseMove        msg;
        
        win = WM_int_GetWindowAtPos(OldX, OldY);
-       msg.X = NewX - win->X;
-       msg.Y = NewY - win->Y;
+       msg.X = NewX - win->X - win->BorderL;
+       msg.Y = NewY - win->Y - win->BorderT;
        msg.dX = NewX - OldX;
        msg.dY = NewY - OldY;
        WM_SendMessage(NULL, win, WNDMSG_MOUSEMOVE, sizeof(msg), &msg);
@@ -62,8 +62,8 @@ void WM_Input_MouseMoved(int OldX, int OldY, int NewX, int NewY)
        // TODO: Send mouseup to match mousedown if the cursor moves out of a window?
 
        win = newWin;
-       msg.X = NewX - win->X;
-       msg.Y = NewY - win->Y;
+       msg.X = NewX - win->X - win->BorderL;
+       msg.Y = NewY - win->Y - win->BorderT;
        msg.dX = NewX - OldX;
        msg.dY = NewY - OldY;
        WM_SendMessage(NULL, win, WNDMSG_MOUSEMOVE, sizeof(msg), &msg);
@@ -73,8 +73,8 @@ inline void WM_Input_int_SendBtnMsg(tWindow *Win, int X, int Y, int Index, int P
 {
        struct sWndMsg_MouseButton      msg;    
 
-       msg.X = X - Win->X;
-       msg.Y = Y - Win->Y;
+       msg.X = X - Win->X - Win->BorderL;
+       msg.Y = Y - Win->Y - Win->BorderT;
        msg.Button = Index;
        msg.bPressed = !!Pressed;
        
@@ -90,7 +90,7 @@ void WM_Input_MouseButton(int X, int Y, int ButtonIndex, int Pressed)
        // Handle press of primary button to change focus
        if( ButtonIndex == 0 && Pressed == 1 )
        {
-               _SysDebug("Gave focus to %p", win);
+//             _SysDebug("Gave focus to %p", win);
                WM_FocusWindow(win);
                WM_RaiseWindow(win);
        }

UCC git Repository :: git.ucc.asn.au