2 * AxWin3 Interface Library
3 * - By John Hodge (thePowersGang)
6 * - Core window management functions
8 #include <axwin3/axwin.h>
11 #include "include/internal.h"
12 #include "include/ipc.h"
13 #include <wm_messages.h>
15 #define WINDOWS_PER_ALLOC (64-1) // -1 to make it 64 pointers (+ Next)
16 #define MAX_HOTKEYS 32
18 typedef struct sWindowBlock tWindowBlock;
20 typedef struct sAxWin3_Window tWindow;
26 tWindow *Windows[WINDOWS_PER_ALLOC];
30 int giAxWin3_LowestFreeWinID;
31 int giAxWin3_HighestUsedWinID;
32 tWindowBlock gAxWin3_WindowList;
33 tAxWin3_HotkeyCallback gAxWin3_Hotkeys[MAX_HOTKEYS];
36 tWindow *AxWin3_int_CreateWindowStruct(uint32_t ServerID, int ExtraBytes)
40 ret = calloc(sizeof(tWindow) + ExtraBytes, 1);
41 ret->ServerID = ServerID;
46 tWindow *AxWin3_int_GetWindowFromID(uint32_t ServerID)
48 tWindowBlock *block = &gAxWin3_WindowList;
49 while(block && ServerID > WINDOWS_PER_ALLOC) {
51 ServerID -= WINDOWS_PER_ALLOC;
53 if(!block) return NULL;
54 return block->Windows[ServerID];
57 tWindow *AxWin3_int_AllocateWindowInfo(int DataBytes, int *WinID)
60 tWindowBlock *block, *prev = NULL;
63 block = &gAxWin3_WindowList;
64 newWinID = giAxWin3_LowestFreeWinID;
65 for( idx = 0; block; newWinID ++ )
67 if( block->Windows[idx] == NULL )
70 if(idx == WINDOWS_PER_ALLOC) {
79 block = calloc(sizeof(tWindowBlock), 1);
84 ret = block->Windows[idx] = AxWin3_int_CreateWindowStruct(newWinID, DataBytes);
85 if(newWinID > giAxWin3_HighestUsedWinID)
86 giAxWin3_HighestUsedWinID = newWinID;
87 if(newWinID == giAxWin3_LowestFreeWinID)
88 giAxWin3_HighestUsedWinID ++;
90 if(WinID) *WinID = newWinID;
95 int AxWin3_GetDisplayCount(void)
97 tAxWin_IPCMessage *msg;
98 tIPCMsg_ReturnInt *ret;
101 msg = AxWin3_int_AllocateIPCMessage(NULL, IPCMSG_GETDISPLAYCOUNT, IPCMSG_FLAG_RETURN, 0);
102 AxWin3_int_SendIPCMessage(msg);
105 msg = AxWin3_int_WaitIPCMessage(IPCMSG_GETDISPLAYCOUNT);
106 if(msg->Size < sizeof(*ret)) return -1;
107 ret = (void*)msg->Data;
113 int AxWin3_GetDisplayDims(int Display, int *X, int *Y, int *Width, int *Height)
115 tAxWin_IPCMessage *msg;
116 tIPCMsg_GetDisplayDims *req;
117 tIPCMsg_RetDisplayDims *ret;
119 msg = AxWin3_int_AllocateIPCMessage(NULL, IPCMSG_GETDISPLAYDIMS, IPCMSG_FLAG_RETURN, sizeof(*req));
120 req = (void*)msg->Data;
121 req->DisplayID = Display;
122 AxWin3_int_SendIPCMessage(msg);
125 msg = AxWin3_int_WaitIPCMessage(IPCMSG_GETDISPLAYDIMS);
126 if(msg->Size < sizeof(*ret)) return -1;
127 ret = (void*)msg->Data;
131 if(Width) *Width = ret->W;
132 if(Height) *Height = ret->H;
137 tHWND AxWin3_CreateWindow(
138 tHWND Parent, const char *Renderer, int RendererArg,
139 int DataBytes, tAxWin3_WindowMessageHandler MessageHandler
144 int dataSize = sizeof(tIPCMsg_CreateWin) + strlen(Renderer) + 1;
145 tAxWin_IPCMessage *msg;
146 tIPCMsg_CreateWin *create_win;
148 // Allocate a window ID
149 ret = AxWin3_int_AllocateWindowInfo(DataBytes, &newWinID);
150 if(!ret) return NULL;
151 ret->Handler = MessageHandler;
154 msg = AxWin3_int_AllocateIPCMessage(Parent, IPCMSG_CREATEWIN, 0, dataSize);
155 create_win = (void*)msg->Data;
156 create_win->NewWinID = newWinID;
157 create_win->RendererArg = RendererArg;
158 strcpy(create_win->Renderer, Renderer);
161 AxWin3_int_SendIPCMessage(msg);
164 _SysDebug("AxWin3_CreateWindow: %i :: '%s'", newWinID, Renderer);
166 // TODO: Detect and handle possible errors
172 void AxWin3_DestroyWindow(tHWND Window)
174 tAxWin_IPCMessage *msg;
176 msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_DESTROYWIN, 0, 0);
177 AxWin3_int_SendIPCMessage(msg);
181 void *AxWin3_int_GetDataPtr(tHWND Window)
186 int AxWin3_int_DefaultMessageHandler(tWindow *Win, int ID, size_t Len, const void *Data)
190 case WNDMSG_HOTKEY: {
191 const struct sWndMsg_Hotkey *mi = Data;
192 if( Len < sizeof(*mi) )
195 if( mi->ID >= MAX_HOTKEYS )
196 _SysDebug("--- Out of range hotkey %i fired", mi->ID);
197 else if( gAxWin3_Hotkeys[mi->ID] == 0 )
198 _SysDebug("--- Unmapped hotkey ID %i fired", mi->ID);
200 gAxWin3_Hotkeys[mi->ID]();
203 // Honour a close message by default
205 AxWin3_DestroyWindow(Win);
209 _SysDebug("TODO: Check that WNDMSG_DESTROY was from us calling _DestroyWindow");
210 // TODO: Finalise cleanup of window, this will be the last message sent to this window
217 void AxWin3_int_HandleMessage(tAxWin_IPCMessage *Msg)
221 dest = AxWin3_int_GetWindowFromID(Msg->Window);
225 case IPCMSG_SENDMSG: {
226 tIPCMsg_SendMsg *info = (void*)Msg->Data;
227 if(Msg->Size < sizeof(*info) || Msg->Size < sizeof(*info) + info->Length) {
228 _SysDebug("Message is undersized (%i < %i + %i)",
229 Msg->Size < sizeof(*info), info->Length);
232 if(!dest || !dest->Handler) {
233 _SysDebug("No handler for destination %p", dest);
236 _SysDebug("IPC Message 0x%x - %i bytes", info->ID, info->Length);
238 if( dest->Handler(dest, info->ID, info->Length, info->Data) )
240 else if( AxWin3_int_DefaultMessageHandler(dest, info->ID, info->Length, info->Data) )
243 _SysDebug("--- Unhandled SENDMSG 0x%x win %i", info->ID, Msg->Window);
245 case IPCMSG_DESTROYWIN:
246 // Clean up resources associated with this window
249 _SysDebug("Unknow message ID %i", Msg->ID);
256 void AxWin3_SetWindowTitle(tHWND Window, const char *Title)
258 tAxWin_IPCMessage *msg;
259 int len = strlen(Title);
261 msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SETWINTITLE, 0, len+1);
262 strcpy(msg->Data, Title);
264 AxWin3_int_SendIPCMessage(msg);
269 void AxWin3_SendMessage(tHWND Window, tHWND Destination, int Message, int Length, void *Data)
271 tAxWin_IPCMessage *msg;
272 tIPCMsg_SendMsg *info;
274 msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SENDMSG, 0, sizeof(*info)+Length);
275 info = (void*)msg->Data;
276 info->Remote = AxWin3_int_GetWindowID(Destination);
278 info->Length = Length;
279 memcpy(info->Data, Data, Length);
281 AxWin3_int_SendIPCMessage(msg);
285 void *AxWin3_WaitMessage(tHWND Window, int MessageID, size_t *Length)
287 tAxWin_IPCMessage *msg;
291 msg = AxWin3_int_WaitIPCMessage(IPCMSG_SENDMSG);
292 if( msg->Window != AxWin3_int_GetWindowID(Window) ) {
293 AxWin3_int_HandleMessage(msg);
296 tIPCMsg_SendMsg *info = (void*)msg->Data;
297 if( info->ID != MessageID ) {
298 AxWin3_int_HandleMessage(msg);
302 *Length = info->Length;
303 void *ret = malloc(info->Length);
304 memcpy(ret, info->Data, info->Length);
311 void AxWin3_SendIPC(tHWND Window, int Message, size_t Length, const void *Data)
313 tAxWin_IPCMessage *msg;
315 msg = AxWin3_int_AllocateIPCMessage(Window, Message, IPCMSG_FLAG_RENDERER, Length);
316 memcpy(msg->Data, Data, Length);
317 AxWin3_int_SendIPCMessage(msg);
321 void *AxWin3_WaitIPCMessage(tHWND Window, int MessageID, size_t *Length)
323 tAxWin_IPCMessage *msg;
326 msg = AxWin3_int_WaitIPCMessage(MessageID);
327 if( !(msg->Flags & IPCMSG_FLAG_RENDERER) || msg->Window != AxWin3_int_GetWindowID(Window) ) {
328 AxWin3_int_HandleMessage(msg);
333 void *ret = malloc(msg->Size);
334 memcpy(ret, msg->Data, msg->Size);
341 void AxWin3_FocusWindow(tHWND Window)
343 tAxWin_IPCMessage *msg;
345 msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_FOCUSWINDOW, 0, 0);
347 AxWin3_int_SendIPCMessage(msg);
351 void AxWin3_ShowWindow(tHWND Window, int bShow)
353 tAxWin_IPCMessage *msg;
354 tIPCMsg_Boolean *info;
356 msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SHOWWINDOW, 0, sizeof(*info));
357 info = (void*)msg->Data;
358 info->Value = !!bShow;
360 AxWin3_int_SendIPCMessage(msg);
365 void AxWin3_DecorateWindow(tHWND Window, int bDecorate)
367 tAxWin_IPCMessage *msg;
368 tIPCMsg_Boolean *info;
370 msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_DECORATEWINDOW, 0, sizeof(*info));
371 info = (void*)msg->Data;
372 info->Value = !!bDecorate;
374 AxWin3_int_SendIPCMessage(msg);
379 void AxWin3_SetWindowPos(tHWND Window, short X, short Y, short W, short H)
381 tAxWin_IPCMessage *msg;
382 tIPCMsg_SetWindowPos *info;
384 msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SETWINPOS, 0, sizeof(*info));
385 info = (void*)msg->Data;
389 info->X = X; info->Y = Y;
390 info->W = W; info->H = H;
392 AxWin3_int_SendIPCMessage(msg);
396 void AxWin3_MoveWindow(tHWND Window, short X, short Y)
398 tAxWin_IPCMessage *msg;
399 tIPCMsg_SetWindowPos *info;
401 msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SETWINPOS, 0, sizeof(*info));
402 info = (void*)msg->Data;
409 AxWin3_int_SendIPCMessage(msg);
414 void AxWin3_ResizeWindow(tHWND Window, short W, short H)
416 tAxWin_IPCMessage *msg;
417 tIPCMsg_SetWindowPos *info;
419 msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SETWINPOS, 0, sizeof(*info));
420 info = (void*)msg->Data;
427 AxWin3_int_SendIPCMessage(msg);
432 int AxWin3_RegisterAction(tHWND Window, const char *Action, tAxWin3_HotkeyCallback cb)
435 for( i = 0; i < MAX_HOTKEYS; i ++ )
437 if( gAxWin3_Hotkeys[i] == NULL )
439 tAxWin_IPCMessage *msg;
440 struct sIPCMsg_RegAction *info;
441 gAxWin3_Hotkeys[i] = cb;
443 msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_REGACTION, 0, sizeof(*info)+strlen(Action)+1);
444 info = (void*)msg->Data;
447 strcpy(info->Action, Action);
449 AxWin3_int_SendIPCMessage(msg);