Usermode/AxWin3 - Changed to use SysSpawn and detect crap server PIDs
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / renderers / widget.c
index f3de26f..b8c454c 100644 (file)
@@ -79,7 +79,6 @@ void Widget_int_SetTypeDef(int Type, tWidgetDef *Ptr)
        }
        
        gaWM_WidgetTypes[Type] = Ptr;
-       _SysDebug("Registered type %i to %p", Type, Ptr);
 }
 
 tWindow        *Renderer_Widget_Create(int Flags)
@@ -88,7 +87,7 @@ tWindow       *Renderer_Widget_Create(int Flags)
        tWidgetWin      *info;
         int    eletable_size = DEFAULT_ELETABLE_SIZE;
 
-       _SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
+       //_SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
 
        // TODO: Use `Flags` as default element count?
        // - Actaully, it's taken by the root ele flags
@@ -98,6 +97,7 @@ tWindow       *Renderer_Widget_Create(int Flags)
        info = ret->RendererInfo;
        
        info->TableSize = eletable_size;
+       info->FocusedElement = &info->RootElement;
        info->RootElement.Window = ret;
        info->RootElement.ID = -1;
        info->RootElement.BackgroundColour = 0xCCCCCC;
@@ -113,7 +113,7 @@ tWindow     *Renderer_Widget_Create(int Flags)
 void Renderer_Widget_Redraw(tWindow *Window)
 {
        tWidgetWin      *info = Window->RendererInfo;
-       WM_Render_FillRect(Window, 0, 0, 0xFFF, 0xFFF, info->RootElement.BackgroundColour);
+       WM_Render_FillRect(Window, 0, 0, Window->W, Window->H, info->RootElement.BackgroundColour);
 
        Widget_UpdateDimensions(&info->RootElement);
        Widget_UpdatePosition(&info->RootElement);
@@ -142,10 +142,6 @@ void Widget_RenderWidget(tWindow *Window, tElement *Element)
        {
                gaWM_WidgetTypes[Element->Type]->Render(Window, Element);
        }
-       else
-       {
-               Widget_Decorator_RenderWidget(Window, Element);
-       }
        
        for(child = Element->FirstChild; child; child = child->NextSibling)
        {
@@ -218,14 +214,14 @@ void Widget_UpdateDimensions(tElement *Element)
        else
                fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
 
-       _SysDebug("%i (p=%i) - WxH=%ix%i",
-               Element->ID, (Element->Parent ? Element->Parent->ID : -1),
-               Element->CachedW, Element->CachedH
-               );
-       _SysDebug("  %s dynWith = %i, fullCross = %i",
-               (Element->Flags & ELEFLAG_VERTICAL ? "Vert" : "Horiz"),
-               dynWith, fullCross
-               );
+       //_SysDebug("%i (p=%i) - WxH=%ix%i",
+       //      Element->ID, (Element->Parent ? Element->Parent->ID : -1),
+       //      Element->CachedW, Element->CachedH
+       //      );
+       //_SysDebug("  %s dynWith = %i, fullCross = %i",
+       //      (Element->Flags & ELEFLAG_VERTICAL ? "Vert" : "Horiz"),
+       //      dynWith, fullCross
+       //      );
        
        // Pass 2 - Set sizes and recurse
        for( child = Element->FirstChild; child; child = child->NextSibling )
@@ -256,7 +252,7 @@ void Widget_UpdateDimensions(tElement *Element)
                if(w < child->MinW)     w = child->MinW;
                if(h < child->MinH)     h = child->MinH;
        
-               _SysDebug("Child %ix%i (min %ix%i)", w, h, child->MinW, child->MinH);
+//             _SysDebug("Child %ix%i (min %ix%i)", w, h, child->MinW, child->MinH);
        
                // Update the dimensions if they have changed
                if( child->CachedW == w && child->CachedH == h )
@@ -396,7 +392,7 @@ tElement *Widget_GetElementByPos(tWidgetWin *Info, int X, int Y)
        tElement        *ret, *next, *ele;
        
        next = &Info->RootElement;
-       while(next)
+       do
        {
                ret = next;
                next = NULL;
@@ -409,7 +405,7 @@ tElement *Widget_GetElementByPos(tWidgetWin *Info, int X, int Y)
                        if(Y >= ele->CachedY + ele->CachedH)    continue;
                        next = ele;
                }
-       }
+       } while(next);
        return ret;
 }
 
@@ -427,11 +423,52 @@ tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID)
        return ele;
 }
 
