From cee7338738f1a68c7eb7b956cab8d9fb83f95714 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 13 Nov 2011 22:08:52 +0800 Subject: [PATCH] Usermode/AxWin3 - Added decorator support - Alongside comes window titles :) --- .../Applications/axwin3_src/Interface/main.c | 59 +++++++++- Usermode/Applications/axwin3_src/WM/Makefile | 4 +- .../Applications/axwin3_src/WM/decorator.c | 103 ++++++++++++++++++ .../axwin3_src/WM/include/decorator.h | 18 +++ .../Applications/axwin3_src/WM/include/wm.h | 11 +- .../axwin3_src/WM/include/wm_internals.h | 15 ++- Usermode/Applications/axwin3_src/WM/ipc.c | 45 +++++++- .../axwin3_src/WM/renderer_menu.c | 24 ++-- .../axwin3_src/WM/renderer_widget.c | 26 ++++- .../axwin3_src/WM/renderer_widget_decorator.c | 25 +++++ Usermode/Applications/axwin3_src/WM/wm.c | 67 +++++++++++- .../Applications/axwin3_src/WM/wm_render.c | 52 ++++++--- .../axwin3_src/WM/wm_render_text.c | 18 ++- .../axwin3_src/include/ipcmessages.h | 8 +- .../libaxwin3.so_src/include/internal.h | 2 + .../axwin3_src/libaxwin3.so_src/wm.c | 31 +++++- Usermode/include/axwin3/axwin.h | 5 + Usermode/include/axwin3/widget.h | 2 + 18 files changed, 455 insertions(+), 60 deletions(-) create mode 100644 Usermode/Applications/axwin3_src/WM/decorator.c create mode 100644 Usermode/Applications/axwin3_src/WM/include/decorator.h diff --git a/Usermode/Applications/axwin3_src/Interface/main.c b/Usermode/Applications/axwin3_src/Interface/main.c index b4f01995..f8e35273 100644 --- a/Usermode/Applications/axwin3_src/Interface/main.c +++ b/Usermode/Applications/axwin3_src/Interface/main.c @@ -12,15 +12,20 @@ #include #define SIDEBAR_WIDTH 36 +#define RUN_WIDTH 200 +#define RUN_HEIGHT 70 // === PROTOTYPES === void create_sidebar(void); void create_mainmenu(void); +void create_run_dialog(void); // === GLOBALS === tHWND gSidebar; -tHWND gSystemMenu; tAxWin3_Widget *gSidebarRoot; +tHWND gSystemMenu; +tHWND gRunDialog; +tAxWin3_Widget *gRunInput; int giScreenWidth; int giScreenHeight; @@ -36,9 +41,13 @@ int main(int argc, char *argv[]) { // Connect to AxWin3 Server AxWin3_Connect(NULL); + + // TODO: Register to be told when the display layout changes + AxWin3_GetDisplayDims(0, NULL, NULL, &giScreenWidth, &giScreenHeight); create_sidebar(); create_mainmenu(); + create_run_dialog(); // Idle loop AxWin3_MainLoop(); @@ -50,9 +59,6 @@ void create_sidebar(void) { tAxWin3_Widget *btn, *txt, *ele; - // TODO: Register to be told when the display layout changes - AxWin3_GetDisplayDims(0, NULL, NULL, &giScreenWidth, &giScreenHeight); - // Create sidebar gSidebar = AxWin3_Widget_CreateWindow(NULL, SIDEBAR_WIDTH, giScreenHeight, ELEFLAG_VERTICAL); AxWin3_MoveWindow(gSidebar, 0, 0); @@ -82,6 +88,9 @@ void create_sidebar(void) AxWin3_Widget_SetSize(txt, 20); AxWin3_Widget_SetText(txt, "3.0"); + // Turn off decorations + AxWin3_DecorateWindow(gSidebar, 0); + // Show! AxWin3_ShowWindow(gSidebar, 1); @@ -95,6 +104,7 @@ void mainmenu_app_textedit(void *unused) void mainmenu_run_dialog(void *unused) { _SysDebug("TODO: Show run dialog"); + AxWin3_ShowWindow(gRunDialog, 1); } void create_mainmenu(void) @@ -106,3 +116,44 @@ void create_mainmenu(void) AxWin3_Menu_AddItem(gSystemMenu, "Run\tWin+R", mainmenu_run_dialog, NULL, 0, NULL); } +int run_dorun(tAxWin3_Widget *unused) +{ +// char *cmd = AxWin3_Widget_GetText(gRunInput); + AxWin3_ShowWindow(gRunDialog, 0); + return 0; +} + +int run_close(tAxWin3_Widget *unused) +{ + AxWin3_ShowWindow(gRunDialog, 0); + return 0; +} + +tAxWin3_Widget *make_textbutton(tAxWin3_Widget *Parent, const char *Label, tAxWin3_Widget_FireCb handler) +{ + tAxWin3_Widget *ret, *txt; + ret = AxWin3_Widget_AddWidget(Parent, ELETYPE_BUTTON, ELEFLAG_NOSTRETCH, "_btn"); + AxWin3_Widget_SetFireHandler(ret, handler); + txt = AxWin3_Widget_AddWidget(ret, ELETYPE_TEXT, 0, "_txt"); + AxWin3_Widget_SetText(ret, Label); + return ret; +} + +void create_run_dialog(void) +{ + tAxWin3_Widget *root, *box, *ele; + + gRunDialog = AxWin3_Widget_CreateWindow(NULL, RUN_WIDTH, RUN_HEIGHT, ELEFLAG_VERTICAL); + AxWin3_SetWindowTitle(gRunDialog, "Run Program..."); + + AxWin3_MoveWindow(gRunDialog, giScreenWidth/2-RUN_WIDTH/2, giScreenHeight/2-RUN_HEIGHT/2); + root = AxWin3_Widget_GetRoot(gRunDialog); + + gRunInput = AxWin3_Widget_AddWidget(root, ELETYPE_TEXTINPUT, 0, "Input"); + AxWin3_Widget_SetFireHandler(gRunInput, run_dorun); + + box = AxWin3_Widget_AddWidget(root, ELETYPE_BOX, ELEFLAG_ALIGN_CENTER|ELEFLAG_NOSTRETCH, "Button Area"); + ele = make_textbutton(box, "Ok", run_dorun); + ele = make_textbutton(box, "Cancel", run_close); +} + diff --git a/Usermode/Applications/axwin3_src/WM/Makefile b/Usermode/Applications/axwin3_src/WM/Makefile index 986ed6d6..0e501e03 100644 --- a/Usermode/Applications/axwin3_src/WM/Makefile +++ b/Usermode/Applications/axwin3_src/WM/Makefile @@ -8,7 +8,9 @@ DIR := Apps/AxWin/3.0 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 += renderer_classes.o renderer_passthru.o renderer_background.o +OBJ += decorator.o +OBJ += renderer_passthru.o +OBJ += renderer_background.o OBJ += renderer_widget.o renderer_widget_decorator.o OBJ += renderer_menu.o diff --git a/Usermode/Applications/axwin3_src/WM/decorator.c b/Usermode/Applications/axwin3_src/WM/decorator.c new file mode 100644 index 00000000..52ffbfb6 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/decorator.c @@ -0,0 +1,103 @@ +/* + * Acess2 Window Manager v3 (axwin3) + * - By John Hodge (thePowersGang) + * + * decorator.c + * - Window Decorator + */ +#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); + +// === CONSTANTS === +tColour cColourActive_Titlebar = 0xFF8800; +tColour cColourActive_TitleText = 0x000000; +tColour cColourInactive_Titlebar = 0xD0D0D0; +tColour cColourInactive_TitleText= 0x000000; +tColour cColour_SideBorder = 0xD0D0D0; +tColour cColour_BottomBorder = 0xD0D0D0; + int ciTitlebarHeight = 18; + int ciSideBorderWidth = 2; + int ciBottomBorderWidth = 4; + +// === CODE === +void Decorator_UpdateBorderSize(tWindow *Window) +{ + Window->BorderT = 0; + Window->BorderB = 0; + Window->BorderL = 0; + Window->BorderR = 0; + + Window->BorderT = ciTitlebarHeight; + if( Window->Flags & WINFLAG_MAXIMIZED ) + return ; + + Window->BorderB = ciBottomBorderWidth; + Window->BorderR = ciSideBorderWidth; + Window->BorderL = ciSideBorderWidth; +} + +void Decorator_Redraw(tWindow *Window) +{ + int bActive = 1; + int text_width, text_height; + + // TODO: Detect if window has focus + + // Draw title bar + WM_Render_FillRect(Window, + 0, -ciTitlebarHeight, Window->W, ciTitlebarHeight, + (bActive ? cColourActive_Titlebar : cColourInactive_Titlebar) + ); + + WM_Render_GetTextDims( + NULL, // TODO: Select font + Window->Title ? Window->Title : "jI", + &text_width, &text_height + ); + WM_Render_DrawText(Window, + ciTitlebarHeight + 4, -(ciTitlebarHeight - (ciTitlebarHeight/2 - text_height/2)), + Window->W - ciTitlebarHeight - 4, text_height, + NULL, // TODO: Select font + (bActive ? cColourActive_TitleText : cColourInactive_TitleText), + Window->Title ? Window->Title : "--" + ); + + // Maximized windows don't have any other borders + if( Window->Flags & WINFLAG_MAXIMIZED ) + return ; + + // Left + WM_Render_FillRect(Window, + -ciSideBorderWidth, -ciTitlebarHeight, + ciSideBorderWidth, Window->H + ciTitlebarHeight + ciBottomBorderWidth, + cColour_SideBorder + ); + // Right + WM_Render_FillRect(Window, + Window->W, -ciTitlebarHeight, + ciSideBorderWidth, Window->H + ciTitlebarHeight + ciBottomBorderWidth, + cColour_SideBorder + ); + // Bottom + WM_Render_FillRect(Window, + -ciSideBorderWidth, Window->H, + ciSideBorderWidth*2+Window->W, ciBottomBorderWidth, + cColour_BottomBorder + ); +} + +int Decorator_HandleMessage(tWindow *Window, int Message, int Length, void *Data) +{ + switch(Message) + { + 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 new file mode 100644 index 00000000..ae84cdb5 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/include/decorator.h @@ -0,0 +1,18 @@ +/* + * Acess2 Window Manager v3 (axwin3) + * - By John Hodge (thePowersGang) + * + * include/decorator.h + * - Decorator definitions + */ +#ifndef _DECORATOR_H_ +#define _DECORATOR_H_ + +#include + +extern void Decorator_UpdateBorderSize(tWindow *Window); +extern void Decorator_Redraw(tWindow *Window); +extern int Decorator_HandleMessage(tWindow *Window, int Message, int Length, void *Data); + +#endif + diff --git a/Usermode/Applications/axwin3_src/WM/include/wm.h b/Usermode/Applications/axwin3_src/WM/include/wm.h index d6fd3ad2..d35a4624 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm.h @@ -8,6 +8,9 @@ #ifndef _WM_H_ #define _WM_H_ +#include +#include + #include "image.h" // === CONSTANTS === @@ -17,8 +20,10 @@ */ //! Render the window #define WINFLAG_SHOW 0x00000001 -//! Window isn't contained within the parent/owner -#define WINFLAG_NONNESTED 0x00000002 +//! Don't decoratate even if root +#define WINFLAG_NODECORATE 0x00000002 +//! Window takes up all of screen +#define WINFLAG_MAXIMIZED 0x00000005 //! Window contents are valid #define WINFLAG_CLEAN 0x00000040 //! All child windows are un-changed @@ -41,9 +46,11 @@ typedef struct sIPC_Client tIPC_Client; // --- Management extern tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int Flags, const char *Renderer); extern void WM_Invalidate(tWindow *Window); +extern void WM_SetWindowTitle(tWindow *Window, const char *Title); extern void WM_FocusWindow(tWindow *Destination); extern void WM_RaiseWindow(tWindow *Window); 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); diff --git a/Usermode/Applications/axwin3_src/WM/include/wm_internals.h b/Usermode/Applications/axwin3_src/WM/include/wm_internals.h index 9b3c7f08..92bde4a7 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm_internals.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm_internals.h @@ -24,12 +24,17 @@ struct sWindow uint32_t ID; //!< Client assigned ID tWMRenderer *Renderer; + char *Title; + int Flags; - - int X; - int Y; - int W; - int H; + + int BorderL, BorderR; + int BorderT, BorderB; + + int RealW, RealH; + + int X, Y; + int W, H; void *RendererInfo; diff --git a/Usermode/Applications/axwin3_src/WM/ipc.c b/Usermode/Applications/axwin3_src/WM/ipc.c index ffad8e5d..46aff215 100644 --- a/Usermode/Applications/axwin3_src/WM/ipc.c +++ b/Usermode/Applications/axwin3_src/WM/ipc.c @@ -331,9 +331,24 @@ int IPC_Msg_CreateWin(tIPC_Client *Client, tAxWin_IPCMessage *Msg) return 0; } +int IPC_Msg_SetWindowTitle(tIPC_Client *Client, tAxWin_IPCMessage *Msg) +{ + tWindow *win; + + if( Msg->Size < 1 ) return -1; + if( Msg->Data[ Msg->Size-1 ] != '\0' ) return -1; + + win = IPC_int_GetWindow(Client, Msg->Window); + if(!win) return 1; + + WM_SetWindowTitle(win, Msg->Data); + + return 0; +} + int IPC_Msg_ShowWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg) { - tIPCMsg_ShowWindow *info = (void*)Msg->Data; + tIPCMsg_Boolean *info = (void*)Msg->Data; tWindow *win; if( Msg->Size < sizeof(*info) ) return -1; @@ -341,8 +356,22 @@ int IPC_Msg_ShowWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg) win = IPC_int_GetWindow(Client, Msg->Window); if(!win) return 1; - WM_ShowWindow(win, !!info->bShow); + WM_ShowWindow(win, !!info->Value); + + return 0; +} + +int IPC_Msg_DecorateWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg) +{ + tIPCMsg_Boolean *info = (void*)Msg->Data; + tWindow *win; + if( Msg->Size < sizeof(*info) ) return -1; + + win = IPC_int_GetWindow(Client, Msg->Window); + if(!win) return 1; + + WM_DecorateWindow(win, !!info->Value); return 0; } @@ -474,6 +503,14 @@ void IPC_Handle(const tIPC_Type *IPCType, const void *Ident, size_t MsgLen, tAxW _SysDebug(" IPC_Handle: IPCMSG_CREATEWIN"); rv = IPC_Msg_CreateWin(client, Msg); break; + // TODO: Destroy window + + // --- Set window title + case IPCMSG_SETWINTITLE: + _SysDebug(" IPC_Handle: IPCMSG_SETWINTITLE"); + rv = IPC_Msg_SetWindowTitle(client, Msg); + break; + // --- Give a window focus case IPCMSG_FOCUSWINDOW: _SysDebug(" IPC_Handle: IPCMSG_FOCUSWINDOW"); @@ -484,6 +521,10 @@ void IPC_Handle(const tIPC_Type *IPCType, const void *Ident, size_t MsgLen, tAxW _SysDebug(" IPC_Handle: IPCMSG_SHOWWINDOW"); rv = IPC_Msg_ShowWindow(client, Msg); break; + case IPCMSG_DECORATEWINDOW: + _SysDebug(" IPC_Handle: IPCMSG_DECORATEWINDOW"); + rv = IPC_Msg_DecorateWindow(client, Msg); + break; // --- Move/Resize a window case IPCMSG_SETWINPOS: _SysDebug(" IPC_Handle: IPCMSG_SETWINPOS"); diff --git a/Usermode/Applications/axwin3_src/WM/renderer_menu.c b/Usermode/Applications/axwin3_src/WM/renderer_menu.c index 7d07c93a..45c6a241 100644 --- a/Usermode/Applications/axwin3_src/WM/renderer_menu.c +++ b/Usermode/Applications/axwin3_src/WM/renderer_menu.c @@ -93,7 +93,10 @@ tWindow *Renderer_Menu_Create(int Argument) info->MaxItems = Argument; info->HilightedItem = -1; - _SysDebug("Renderer_Menu_Create: ->MaxItems = %i", info->MaxItems); + ret->Flags |= WINFLAG_NODECORATE; + ret->H = ciMenu_TopPadding + ciMenu_BottomPadding; + +// _SysDebug("Renderer_Menu_Create: ->MaxItems = %i", info->MaxItems); return ret; } @@ -104,6 +107,7 @@ void Renderer_Menu_Redraw(tWindow *Window) int w, h, y, i; w = info->CachedW; + #if 0 h = ciMenu_TopPadding + ciMenu_BottomPadding; for( i = 0; i < info->nItems; i ++ ) { @@ -114,12 +118,12 @@ void Renderer_Menu_Redraw(tWindow *Window) else h += ciMenu_SpacerHeight; } + #else + h = Window->H; + #endif // _SysDebug("w = %i, h = %i", w, h); - // - Resize window to contain all items - WM_ResizeWindow(Window, w, h); - // - Move the window such that it is on screen // > Make sure to catch if the menu can't fit fully onscreen @@ -212,7 +216,10 @@ int Renderer_Menu_int_AddItem(tWindow *Window, int Length, void *Data) } // Don't overwrite - if(info->Items[req->ID]) return 0; + 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 @@ -223,6 +230,7 @@ int Renderer_Menu_int_AddItem(tWindow *Window, int Length, void *Data) { // Spacer item->Label = NULL; + WM_ResizeWindow(Window, info->CachedW, Window->H+ciMenu_SpacerHeight); return 0; } @@ -300,10 +308,8 @@ int Renderer_Menu_int_AddItem(tWindow *Window, int Length, void *Data) info->CachedW = ciMenu_LeftPadding + info->MaxLabelWidth + ciMenu_Gap + info->MaxShortcutWidth + ciMenu_RightPadding; - // TODO: Smarter height? - // Doesn't matter a lot here really - WM_ResizeWindow(Window, info->CachedW, info->nItems*ciMenu_ItemHeight); } + WM_ResizeWindow(Window, info->CachedW, Window->H+ciMenu_ItemHeight); return 0; } @@ -414,7 +420,7 @@ int Renderer_Menu_HandleMessage(tWindow *Window, int Msg, int Length, void *Data // Manipulation messages case MSG_MENU_ADDITEM: - _SysDebug("MSG_MENU_ADDITEM"); +// _SysDebug("MSG_MENU_ADDITEM"); return Renderer_Menu_int_AddItem(Window, Length, Data); // Only message to pass to client diff --git a/Usermode/Applications/axwin3_src/WM/renderer_widget.c b/Usermode/Applications/axwin3_src/WM/renderer_widget.c index 2c47bb7e..c4799e99 100644 --- a/Usermode/Applications/axwin3_src/WM/renderer_widget.c +++ b/Usermode/Applications/axwin3_src/WM/renderer_widget.c @@ -31,9 +31,10 @@ 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_TextBox_UpdateText(tElement *Element, const char *Text); +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 = { @@ -68,9 +69,11 @@ struct { } gaWM_WidgetTypes[NUM_ELETYPES] = { {0}, // NULL {0}, // Box - {.UpdateText = Widget_TextBox_UpdateText}, // Text + {.UpdateText = Widget_DispText_UpdateText}, // Text {.UpdateText = Widget_Image_UpdateText}, // Image - {.MouseButton = Widget_Button_MouseButton} // Button + {.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]); @@ -604,7 +607,7 @@ void Widget_Fire(tElement *Element) } // --- Type Helpers -void Widget_TextBox_UpdateText(tElement *Element, const char *Text) +void Widget_DispText_UpdateText(tElement *Element, const char *Text) { int w=0, h=0; @@ -660,3 +663,18 @@ int Widget_Button_MouseButton(tElement *Element, int X, int Y, int Button, int b 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 index e66da733..8f6309f9 100644 --- a/Usermode/Applications/axwin3_src/WM/renderer_widget_decorator.c +++ b/Usermode/Applications/axwin3_src/WM/renderer_widget_decorator.c @@ -16,6 +16,8 @@ #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) @@ -93,6 +95,29 @@ void Widget_Decorator_RenderWidget(tWindow *Window, tElement *Element) 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( diff --git a/Usermode/Applications/axwin3_src/WM/wm.c b/Usermode/Applications/axwin3_src/WM/wm.c index 17540a8a..a056a52b 100644 --- a/Usermode/Applications/axwin3_src/WM/wm.c +++ b/Usermode/Applications/axwin3_src/WM/wm.c @@ -11,6 +11,7 @@ #include #include #include +#include // === IMPORTS === extern void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int Msg, int Len, void *Data); @@ -27,7 +28,7 @@ void WM_Initialise(void) WM_CreateWindow(NULL, NULL, 0, 0x0088FF, "Background"); gpWM_RootWindow->W = giScreenWidth; gpWM_RootWindow->H = giScreenHeight; - gpWM_RootWindow->Flags = WINFLAG_SHOW; + gpWM_RootWindow->Flags = WINFLAG_SHOW|WINFLAG_NODECORATE; } void WM_RegisterRenderer(tWMRenderer *Renderer) @@ -61,7 +62,7 @@ tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int ret->ID = ID; ret->Parent = Parent; ret->Renderer = renderer; - ret->Flags = WINFLAG_CLEAN; // Needed to stop invaildate early exiting + ret->Flags |= WINFLAG_CLEAN; // Needed to stop invaildate early exiting // Append to parent if(Parent) @@ -79,6 +80,12 @@ tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int gpWM_RootWindow = ret; } + // Don't decorate child windows by default + if(Parent != gpWM_RootWindow) + { + ret->Flags |= WINFLAG_NODECORATE; + } + // - Return! return ret; } @@ -93,6 +100,14 @@ tWindow *WM_CreateWindowStruct(size_t ExtraSize) return ret; } +void WM_SetWindowTitle(tWindow *Window, const char *Title) +{ + if(Window->Title) + free(Window->Title); + Window->Title = strdup(Title); + _SysDebug("Window %p title set to '%s'", Window, Title); +} + void WM_RaiseWindow(tWindow *Window) { tWindow *parent = Window->Parent; @@ -154,6 +169,27 @@ void WM_ShowWindow(tWindow *Window, int bShow) if( Window == gpWM_FocusedWindow ) WM_FocusWindow(Window->Parent); } + // Just a little memory saving for large hidden windows + if(Window->RenderBuffer) + free(Window->RenderBuffer); + + WM_Invalidate(Window); +} + +void WM_DecorateWindow(tWindow *Window, int bDecorate) +{ + if( !(Window->Flags & WINFLAG_NODECORATE) == !!bDecorate ) + return ; + + if(bDecorate) + Window->Flags &= ~WINFLAG_NODECORATE; + else + Window->Flags |= WINFLAG_NODECORATE; + + // Needed because the window size changes + if(Window->RenderBuffer) + free(Window->RenderBuffer); + WM_Invalidate(Window); } @@ -177,9 +213,11 @@ int WM_ResizeWindow(tWindow *Window, int W, int H) if(W <= 0 || H <= 0 ) return 1; if(Window->X + W < 0) Window->X = -W + 1; if(Window->Y + H < 0) Window->Y = -H + 1; - + Window->W = W; Window->H = H; + if(Window->RenderBuffer) + free(Window->RenderBuffer); WM_Invalidate(Window); { @@ -252,6 +290,25 @@ void WM_int_UpdateWindow(tWindow *Window) // Render if( !(Window->Flags & WINFLAG_CLEAN) ) { + // Calculate RealW/RealH + if( !(Window->Flags & WINFLAG_NODECORATE) ) + { + _SysDebug("Applying decorations to %p", Window); + Decorator_UpdateBorderSize(Window); + Window->RealW = Window->BorderL + Window->W + Window->BorderR; + Window->RealH = Window->BorderT + Window->H + Window->BorderB; + Decorator_Redraw(Window); + } + else + { + Window->BorderL = 0; + Window->BorderR = 0; + Window->BorderT = 0; + Window->BorderB = 0; + Window->RealW = Window->W; + Window->RealH = Window->H; + } + Window->Renderer->Redraw(Window); Window->Flags |= WINFLAG_CLEAN; } @@ -276,8 +333,8 @@ void WM_int_BlitWindow(tWindow *Window) if( !(Window->Flags & WINFLAG_SHOW) ) return ; - _SysDebug("Blit %p to (%i,%i) %ix%i", Window, Window->X, Window->Y, Window->W, Window->H); - Video_Blit(Window->RenderBuffer, Window->X, Window->Y, Window->W, Window->H); + _SysDebug("Blit %p to (%i,%i) %ix%i", Window, Window->X, Window->Y, Window->RealW, Window->RealH); + Video_Blit(Window->RenderBuffer, Window->X, Window->Y, Window->RealW, Window->RealH); for( child = Window->FirstChild; child; child = child->NextSibling ) { diff --git a/Usermode/Applications/axwin3_src/WM/wm_render.c b/Usermode/Applications/axwin3_src/WM/wm_render.c index 7f4a53b3..84b7b412 100644 --- a/Usermode/Applications/axwin3_src/WM/wm_render.c +++ b/Usermode/Applications/axwin3_src/WM/wm_render.c @@ -15,23 +15,26 @@ void WM_Render_FillRect(tWindow *Window, int X, int Y, int W, int H, tColour Col { uint32_t *dest; int i; -// _SysDebug("WM_Render_FilledRect(%p, 0x%x...", Window, Colour); -// _SysDebug(" (%i,%i), %ix%i)", X, Y, W, H); + + X += Window->BorderL; + Y += Window->BorderT; + // Clip to window dimensions if(X < 0) { W += X; X = 0; } if(Y < 0) { H += Y; Y = 0; } if(W <= 0 || H <= 0) return; - if(X >= Window->W) return; - if(Y >= Window->H) return; - if(X + W > Window->W) W = Window->W - X; - if(Y + H > Window->H) H = Window->H - Y; -// _SysDebug(" Clipped to (%i,%i), %ix%i", X, Y, W, H); + if(X >= Window->RealW) return; + if(Y >= Window->RealH) return; + if(X + W > Window->RealW) W = Window->RealW - X; + if(Y + H > Window->RealH) H = Window->RealH - Y; + + // TODO: Catch overflow into decorator area if(!Window->RenderBuffer) { - Window->RenderBuffer = malloc(Window->W*Window->H*4); + Window->RenderBuffer = malloc(Window->RealW*Window->RealH*4); } - dest = (uint32_t*)Window->RenderBuffer + Y*Window->W + X; + dest = (uint32_t*)Window->RenderBuffer + Y*Window->RealW + X; while( H -- ) { for( i = W; i --; ) @@ -65,20 +68,35 @@ void WM_Render_DrawImage(tWindow *Window, int X, int Y, int W, int H, tImage *Im if(!Window->RenderBuffer) { Window->RenderBuffer = malloc(Window->W*Window->H*4); } - + + // Apply offset + X += Window->BorderL; + Y += Window->BorderT; + // Bounds Check - if( X >= Window->W ) return ; - if( Y >= Window->H ) return ; + if( X >= Window->RealW ) return ; + if( Y >= Window->RealH ) 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; + if( X + W > Window->RealW ) W = Window->RealW - X; + if( Y + H > Window->RealH ) H = Window->RealH - Y; + + // TODO: Catch overflow into decorator area + #if 0 + if( !Window->bDrawingDecorations ) + { + if( X < Window->BorderL ) return ; + if( Y < Window->BorderT ) return ; + if( X + W > Window->BorderL + Window->W ) W = X - (Window->BorderL + Window->W); + if( Y + H > Window->BorderT + Window->H ) H = Y - (Window->BorderT + Window->H); + } + #endif - dest = (uint32_t*)Window->RenderBuffer + Y * Window->W + X; + dest = (uint32_t*)Window->RenderBuffer + Y * Window->RealW + X; data = Image->Data; // Do the render @@ -116,7 +134,7 @@ void WM_Render_DrawImage(tWindow *Window, int X, int Y, int W, int H, tImage *Im dest[x] = b | (g << 8) | (r << 16); } data += Image->Width * 4; - dest += Window->W; + dest += Window->RealW; } break; @@ -130,7 +148,7 @@ void WM_Render_DrawImage(tWindow *Window, int X, int Y, int W, int H, tImage *Im dest[x] = data[x*3+2] | (data[x*3+1] << 8) | (data[x*3+0] << 16); } data += W * 3; - dest += Window->W; + dest += Window->RealW; } break; default: diff --git a/Usermode/Applications/axwin3_src/WM/wm_render_text.c b/Usermode/Applications/axwin3_src/WM/wm_render_text.c index 362669bf..4ce35cb7 100644 --- a/Usermode/Applications/axwin3_src/WM/wm_render_text.c +++ b/Usermode/Applications/axwin3_src/WM/wm_render_text.c @@ -78,13 +78,19 @@ int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, if(!Text) return 0; + + X += Window->BorderL; + Y += Window->BorderT; + // Check the bounds - if(W < 0 || X < 0 || X >= Window->W) return 0; - if(X + W > Window->W) W = Window->W - X; + if(W < 0 || X < 0 || X >= Window->RealW) return 0; + if(X + W > Window->RealW) W = Window->RealW - X; - if(H < 0 || Y < 0 || Y >= Window->H) return 0; - if(Y + H > Window->H) H = Window->H - Y; + if(H < 0 || Y < 0 || Y >= Window->RealH) return 0; + if(Y + H > Window->RealH) H = Window->RealH - Y; + // TODO: Catch trampling of decorations + // Handle NULL font (system default monospace) if( !Font ) Font = &gSystemFont; @@ -239,7 +245,7 @@ void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Col } // _SysDebug("X = %i, Y = %i", X, Y); - outBuf = (uint32_t*)Window->RenderBuffer + Y*Window->W + X; + outBuf = (uint32_t*)Window->RenderBuffer + Y*Window->RealW + X; inBuf = Glyph->Bitmap + yStart*Glyph->TrueWidth; for( y = yStart; y < Glyph->TrueHeight; y ++ ) @@ -248,7 +254,7 @@ void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Col { outBuf[dst_x] = Video_AlphaBlend( outBuf[dst_x], Color, inBuf[x] ); } - outBuf += Window->W; + outBuf += Window->RealW; inBuf += Glyph->TrueWidth; } } diff --git a/Usermode/Applications/axwin3_src/include/ipcmessages.h b/Usermode/Applications/axwin3_src/include/ipcmessages.h index a3fda63b..a752e368 100644 --- a/Usermode/Applications/axwin3_src/include/ipcmessages.h +++ b/Usermode/Applications/axwin3_src/include/ipcmessages.h @@ -14,7 +14,7 @@ typedef struct sAxWin_IPCMessage tAxWin_IPCMessage; typedef struct sIPCMsg_ReturnInt tIPCMsg_ReturnInt; typedef struct sIPCMsg_CreateWin tIPCMsg_CreateWin; -typedef struct sIPCMsg_ShowWindow tIPCMsg_ShowWindow; +typedef struct sIPCMsg_Boolean tIPCMsg_Boolean; typedef struct sIPCMsg_SetWindowPos tIPCMsg_SetWindowPos; typedef struct sIPCMsg_SendMsg tIPCMsg_SendMsg; @@ -60,9 +60,9 @@ struct sIPCMsg_SendMsg char Data[]; }; -struct sIPCMsg_ShowWindow +struct sIPCMsg_Boolean { - uint32_t bShow; + uint32_t Value; }; struct sIPCMsg_SetWindowPos @@ -95,7 +95,9 @@ enum eAxWin_IPCMessageTypes IPCMSG_SENDMSG, //!< Send a message to another window (or to self) IPCMSG_CREATEWIN, //!< Create a window IPCMSG_DESTROYWIN, //!< Destroy a window + IPCMSG_SETWINTITLE, //!< Set window title IPCMSG_SHOWWINDOW, //!< Show/Hide a window + IPCMSG_DECORATEWINDOW, //!< Enable/Disable decorations IPCMSG_FOCUSWINDOW, //!< Give a window focus (no data) IPCMSG_SETWINPOS, //!< Set a window position }; diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/include/internal.h b/Usermode/Applications/axwin3_src/libaxwin3.so_src/include/internal.h index f7fd2576..913cf35c 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/include/internal.h +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/include/internal.h @@ -10,6 +10,8 @@ #include +extern void _SysDebug(const char *Fmt, ...); + struct sAxWin3_Window { uint32_t ServerID; diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c index d64bcbc8..4a6242b1 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c @@ -196,6 +196,19 @@ void AxWin3_int_HandleMessage(tAxWin_IPCMessage *Msg) } } +void AxWin3_SetWindowTitle(tHWND Window, const char *Title) +{ + tAxWin_IPCMessage *msg; + int len = strlen(Title); + + msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SETWINTITLE, 0, len+1); + strcpy(msg->Data, Title); + + AxWin3_int_SendIPCMessage(msg); + + free(msg); +} + void AxWin3_SendMessage(tHWND Window, tHWND Destination, int Message, int Length, void *Data) { tAxWin_IPCMessage *msg; @@ -225,11 +238,25 @@ void AxWin3_FocusWindow(tHWND Window) void AxWin3_ShowWindow(tHWND Window, int bShow) { tAxWin_IPCMessage *msg; - tIPCMsg_ShowWindow *info; + tIPCMsg_Boolean *info; msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SHOWWINDOW, 0, sizeof(*info)); info = (void*)msg->Data; - info->bShow = !!bShow; + info->Value = !!bShow; + + AxWin3_int_SendIPCMessage(msg); + + free(msg); +} + +void AxWin3_DecorateWindow(tHWND Window, int bDecorate) +{ + tAxWin_IPCMessage *msg; + tIPCMsg_Boolean *info; + + msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_DECORATEWINDOW, 0, sizeof(*info)); + info = (void*)msg->Data; + info->Value = !!bDecorate; AxWin3_int_SendIPCMessage(msg); diff --git a/Usermode/include/axwin3/axwin.h b/Usermode/include/axwin3/axwin.h index 07bfe045..fe116e9d 100644 --- a/Usermode/include/axwin3/axwin.h +++ b/Usermode/include/axwin3/axwin.h @@ -8,6 +8,9 @@ #ifndef _AXWIN3_AXWIN_H_ #define _AXWIN3_AXWIN_H_ +// === CONSTANTS === + +// === TYPES === typedef struct sAxWin3_Window *tHWND; typedef unsigned int tAxWin3_Colour; // TODO: Actual 32-bit @@ -49,8 +52,10 @@ extern void AxWin3_DestroyWindow(tHWND Window); // --- Core window management functions extern void AxWin3_SendMessage(tHWND Window, tHWND Dest, int Message, int Length, void *Data); +extern void AxWin3_SetWindowTitle(tHWND Window, const char *Title); extern void AxWin3_FocusWindow(tHWND Window); extern void AxWin3_ShowWindow(tHWND Window, int bShow); +extern void AxWin3_DecorateWindow(tHWND Window, int bDecorate); extern void AxWin3_SetWindowPos(tHWND Window, short X, short Y, short W, short H); extern void AxWin3_MoveWindow(tHWND Window, short X, short Y); extern void AxWin3_ResizeWindow(tHWND Window, short W, short H); diff --git a/Usermode/include/axwin3/widget.h b/Usermode/include/axwin3/widget.h index fca8f049..03294257 100644 --- a/Usermode/include/axwin3/widget.h +++ b/Usermode/include/axwin3/widget.h @@ -49,6 +49,8 @@ enum eElementTypes ELETYPE_IMAGE, //!< Image ELETYPE_BUTTON, //!< Push Button ELETYPE_SPACER, //!< Visual Spacer (horizontal / vertical rule) + ELETYPE_TEXTINPUT, //!< Text Input Field + ELETYPE_TEXTBOX, //!< Text Box Input ELETYPE_TABBAR, //!< Tab Bar ELETYPE_TOOLBAR, //!< Tool Bar -- 2.20.1