#include <stdint.h>
#include <acess/sys.h> // _SysDebug
-typedef void tMessages_Handle_Callback(void*, size_t, void*);
+// === TYPES ===
+typedef struct sIPC_Type tIPC_Type;
typedef struct sFont tFont;
+struct sIPC_Type
+{
+ int (*GetIdentSize)(void *Ident);
+ int (*CompareIdent)(void *Ident1, void *Ident2);
+ void (*SendMessage)(void *Ident, size_t, void *Data);
+};
+
#include "wm.h"
#include "image.h"
//#include "font.h"
extern void memset32(void *ptr, uint32_t val, size_t count);
// --- Initialisation ---
extern void ParseCommandline(int argc, char *argv[]);
+// --- Messages / IPC ---
extern void IPC_Init(void);
extern void IPC_FillSelect(int *nfds, fd_set *set);
extern void IPC_HandleSelect(fd_set *set);
+// --- Input ---
extern void Input_FillSelect(int *nfds, fd_set *set);
extern void Input_HandleSelect(fd_set *set);
// --- Local WM ---
-extern tApplication *AxWin_RegisterClient(int IdentLen, void *Ident, tMessages_Handle_Callback *Cb, const char *Name);
+extern tApplication *AxWin_RegisterClient(tIPC_Type *Method, void *Ident, const char *Name);
extern void AxWin_DeregisterClient(tApplication *App);
+extern tApplication *AxWin_GetClient(tIPC_Type *Method, void *Ident);
// --- Video ---
extern void Video_Setup(void);
extern void Video_Update(void);
void IPC_Init(void);
void IPC_FillSelect(int *nfds, fd_set *set);
void IPC_HandleSelect(fd_set *set);
-void Messages_RespondDatagram(void *Ident, size_t Length, void *Data);
-void Messages_RespondIPC(void *Ident, size_t Length, void *Data);
-void Messages_Handle(size_t IdentLen, void *Ident, size_t MsgLen, tAxWin_Message *Msg, tMessages_Handle_Callback *Respond);
+void IPC_Handle(tIPC_Type *IPCType, void *Ident, size_t MsgLen, tAxWin_Message *Msg);
+ int IPC_Type_Datagram_GetSize(void *Ident);
+ int IPC_Type_Datagram_Compare(void *Ident1, void *Ident2);
+void IPC_Type_Datagram_Send(void *Ident, size_t Length, void *Data);
+ int IPC_Type_Sys_GetSize(void *Ident);
+ int IPC_Type_Sys_Compare(void *Ident1, void *Ident2);
+void IPC_Type_Sys_Send(void *Ident, size_t Length, void *Data);
// === GLOBALS ===
int giNetworkFileHandle = -1;
int giMessagesFileHandle = -1;
+tIPC_Type gIPC_Type_Datagram = {
+ IPC_Type_Datagram_GetSize,
+ IPC_Type_Datagram_Compare,
+ IPC_Type_Datagram_Send
+};
+tIPC_Type gIPC_Type_SysMessage = {
+ IPC_Type_Sys_GetSize,
+ IPC_Type_Sys_Compare,
+ IPC_Type_Sys_Send
+};
// === CODE ===
void IPC_Init(void)
identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] );
msg = staticBuf + identlen;
- Messages_Handle(identlen, staticBuf, readlen - identlen, (void*)msg, Messages_RespondDatagram);
+ IPC_Handle(&gIPC_Type_Datagram, staticBuf, readlen - identlen, (void*)msg);
}
while(SysGetMessage(NULL, NULL))
char data[len];
SysGetMessage(NULL, data);
- Messages_Handle(sizeof(tid), &tid, len, (void*)data, Messages_RespondIPC);
+ IPC_Handle(&gIPC_Type_SysMessage, &tid, len, (void*)data);
}
}
-void Messages_RespondDatagram(void *Ident, size_t Length, void *Data)
-{
- int addrSize = Net_GetAddressSize( ((uint16_t*)Ident)[1] );
- char tmpbuf[ 4 + addrSize + Length ];
- memcpy(tmpbuf, Ident, 4 + addrSize);
- memcpy(tmpbuf + 4 + addrSize, Data, Length);
- // TODO: Handle fragmented packets
- write(giNetworkFileHandle, sizeof(tmpbuf), tmpbuf);
-}
-
-void Messages_RespondIPC(void *Ident, size_t Length, void *Data)
-{
- SysSendMessage( *(tid_t*)Ident, Length, Data );
-}
-
-void Messages_Handle(size_t IdentLen, void *Ident, size_t MsgLen, tAxWin_Message *Msg, tMessages_Handle_Callback *Respond)
+void IPC_Handle(tIPC_Type *IPCType, void *Ident, size_t MsgLen, tAxWin_Message *Msg)
{
+ tApplication *app;
+
if( MsgLen < sizeof(tAxWin_Message) )
return ;
if( MsgLen < sizeof(tAxWin_Message) + Msg->Size )
return ;
+
+ app = AxWin_GetClient(IPCType, Ident);
- switch(Msg->ID)
+ switch((enum eAxWin_Messages) Msg->ID)
{
+ // --- Ping message (reset timeout and get server version)
case MSG_SREQ_PING:
if( MsgLen < sizeof(tAxWin_Message) + 4 ) return;
Msg->ID = MSG_SRSP_VERSION;
Msg->Data[0] = 0;
Msg->Data[1] = 1;
*(uint16_t*)&Msg->Data[2] = -1;
- Respond(Ident, sizeof(Msg->ID), Msg);
+ IPCType->SendMessage(Ident, sizeof(Msg->ID), Msg);
break;
+
+ // --- Register an application
case MSG_SREQ_REGISTER:
if( Msg->Data[Msg->Size-1] != '\0' ) {
// Invalid message
return ;
}
- AxWin_RegisterClient(IdentLen, Ident, Respond, Msg->Data);
-
+ if( app != NULL ) {
+ _SysDebug("Notice: Duplicate registration (%s)\n", Msg->Data);
+ return ;
+ }
+
+ // TODO: Should this function be implemented here?
+ AxWin_RegisterClient(IPCType, Ident, Msg->Data);
break;
-
+
+ // --- Create a window
+ case MSG_SREQ_ADDWIN:
+ if( Msg->Data[Msg->Size-1] != '\0' ) {
+ // Invalid message
+ return ;
+ }
+
+ break;
+
+ // --- Unknown message
default:
- fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, Respond);
- _SysDebug("WARNING: Unknown message %i (%p)\n", Msg->ID, Respond);
+ fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
+ _SysDebug("WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
break;
}
}
+int IPC_Type_Datagram_GetSize(void *Ident)
+{
+ return 4 + Net_GetAddressSize( ((uint16_t*)Ident)[1] );
+}
+
+int IPC_Type_Datagram_Compare(void *Ident1, void *Ident2)
+{
+ // Pass the buck :)
+ // - No need to worry about mis-matching sizes, as the size is computed
+ // from the 3rd/4th bytes, hence it will differ before the size is hit.
+ return memcmp(Ident1, Ident2, IPC_Type_Datagram_GetSize(Ident1));
+}
+
+void IPC_Type_Datagram_Send(void *Ident, size_t Length, void *Data)
+{
+ int identlen = IPC_Type_Datagram_GetSize(Ident);
+ char tmpbuf[ identlen + Length ];
+ memcpy(tmpbuf, Ident, identlen); // Header
+ memcpy(tmpbuf + identlen, Data, Length); // Data
+ // TODO: Handle fragmented packets
+ write(giNetworkFileHandle, sizeof(tmpbuf), tmpbuf);
+}
+
+int IPC_Type_Sys_GetSize(void *Ident)
+{
+ return sizeof(pid_t);
+}
+
+int IPC_Type_Sys_Compare(void *Ident1, void *Ident2)
+{
+ return *(int*)Ident1 - *(int*)Ident2;
+}
+
+void IPC_Type_Sys_Send(void *Ident, size_t Length, void *Data)
+{
+ SysSendMessage( *(tid_t*)Ident, Length, Data );
+}
extern void Video_GetTextDims(tFont *Font, const char *Text, int *W, int *H);
// === PROTOTYPES ===
+tApplication *AxWin_RegisterClient(tIPC_Type *IPCType, void *Ident, const char *Name);
+void AxWin_DeregisterClient(tApplication *App);
+tApplication *AxWin_GetClient(tIPC_Type *Method, void *Ident);
tElement *AxWin_CreateElement(tElement *Parent, int Type, int Flags, const char *DebugName);
void AxWin_DeleteElement(tElement *Element);
void AxWin_SetFlags(tElement *Element, int Flags);
tElement gWM_RootElement = {
.DebugName = "ROOT"
};
-
tApplication *gWM_Applications;
// --- Element type flags
const int ciWM_NumWidgetTypes = sizeof(gaWM_WidgetTypes)/sizeof(gaWM_WidgetTypes[0]);
// === CODE ===
-tApplication *AxWin_RegisterClient(int IdentLen, void *Ident, tMessages_Handle_Callback *Cb, const char *Name)
+tApplication *AxWin_RegisterClient(tIPC_Type *Method, void *Ident, const char *Name)
{
- tApplication *ret = calloc( 1, sizeof(tApplication) + 1 + strlen(Name) + 1 + IdentLen );
+ int identlen = Method->GetIdentSize(Ident);
+ // Structure, empty string, Name, Ident
+ tApplication *ret = calloc( 1, sizeof(tApplication) + 1 + strlen(Name) + 1 + identlen );
+
+ // DebugName is empty
+ // Name/Title
ret->Name = &ret->MetaElement.DebugName[1];
strcpy(ret->Name, Name);
+ // Ident
ret->Ident = ret->Name + strlen(Name) + 1;
- memcpy(ret->Ident, Ident, IdentLen);
- ret->SendMessage = Cb;
+ memcpy(ret->Ident, Ident, identlen);
+ // IPC Type
+ ret->IPCType = Method;
+ // Element index
ret->MaxElementIndex = DEFAULT_ELEMENTS_PER_APP;
ret->EleIndex = calloc( 1, ret->MaxElementIndex * sizeof(*ret->EleIndex) );
+ // Add to global list
ret->Next = gWM_Applications;
gWM_Applications = ret;
void AxWin_DeregisterClient(tApplication *App)
{
+ // TODO: Complete implementing DeregisterClient
tElement *win, *next;
- // TODO: Implement DeregisterClient
for( win = App->MetaElement.FirstChild; win; win = next )
{
}
// TODO: Inform listeners of deleted application
- // TODO: Remove from list
+
+ // Remove from list
+ {
+ tApplication *app, *prev = NULL;
+ for( app = gWM_Applications; app; app = app->Next )
+ {
+ if( app == App ) break;
+ prev = app;
+ }
+
+ if( app )
+ {
+ if(prev)
+ prev->Next = App->Next;
+ else
+ gWM_Applications = App->Next;
+ }
+ }
+
free(App);
}
+/**
+ * \brief Get an application handle from a client identifier
+ */
+tApplication *AxWin_GetClient(tIPC_Type *Method, void *Ident)
+{
+ // TODO: Faster and smarter technique
+ tApplication *app;
+ for( app = gWM_Applications; app; app = app->Next )
+ {
+ if( app->IPCType != Method ) continue;
+ if( Method->CompareIdent( app->Ident, Ident ) != 0 ) continue;
+ return app;
+ }
+ return NULL;
+}
+
tElement *AxWin_CreateWindow(tApplication *App, const char *Name)
{
tElement *ret;