From: John Hodge Date: Thu, 17 Nov 2011 14:15:27 +0000 (+0800) Subject: Usermode/AxWin3 - Splitting widget types out into separate files X-Git-Tag: rel0.14~92 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=2f16fec349eabb42f5e23ea2b821f149fa6b767e;p=tpg%2Facess2.git Usermode/AxWin3 - Splitting widget types out into separate files --- diff --git a/Usermode/Applications/axwin3_src/Interface/main.c b/Usermode/Applications/axwin3_src/Interface/main.c index 61ba4ac3..d43845b5 100644 --- a/Usermode/Applications/axwin3_src/Interface/main.c +++ b/Usermode/Applications/axwin3_src/Interface/main.c @@ -11,7 +11,7 @@ #include #include -#define SIDEBAR_WIDTH 36 +#define SIDEBAR_WIDTH 40 #define RUN_WIDTH 200 #define RUN_HEIGHT 70 diff --git a/Usermode/Applications/axwin3_src/WM/Makefile b/Usermode/Applications/axwin3_src/WM/Makefile index 0e501e03..60669b77 100644 --- a/Usermode/Applications/axwin3_src/WM/Makefile +++ b/Usermode/Applications/axwin3_src/WM/Makefile @@ -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 diff --git a/Usermode/Applications/axwin3_src/WM/decorator.c b/Usermode/Applications/axwin3_src/WM/decorator.c index 52ffbfb6..d1e24610 100644 --- a/Usermode/Applications/axwin3_src/WM/decorator.c +++ b/Usermode/Applications/axwin3_src/WM/decorator.c @@ -8,17 +8,19 @@ #include #include #include +#include // === 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; } diff --git a/Usermode/Applications/axwin3_src/WM/include/decorator.h b/Usermode/Applications/axwin3_src/WM/include/decorator.h index ae84cdb5..26505843 100644 --- a/Usermode/Applications/axwin3_src/WM/include/decorator.h +++ b/Usermode/Applications/axwin3_src/WM/include/decorator.h @@ -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 diff --git a/Usermode/Applications/axwin3_src/WM/include/wm.h b/Usermode/Applications/axwin3_src/WM/include/wm.h index d35a4624..1c0671f5 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm.h @@ -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); diff --git a/Usermode/Applications/axwin3_src/WM/include/wm_messages.h b/Usermode/Applications/axwin3_src/WM/include/wm_messages.h index df20d775..a64ac99e 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm_messages.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm_messages.h @@ -50,7 +50,7 @@ struct sWndMsg_MouseMove struct sWndMsg_MouseButton { - uint16_t X, Y; + int16_t X, Y; uint8_t Button; uint8_t bPressed; }; diff --git a/Usermode/Applications/axwin3_src/WM/include/wm_renderer.h b/Usermode/Applications/axwin3_src/WM/include/wm_renderer.h index b734348f..58825491 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm_renderer.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm_renderer.h @@ -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 index 7772cddb..00000000 --- a/Usermode/Applications/axwin3_src/WM/renderer_background.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Acess2 Window Manager v3 - * - By John Hodge (thePowersGang) - * - * render_widget.c - * - AxWin2 Background port - */ -#include -#include - -// === 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 index 4b0f3c61..00000000 --- a/Usermode/Applications/axwin3_src/WM/renderer_classes.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Acess2 Window Manager v3 - * - By John Hodge (thePowersGang) - * - * render_classes.c - * - Simple class based window renderer - */ -#include -#include -#include - -// === 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 index 45c6a241..00000000 --- a/Usermode/Applications/axwin3_src/WM/renderer_menu.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Acess2 Window Manager v3 - * - By John Hodge (thePowersGang) - * - * render_menu.c - * - Pop-up menu window class/renderer - */ -#include -#include -#include -#include -#include -#include - -// === 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 index 6e16e6a2..00000000 --- a/Usermode/Applications/axwin3_src/WM/renderer_passthru.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Acess2 Window Manager v3 - * - By John Hodge (thePowersGang) - * - * renderer_passthru.c - * - Passthrough window render (framebuffer essentially) - */ -#include -#include - -// === 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 index c4799e99..00000000 --- a/Usermode/Applications/axwin3_src/WM/renderer_widget.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Acess2 Window Manager v3 - * - By John Hodge (thePowersGang) - * - * render_widget.c - * - AxWin2 Widget port - */ -#include -#include -#include -#include -#include -#include -#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 index 8f6309f9..00000000 --- a/Usermode/Applications/axwin3_src/WM/renderer_widget_decorator.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Acess2 Window Manager v3 - * - By John Hodge (thePowersGang) - * - * renderer_widget_decorator.c - * - Widget Decorator - */ -#include -#include -#include - -#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 index 00000000..d67ca743 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/background.c @@ -0,0 +1,71 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * render_widget.c + * - AxWin2 Background port + */ +#include +#include + +// === 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 index 00000000..4b0f3c61 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/classes.c @@ -0,0 +1,69 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * render_classes.c + * - Simple class based window renderer + */ +#include +#include +#include + +// === 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 index 00000000..4506ad25 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/menu.c @@ -0,0 +1,431 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * render_menu.c + * - Pop-up menu window class/renderer + */ +#include +#include +#include +#include +#include +#include + +// === 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 index 00000000..9cd112c0 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/passthru.c @@ -0,0 +1,45 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * renderer_passthru.c + * - Passthrough window render (framebuffer essentially) + */ +#include +#include + +// === 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 index 00000000..1bd437da --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget.c @@ -0,0 +1,610 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * render_widget.c + * - AxWin2 Widget port + */ +#include +#include +#include +#include +#include +#include +#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 index 00000000..e4b252c3 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget/button.c @@ -0,0 +1,42 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * renderer/widget/button.c + * - Button Widget Type + */ +#include +#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 index 00000000..75500223 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget/colours.h @@ -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 index 00000000..b4913334 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget/common.h @@ -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 // 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 index 00000000..4a091def --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget/disptext.c @@ -0,0 +1,48 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * renderer/widget/button.c + * - Button Widget Type + */ +#include +#include "./common.h" +#include "./colours.h" +#include + +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 index 00000000..f1f3155c --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget/image.c @@ -0,0 +1,53 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * renderer/widget/image.c + * - Image Widget Type + */ +#include +#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 index 00000000..c2eea82c --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c @@ -0,0 +1,55 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * renderer/widget/textinput.c + * - Single line text box + */ +#include +#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 index 00000000..442e9fcc --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget/widget_decorator.c @@ -0,0 +1,96 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * renderer_widget_decorator.c + * - Widget Decorator + */ +#include +#include +#include + +#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; + } +} diff --git a/Usermode/Applications/axwin3_src/WM/wm.c b/Usermode/Applications/axwin3_src/WM/wm.c index a056a52b..dad3b6eb 100644 --- a/Usermode/Applications/axwin3_src/WM/wm.c +++ b/Usermode/Applications/axwin3_src/WM/wm.c @@ -14,7 +14,7 @@ #include // === 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 ) diff --git a/Usermode/Applications/axwin3_src/WM/wm_input.c b/Usermode/Applications/axwin3_src/WM/wm_input.c index 66088f92..f15d25a7 100644 --- a/Usermode/Applications/axwin3_src/WM/wm_input.c +++ b/Usermode/Applications/axwin3_src/WM/wm_input.c @@ -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); }