X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FApplications%2Faxwin3_src%2FWM%2Frenderers%2Fwidget.c;h=0261beabb7327644e45c4e420d2634f539e5fe5e;hb=3ad4532bb952dbcb28a2b9fa72d7f1f87b5f8fd4;hp=f3de26f573c88499b2444a1ff85d2723371f16d8;hpb=e62ce4c06895976eeabd6f91803f5a4194ccc902;p=tpg%2Facess2.git diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget.c b/Usermode/Applications/axwin3_src/WM/renderers/widget.c index f3de26f5..0261beab 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/widget.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget.c @@ -26,10 +26,15 @@ void Widget_UpdateDimensions(tElement *Element); void Widget_UpdatePosition(tElement *Element); // --- Messages tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID); -void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg); -void Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg); -void Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg); -void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg); + int Widget_IPC_Create(tWindow *Win, size_t Len, const void *Data); + int Widget_IPC_NewWidgetSubwin(tWindow *Win, size_t Len, const void *Data); +// int Widget_IPC_Delete(tWindow *Win, size_t Len, const void *Data); + int Widget_IPC_SetFocus(tWindow *Win, size_t Len, const void *Data); + int Widget_IPC_SetFlags(tWindow *Win, size_t Len, const void *Data); + int Widget_IPC_SetSize(tWindow *Win, size_t Len, const void *Data); + int Widget_IPC_SetText(tWindow *Win, size_t Len, const void *Data); + int Widget_IPC_GetText(tWindow *Win, size_t Len, const void *Data); +// int Widget_IPC_SetColour(tWindow *Win, size_t Len, const void *Data); int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data); // === GLOBALS === @@ -37,7 +42,17 @@ tWMRenderer gRenderer_Widget = { .Name = "Widget", .CreateWindow = Renderer_Widget_Create, .Redraw = Renderer_Widget_Redraw, - .HandleMessage = Renderer_Widget_HandleMessage + .HandleMessage = Renderer_Widget_HandleMessage, + .nIPCHandlers = N_IPC_WIDGET, + .IPCHandlers = { + [IPC_WIDGET_CREATE] = Widget_IPC_Create, + [IPC_WIDGET_CREATESUBWIN] = Widget_IPC_NewWidgetSubwin, + [IPC_WIDGET_SETFOCUS] = Widget_IPC_SetFocus, + [IPC_WIDGET_SETFLAGS] = Widget_IPC_SetFlags, + [IPC_WIDGET_SETSIZE] = Widget_IPC_SetSize, + [IPC_WIDGET_SETTEXT] = Widget_IPC_SetText, + [IPC_WIDGET_GETTEXT] = Widget_IPC_GetText, + } }; // --- Element callbacks @@ -79,7 +94,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 +102,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 +112,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 +128,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 +157,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 +229,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 ) @@ -238,7 +249,7 @@ void Widget_UpdateDimensions(tElement *Element) if( child->Flags & ELEFLAG_ABSOLUTEPOS ) continue ; // --- Width --- - if( child->Flags & ELEFLAG_NOEXPAND ) + if( child->Flags & (bVertical ? ELEFLAG_NOEXPAND : ELEFLAG_NOSTRETCH) ) w = child->MinW; else if( bVertical ) w = child->FixedCross ? child->FixedCross : fullCross; @@ -246,7 +257,7 @@ void Widget_UpdateDimensions(tElement *Element) w = child->FixedWith ? child->FixedWith : dynWith; // --- Height --- - if( child->Flags & ELEFLAG_NOSTRETCH ) + if( child->Flags & (bVertical ? ELEFLAG_NOSTRETCH : ELEFLAG_NOEXPAND) ) h = child->MinH; else if( bVertical ) h = child->FixedWith ? child->FixedWith : dynWith; @@ -256,7 +267,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 +407,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 +420,7 @@ tElement *Widget_GetElementByPos(tWidgetWin *Info, int X, int Y) if(Y >= ele->CachedY + ele->CachedH) continue; next = ele; } - } + } while(next); return ret; } @@ -427,17 +438,68 @@ 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; +} + +void Widget_SetFocus(tWidgetWin *Info, tElement *Ele) +{ + // TODO: Callbacks + + Info->FocusedElement = Ele; +} + + // --- Message Handlers --- -void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg) +int Widget_IPC_Create(tWindow *Win, size_t Len, const void *Data) { - const int max_debugname_len = Len - sizeof(tWidgetMsg_Create); - tElement *parent, *new; + tWidgetWin *Info = Win->RendererInfo; + const tWidgetIPC_Create *Msg = Data; + const int max_debugname_len = Len - sizeof(*Msg); + tElement *parent; // Sanity check if( Len < sizeof(*Msg) ) - return ; + return -1; if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len ) - return ; + return -1; _SysDebug("Widget_NewWidget (%i %i Type %i Flags 0x%x)", Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags); @@ -445,7 +507,7 @@ void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg if(Msg->Type >= ciWM_NumWidgetTypes) { _SysDebug("Widget_NewWidget - Bad widget type %i", Msg->Type); - return ; + return 1; } // Create @@ -453,90 +515,109 @@ void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg if(!parent) { _SysDebug("Widget_NewWidget - Bad parent ID %i", Msg->Parent); - return ; + return 1; } - // 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); + return 0; +} + +int Widget_IPC_NewWidgetSubwin(tWindow *Win, size_t Len, const void *Data) +{ + tWidgetWin *Info = Win->RendererInfo; + const tWidgetIPC_CreateSubWin *Msg = Data; + const int max_debugname_len = Len - sizeof(*Msg); + tElement *parent, *new; + + // Sanity check + if( Len < sizeof(*Msg) ) + return -1; + if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len ) + return -1; + + _SysDebug("Widget_NewWidgetSubwin(%i %i Type %i Flags 0x%x Subwin %i)", + Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags, Msg->WindowHandle); - if( gaWM_WidgetTypes[new->Type]->Init ) - gaWM_WidgetTypes[new->Type]->Init(new); + parent = Widget_GetElementById(Info, Msg->Parent); + if(!parent) return 1; + if( Widget_GetElementById(Info, Msg->NewID) ) return 1; - // 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); + return 0; +} - // 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; - } +// TODO: Widget_IPC_Delete - Widget_UpdateMinDims(parent); +int Widget_IPC_SetFocus(tWindow *Win, size_t Len, const void *Data) +{ + tWidgetWin *info = Win->RendererInfo; + tElement *ele; + const tWidgetIPC_SetFocus *msg = Data; + if(Len < sizeof(*msg)) return -1; + + _SysDebug("Widget_SetFocus(%i)", msg->WidgetID); + + ele = Widget_GetElementById(info, msg->WidgetID); + Widget_SetFocus(info, ele); + return 0; } -void Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg) +int Widget_IPC_SetFlags(tWindow *Win, size_t Len, const void *Data) { + tWidgetWin *Info = Win->RendererInfo; + const tWidgetIPC_SetFlags *Msg = Data; tElement *ele; if( Len < sizeof(*Msg) ) - return ; + return -1; _SysDebug("Widget_SetFlags: (%i 0x%x 0x%x)", Msg->WidgetID, Msg->Value, Msg->Mask); ele = Widget_GetElementById(Info, Msg->WidgetID); - if(!ele) return; + if(!ele) return 1; ele->Flags &= ~Msg->Mask; ele->Flags |= Msg->Value & Msg->Mask; + + return 0; } -void Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg) +int Widget_IPC_SetSize(tWindow *Win, size_t Len, const void *Data) { + tWidgetWin *Info = Win->RendererInfo; + const tWidgetIPC_SetSize *Msg = Data; tElement *ele; if( Len < sizeof(*Msg) ) - return ; + return -1; + + _SysDebug("Widget_SetSize(%i, %i)", Msg->WidgetID, Msg->Value); ele = Widget_GetElementById(Info, Msg->WidgetID); - if(!ele) return ; + if(!ele) return 1; ele->FixedWith = Msg->Value; + return 0; } -void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg) +int Widget_IPC_SetText(tWindow *Win, size_t Len, const void *Data) { + tWidgetWin *Info = Win->RendererInfo; + const tWidgetIPC_SetText *Msg = Data; tElement *ele; if( Len < sizeof(*Msg) + 1 ) - return ; + return -1; if( Msg->Text[Len - sizeof(*Msg) - 1] != '\0' ) - return ; + return -1; + _SysDebug("Widget_SetText(%i, '%.30s')", Msg->WidgetID, Msg->Text); ele = Widget_GetElementById(Info, Msg->WidgetID); - if(!ele) return ; - + if(!ele) return 1; if( gaWM_WidgetTypes[ele->Type]->UpdateText ) { @@ -547,11 +628,41 @@ void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg) // if(ele->Text) free(ele->Text); // ele->Text = strdup(Msg->Text); // } + return 0; +} + +int Widget_IPC_GetText(tWindow *Win, size_t Len, const void *Data) +{ + tWidgetWin *Info = Win->RendererInfo; + const tWidgetIPC_SetText *Msg = Data; + if( Len < sizeof(*Msg) ) + return -1; + + const char *text = NULL; + tElement *ele = Widget_GetElementById(Info, Msg->WidgetID); + if(ele) + text = ele->Text; + + char buf[sizeof(tWidgetIPC_SetText) + strlen(text?text:"") + 1]; + tWidgetIPC_SetText *omsg = (void*)buf; + + if( text ) { + omsg->WidgetID = Msg->WidgetID; + strcpy(omsg->Text, text); + } + else { + omsg->WidgetID = -1; + omsg->Text[0] = 0; + } + + WM_SendIPCReply(Win, IPC_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 +683,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 +693,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,30 +718,52 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void } return 0; } - // New Widget - case MSG_WIDGET_CREATE: - Widget_NewWidget(info, Len, Data); - 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; - case MSG_WIDGET_DELETE: - _SysDebug("TODO: Implement MSG_WIDGET_DELETE"); - return 0; + if(gaWM_WidgetTypes[ele->Type]->KeyDown) + gaWM_WidgetTypes[ele->Type]->KeyDown(ele, msg->KeySym, msg->UCS32); + else + { + // TODO: Pass to user + } - // Set Flags - case MSG_WIDGET_SETFLAGS: - Widget_SetFlags(info, Len, Data); - return 0; - - // Set length - case MSG_WIDGET_SETSIZE: - Widget_SetSize(info, Len, Data); - return 0; + return 0; } - // Set text - case MSG_WIDGET_SETTEXT: - Widget_SetText(info, Len, Data); - 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; } + // default: return 1; // Unhandled, pass to user @@ -641,6 +774,7 @@ void Widget_Fire(tElement *Element) { tWidgetMsg_Fire msg; msg.WidgetID = Element->ID; + _SysDebug("Widget_Fire: Fire on %p %i", Element->Window, Element->ID); WM_SendMessage(Element->Window, Element->Window, MSG_WIDGET_FIRE, sizeof(msg), &msg); }