X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FApplications%2Faxwin3_src%2FWM%2Fwm.c;h=cc7e86ea96d20e22f924ff268ced3033e1c1dc82;hb=32980a36e515d1be2da1c7bf551070d4e972963e;hp=8886af1947e2d78cfc3317c4c9e33fd207130624;hpb=b0da731b2d89b9dd58de2c98eaf6218a41a21920;p=tpg%2Facess2.git diff --git a/Usermode/Applications/axwin3_src/WM/wm.c b/Usermode/Applications/axwin3_src/WM/wm.c index 8886af19..cc7e86ea 100644 --- a/Usermode/Applications/axwin3_src/WM/wm.c +++ b/Usermode/Applications/axwin3_src/WM/wm.c @@ -12,11 +12,20 @@ #include #include #include +#include +#include // === IMPORTS === +extern int Renderer_Menu_Init(void); +extern int Renderer_Widget_Init(void); +extern int Renderer_Background_Init(void); +extern int Renderer_Framebuffer_Init(void); +extern int Renderer_RichText_Init(void); + extern void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int Msg, int Len, const void *Data); extern void IPC_SendReply(tIPC_Client *Client, uint32_t WinID, int MsgID, size_t Len, const void *Data); extern tWindow *IPC_int_GetWindow(tIPC_Client *Client, uint32_t ID); +extern void IPC_int_SetWindow(tIPC_Client *Client, uint32_t ID, tWindow *Window); // === GLOBALS === tWMRenderer *gpWM_Renderers; @@ -29,15 +38,40 @@ tWindow *gpWM_HilightedWindow; // === CODE === void WM_Initialise(void) { + // TODO: Autodetect these + Renderer_Menu_Init(); + Renderer_Widget_Init(); + Renderer_Background_Init(); + Renderer_Framebuffer_Init(); + Renderer_RichText_Init(); + WM_CreateWindow(NULL, NULL, 0, 0x0088FF, "Background"); gpWM_RootWindow->W = giScreenWidth; gpWM_RootWindow->H = giScreenHeight; gpWM_RootWindow->Flags = WINFLAG_SHOW|WINFLAG_NODECORATE; + + // TODO: Move these to config + uint32_t keys[4]; + keys[0] = KEYSYM_LEFTGUI; keys[1] = KEYSYM_r; + WM_Hotkey_Register(2, keys, "Interface>Run"); + keys[0] = KEYSYM_LEFTGUI; keys[1] = KEYSYM_t; + WM_Hotkey_Register(2, keys, "Interface>Terminal"); + keys[0] = KEYSYM_LEFTGUI; keys[1] = KEYSYM_e; + WM_Hotkey_Register(2, keys, "Interface>TextEdit"); } void WM_RegisterRenderer(tWMRenderer *Renderer) { - // TODO: Catch out duplicates + // Catch out duplicates + for(tWMRenderer *r = gpWM_Renderers; r; r = r->Next ) { + if( r == Renderer ) { + return ; + } + if( strcmp(r->Name, Renderer->Name) == 0 ) { + return ; + } + } + Renderer->Next = gpWM_Renderers; gpWM_Renderers = Renderer; } @@ -94,6 +128,60 @@ tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int return ret; } +void WM_DestroyWindow(tWindow *Window) +{ + // TODO: Lock window and flag as invalid + + // - Remove from render tree + { + // TODO: Lock render tree? + tWindow *prev = Window->PrevSibling; + tWindow *next = Window->NextSibling; + if(prev) + prev->NextSibling = next; + else + Window->Parent->FirstChild = next; + if(next) + next->PrevSibling = prev; + else + Window->Parent->LastChild = prev; + } + // - Full invalidate + WM_Invalidate(Window, 0); + Window->Parent->Flags &= ~WINFLAG_CLEAN; // Mark parent as unclean, forcing redraw + + // - Remove from inheritance tree? + + // - Clean up render children + { + // Lock should not be needed + tWindow *win, *next; + for( win = Window->FirstChild; win; win = next ) + { + next = win->NextSibling; + ASSERT(Window->FirstChild->Parent == Window); + WM_DestroyWindow(win); + } + } + + // - Clean up inheriting children? + + // - Tell renderer to clean up + if( Window->Renderer->DestroyWindow ) + Window->Renderer->DestroyWindow(Window); + else + _SysDebug("WARN: Renderer '%s' does not have a destroy function", Window->Renderer->Name); + + // - Tell client to clean up + WM_SendMessage(NULL, Window, WNDMSG_DESTROY, 0, NULL); + + // - Clean up render cache and window structure + free(Window->Title); + free(Window->RenderBuffer); + free(Window); + IPC_int_SetWindow(Window->Client, Window->ID, NULL); +} + tWindow *WM_GetWindowByID(tWindow *Requester, uint32_t ID) { return IPC_int_GetWindow(Requester->Client, ID); @@ -190,9 +278,10 @@ void WM_FocusWindow(tWindow *Destination) _msg.Val = 1; WM_SendMessage(NULL, Destination, WNDMSG_FOCUS, sizeof(_msg), &_msg); } - - WM_Invalidate(gpWM_FocusedWindow); - WM_Invalidate(Destination); + + // TODO: Leave it up to the renderer to decide to invalidate + WM_Invalidate(gpWM_FocusedWindow, 1); + WM_Invalidate(Destination, 1); gpWM_FocusedWindow = Destination; } @@ -204,6 +293,10 @@ void WM_ShowWindow(tWindow *Window, int bShow) if( !!(Window->Flags & WINFLAG_SHOW) == bShow ) return ; + + // Window is being hidden, invalidate parents + if( !bShow ) + WM_Invalidate(Window, 0); // Message window _msg.Val = !!bShow; @@ -229,7 +322,9 @@ void WM_ShowWindow(tWindow *Window, int bShow) _SysDebug("Window %p hidden", Window); } - WM_Invalidate(Window); + // Window has been shown, invalidate everything + if( bShow ) + WM_Invalidate(Window, 1); } void WM_DecorateWindow(tWindow *Window, int bDecorate) @@ -248,7 +343,7 @@ void WM_DecorateWindow(tWindow *Window, int bDecorate) Window->RenderBuffer = NULL; } - WM_Invalidate(Window); + WM_Invalidate(Window, 1); } void WM_SetRelative(tWindow *Window, int bRelativeToParent) @@ -291,12 +386,19 @@ int WM_MoveWindow(tWindow *Window, int X, int Y) } // TODO: Re-sanitise + if( Window->X == X && Window->Y == Y ) { + _SysDebug("WM_MoveWindow: Equal (%i,%i)", X, Y); + return 0; + } + + if( Window->Parent ) + Window->Parent->Flags |= WINFLAG_NEEDREBLIT; + _SysDebug("WM_MoveWindow: (%i,%i)", X, Y); Window->X = X; Window->Y = Y; // Mark up the tree that a child window has changed - while( (Window = Window->Parent) ) - Window->Flags &= ~WINFLAG_CHILDCLEAN; + WM_Invalidate(Window, 0); return 0; } @@ -309,15 +411,19 @@ int WM_ResizeWindow(tWindow *Window, int W, int H) if( Window->W == W && Window->H == H ) return 0; + + // If the window size has decreased, force the parent to reblit + if( Window->Parent && (Window->W > W || Window->H > H) ) + Window->Parent->Flags |= WINFLAG_NEEDREBLIT; - _SysDebug("WM_Resizeindow: %ix%i", W, H); + _SysDebug("WM_ResizeWindow: %p:%i %ix%i", Window->Client, Window->ID, W, H); Window->W = W; Window->H = H; if(Window->RenderBuffer) { free(Window->RenderBuffer); Window->RenderBuffer = NULL; } - WM_Invalidate(Window); + WM_Invalidate(Window, 1); { struct sWndMsg_Resize msg; @@ -386,18 +492,20 @@ int WM_SendIPCReply(tWindow *Window, int Message, size_t Length, const void *Dat return 0; } -void WM_Invalidate(tWindow *Window) +void WM_Invalidate(tWindow *Window, int bClearClean) { if(!Window) return ; -// _SysDebug("Invalidating %p", Window); - // Don't invalidate twice (speedup) -// if( !(Window->Flags & WINFLAG_CLEAN) ) return; - + + // Don't bother invalidating if the window isn't shown + if( !(Window->Flags & WINFLAG_SHOW) ) + return ; + // Mark for re-render - Window->Flags &= ~WINFLAG_CLEAN; + if( bClearClean ) + Window->Flags &= ~WINFLAG_CLEAN; // Mark up the tree that a child window has changed - while( (Window = Window->Parent) ) + while( (Window = Window->Parent) && (Window->Flags & WINFLAG_SHOW) ) Window->Flags &= ~WINFLAG_CHILDCLEAN; } @@ -444,7 +552,7 @@ void WM_int_UpdateWindow(tWindow *Window) } Window->Renderer->Redraw(Window); - Window->Flags |= WINFLAG_CLEAN; + Window->Flags |= WINFLAG_CLEAN|WINFLAG_NEEDREBLIT; } // Process children @@ -462,7 +570,7 @@ void WM_int_UpdateWindow(tWindow *Window) Decorator_Redraw(Window); } -void WM_int_BlitWindow(tWindow *Window) +void WM_int_BlitWindow(tWindow *Window, int bForceReblit) { tWindow *child; @@ -484,8 +592,17 @@ void WM_int_BlitWindow(tWindow *Window) // _SysDebug("Blit %p (%p) to (%i,%i) %ix%i", Window, Window->RenderBuffer, // Window->RealX, Window->RealY, Window->RealW, Window->RealH); - Video_Blit(Window->RenderBuffer, Window->RealX, Window->RealY, Window->RealW, Window->RealH); + // TODO Don't blit unless: + // a) A parent has been reblitted (thus clobbering the existing content) + // b) A child has moved (exposing a previously hidden area) + if( bForceReblit || (Window->Flags & WINFLAG_NEEDREBLIT) ) + { + Video_Blit(Window->RenderBuffer, Window->RealX, Window->RealY, Window->RealW, Window->RealH); + Window->Flags &= ~WINFLAG_NEEDREBLIT; + bForceReblit = 1; + } + // Draw cursor if( Window == gpWM_FocusedWindow && Window->CursorW ) { Video_FillRect( @@ -498,7 +615,7 @@ void WM_int_BlitWindow(tWindow *Window) for( child = Window->FirstChild; child; child = child->NextSibling ) { - WM_int_BlitWindow(child); + WM_int_BlitWindow(child, bForceReblit); } } @@ -512,7 +629,7 @@ void WM_Update(void) WM_int_UpdateWindow(gpWM_RootWindow); // - Draw windows from back to front to the render buffer - WM_int_BlitWindow(gpWM_RootWindow); + WM_int_BlitWindow(gpWM_RootWindow, 0); Video_Update(); }