Usermode/AxWin3 - Speedups mostly, required some restructure
authorJohn Hodge <[email protected]>
Sun, 12 May 2013 11:07:17 +0000 (19:07 +0800)
committerJohn Hodge <[email protected]>
Sun, 12 May 2013 11:07:17 +0000 (19:07 +0800)
13 files changed:
Usermode/Applications/axwin3_src/Interface/main.c
Usermode/Applications/axwin3_src/WM/include/common.h
Usermode/Applications/axwin3_src/WM/include/wm.h
Usermode/Applications/axwin3_src/WM/ipc.c
Usermode/Applications/axwin3_src/WM/renderers/menu.c
Usermode/Applications/axwin3_src/WM/renderers/richtext.c
Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c
Usermode/Applications/axwin3_src/WM/video.c
Usermode/Applications/axwin3_src/WM/wm.c
Usermode/Applications/axwin3_src/include/wm_messages.h
Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c
Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c
Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c

index a098614..abe21e5 100644 (file)
@@ -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;
 }
index 1be86ff..e074450 100644 (file)
@@ -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;
index a4275c9..914058f 100644 (file)
@@ -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);
index 4460184..79e0956 100644 (file)
@@ -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 = &target;  // 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;
index d353442..e17d954 100644 (file)
@@ -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; }
index 8f69c9c..5f31057 100644 (file)
@@ -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:
index fc7e107..831565b 100644 (file)
@@ -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;
 }
index a30dd37..dfdd2e5 100644 (file)
@@ -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)
index cc9d81d..4b28d11 100644 (file)
@@ -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();
 }
index a0c4919..1cc7697 100644 (file)
  */
 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,   // Called on change
+       WNDMSG_SHOW,    // 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,
        
index 9fed544..1ac98fe 100644 (file)
@@ -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;
 }
index 62e4277..22a934b 100644 (file)
@@ -12,6 +12,9 @@
 #include <widget_messages.h>
 #include <string.h>
 
+//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;
index 99b9a1b..f1ffd3b 100644 (file)
@@ -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;

UCC git Repository :: git.ucc.asn.au