From: John Hodge Date: Sun, 12 May 2013 11:07:17 +0000 (+0800) Subject: Usermode/AxWin3 - Speedups mostly, required some restructure X-Git-Tag: rel0.15~499 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=6397a743456a11e9c38b7e2cf46f41b2b7083365;p=tpg%2Facess2.git Usermode/AxWin3 - Speedups mostly, required some restructure --- diff --git a/Usermode/Applications/axwin3_src/Interface/main.c b/Usermode/Applications/axwin3_src/Interface/main.c index a0986147..abe21e51 100644 --- a/Usermode/Applications/axwin3_src/Interface/main.c +++ b/Usermode/Applications/axwin3_src/Interface/main.c @@ -147,6 +147,10 @@ int run_dorun(tAxWin3_Widget *unused) _SysDebug("DoRun pressed"); char *cmd = AxWin3_Widget_GetText(gRunInput); _SysDebug("Command string '%s'", cmd); + + // TODO: Parse the command string into components + // TODO: Call _SysSpawn + AxWin3_ShowWindow(gRunDialog, 0); return 0; } diff --git a/Usermode/Applications/axwin3_src/WM/include/common.h b/Usermode/Applications/axwin3_src/WM/include/common.h index 1be86ffe..e074450d 100644 --- a/Usermode/Applications/axwin3_src/WM/include/common.h +++ b/Usermode/Applications/axwin3_src/WM/include/common.h @@ -18,6 +18,9 @@ #define AXWIN_VERSION 0x300 +static inline int MIN(int a, int b) { return (a < b) ? a : b; } +static inline int MAX(int a, int b) { return (a > b) ? a : b; } + // === GLOBALS === extern int giTerminalFD; extern const char *gsTerminalDevice; diff --git a/Usermode/Applications/axwin3_src/WM/include/wm.h b/Usermode/Applications/axwin3_src/WM/include/wm.h index a4275c9f..914058ff 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm.h @@ -26,6 +26,8 @@ #define WINFLAG_MAXIMIZED 0x00000004 //! Window is contained within the parent #define WINFLAG_RELATIVE 0x00000008 +//! Window needs to be reblitted (child moved or contents changed) +#define WINFLAG_NEEDREBLIT 0x00000020 //! Window contents are valid #define WINFLAG_CLEAN 0x00000040 //! All child windows are un-changed @@ -49,7 +51,7 @@ typedef struct sIPC_Client tIPC_Client; extern tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int Flags, const char *Renderer); extern void WM_DestroyWindow(tWindow *Window); extern tWindow *WM_GetWindowByID(tWindow *Requester, uint32_t ID); -extern void WM_Invalidate(tWindow *Window); +extern void WM_Invalidate(tWindow *Window, int bClearClean); extern void WM_SetWindowTitle(tWindow *Window, const char *Title); extern void WM_FocusWindow(tWindow *Destination); extern void WM_RaiseWindow(tWindow *Window); diff --git a/Usermode/Applications/axwin3_src/WM/ipc.c b/Usermode/Applications/axwin3_src/WM/ipc.c index 44601841..79e0956f 100644 --- a/Usermode/Applications/axwin3_src/WM/ipc.c +++ b/Usermode/Applications/axwin3_src/WM/ipc.c @@ -57,6 +57,7 @@ void IPC_Type_Sys_Send(const void *Ident, size_t Length, const void *Data); int IPC_Type_IPCPipe_Compare(const void *Ident1, const void *Ident2); void IPC_Type_IPCPipe_Send(const void *Ident, size_t Length, const void *Data); tIPC_Client *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident); +void IPC_int_DropClient(tIPC_Client *Client); void IPC_Handle(tIPC_Client *Client, size_t MsgLen, tAxWin_IPCMessage *Msg); // === GLOBALS === @@ -138,7 +139,7 @@ void IPC_HandleSelect(fd_set *set) if( giIPCPipeHandle != -1 && FD_ISSET(giIPCPipeHandle, set) ) { int newfd = _SysOpenChild(giIPCPipeHandle, "newclient", OPENFLAG_READ|OPENFLAG_WRITE); - _SysDebug("newfd = %i"); + _SysDebug("newfd = %i", newfd); IPC_int_GetClient(&gIPC_Type_IPCPipe, &newfd); } @@ -152,6 +153,11 @@ void IPC_HandleSelect(fd_set *set) char staticBuf[STATICBUF_SIZE]; size_t len; len = _SysRead(fd, staticBuf, sizeof(staticBuf)); + if( len == (size_t)-1 ) { + // TODO: Check errno for EINTR + IPC_int_DropClient(gIPC_Clients[i]); + break; + } IPC_Handle( gIPC_Clients[i], len, (void*)staticBuf ); } } @@ -238,6 +244,38 @@ int _CompareClientPtrs(const void *_a, const void *_b) return a->IPCType->CompareIdent(a->Ident, b->Ident); } +int IPC_int_BSearchClients(const tIPC_Client *TargetClient, int *Pos) +{ + int div; + int cmp = -1; + int pos = 0; + + div = giIPC_ClientCount; + pos = div/2; + while(div > 0) + { + div /= 2; + cmp = _CompareClientPtrs(&TargetClient, &gIPC_Clients[pos]); +// _SysDebug("Checking against %i gives %i", pos, cmp); + if(cmp == 0) break; + if(cmp < 0) + pos -= div; + else + pos += div; + } + + // - Return if found + if(cmp == 0) { + *Pos = pos; + return 1; + } + + // Adjust pos to be the index where the new client will be placed + if(cmp > 0) pos ++; + *Pos = pos; + return 0; +} + tIPC_Client *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident) { int pos = 0; // Position where the new client will be inserted @@ -248,33 +286,10 @@ tIPC_Client *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident) if(giIPC_ClientCount > 0) { tIPC_Client target; - int div; - int cmp = -1; - target.IPCType = IPCType; target.Ident = Ident; - ret = ⌖ // Abuse ret to get a pointer - - div = giIPC_ClientCount; - pos = div/2; - while(div > 0) - { - div /= 2; - cmp = _CompareClientPtrs(&ret, &gIPC_Clients[pos]); -// _SysDebug("Checking against %i gives %i", pos, cmp); - if(cmp == 0) break; - if(cmp < 0) - pos -= div; - else - pos += div; - } - - // - Return if found - if(cmp == 0) + if( IPC_int_BSearchClients(&target, &pos) ) return gIPC_Clients[pos]; - - // Adjust pos to be the index where the new client will be placed - if(cmp > 0) pos ++; } @@ -302,6 +317,40 @@ tIPC_Client *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident) return ret; } +void IPC_int_DropClient(tIPC_Client *Client) +{ + // Remove from client list + int pos; + if( !IPC_int_BSearchClients(Client, &pos) ) { + _SysDebug("IPC_int_DropClient: Can't find client %p", Client); + return ; + } + + giIPC_ClientCount --; + memmove(&gIPC_Clients[pos], &gIPC_Clients[pos+1], (giIPC_ClientCount-pos)*sizeof(tIPC_Client*)); + + // Terminate client's windows + // - If there were active windows, show an error? + int nWindowsDestroyed = 0; + for(int i = 0; i < Client->nWindows; i ++) + { + if( Client->Windows[i] ) + { + _SysDebug("Window %p:%i %p still exists", Client, i, Client->Windows[i]); + WM_DestroyWindow(Client->Windows[i]); + nWindowsDestroyed ++; + } + } + if( nWindowsDestroyed ) + { + _SysDebug("TODO: Show notice that application exited without destroying windows"); + } + + // Free client structure + free(Client); + _SysDebug("Dropped client %p", Client); +} + tWindow *IPC_int_GetWindow(tIPC_Client *Client, uint32_t WindowID) { if( WindowID == -1 ) @@ -480,6 +529,7 @@ int IPC_Msg_DestroyWin(tIPC_Client *Client, tAxWin_IPCMessage *Msg) return 0; WM_DestroyWindow(win); + IPC_int_SetWindow(Client, Msg->Window, NULL); return 0; } @@ -628,7 +678,7 @@ void IPC_Handle(tIPC_Client *Client, size_t MsgLen, tAxWin_IPCMessage *Msg) { tWindow *win = IPC_int_GetWindow(Client, Msg->Window); if( !win ) { - _SysDebug("WARNING: NULL window in message %i", Msg->ID); + _SysDebug("WARNING: NULL window in message %i (%x)", Msg->ID, Msg->Window); return ; } tWMRenderer *renderer = win->Renderer; diff --git a/Usermode/Applications/axwin3_src/WM/renderers/menu.c b/Usermode/Applications/axwin3_src/WM/renderers/menu.c index d3534423..e17d9542 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/menu.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/menu.c @@ -422,7 +422,7 @@ int Renderer_Menu_HandleMessage(tWindow *Window, int Msg, int Length, const void { info->HilightedItem = new_hilight; // TODO: Change sub-menu - WM_Invalidate(Window); + WM_Invalidate(Window, 1); } return 0; } diff --git a/Usermode/Applications/axwin3_src/WM/renderers/richtext.c b/Usermode/Applications/axwin3_src/WM/renderers/richtext.c index 8f69c9ca..5f31057a 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/richtext.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/richtext.c @@ -20,6 +20,7 @@ typedef struct sRichText_Line struct sRichText_Line *Next; struct sRichText_Line *Prev; int Num; + char bIsClean; // TODO: Pre-rendered cache? short ByteLength; short Space; @@ -36,6 +37,7 @@ typedef struct sRichText_Window tColour DefaultFG; tColour DefaultBG; tFont *Font; + char bNeedsFullRedraw; short LineHeight; } tRichText_Window; @@ -201,7 +203,6 @@ void Renderer_RichText_RenderText(tWindow *Window, int Line, const char *Text) void Renderer_RichText_Redraw(tWindow *Window) { tRichText_Window *info = Window->RendererInfo; - int i; tRichText_Line *line = info->FirstVisLine; if( !line ) { @@ -213,41 +214,66 @@ void Renderer_RichText_Redraw(tWindow *Window) while( line && line->Prev && line->Prev->Num > info->FirstVisRow ) line = line->Prev; + int i; for( i = 0; i < info->DispLines && line; i ++ ) { if( i >= info->nLines - info->FirstVisRow ) break; - // TODO: Dirty rectangles? + // Empty line is noted by a discontinuity + if( line->Num > info->FirstVisRow + i ) { + // Clear line if window needs full redraw + if( info->bNeedsFullRedraw ) { + WM_Render_FillRect(Window, + 0, i*info->LineHeight, + Window->W, info->LineHeight, + info->DefaultBG + ); + } + else { + // Hack to clear cursor on NULL lines + WM_Render_FillRect(Window, + 0, i*info->LineHeight, + 1, info->LineHeight, + info->DefaultBG + ); + } + continue ; + } + + if( info->bNeedsFullRedraw || !line->bIsClean ) + { + WM_Render_FillRect(Window, + 0, i*info->LineHeight, + Window->W, info->LineHeight, + info->DefaultBG + ); + + // Formatted text out + Renderer_RichText_RenderText(Window, i, line->Data); + _SysDebug("RichText: %p - Render %i '%.*s'", Window, + line->Num, line->ByteLength, line->Data); + line->bIsClean = 1; + } + + line = line->Next; + } + // Clear out lines i to info->DispLines-1 + if( info->bNeedsFullRedraw ) + { + _SysDebug("RichText: %p - Clear %i px lines with %06x starting at %i", + Window, (info->DispLines-i)*info->LineHeight, info->DefaultBG, i*info->LineHeight); WM_Render_FillRect(Window, 0, i*info->LineHeight, - Window->W, info->LineHeight, + Window->W, (info->DispLines-i)*info->LineHeight, info->DefaultBG ); - if( line->Num > info->FirstVisRow + i ) - continue ; - // TODO: Horizontal scrolling? - // TODO: Formatting - - // Formatted text out - Renderer_RichText_RenderText(Window, i, line->Data); - _SysDebug("RichText: %p - Render %i '%.*s'", Window, - line->Num, line->ByteLength, line->Data); - - line = line->Next; } - // Clear out i -- info->DispLines - _SysDebug("RichText: %p - Clear %i px lines with %06x starting at %i", - Window, (info->DispLines-i)*info->LineHeight, info->DefaultBG, i*info->LineHeight); - WM_Render_FillRect(Window, - 0, i*info->LineHeight, - Window->W, (info->DispLines-i)*info->LineHeight, - info->DefaultBG - ); + info->bNeedsFullRedraw = 0; - // HACK! + // HACK: Hardcoded text width of 8 info->DispCols = Window->W / 8; - // TODO: Text cursor + // Text cursor _SysDebug("Cursor at %i,%i", info->CursorCol, info->CursorRow); _SysDebug(" Range [%i+%i],[%i+%i]", info->FirstVisRow, info->DispLines, info->FirstVisCol, info->DispCols); if( info->CursorRow >= info->FirstVisRow && info->CursorRow < info->FirstVisRow + info->DispLines ) @@ -266,6 +292,22 @@ void Renderer_RichText_Redraw(tWindow *Window) } } +tRichText_Line *Renderer_RichText_int_GetLine(tWindow *Window, int LineNum, tRichText_Line **Prev) +{ + tRichText_Window *info = Window->RendererInfo; + tRichText_Line *line = info->FirstLine; + tRichText_Line *prev = NULL; + while(line && line->Num < LineNum) + prev = line, line = line->Next; + + if( Prev ) + *Prev = prev; + + if( !line || line->Num > LineNum ) + return NULL; + return line; +} + int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data) { tRichText_Window *info = Window->RendererInfo; @@ -281,10 +323,22 @@ int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void case _ATTR_DEFFG: info->DefaultFG = msg->Value; break; - case _ATTR_CURSORPOS: - info->CursorRow = msg->Value >> 12; - info->CursorCol = msg->Value & 0xFFF; - break; + case _ATTR_CURSORPOS: { + int newRow = msg->Value >> 12; + int newCol = msg->Value & 0xFFF; + // Force redraw of old and new row + tRichText_Line *line = Renderer_RichText_int_GetLine(Window, info->CursorRow, NULL); + if( line ) + line->bIsClean = 0; + if( newRow != info->CursorRow ) { + line = Renderer_RichText_int_GetLine(Window, newRow, NULL); + if(line) + line->bIsClean = 0; + } + info->CursorRow = newRow; + info->CursorCol = newCol; + WM_Invalidate(Window, 1); + break; } case _ATTR_SCROLL: // TODO: Set scroll flag break; @@ -303,18 +357,16 @@ int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const voi if( Len < sizeof(*msg) ) return -1; if( msg->Line >= info->nLines ) return 1; // Bad count - tRichText_Line *line = info->FirstLine; tRichText_Line *prev = NULL; - while(line && line->Num < msg->Line) - prev = line, line = line->Next; - if( !line || line->Num > msg->Line ) + tRichText_Line *line = Renderer_RichText_int_GetLine(Window, msg->Line, &prev); + if( !line ) { // New line! // Round up to 32 int space = ((Len - sizeof(*msg)) + 32-1) & ~(32-1); tRichText_Line *new = malloc(sizeof(*line) + space); // TODO: Bookkeeping on how much memory each window uses - new->Next = line; + new->Next = (prev ? prev->Next : NULL); new->Prev = prev; new->Num = msg->Line; new->Space = space; @@ -342,10 +394,11 @@ int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const voi } line->ByteLength = Len - sizeof(*msg); memcpy(line->Data, msg->LineData, Len - sizeof(*msg)); + line->bIsClean = 0; - WM_Invalidate( Window ); +// WM_Invalidate(Window, 1); - return 0; + return 0; } int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data) @@ -357,6 +410,7 @@ int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const voi const struct sWndMsg_Resize *msg = Data; if(Len < sizeof(*msg)) return -1; info->DispLines = msg->H / info->LineHeight; + info->bNeedsFullRedraw = 1; // force full rerender return 1; } case WNDMSG_KEYDOWN: case WNDMSG_KEYUP: diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c b/Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c index fc7e1077..831565b3 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c @@ -213,7 +213,7 @@ int Widget_TextInput_KeyFire(tElement *Element, int KeySym, int Character) } // TODO: Have a Widget_ function to do this instead - WM_Invalidate(Element->Window); + WM_Invalidate(Element->Window, 1); return 0; } diff --git a/Usermode/Applications/axwin3_src/WM/video.c b/Usermode/Applications/axwin3_src/WM/video.c index a30dd377..dfdd2e50 100644 --- a/Usermode/Applications/axwin3_src/WM/video.c +++ b/Usermode/Applications/axwin3_src/WM/video.c @@ -92,7 +92,7 @@ void Video_Update(void) _SysDebug("Video_Update - Sending FD %i %p 0x%x", giTerminalFD, gpScreenBuffer+ofs, size*4); _SysWrite(giTerminalFD, gpScreenBuffer+ofs, size*4); _SysDebug("Video_Update - Done"); - giVideo_FirstDirtyLine = 0; + giVideo_FirstDirtyLine = giScreenHeight; giVideo_LastDirtyLine = 0; } @@ -159,10 +159,8 @@ void Video_Blit(uint32_t *Source, short DstX, short DstY, short W, short H) if( W <= 0 || H <= 0 ) return; - if( DstY < giVideo_FirstDirtyLine ) - giVideo_FirstDirtyLine = DstY; - if( DstY + H > giVideo_LastDirtyLine ) - giVideo_LastDirtyLine = DstY + H; + giVideo_FirstDirtyLine = MIN(DstY, giVideo_FirstDirtyLine); + giVideo_LastDirtyLine = MAX(DstY+H, giVideo_LastDirtyLine); buf = gpScreenBuffer + DstY*giScreenWidth + DstX; if(drawW != giScreenWidth || W != giScreenWidth) diff --git a/Usermode/Applications/axwin3_src/WM/wm.c b/Usermode/Applications/axwin3_src/WM/wm.c index cc9d81d0..4b28d11d 100644 --- a/Usermode/Applications/axwin3_src/WM/wm.c +++ b/Usermode/Applications/axwin3_src/WM/wm.c @@ -112,7 +112,8 @@ void WM_DestroyWindow(tWindow *Window) else Window->Parent->LastChild = prev; } - WM_Invalidate(Window->Parent); + // - Full invalidate + WM_Invalidate(Window, 1); // - Remove from inheritance tree? @@ -134,7 +135,7 @@ void WM_DestroyWindow(tWindow *Window) if( Window->Renderer->DestroyWindow ) Window->Renderer->DestroyWindow(Window); else - _SysDebug("WARN: Renderer %s does not have a destroy function", Window->Renderer->Name); + _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); @@ -241,9 +242,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; } @@ -255,6 +257,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; @@ -280,7 +286,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) @@ -299,7 +307,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) @@ -342,12 +350,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; } @@ -360,15 +375,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_ResizeWindow: %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; @@ -437,18 +456,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; } @@ -495,7 +516,7 @@ void WM_int_UpdateWindow(tWindow *Window) } Window->Renderer->Redraw(Window); - Window->Flags |= WINFLAG_CLEAN; + Window->Flags |= WINFLAG_CLEAN|WINFLAG_NEEDREBLIT; } // Process children @@ -513,7 +534,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; @@ -535,7 +556,15 @@ 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; + } if( Window == gpWM_FocusedWindow && Window->CursorW ) { @@ -549,7 +578,7 @@ void WM_int_BlitWindow(tWindow *Window) for( child = Window->FirstChild; child; child = child->NextSibling ) { - WM_int_BlitWindow(child); + WM_int_BlitWindow(child, bForceReblit); } } @@ -563,7 +592,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(); } diff --git a/Usermode/Applications/axwin3_src/include/wm_messages.h b/Usermode/Applications/axwin3_src/include/wm_messages.h index a0c49198..1cc7697a 100644 --- a/Usermode/Applications/axwin3_src/include/wm_messages.h +++ b/Usermode/Applications/axwin3_src/include/wm_messages.h @@ -13,21 +13,21 @@ */ enum eWM_WindowMessages { - WNDMSG_NULL, + WNDMSG_NULL, // 0 - WNDMSG_CREATE, - WNDMSG_DESTROY, - WNDMSG_CLOSE, - WNDMSG_FOCUS, // Called on change - WNDMSG_SHOW, // Called on change + WNDMSG_CREATE, // 1 + WNDMSG_DESTROY, // 2 + WNDMSG_CLOSE, // 3 + WNDMSG_FOCUS, // 4 Called on change + WNDMSG_SHOW, // 5 Called on change - WNDMSG_RESIZE, + WNDMSG_RESIZE, // 6 - WNDMSG_MOUSEMOVE, - WNDMSG_MOUSEBTN, - WNDMSG_KEYDOWN, - WNDMSG_KEYFIRE, - WNDMSG_KEYUP, + WNDMSG_MOUSEMOVE, // 7 + WNDMSG_MOUSEBTN, // 8 + WNDMSG_KEYDOWN, // 9 + WNDMSG_KEYFIRE, // 10 + WNDMSG_KEYUP, // 11 WNDMSG_HOTKEY, diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c index 9fed5449..1ac98fe5 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c @@ -26,13 +26,20 @@ int AxWin3_RichText_MessageHandler(tHWND Window, int MessageID, int Size, void * { tRichText_Window *info = AxWin3_int_GetDataPtr(Window); struct sWndMsg_KeyAction *keyaction = Data; - _SysDebug("MessageID = %i", MessageID); switch(MessageID) { case WNDMSG_KEYFIRE: if(Size < sizeof(*keyaction)) return -1; info->KeyCallback(Window, 2, keyaction->KeySym, keyaction->UCS32); return 1; + case WNDMSG_KEYDOWN: + if(Size < sizeof(*keyaction)) return -1; + info->KeyCallback(Window, 1, keyaction->KeySym, keyaction->UCS32); + return 1; + case WNDMSG_KEYUP: + if(Size < sizeof(*keyaction)) return -1; + info->KeyCallback(Window, 0, keyaction->KeySym, 0); + return 1; } return 0; } 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 62e42779..22a934bb 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c @@ -12,6 +12,9 @@ #include #include +//static const int ciBaseElementCount = 16; +static const int ciStepElementCount = 16; + // === STRUCTURES === struct sAxWin3_Widget { @@ -58,11 +61,10 @@ uint32_t AxWin3_Widget_int_AllocateID(tWidgetWindowInfo *Info) } if( newID == Info->nElements ) { - const int size_step = 4; - Info->nElements += 4; + Info->nElements += ciStepElementCount; Info->Elements = realloc(Info->Elements, sizeof(*Info->Elements)*Info->nElements); - newID = Info->nElements - 4; - memset( &Info->Elements[newID+1], 0, (size_step-1)*sizeof(Info->Elements)); + newID = Info->nElements - ciStepElementCount; + memset( &Info->Elements[newID+1], 0, (ciStepElementCount-1)*sizeof(Info->Elements)); _SysDebug("Widget: Expanded to %i and allocated %i", Info->nElements, newID); } else @@ -79,12 +81,19 @@ int AxWin3_Widget_MessageHandler(tHWND Window, int MessageID, int Size, void *Da switch(MessageID) { +// case WNDMSG_DESTROY: { +// return 0; } case MSG_WIDGET_FIRE: { tWidgetMsg_Fire *msg = Data; if(Size < sizeof(*msg)) return -1; widget = AxWin3_Widget_int_GetElementByID(Window, msg->WidgetID); if(widget->Fire) widget->Fire(widget); + return 1; } + case MSG_WIDGET_KEYPRESS: { + return 0; } + case MSG_WIDGET_MOUSEBTN: { + // TODO: Do something return 1; } default: return 0; diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c index 99b9a1b6..f1ffd3b2 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c @@ -54,6 +54,20 @@ tWindow *AxWin3_int_GetWindowFromID(uint32_t ServerID) return block->Windows[ServerID]; } +void AxWin3_int_DelWindowByID(uint32_t ServerID) +{ + int orig_id = ServerID; + tWindowBlock *block = &gAxWin3_WindowList; + while(block && ServerID > WINDOWS_PER_ALLOC) { + block = block->Next; + ServerID -= WINDOWS_PER_ALLOC; + } + if( !block || !block->Windows[ServerID] ) + _SysDebug("AxWin3_int_DelWindowByID - Id %i out of range", orig_id); + else + block->Windows[ServerID] = NULL; +} + tWindow *AxWin3_int_AllocateWindowInfo(int DataBytes, int *WinID) { int idx, newWinID; @@ -208,6 +222,7 @@ int AxWin3_int_DefaultMessageHandler(tWindow *Win, int ID, size_t Len, const voi case WNDMSG_DESTROY: _SysDebug("TODO: Check that WNDMSG_DESTROY was from us calling _DestroyWindow"); // TODO: Finalise cleanup of window, this will be the last message sent to this window + AxWin3_int_DelWindowByID(Win->ServerID); return 1; default: return 0;