X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;ds=sidebyside;f=Usermode%2FApplications%2Faxwin3_src%2FWM%2Fwm.c;h=8886af1947e2d78cfc3317c4c9e33fd207130624;hb=ae4f74ae1303ff2ef59d0885606f607e529c5ca0;hp=a056a52b704e0bef5fce8ef26e457cfa7221cd5b;hpb=cee7338738f1a68c7eb7b956cab8d9fb83f95714;p=tpg%2Facess2.git diff --git a/Usermode/Applications/axwin3_src/WM/wm.c b/Usermode/Applications/axwin3_src/WM/wm.c index a056a52b..8886af19 100644 --- a/Usermode/Applications/axwin3_src/WM/wm.c +++ b/Usermode/Applications/axwin3_src/WM/wm.c @@ -14,13 +14,17 @@ #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); +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); // === GLOBALS === tWMRenderer *gpWM_Renderers; tWindow *gpWM_RootWindow; //! Window which will recieve the next keyboard event tWindow *gpWM_FocusedWindow; +//! Hilighted window (owner of the currently focused window) +tWindow *gpWM_HilightedWindow; // === CODE === void WM_Initialise(void) @@ -53,26 +57,26 @@ tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int if(renderer == NULL) return NULL; - if(!Parent) - Parent = gpWM_RootWindow; - // - Call create window function ret = renderer->CreateWindow(RendererArg); ret->Client = Client; ret->ID = ID; ret->Parent = Parent; + if(!ret->Parent) + ret->Parent = gpWM_RootWindow; + ret->Owner = Parent; ret->Renderer = renderer; ret->Flags |= WINFLAG_CLEAN; // Needed to stop invaildate early exiting // Append to parent - if(Parent) + if(ret->Parent) { - if(Parent->LastChild) - Parent->LastChild->NextSibling = ret; + if(ret->Parent->LastChild) + ret->Parent->LastChild->NextSibling = ret; else - Parent->FirstChild = ret; - ret->PrevSibling = Parent->LastChild; - Parent->LastChild = ret; + ret->Parent->FirstChild = ret; + ret->PrevSibling = ret->Parent->LastChild; + ret->Parent->LastChild = ret; ret->NextSibling = NULL; } else @@ -81,7 +85,7 @@ tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int } // Don't decorate child windows by default - if(Parent != gpWM_RootWindow) + if(Parent) { ret->Flags |= WINFLAG_NODECORATE; } @@ -90,6 +94,11 @@ tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int return ret; } +tWindow *WM_GetWindowByID(tWindow *Requester, uint32_t ID) +{ + return IPC_int_GetWindow(Requester->Client, ID); +} + tWindow *WM_CreateWindowStruct(size_t ExtraSize) { tWindow *ret; @@ -131,47 +140,94 @@ void WM_RaiseWindow(tWindow *Window) Window->PrevSibling = parent->LastChild; Window->NextSibling = NULL; parent->LastChild = Window; + + _SysDebug("Raised %p", Window); +} + +/* +void WM_RaiseWindow(tWindow *Window) +{ + // Move to the last render position (move to top) + while(Window && Window->Parent) + { + if( Window->NextSibling ) + { + // remove + if( Window->PrevSibling ) + Window->PrevSibling->NextSibling = Window->NextSibling; + Window->NextSibling->PrevSibling = Window->PrevSibling; + // Mutate self + Window->PrevSibling = Window->Parent->LastChild; + Window->NextSibling = NULL; + // re-add + Window->PrevSibling->NextSibling = Window; + Window->Parent->LastChild = Window; + } + _SysDebug("WM_RaiseWindow: Raised %p", Window); + Window = Window->Parent; + } } +*/ void WM_FocusWindow(tWindow *Destination) { struct sWndMsg_Bool _msg; + _SysDebug("WM_FocusWindow(%p)", Destination); + if( gpWM_FocusedWindow == Destination ) return ; if( Destination && !(Destination->Flags & WINFLAG_SHOW) ) 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); - + if( gpWM_FocusedWindow ) + { + _msg.Val = 0; + WM_SendMessage(NULL, gpWM_FocusedWindow, WNDMSG_FOCUS, sizeof(_msg), &_msg); + } + if( Destination ) + { + _msg.Val = 1; + WM_SendMessage(NULL, Destination, WNDMSG_FOCUS, sizeof(_msg), &_msg); + } + + WM_Invalidate(gpWM_FocusedWindow); + WM_Invalidate(Destination); + gpWM_FocusedWindow = Destination; } void WM_ShowWindow(tWindow *Window, int bShow) { - // Message window struct sWndMsg_Bool _msg; if( !!(Window->Flags & WINFLAG_SHOW) == bShow ) return ; + // Message window _msg.Val = !!bShow; WM_SendMessage(NULL, Window, WNDMSG_SHOW, sizeof(_msg), &_msg); - - if(bShow) + + // Update the flag + if(bShow) { Window->Flags |= WINFLAG_SHOW; - else { + _SysDebug("Window %p shown", Window); + } + else + { Window->Flags &= ~WINFLAG_SHOW; + if( Window == gpWM_FocusedWindow ) WM_FocusWindow(Window->Parent); + + // Just a little memory saving for large hidden windows + if(Window->RenderBuffer) { + free(Window->RenderBuffer); + Window->RenderBuffer = NULL; + } + _SysDebug("Window %p hidden", Window); } - // Just a little memory saving for large hidden windows - if(Window->RenderBuffer) - free(Window->RenderBuffer); WM_Invalidate(Window); } @@ -187,23 +243,60 @@ void WM_DecorateWindow(tWindow *Window, int bDecorate) Window->Flags |= WINFLAG_NODECORATE; // Needed because the window size changes - if(Window->RenderBuffer) + if(Window->RenderBuffer) { free(Window->RenderBuffer); + Window->RenderBuffer = NULL; + } WM_Invalidate(Window); } +void WM_SetRelative(tWindow *Window, int bRelativeToParent) +{ +// _SysDebug("WM_SetRelative: (%p{Parent=%p},%i)", Window, Window->Parent, bRelativeToParent); + // No meaning if no parent + if( !Window->Parent ) + return ; + + // Check that the flag is changing + if( !!bRelativeToParent == !!(Window->Flags & WINFLAG_RELATIVE) ) + return ; + + if( bRelativeToParent ) { + // Set + Window->Flags |= WINFLAG_RELATIVE; + WM_MoveWindow(Window, Window->X, Window->Y); + } + else { + // Clear + Window->Flags &= ~WINFLAG_RELATIVE; + WM_MoveWindow(Window, Window->X - Window->Parent->X, Window->Y - Window->Parent->Y); + } +} + int WM_MoveWindow(tWindow *Window, int X, int Y) { +// _SysDebug("Move %p to (%i,%i)", Window, X, Y); // Clip coordinates if(X + Window->W < 0) X = -Window->W + 1; if(Y + Window->H < 0) Y = -Window->H + 1; if(X >= giScreenWidth) X = giScreenWidth - 1; if(Y >= giScreenHeight) Y = giScreenHeight - 1; + // If relative to the parent, extra checks + if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent ) + { + if( X > Window->Parent->W ) return 1; + if( Y > Window->Parent->H ) return 1; + } + // TODO: Re-sanitise + + _SysDebug("WM_MoveWindow: (%i,%i)", X, Y); Window->X = X; Window->Y = Y; - WM_Invalidate(Window); + // Mark up the tree that a child window has changed + while( (Window = Window->Parent) ) + Window->Flags &= ~WINFLAG_CHILDCLEAN; return 0; } @@ -214,10 +307,16 @@ int WM_ResizeWindow(tWindow *Window, int W, int H) if(Window->X + W < 0) Window->X = -W + 1; if(Window->Y + H < 0) Window->Y = -H + 1; + if( Window->W == W && Window->H == H ) + return 0; + + _SysDebug("WM_Resizeindow: %ix%i", W, H); Window->W = W; Window->H = H; - if(Window->RenderBuffer) + if(Window->RenderBuffer) { free(Window->RenderBuffer); + Window->RenderBuffer = NULL; + } WM_Invalidate(Window); { @@ -230,20 +329,36 @@ 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; +// _SysDebug("WM_SendMessage: (%p, %p, %i, %i, %p)", Source, Dest, Message, Length, Data); + if(Dest == NULL) { + _SysDebug("WM_SendMessage: NULL destination from %p", __builtin_return_address(0)); + return -2; + } + if(Length > 0 && Data == NULL) { + _SysDebug("WM_SendMessage: non-zero length and NULL data"); + return -1; + } + + if( Decorator_HandleMessage(Dest, Message, Length, Data) != 1 ) + { + // TODO: Catch errors from ->HandleMessage +// _SysDebug("WM_SendMessage: Decorator grabbed message?"); + return 0; + } // ->HandleMessage returns 1 when the message was not handled if( Dest->Renderer->HandleMessage(Dest, Message, Length, Data) != 1 ) { // TODO: Catch errors from ->HandleMessage +// _SysDebug("WM_SendMessage: Renderer grabbed message?"); return 0; } // TODO: Implement message masking + // Dispatch to client if(Dest->Client) { uint32_t src_id; @@ -258,15 +373,23 @@ int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, void src_id = Source->ID; } +// _SysDebug("WM_SendMessage: IPC Dispatch"); IPC_SendWMMessage(Dest->Client, src_id, Dest->ID, Message, Length, Data); } return 1; } +int WM_SendIPCReply(tWindow *Window, int Message, size_t Length, const void *Data) +{ + IPC_SendReply(Window->Client, Window->ID, Message, Length, Data); + return 0; +} + void WM_Invalidate(tWindow *Window) { - _SysDebug("Invalidating %p", Window); + if(!Window) return ; +// _SysDebug("Invalidating %p", Window); // Don't invalidate twice (speedup) // if( !(Window->Flags & WINFLAG_CLEAN) ) return; @@ -281,23 +404,34 @@ void WM_Invalidate(tWindow *Window) // --- Rendering / Update void WM_int_UpdateWindow(tWindow *Window) { - tWindow *child; + int bDecoratorRedraw = 0; // Ignore hidden windows if( !(Window->Flags & WINFLAG_SHOW) ) return ; + if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent ) + { + Window->RealX = Window->Parent->RealX + Window->Parent->BorderL + Window->X; + Window->RealY = Window->Parent->RealY + Window->Parent->BorderT + Window->Y; + } + else + { + Window->RealX = Window->X; + Window->RealY = Window->Y; + } + // Render if( !(Window->Flags & WINFLAG_CLEAN) ) { // Calculate RealW/RealH if( !(Window->Flags & WINFLAG_NODECORATE) ) { - _SysDebug("Applying decorations to %p", Window); + //_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); + bDecoratorRedraw = 1; } else { @@ -308,7 +442,7 @@ void WM_int_UpdateWindow(tWindow *Window) Window->RealW = Window->W; Window->RealH = Window->H; } - + Window->Renderer->Redraw(Window); Window->Flags |= WINFLAG_CLEAN; } @@ -316,6 +450,7 @@ void WM_int_UpdateWindow(tWindow *Window) // Process children if( !(Window->Flags & WINFLAG_CHILDCLEAN) ) { + tWindow *child; for( child = Window->FirstChild; child; child = child->NextSibling ) { WM_int_UpdateWindow(child); @@ -323,6 +458,8 @@ void WM_int_UpdateWindow(tWindow *Window) Window->Flags |= WINFLAG_CHILDCLEAN; } + if( bDecoratorRedraw ) + Decorator_Redraw(Window); } void WM_int_BlitWindow(tWindow *Window) @@ -332,10 +469,33 @@ void WM_int_BlitWindow(tWindow *Window) // Ignore hidden windows if( !(Window->Flags & WINFLAG_SHOW) ) return ; + + // Duplicated position update to handle window moving + if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent ) + { + Window->RealX = Window->Parent->RealX + Window->Parent->BorderL + Window->X; + Window->RealY = Window->Parent->RealY + Window->Parent->BorderT + Window->Y; + } + else + { + Window->RealX = Window->X; + Window->RealY = Window->Y; + } - _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); +// _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); + if( Window == gpWM_FocusedWindow && Window->CursorW ) + { + Video_FillRect( + Window->RealX + Window->BorderL + Window->CursorX, + Window->RealY + Window->BorderT + Window->CursorY, + Window->CursorW, Window->CursorH, + 0x000000 + ); + } + for( child = Window->FirstChild; child; child = child->NextSibling ) { WM_int_BlitWindow(child);