From 086346323aae470047d375a12104872c899056d6 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 12 Nov 2011 22:41:42 +0800 Subject: [PATCH] Usermode/AxWin3 - Implemented Focus/Raising support - Menus can now be closed :) --- .../Applications/axwin3_src/WM/include/wm.h | 8 +- .../axwin3_src/WM/include/wm_internals.h | 2 +- .../axwin3_src/WM/include/wm_messages.h | 5 + Usermode/Applications/axwin3_src/WM/main.c | 1 + .../axwin3_src/WM/renderer_menu.c | 118 ++++++++++++------ Usermode/Applications/axwin3_src/WM/wm.c | 33 ++++- .../Applications/axwin3_src/WM/wm_input.c | 65 ++++++++-- 7 files changed, 185 insertions(+), 47 deletions(-) diff --git a/Usermode/Applications/axwin3_src/WM/include/wm.h b/Usermode/Applications/axwin3_src/WM/include/wm.h index 86008be6..35e7e212 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm.h @@ -17,10 +17,12 @@ */ //! Render the window #define WINFLAG_SHOW 0x00000001 +//! Window isn't contained within the parent/owner +#define WINFLAG_NONNESTED 0x00000002 //! Window contents are valid -#define WINFLAG_CLEAN 0x00000002 +#define WINFLAG_CLEAN 0x00000040 //! All child windows are un-changed -#define WINFLAG_CHILDCLEAN 0x00000004 +#define WINFLAG_CHILDCLEAN 0x00000080 #define WINFLAG_RENDER_MASK 0x00FFFF00 #define WINFLAG_USR_MASK 0xFF000000 @@ -43,6 +45,8 @@ extern void WM_ShowWindow(tWindow *Window, int bShow); 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 void WM_GiveFocus(tWindow *Destination); +extern void WM_RaiseWindow(tWindow *Window); // --- 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_internals.h b/Usermode/Applications/axwin3_src/WM/include/wm_internals.h index ea0826c2..9b3c7f08 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm_internals.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm_internals.h @@ -15,8 +15,8 @@ struct sWindow tWindow *NextSibling; tWindow *PrevSibling; + // Render tree tWindow *Parent; - tWindow *FirstChild; tWindow *LastChild; diff --git a/Usermode/Applications/axwin3_src/WM/include/wm_messages.h b/Usermode/Applications/axwin3_src/WM/include/wm_messages.h index e4b46225..df20d775 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm_messages.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm_messages.h @@ -32,6 +32,11 @@ enum eWM_WindowMessages WNDMSG_CLASS_MAX = 0x2000, }; +struct sWndMsg_Bool +{ + uint8_t Val; +}; + struct sWndMsg_Resize { uint16_t W, H; diff --git a/Usermode/Applications/axwin3_src/WM/main.c b/Usermode/Applications/axwin3_src/WM/main.c index a2e1fdae..a9c34b74 100644 --- a/Usermode/Applications/axwin3_src/WM/main.c +++ b/Usermode/Applications/axwin3_src/WM/main.c @@ -69,6 +69,7 @@ int main(int argc, char *argv[]) char server_info[] = "AXWIN3_SERVER=00000"; char *envp[] = {server_info, NULL}; char *argv[] = {csInterfaceApp, NULL}; + _SysDebug("server_tid = %i, &server_tid = %p", server_tid, &server_tid); sprintf(server_info, "AXWIN3_SERVER=%i", server_tid); execve(csInterfaceApp, argv, envp); exit(1); diff --git a/Usermode/Applications/axwin3_src/WM/renderer_menu.c b/Usermode/Applications/axwin3_src/WM/renderer_menu.c index d4e078bd..b70016da 100644 --- a/Usermode/Applications/axwin3_src/WM/renderer_menu.c +++ b/Usermode/Applications/axwin3_src/WM/renderer_menu.c @@ -102,9 +102,6 @@ void Renderer_Menu_Redraw(tWindow *Window) { tMenuWindowInfo *info = Window->RendererInfo; int w, h, y, i; - _SysDebug("TODO: Implement Renderer_Menu_Redraw"); - -// _SysDebug("info->nItems = %i", info->nItems); w = info->CachedW; h = ciMenu_TopPadding + ciMenu_BottomPadding; @@ -310,54 +307,103 @@ int Renderer_Menu_int_AddItem(tWindow *Window, int Length, void *Data) 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 - doesn't hilight + if(Y < ciMenu_SpacerHeight) { + return -1; + } + Y -= ciMenu_SpacerHeight; + } + else + { + // Normal item, set the hilight + 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_MOUSEMOVE: { - tMenuWindowInfo *info = Window->RendererInfo; - struct sWndMsg_MouseMove *msg = Data; - int new_hilight; - + case WNDMSG_SHOW: { + struct sWndMsg_Bool *msg = Data; if(Length < sizeof(*msg)) return -1; - - if( msg->X < 0 || msg->X >= Window->W ) - { - new_hilight = -1; + if(msg->Val) { + // Take focus? + _SysDebug(" - Shown, take focus"); + WM_GiveFocus(Window); } else { - int i, y; - y = msg->Y; - new_hilight = -1; - for( i = 0; i < info->nItems; i ++ ) + // 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) { - if( !info->Items[i] ) continue; - - if( !info->Items[i]->Label ) - { - // Spacer - doesn't hilight - if(y < ciMenu_SpacerHeight) { - new_hilight = -1; - break; - } - y -= ciMenu_SpacerHeight; - } - else - { - // Normal item, set the hilight - if(y < ciMenu_ItemHeight) { - new_hilight = i; - break; - } - y -= ciMenu_ItemHeight; - } + 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); } diff --git a/Usermode/Applications/axwin3_src/WM/wm.c b/Usermode/Applications/axwin3_src/WM/wm.c index 41691554..38bbbf34 100644 --- a/Usermode/Applications/axwin3_src/WM/wm.c +++ b/Usermode/Applications/axwin3_src/WM/wm.c @@ -70,6 +70,7 @@ tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int Parent->FirstChild = ret; ret->PrevSibling = Parent->LastChild; Parent->LastChild = ret; + ret->NextSibling = NULL; } else { @@ -90,9 +91,39 @@ tWindow *WM_CreateWindowStruct(size_t ExtraSize) return ret; } +void WM_RaiseWindow(tWindow *Window) +{ + tWindow *parent = Window->Parent; + if(!Window->Parent) return ; + + // Remove from list + if(Window->PrevSibling) + Window->PrevSibling->NextSibling = Window->NextSibling; + if(Window->NextSibling) + Window->NextSibling->PrevSibling = Window->PrevSibling; + if(parent->FirstChild == Window) + parent->FirstChild = Window->NextSibling; + if(parent->LastChild == Window) + parent->LastChild = Window->PrevSibling; + + // Append to end + if(parent->LastChild) + parent->LastChild->NextSibling = Window; + else + parent->FirstChild = Window; + Window->PrevSibling = parent->LastChild; + Window->NextSibling = NULL; + parent->LastChild = Window; +} + void WM_ShowWindow(tWindow *Window, int bShow) { - // TODO: Message window + // Message window + struct sWndMsg_Bool _msg; + + _msg.Val = !!bShow; + WM_SendMessage(NULL, Window, WNDMSG_SHOW, sizeof(_msg), &_msg); + if(bShow) Window->Flags |= WINFLAG_SHOW; else diff --git a/Usermode/Applications/axwin3_src/WM/wm_input.c b/Usermode/Applications/axwin3_src/WM/wm_input.c index 991b74ee..af258ff1 100644 --- a/Usermode/Applications/axwin3_src/WM/wm_input.c +++ b/Usermode/Applications/axwin3_src/WM/wm_input.c @@ -9,9 +9,17 @@ #include #include +#define MAX_BUTTONS 3 + // === IMPORTS === extern tWindow *gpWM_RootWindow; +// === GLOBALS === +//! Window which will recieve the next keyboard event +tWindow *gpWM_FocusedWindow; +//! Window in which the mouse button was originally pressed +tWindow *gpWM_DownStartWindow[MAX_BUTTONS]; + // === CODE === tWindow *WM_int_GetWindowAtPos(int X, int Y) { @@ -63,17 +71,60 @@ void WM_Input_MouseMoved(int OldX, int OldY, int NewX, int NewY) WM_SendMessage(NULL, win, WNDMSG_MOUSEMOVE, sizeof(msg), &msg); } -void WM_Input_MouseButton(int X, int Y, int ButtonIndex, int Pressed) +inline void WM_Input_int_SendBtnMsg(tWindow *Win, int X, int Y, int Index, int Pressed) { - tWindow *win = WM_int_GetWindowAtPos(X, Y); struct sWndMsg_MouseButton msg; - // Send Press/Release message - msg.X = X - win->X; - msg.Y = Y - win->Y; - msg.Button = ButtonIndex; + msg.X = X - Win->X; + msg.Y = Y - Win->Y; + msg.Button = Index; msg.bPressed = !!Pressed; - WM_SendMessage(NULL, win, WNDMSG_MOUSEBTN, sizeof(msg), &msg); + WM_SendMessage(NULL, Win, WNDMSG_MOUSEBTN, sizeof(msg), &msg); +} + +void WM_Input_MouseButton(int X, int Y, int ButtonIndex, int Pressed) +{ + tWindow *win; + + win = WM_int_GetWindowAtPos(X, Y); + + // Handle press of primary button to change focus + if( ButtonIndex == 0 && Pressed == 1 ) + { + _SysDebug("Gave focus to %p", win); + WM_GiveFocus(win); + WM_RaiseWindow(win); + } + + // Make sure that even if the mouse has moved out of the original window, + // mouse release messages reach the window. + if( !Pressed && ButtonIndex < MAX_BUTTONS && gpWM_DownStartWindow[ButtonIndex] != win ) + { + WM_Input_int_SendBtnMsg(gpWM_DownStartWindow[ButtonIndex], X, Y, ButtonIndex, 0); + } + if( Pressed && ButtonIndex < MAX_BUTTONS ) + { + gpWM_DownStartWindow[ButtonIndex] = win; + } + + // Send Press/Release message + WM_Input_int_SendBtnMsg(win, X, Y, ButtonIndex, Pressed); +} + +// --- Manipulation Functions --- +void WM_GiveFocus(tWindow *Destination) +{ + struct sWndMsg_Bool _msg; + + if( gpWM_FocusedWindow == Destination ) + return ; + + _msg.Val = 0; + WM_SendMessage(NULL, gpWM_FocusedWindow, WNDMSG_FOCUS, sizeof(_msg), &_msg); + _msg.Val = 1; + WM_SendMessage(NULL, Destination, WNDMSG_FOCUS, sizeof(_msg), &_msg); + + gpWM_FocusedWindow = Destination; } -- 2.20.1