+tElement *Widget_int_Create(tWidgetWin *Info, tElement *Parent, int ID, int Type, int Flags)
+{
+       if( Widget_GetElementById(Info, ID) )
+               return NULL;
+
+       // Create new element
+       tElement *new = calloc(sizeof(tElement), 1);
+       new->Window = Parent->Window;
+       new->ID = ID;
+       new->Type = Type;
+       new->Parent = Parent;
+       new->Flags = Flags;
+       new->PaddingT = 2;
+       new->PaddingB = 2;
+       new->PaddingL = 2;
+       new->PaddingR = 2;
+       new->CachedX = -1;
+       
+       if( gaWM_WidgetTypes[Type]->Init )
+               gaWM_WidgetTypes[Type]->Init(new);
+       
+       // Add to parent's list
+       if(Parent->LastChild)
+               Parent->LastChild->NextSibling = new;
+       else
+               Parent->FirstChild = new;
+       Parent->LastChild = new;
+
+       // Add to info
+       {
+               tElement        *ele, *prev = NULL;
+               for(ele = Info->ElementTable[new->ID % Info->TableSize]; ele; prev = ele, ele = ele->ListNext);
+               if(prev)
+                       prev->ListNext = new;
+               else
+                       Info->ElementTable[new->ID % Info->TableSize] = new;
+       }
+       
+       return new;
+}
+
 // --- Message Handlers ---
 void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg)
 {
        const int       max_debugname_len = Len - sizeof(tWidgetMsg_Create);
-       tElement        *parent, *new;
+       tElement        *parent;
 
        // Sanity check
        if( Len < sizeof(*Msg) )
@@ -456,44 +493,36 @@ void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg
                return ;
        }
 
-       // Check if the ID is already in use
-       if( Widget_GetElementById(Info, Msg->NewID) )
-               return ;
+       Widget_int_Create(Info, parent, Msg->NewID, Msg->Type, Msg->Flags);
 
-       // Create new element
-       new = calloc(sizeof(tElement), 1);
-       new->Window = parent->Window;
-       new->ID = Msg->NewID;
-       new->Type = Msg->Type;
-       new->Parent = parent;
-       new->Flags = Msg->Flags;
-       new->PaddingT = 2;
-       new->PaddingB = 2;
-       new->PaddingL = 2;
-       new->PaddingR = 2;
-       new->CachedX = -1;
+       Widget_UpdateMinDims(parent);
+}
+
+void Widget_NewWidgetSubwin(tWidgetWin *Info, size_t Len, const tWidgetMsg_CreateSubWin *Msg)
+{
+       const int       max_debugname_len = Len - sizeof(tWidgetMsg_CreateSubWin);
+       tElement        *parent, *new;
+
+       // Sanity check
+       if( Len < sizeof(*Msg) )
+               return ;
+       if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
+               return ;
        
-       if( gaWM_WidgetTypes[new->Type]->Init )
-               gaWM_WidgetTypes[new->Type]->Init(new);
+       parent = Widget_GetElementById(Info, Msg->Parent);
+       if(!parent)     return;
+       if( Widget_GetElementById(Info, Msg->NewID) )   return ;
        
-       // Add to parent's list
-       if(parent->LastChild)
-               parent->LastChild->NextSibling = new;
-       else
-               parent->FirstChild = new;
-       parent->LastChild = new;
+       new = Widget_int_Create(Info, parent, Msg->NewID, Msg->Type, Msg->Flags);
+       new->Data = WM_GetWindowByID(parent->Window, Msg->WindowHandle);
+       Widget_UpdateMinDims(parent);
+}
 
-       // Add to info
-       {
-               tElement        *ele, *prev = NULL;
-               for(ele = Info->ElementTable[new->ID % Info->TableSize]; ele; prev = ele, ele = ele->ListNext);
-               if(prev)
-                       prev->ListNext = new;
-               else
-                       Info->ElementTable[new->ID % Info->TableSize] = new;
-       }
+void Widget_SetFocus(tWidgetWin *Info, tElement *Ele)
+{
+       // TODO: Callbacks
 
-       Widget_UpdateMinDims(parent);
+       Info->FocusedElement = Ele;
 }
 
 void Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg)
@@ -549,9 +578,38 @@ void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg)
 //     }
 }
 
