2 * Acess2 Window Manager v3
3 * - By John Hodge (thePowersGang)
6 * - Window manager core
9 #include <wm_renderer.h>
13 #include <wm_messages.h>
14 #include <decorator.h>
17 extern void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int Msg, int Len, const void *Data);
18 extern tWindow *IPC_int_GetWindow(tIPC_Client *Client, uint32_t ID);
21 tWMRenderer *gpWM_Renderers;
22 tWindow *gpWM_RootWindow;
23 //! Window which will recieve the next keyboard event
24 tWindow *gpWM_FocusedWindow;
25 //! Hilighted window (owner of the currently focused window)
26 tWindow *gpWM_HilightedWindow;
29 void WM_Initialise(void)
31 WM_CreateWindow(NULL, NULL, 0, 0x0088FF, "Background");
32 gpWM_RootWindow->W = giScreenWidth;
33 gpWM_RootWindow->H = giScreenHeight;
34 gpWM_RootWindow->Flags = WINFLAG_SHOW|WINFLAG_NODECORATE;
37 void WM_RegisterRenderer(tWMRenderer *Renderer)
39 // TODO: Catch out duplicates
40 Renderer->Next = gpWM_Renderers;
41 gpWM_Renderers = Renderer;
45 tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int RendererArg, const char *RendererName)
47 tWMRenderer *renderer;
51 for( renderer = gpWM_Renderers; renderer; renderer = renderer->Next )
53 if(strcmp(RendererName, renderer->Name) == 0)
59 // - Call create window function
60 ret = renderer->CreateWindow(RendererArg);
65 ret->Parent = gpWM_RootWindow;
67 ret->Renderer = renderer;
68 ret->Flags |= WINFLAG_CLEAN; // Needed to stop invaildate early exiting
73 if(ret->Parent->LastChild)
74 ret->Parent->LastChild->NextSibling = ret;
76 ret->Parent->FirstChild = ret;
77 ret->PrevSibling = ret->Parent->LastChild;
78 ret->Parent->LastChild = ret;
79 ret->NextSibling = NULL;
83 gpWM_RootWindow = ret;
86 // Don't decorate child windows by default
89 ret->Flags |= WINFLAG_NODECORATE;
96 tWindow *WM_GetWindowByID(tWindow *Requester, uint32_t ID)
98 return IPC_int_GetWindow(Requester->Client, ID);
101 tWindow *WM_CreateWindowStruct(size_t ExtraSize)
105 ret = calloc( sizeof(tWindow) + ExtraSize, 1 );
106 ret->RendererInfo = ret + 1; // Get end of tWindow
111 void WM_SetWindowTitle(tWindow *Window, const char *Title)
115 Window->Title = strdup(Title);
116 _SysDebug("Window %p title set to '%s'", Window, Title);
119 void WM_RaiseWindow(tWindow *Window)
121 tWindow *parent = Window->Parent;
122 if(!Window->Parent) return ;
125 if(Window->PrevSibling)
126 Window->PrevSibling->NextSibling = Window->NextSibling;
127 if(Window->NextSibling)
128 Window->NextSibling->PrevSibling = Window->PrevSibling;
129 if(parent->FirstChild == Window)
130 parent->FirstChild = Window->NextSibling;
131 if(parent->LastChild == Window)
132 parent->LastChild = Window->PrevSibling;
135 if(parent->LastChild)
136 parent->LastChild->NextSibling = Window;
138 parent->FirstChild = Window;
139 Window->PrevSibling = parent->LastChild;
140 Window->NextSibling = NULL;
141 parent->LastChild = Window;
144 void WM_FocusWindow(tWindow *Destination)
146 struct sWndMsg_Bool _msg;
148 if( gpWM_FocusedWindow == Destination )
150 if( Destination && !(Destination->Flags & WINFLAG_SHOW) )
154 WM_SendMessage(NULL, gpWM_FocusedWindow, WNDMSG_FOCUS, sizeof(_msg), &_msg);
156 WM_SendMessage(NULL, Destination, WNDMSG_FOCUS, sizeof(_msg), &_msg);
158 WM_Invalidate(gpWM_FocusedWindow);
159 WM_Invalidate(Destination);
160 gpWM_FocusedWindow = Destination;
163 // Get the owner of the focused window
164 // while(Destination && Destination->Owner) Destination = Destination->Owner;
165 // gpWM_HilightedWindow = Destination;
169 void WM_ShowWindow(tWindow *Window, int bShow)
171 struct sWndMsg_Bool _msg;
173 if( !!(Window->Flags & WINFLAG_SHOW) == bShow )
178 WM_SendMessage(NULL, Window, WNDMSG_SHOW, sizeof(_msg), &_msg);
182 Window->Flags |= WINFLAG_SHOW;
185 Window->Flags &= ~WINFLAG_SHOW;
187 if( Window == gpWM_FocusedWindow )
188 WM_FocusWindow(Window->Parent);
190 // Just a little memory saving for large hidden windows
191 if(Window->RenderBuffer) {
192 free(Window->RenderBuffer);
193 Window->RenderBuffer = NULL;
197 WM_Invalidate(Window);
200 void WM_DecorateWindow(tWindow *Window, int bDecorate)
202 if( !(Window->Flags & WINFLAG_NODECORATE) == !!bDecorate )
206 Window->Flags &= ~WINFLAG_NODECORATE;
208 Window->Flags |= WINFLAG_NODECORATE;
210 // Needed because the window size changes
211 if(Window->RenderBuffer) {
212 free(Window->RenderBuffer);
213 Window->RenderBuffer = NULL;
216 WM_Invalidate(Window);
219 int WM_MoveWindow(tWindow *Window, int X, int Y)
222 if(X + Window->W < 0) X = -Window->W + 1;
223 if(Y + Window->H < 0) Y = -Window->H + 1;
224 if(X >= giScreenWidth) X = giScreenWidth - 1;
225 if(Y >= giScreenHeight) Y = giScreenHeight - 1;
227 Window->X = X; Window->Y = Y;
229 WM_Invalidate(Window);
234 int WM_ResizeWindow(tWindow *Window, int W, int H)
236 if(W <= 0 || H <= 0 ) return 1;
237 if(Window->X + W < 0) Window->X = -W + 1;
238 if(Window->Y + H < 0) Window->Y = -H + 1;
240 if( Window->W == W && Window->H == H )
243 Window->W = W; Window->H = H;
245 if(Window->RenderBuffer) {
246 free(Window->RenderBuffer);
247 Window->RenderBuffer = NULL;
249 WM_Invalidate(Window);
252 struct sWndMsg_Resize msg;
255 WM_SendMessage(NULL, Window, WNDMSG_RESIZE, sizeof(msg), &msg);
261 int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, const void *Data)
263 if(Dest == NULL) return -2;
264 if(Length > 0 && Data == NULL) return -1;
266 if( Decorator_HandleMessage(Dest, Message, Length, Data) != 1 )
268 // TODO: Catch errors from ->HandleMessage
272 // ->HandleMessage returns 1 when the message was not handled
273 if( Dest->Renderer->HandleMessage(Dest, Message, Length, Data) != 1 )
275 // TODO: Catch errors from ->HandleMessage
279 // TODO: Implement message masking
286 else if(Source->Client != Dest->Client) {
287 // TODO: Support different client source windows
288 _SysDebug("WM_SendMessage: TODO - Support inter-client messages");
295 IPC_SendWMMessage(Dest->Client, src_id, Dest->ID, Message, Length, Data);
301 void WM_Invalidate(tWindow *Window)
304 _SysDebug("Invalidating %p", Window);
305 // Don't invalidate twice (speedup)
306 // if( !(Window->Flags & WINFLAG_CLEAN) ) return;
308 // Mark for re-render
309 Window->Flags &= ~WINFLAG_CLEAN;
311 // Mark up the tree that a child window has changed
312 while( (Window = Window->Parent) )
313 Window->Flags &= ~WINFLAG_CHILDCLEAN;
316 // --- Rendering / Update
317 void WM_int_UpdateWindow(tWindow *Window)
319 int bDecoratorRedraw = 0;
321 // Ignore hidden windows
322 if( !(Window->Flags & WINFLAG_SHOW) )
326 if( !(Window->Flags & WINFLAG_CLEAN) )
328 // Calculate RealW/RealH
329 if( !(Window->Flags & WINFLAG_NODECORATE) )
331 _SysDebug("Applying decorations to %p", Window);
332 Decorator_UpdateBorderSize(Window);
333 Window->RealW = Window->BorderL + Window->W + Window->BorderR;
334 Window->RealH = Window->BorderT + Window->H + Window->BorderB;
335 bDecoratorRedraw = 1;
343 Window->RealW = Window->W;
344 Window->RealH = Window->H;
347 Window->Renderer->Redraw(Window);
348 Window->Flags |= WINFLAG_CLEAN;
352 if( !(Window->Flags & WINFLAG_CHILDCLEAN) )
355 for( child = Window->FirstChild; child; child = child->NextSibling )
357 WM_int_UpdateWindow(child);
359 Window->Flags |= WINFLAG_CHILDCLEAN;
362 if( bDecoratorRedraw )
363 Decorator_Redraw(Window);
366 void WM_int_BlitWindow(tWindow *Window)
370 // Ignore hidden windows
371 if( !(Window->Flags & WINFLAG_SHOW) )
374 _SysDebug("Blit %p (%p) to (%i,%i) %ix%i", Window, Window->RenderBuffer,
375 Window->X, Window->Y, Window->RealW, Window->RealH);
376 Video_Blit(Window->RenderBuffer, Window->X, Window->Y, Window->RealW, Window->RealH);
378 if( Window == gpWM_FocusedWindow && Window->CursorW )
381 Window->X + Window->BorderL + Window->CursorX,
382 Window->Y + Window->BorderT + Window->CursorY,
383 Window->CursorW, Window->CursorH,
388 for( child = Window->FirstChild; child; child = child->NextSibling )
390 WM_int_BlitWindow(child);
396 // Don't redraw if nothing has changed
397 if( (gpWM_RootWindow->Flags & WINFLAG_CHILDCLEAN) )
400 // - Iterate through visible windows, updating them as needed
401 WM_int_UpdateWindow(gpWM_RootWindow);
403 // - Draw windows from back to front to the render buffer
404 WM_int_BlitWindow(gpWM_RootWindow);