From 637cd82c20678638c93d7ee0b8ce81a597e8f8d2 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 10 Nov 2011 09:23:13 +0800 Subject: [PATCH] Usermode/AxWin3 - Adding pop-up menu support (via a new window type) --- .../Applications/axwin3_src/Interface/main.c | 20 +++ .../axwin3_src/WM/renderer_menu.c | 166 ++++++++++++++++++ .../axwin3_src/include/menu_messages.h | 42 +++++ .../axwin3_src/libaxwin3.so_src/Makefile | 2 +- .../axwin3_src/libaxwin3.so_src/r_menu.c | 112 ++++++++++++ .../axwin3_src/libaxwin3.so_src/r_widget.c | 4 +- Usermode/include/axwin3/menu.h | 26 +++ 7 files changed, 369 insertions(+), 3 deletions(-) create mode 100644 Usermode/Applications/axwin3_src/WM/renderer_menu.c create mode 100644 Usermode/Applications/axwin3_src/include/menu_messages.h create mode 100644 Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c create mode 100644 Usermode/include/axwin3/menu.h diff --git a/Usermode/Applications/axwin3_src/Interface/main.c b/Usermode/Applications/axwin3_src/Interface/main.c index 990489ed..0065686b 100644 --- a/Usermode/Applications/axwin3_src/Interface/main.c +++ b/Usermode/Applications/axwin3_src/Interface/main.c @@ -9,14 +9,17 @@ #include #include #include +#include #define SIDEBAR_WIDTH 36 // === PROTOTYPES === void create_sidebar(void); +void create_mainmenu(void); // === GLOBALS === tHWND gSidebar; +tHWND gSystemMenu; tAxWin3_Widget *gSidebarRoot; int giScreenWidth; int giScreenHeight; @@ -25,6 +28,7 @@ tAxWin3_Widget *gSidebarRoot; int systembutton_fire(tAxWin3_Widget *Widget) { _SysDebug("SystemButton pressed"); + AxWin3_Menu_ShowAt(gSystemMenu, SIDEBAR_WIDTH, 0); return 0; } @@ -34,6 +38,7 @@ int main(int argc, char *argv[]) AxWin3_Connect(NULL); create_sidebar(); + create_mainmenu(); // Idle loop AxWin3_MainLoop(); @@ -82,7 +87,22 @@ void create_sidebar(void) } +void mainmenu_app_textedit(void *unused) +{ + _SysDebug("TODO: Launch text editor"); +} + +void mainmenu_run_dialog(void *unused) +{ + _SysDebug("TODO: Show run dialog"); +} + void create_mainmenu(void) { + gSystemMenu = AxWin3_Menu_Create(gSidebar); + + AxWin3_Menu_AddItem(gSystemMenu, "Text &Editor\tWin+E", mainmenu_app_textedit, NULL, 0, NULL); + AxWin3_Menu_AddItem(gSystemMenu, NULL, NULL, NULL, 0, NULL); + AxWin3_Menu_AddItem(gSystemMenu, "Run\tWin+R", mainmenu_run_dialog, NULL, 0, NULL); } diff --git a/Usermode/Applications/axwin3_src/WM/renderer_menu.c b/Usermode/Applications/axwin3_src/WM/renderer_menu.c new file mode 100644 index 00000000..bf8b8453 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderer_menu.c @@ -0,0 +1,166 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * render_menu.c + * - Pop-up menu window class/renderer + */ +#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 MinLabelWidth; + + int MaxItems; + int nItems; + tMenuItem *Items[]; +} tMenuWindowInfo; + +// === GLOBALS === +tWMRenderer gRenderer_Menu = { + .Name = "Menu", + .CreateWindow = Renderer_Menu_Create, + .Redraw = Renderer_Menu_Redraw, + .HandleMessage = Renderer_Menu_HandleMessage +}; + +// === 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; + + return ret; +} + +void Renderer_Menu_Redraw(tWindow *Window) +{ + // TODO: Implement Renderer_Menu_Redraw + + // - Resize window to contain all items + + // - Move the window such that it is on screen + // > Make sure to catch if the menu can't fit fully onscreen + + // - Render each item +} + +int Renderer_Menu_HandleMessage(tWindow *Window, int Msg, int Length, void *Data) +{ + switch(Msg) + { + case MSG_MENU_ADDITEM: { + tMenuMsg_AddItem *req = Data; + tMenuItem *item; + if(Length < sizeof(*req) + 1) return -1; + if(req->Label[Length-sizeof(*req)] != '\0') return -1; + + if(info->Items[req->ID]) break; + item = malloc(sizeof(tMenuItem)+strlen(req->Label)); + info->Items[req->ID] = item; + + if(req->Label[0] == '\0') + { + // Spacer + item->Label = NULL; + } + else + { + // 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]; + item->Label[item->KeyOffset] = '\0'; + WM_Render_GetTextDims(NULL, item->Label, &item->UnderlineX, NULL); + 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; + } + + break; } + + // Only message to pass to client + case MSG_MENU_SELECT: + return 1; + } + return 0; +} + diff --git a/Usermode/Applications/axwin3_src/include/menu_messages.h b/Usermode/Applications/axwin3_src/include/menu_messages.h new file mode 100644 index 00000000..04dcd2da --- /dev/null +++ b/Usermode/Applications/axwin3_src/include/menu_messages.h @@ -0,0 +1,42 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * menu_messages.h + * - AxWin3 Menu IPC Messages + */ +#ifndef _MENU_MESSAGES_H_ +#define _MENU_MESSAGES_H_ + +#include "ipcmessages.h" + +enum eMenuMessages +{ + MSG_MENU_ADDITEM = 0x1000, + MSG_MENU_SETFLAGS, + + MSG_MENU_SELECT +}; + +typedef struct +{ + uint16_t ID; + uint16_t Flags; + uint32_t SubMenuID; + char Label[]; +} tMenuMsg_AddItem; + +typedef struct +{ + uint16_t ID; + uint16_t Value; + uint16_t Mask; +} tMenuMsg_SetFlags; + +typedef struct +{ + uint16_t ID; +} tMenuMsg_Select; + +#endif + diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/Makefile b/Usermode/Applications/axwin3_src/libaxwin3.so_src/Makefile index b8742911..3d37b5b5 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/Makefile +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/Makefile @@ -7,7 +7,7 @@ CPPFLAGS += -I ../include/ CFLAGS += -Wall LDFLAGS += -lc -soname libaxwin3.so -OBJ = main.o msg.o wm.o r_widget.o +OBJ = main.o msg.o wm.o r_widget.o r_menu.o BIN = libaxwin3.so include ../../../Libraries/Makefile.tpl diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c new file mode 100644 index 00000000..e7bd2bf8 --- /dev/null +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c @@ -0,0 +1,112 @@ +/* + * AxWin3 Interface Library + * - By John Hodge (thePowersGang) + * + * r_menu.c + * - Menu renderer interface + */ +#include +#include +#include +#include +#include "include/internal.h" +#include "include/ipc.h" +#include + +// === TYPES === +typedef struct sMenuWindowInfo tMenuWindowInfo; + +struct sAxWin3_MenuItem +{ + tHWND Window; + int ID; + tAxWin3_Menu_Callback Callback; + void *CbPtr; + tHWND SubMenu; +}; + +struct sMenuWindowInfo +{ + int nItems; + tAxWin3_MenuItem *Items; +}; + +// === CODE === +int AxWin3_Menu_int_Callback(tHWND Window, int Message, int Length, void *Data) +{ + tMenuWindowInfo *info = AxWin3_int_GetDataPtr(Window); + switch(Message) + { + case MSG_MENU_SELECT: { + tMenuMsg_Select *msg = Data; + tAxWin3_MenuItem *item; + if(Length < sizeof(tMenuMsg_Select)) return -1; + if(msg->ID >= info->nItems) return -1; + item = &info->Items[msg->ID]; + if(item->Callback) item->Callback(item->CbPtr); + return 0; } + } + return 1; +} + +tHWND AxWin3_Menu_Create(tHWND Parent) +{ + tHWND ret; + tMenuWindowInfo *info; + + ret = AxWin3_CreateWindow(Parent, "Menu", 0, sizeof(*info), AxWin3_Menu_int_Callback); + if(!ret) return ret; + + info = AxWin3_int_GetDataPtr(ret); + info->nItems = 0; + info->Items = NULL; + + return ret; +} + +void AxWin3_Menu_ShowAt(tHWND Menu, int X, int Y) +{ + AxWin3_MoveWindow(Menu, X, Y); + AxWin3_ShowWindow(Menu, 1); +} + +tAxWin3_MenuItem *AxWin3_Menu_AddItem( + tHWND Menu, const char *Label, + tAxWin3_Menu_Callback Cb, void *Ptr, + int Flags, tHWND SubMenu + ) +{ + tMenuWindowInfo *info; + tAxWin3_MenuItem *ret; + + info = AxWin3_int_GetDataPtr(Menu); + + info->nItems ++; + info->Items = realloc(info->Items, sizeof(*info->Items)*info->nItems); + if(!info->Items) { + _SysDebug("ERROR: Realloc Failed"); + return NULL; + } + + ret = &info->Items[info->nItems-1]; + ret->ID = info->nItems - 1; + ret->Window = Menu; + ret->Callback = Cb; + ret->CbPtr = Ptr; + ret->SubMenu = SubMenu; + + { + tAxWin_IPCMessage *msg; + tMenuMsg_AddItem *req; + msg = AxWin3_int_AllocateIPCMessage(Menu, MSG_MENU_ADDITEM, 0, sizeof(*req)+strlen(Label)); + req = (void*)msg->Data; + req->ID = ret->ID; + req->Flags = Flags; + req->SubMenuID = AxWin3_int_GetWindowID(SubMenu); + strcpy(req->Label, Label); + AxWin3_int_SendIPCMessage(msg); + free(msg); + } + + return ret; +} diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c index 43eef70d..17dd16e9 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c @@ -2,8 +2,8 @@ * AxWin3 Interface Library * - By John Hodge (thePowersGang) * - * main.c - * - Entrypoint and setup + * r_widget.c + * - Widget window type interface */ #include #include diff --git a/Usermode/include/axwin3/menu.h b/Usermode/include/axwin3/menu.h new file mode 100644 index 00000000..323bf301 --- /dev/null +++ b/Usermode/include/axwin3/menu.h @@ -0,0 +1,26 @@ +/* + * Acess2 GUI Version 3 (AxWin3) + * - By John Hodge (thePowersGang) + * + * menu.h + * - Menu window type + */ +#ifndef _AXWIN3_MENU_H_ +#define _AXWIN3_MENU_H_ + +typedef void (*tAxWin3_Menu_Callback)(void *Ptr); +typedef struct sAxWin3_MenuItem tAxWin3_MenuItem; + +extern tHWND AxWin3_Menu_Create(tHWND Parent); +extern void AxWin3_Menu_ShowAt(tHWND Menu, int X, int Y); + +extern tAxWin3_MenuItem *AxWin3_Menu_AddItem( + tHWND Menu, const char *Label, + tAxWin3_Menu_Callback Cb, void *Ptr, + int Flags, tHWND SubMenu + ); +extern tAxWin3_MenuItem *AxWin3_Menu_GetItem(tHWND Menu, int Index); +extern void AxWin3_Menu_SetFlags(tAxWin3_MenuItem *Item, int Flags, int Mask); + +#endif + -- 2.20.1