+int Widget_GetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg)
+{
+       if( Len < sizeof(*Msg) )
+               return 0;
+       if( Len > sizeof(*Msg) )
+               return 1;       // Pass to user
+       
+       const char      *text = NULL;
+       tElement *ele = Widget_GetElementById(Info, Msg->WidgetID);
+       if(ele)
+               text = ele->Text;
+       
+       char    buf[sizeof(tWidgetMsg_SetText) + strlen(text?text:"") + 1];
+       tWidgetMsg_SetText      *omsg = (void*)buf;
+       
+       if( text ) {
+               omsg->WidgetID = Msg->WidgetID;
+               strcpy(omsg->Text, text);
+       }
+       else {
+               omsg->WidgetID = -1;
+               omsg->Text[0] = 0;
+       }
+       
+       WM_SendMessage(Info->RootElement.Window, Info->RootElement.Window, MSG_WIDGET_GETTEXT, sizeof(buf), buf);
+       return 0;
+}
+
 int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
 {
        tWidgetWin      *info = Target->RendererInfo;
+       tElement        *ele;
        switch(Msg)
        {
        case WNDMSG_RESIZE: {
@@ -572,7 +630,6 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void
        case WNDMSG_MOUSEBTN: {
                const struct sWndMsg_MouseButton        *msg = Data;
                tWidgetMsg_MouseBtn     client_msg;
-               tElement        *ele;
                 int    x, y;
                 int    rv;
                
@@ -583,6 +640,7 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void
                client_msg.bPressed = msg->bPressed;
 
                ele = Widget_GetElementByPos(info, x, y);
+               Widget_SetFocus(info, ele);
                // Send event to all elements from `ele` upwards
                for( ; ele; ele = ele->Parent )
                {
@@ -607,15 +665,75 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void
                }
                return 0; }
 
+       case WNDMSG_KEYDOWN: {
+               const struct sWndMsg_KeyAction  *msg = Data;
+               if(Len < sizeof(*msg))  return -1;
+               
+               if(!info->FocusedElement)       return 0;
+               ele = info->FocusedElement;
+
+               if(gaWM_WidgetTypes[ele->Type]->KeyDown)
+                       gaWM_WidgetTypes[ele->Type]->KeyDown(ele, msg->KeySym, msg->UCS32);
+               else
+               {
+                       // TODO: Pass to user
+               }       
+
+               return 0; }
+       
+       case WNDMSG_KEYFIRE: {
+               const struct sWndMsg_KeyAction  *msg = Data;
+               if(Len < sizeof(*msg))  return -1;
+               
+               if(!info->FocusedElement)       return 0;
+               ele = info->FocusedElement;
+
+               if(gaWM_WidgetTypes[ele->Type]->KeyFire)
+                       gaWM_WidgetTypes[ele->Type]->KeyFire(ele, msg->KeySym, msg->UCS32);
+               else
+               {
+                       // TODO: Pass the buck
+               }
+               return 0; }
+       
+       case WNDMSG_KEYUP: {
+               const struct sWndMsg_KeyAction  *msg = Data;
+               if(Len < sizeof(*msg))  return -1;
+               
+               if(!info->FocusedElement)       return 0;
+               ele = info->FocusedElement;
+
+               if(gaWM_WidgetTypes[ele->Type]->KeyUp)
+                       gaWM_WidgetTypes[ele->Type]->KeyUp(ele, msg->KeySym);
+               else
+               {
+                       // TODO: Pass the buck
+               }
+               return 0; }
+
        // New Widget
        case MSG_WIDGET_CREATE:
                Widget_NewWidget(info, Len, Data);
                return 0;
+       case MSG_WIDGET_CREATESUBWIN:
+               Widget_NewWidgetSubwin(info, Len, Data);
+               return 0;
 
+       // Delete a widget
        case MSG_WIDGET_DELETE:
                _SysDebug("TODO: Implement MSG_WIDGET_DELETE");
                return 0;
 
+       // Set focused widget
+       case MSG_WIDGET_SETFOCUS: {
+               tElement        *ele;
+               const tWidgetMsg_SetFocus       *msg = Data;
+               if(Len < sizeof(*msg))  return -1;
+               
+               ele = Widget_GetElementById(info, msg->WidgetID);
+               Widget_SetFocus(info, ele);
+               return 0; }
+
        // Set Flags
        case MSG_WIDGET_SETFLAGS:
                Widget_SetFlags(info, Len, Data);
@@ -630,6 +748,8 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void
        case MSG_WIDGET_SETTEXT:
                Widget_SetText(info, Len, Data);
                return 0;
+       case MSG_WIDGET_GETTEXT:
+               return Widget_GetText(info, Len, Data);
        
        // 
        default:

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