BIN := AxWinWM
OBJ := main.o wm.o input.o video.o ipc.o
OBJ += messageio.o
-OBJ += renderer_classes.o renderer_passthru.o renderer_widget.o renderer_background.o
+OBJ += renderer_classes.o renderer_passthru.o renderer_background.o
+OBJ += renderer_widget.o renderer_widget_decorator.o
LDFLAGS += -limage_sif -luri -lnet
#include <widget_messages.h>
+// === TYPES ===
+typedef struct sWidgetWin tWidgetWin;
+typedef struct sAxWin_Element tElement;
+
+// === STRUCTURES ===
+struct sAxWin_Element
+{
+ enum eElementTypes Type;
+
+ uint32_t ID; //!< Application provided ID number
+ tElement *ListNext; //!< Next element in bucket
+
+ // Element Tree
+ tElement *Parent;
+ tElement *FirstChild;
+ tElement *LastChild;
+ tElement *NextSibling;
+
+ // User modifiable attributes
+ short PaddingL, PaddingR;
+ short PaddingT, PaddingB;
+ short GapSize;
+
+ uint32_t Flags;
+
+ short FixedWith; //!< Fixed lengthways Size attribute (height)
+ short FixedCross; //!< Fixed Cross Size attribute (width)
+
+ tColour BackgroundColour;
+
+ char *Text;
+
+ // -- Attributes maitained by the element code
+ // Not touched by the user
+ short MinWith; //!< Minimum long size
+ short MinCross; //!< Minimum cross size
+ void *Data; //!< Per-type data
+
+ // -- Render Cache
+ short CachedX, CachedY;
+ short CachedW, CachedH;
+
+ char DebugName[];
+};
+struct sWidgetWin
+{
+ tElement RootElement;
+
+ int TableSize; //!< Number of entries, anything over will wrap
+ tElement *ElementTable[]; //!< Hash table essentially
+};
+
+// === FUNCTIONS ===
+extern void Widget_Decorator_RenderWidget(tWindow *Window, tElement *Element);
+
#endif
#ifndef _WM_H_
#define _WM_H_
+#include <image.h>
+
// === CONSTANTS ===
/**
* \brief Window Flags
extern int WM_MoveWindow(tWindow *Window, int X, int Y);
extern int WM_SendMessage(tWindow *Window, int MessageID, int Length, void *Data);
// --- Rendering
-extern void WM_Render_FilledRect(tWindow *Window, tColour Colour, int X, int Y, int W, int H);
+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);
+extern void WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, void *Font, tColour Colour, const char *Text);
+extern void WM_Render_DrawImage(tWindow *Window, int X, int Y, int W, int H, tImage *Image);
#endif
#ifndef _WM_MESSAGES_H_
#define _WM_MESSAGES_H_
+/**
+ * \brief Messages delivered to windows
+ */
enum eWM_WindowMessages
{
WNDMSG_NULL,
WNDMSG_DESTROY,
WNDMSG_FOCUS, // Called on change
WNDMSG_SHOW, // Called on change
+
+ WNDMSG_RESIZE,
WNDMSG_MOUSEMOVE,
WNDMSG_MOUSEBTN,
WNDMSG_CLASS_MAX = 0x2000,
};
+struct sWndMsg_Resize
+{
+ uint16_t W, H;
+};
+
#endif
{
struct sBgWin *info = Window->RendererInfo;
- WM_Render_FilledRect(Window, info->Colour, 0, 0, 0xFFFF, 0xFFFF);
+ WM_Render_FillRect(Window, 0, 0, 0xFFFF, 0xFFFF, info->Colour);
}
int Renderer_Background_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
void Renderer_Class_Redraw(tWindow *Window)
{
tClassfulInfo *info = Window->RendererInfo;
- WM_Render_FilledRect(Window, info->BGColour, 0, 0, Window->W, Window->H);
+ WM_Render_FillRect(Window, 0, 0, Window->W, Window->H, info->BGColour);
}
int Renderer_Class_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
#include <renderer_widget.h>
#include <string.h>
-// === TYPES ===
-typedef struct sWidgetWin tWidgetWin;
-typedef struct sAxWin_Element tElement;
-
-// === STRUCTURES ===
-struct sAxWin_Element
-{
- enum eElementTypes Type;
-
- uint32_t ID; //!< Application provided ID number
- tElement *ListNext; //!< Next element in bucket
-
- // Element Tree
- tElement *Parent;
- tElement *FirstChild;
- tElement *LastChild;
- tElement *NextSibling;
-
- // User modifiable attributes
- short PaddingL, PaddingR;
- short PaddingT, PaddingB;
- short GapSize;
-
- uint32_t Flags;
-
- short FixedWith; //!< Fixed lengthways Size attribute (height)
- short FixedCross; //!< Fixed Cross Size attribute (width)
-
- tColour BackgroundColour;
-
- char *Text;
-
- // -- Attributes maitained by the element code
- // Not touched by the user
- short MinWith; //!< Minimum long size
- short MinCross; //!< Minimum cross size
- void *Data; //!< Per-type data
-
- // -- Render Cache
- short CachedX, CachedY;
- short CachedW, CachedH;
-
- char DebugName[];
-};
-struct sWidgetWin
-{
- tElement RootElement;
-
- int TableSize; //!< Number of entries, anything over will wrap
- tElement *ElementTable[]; //!< Hash table essentially
-};
-
// === PROTOTYPES ===
+ int Renderer_Widget_Init(void);
tWindow *Renderer_Widget_Create(int Flags);
void Renderer_Widget_Redraw(tWindow *Window);
-int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data);
+void Widget_RenderWidget(tWindow *Window, tElement *Element);
+ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data);
+void Widget_UpdateDimensions(tElement *Element);
+void Widget_UpdatePosition(tElement *Element);
+tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID);
+void Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg);
// === GLOBALS ===
tWMRenderer gRenderer_Widget = {
void Renderer_Widget_Redraw(tWindow *Window)
{
tWidgetWin *info = Window->RendererInfo;
- WM_Render_FilledRect(Window, info->RootElement.BackgroundColour, 0, 0, 0xFFF, 0xFFF);
+ 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;
tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID)
{
tElement *ele;
+
+ if(ID == -1)
+ return &Info->RootElement;
if( ID < Info->TableSize ) return Info->ElementTable[ID];
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;
+ return 0; }
+
// New Widget
case MSG_WIDGET_CREATE:
Widget_NewWidget(info, Len, Data);
--- /dev/null
+/*
+ * 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
+
+// === 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;
+
+ 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;
+ }
+}
// --- WM Render Routines
// TODO: Move to another file?
-void WM_Render_FilledRect(tWindow *Window, tColour Colour, int X, int Y, int W, int H)
+void WM_Render_FillRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour)
{
uint32_t *dest;
int i;
}
}
+void WM_Render_DrawRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour)
+{
+ WM_Render_FillRect(Window, X, Y, W, 1, Colour);
+ WM_Render_FillRect(Window, X, Y+H-1, W, 1, Colour);
+ WM_Render_FillRect(Window, X, Y, 1, H, Colour);
+ WM_Render_FillRect(Window, X+W-1, Y, 1, H, Colour);
+}
+
+void WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, void *Font, tColour Colour, const char *Text)
+{
+ // TODO: Implement
+}
+
+/**
+ * \brief Draw an image to the screen
+ * \todo Maybe have support for an offset in the image
+ */
+void WM_Render_DrawImage(tWindow *Window, int X, int Y, int W, int H, tImage *Image)
+{
+ int x, y;
+ uint32_t *dest;
+ uint8_t *data;
+
+ // Sanity please
+ if( !Image ) return ;
+
+ // Allocate
+ if(!Window->RenderBuffer) {
+ Window->RenderBuffer = malloc(Window->W*Window->H*4);
+ }
+
+ // Bounds Check
+ if( X >= Window->W ) return ;
+ if( Y >= Window->H ) return ;
+
+ // Wrap to image size
+ if( W > Image->Width ) W = Image->Width;
+ if( H > Image->Height ) H = Image->Height;
+
+ // Wrap to screen size
+ if( X + W > Window->W ) W = Window->W - X;
+ if( Y + H > Window->H ) H = Window->H - Y;
+
+ dest = (uint32_t*)Window->RenderBuffer + Y * Window->W + X;
+ data = Image->Data;
+
+ // Do the render
+ switch( Image->Format )
+ {
+ case IMGFMT_BGRA:
+ for( y = 0; y < H; y ++ )
+ {
+ int r, g, b, a; // New
+ int or, og, ob; // Original
+ for( x = 0; x < W; x ++ )
+ {
+ b = data[x*4+0]; g = data[x*4+1]; r = data[x*4+2]; a = data[x*4+3];
+ if( a == 0 ) continue; // 100% transparent
+ ob = dest[x]&0xFF; og = (dest[x] >> 8)&0xFF; or = (dest[x] >> 16)&0xFF;
+ // Handle Alpha
+ switch(a)
+ {
+ // Transparent: Handled above
+ // Solid
+ case 0xFF: break;
+ // Half
+ case 0x80:
+ r = (or + r) / 2;
+ g = (og + g) / 2;
+ b = (ob + b) / 2;
+ break;
+ // General
+ default:
+ r = (or * (255-a) + r * a) / 255;
+ g = (og * (255-a) + g * a) / 255;
+ b = (ob * (255-a) + b * a) / 255;
+ break;
+ }
+ dest[x] = b | (g << 8) | (r << 16);
+ }
+ data += Image->Width * 4;
+ dest += Window->W;
+ }
+ break;
+
+ // RGB
+ case IMGFMT_RGB:
+ for( y = 0; y < H; y ++ )
+ {
+ for( x = 0; x < W; x ++ )
+ {
+ // Blue Green Red
+ dest[x] = data[x*3+2] | (data[x*3+1] << 8) | (data[x*3+0] << 16);
+ }
+ data += W * 3;
+ dest += Window->W;
+ }
+ break;
+ default:
+ _SysDebug("ERROR: Unknown image format %i\n", Image->Format);
+ break;
+ }
+}
+