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 void WM_SetRelative(tWindow *Window, int bRelativeToParent)
221 // _SysDebug("WM_SetRelative: (%p{Parent=%p},%i)", Window, Window->Parent, bRelativeToParent);
222 // No meaning if no parent
223 if( !Window->Parent )
226 // Check that the flag is changing
227 if( !!bRelativeToParent == !!(Window->Flags & WINFLAG_RELATIVE) )
230 if( bRelativeToParent ) {
232 Window->Flags |= WINFLAG_RELATIVE;
233 WM_MoveWindow(Window, Window->X, Window->Y);
237 Window->Flags &= ~WINFLAG_RELATIVE;
238 WM_MoveWindow(Window, Window->X - Window->Parent->X, Window->Y - Window->Parent->Y);
242 int WM_MoveWindow(tWindow *Window, int X, int Y)
244 // _SysDebug("Move %p to (%i,%i)", Window, X, Y);
246 if(X + Window->W < 0) X = -Window->W + 1;
247 if(Y + Window->H < 0) Y = -Window->H + 1;
248 if(X >= giScreenWidth) X = giScreenWidth - 1;
249 if(Y >= giScreenHeight) Y = giScreenHeight - 1;
251 // If relative to the parent, extra checks
252 if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent )
254 if( X > Window->Parent->W ) return 1;
255 if( Y > Window->Parent->H ) return 1;
259 Window->X = X; Window->Y = Y;
261 // TODO: Why invalidate buffer?
262 WM_Invalidate(Window);
267 int WM_ResizeWindow(tWindow *Window, int W, int H)
269 if(W <= 0 || H <= 0 ) return 1;
270 if(Window->X + W < 0) Window->X = -W + 1;
271 if(Window->Y + H < 0) Window->Y = -H + 1;
273 if( Window->W == W && Window->H == H )
276 Window->W = W; Window->H = H;
278 if(Window->RenderBuffer) {
279 free(Window->RenderBuffer);
280 Window->RenderBuffer = NULL;
282 WM_Invalidate(Window);
285 struct sWndMsg_Resize msg;
288 WM_SendMessage(NULL, Window, WNDMSG_RESIZE, sizeof(msg), &msg);
294 int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, const void *Data)
296 if(Dest == NULL) return -2;
297 if(Length > 0 && Data == NULL) return -1;
299 if( Decorator_HandleMessage(Dest, Message, Length, Data) != 1 )
301 // TODO: Catch errors from ->HandleMessage
305 // ->HandleMessage returns 1 when the message was not handled
306 if( Dest->Renderer->HandleMessage(Dest, Message, Length, Data) != 1 )
308 // TODO: Catch errors from ->HandleMessage
312 // TODO: Implement message masking
319 else if(Source->Client != Dest->Client) {
320 // TODO: Support different client source windows
321 _SysDebug("WM_SendMessage: TODO - Support inter-client messages");
328 IPC_SendWMMessage(Dest->Client, src_id, Dest->ID, Message, Length, Data);
334 void WM_Invalidate(tWindow *Window)
337 // _SysDebug("Invalidating %p", Window);
338 // Don't invalidate twice (speedup)
339 // if( !(Window->Flags & WINFLAG_CLEAN) ) return;
341 // Mark for re-render
342 Window->Flags &= ~WINFLAG_CLEAN;
344 // Mark up the tree that a child window has changed
345 while( (Window = Window->Parent) )
346 Window->Flags &= ~WINFLAG_CHILDCLEAN;
349 // --- Rendering / Update
350 void WM_int_UpdateWindow(tWindow *Window)
352 int bDecoratorRedraw = 0;
354 // Ignore hidden windows
355 if( !(Window->Flags & WINFLAG_SHOW) )
359 if( !(Window->Flags & WINFLAG_CLEAN) )
361 // Calculate RealW/RealH
362 if( !(Window->Flags & WINFLAG_NODECORATE) )
364 //_SysDebug("Applying decorations to %p", Window);
365 Decorator_UpdateBorderSize(Window);
366 Window->RealW = Window->BorderL + Window->W + Window->BorderR;
367 Window->RealH = Window->BorderT + Window->H + Window->BorderB;
368 bDecoratorRedraw = 1;
376 Window->RealW = Window->W;
377 Window->RealH = Window->H;
380 if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent )
382 Window->RealX = Window->Parent->X + Window->Parent->BorderL + Window->X;
383 Window->RealY = Window->Parent->Y + Window->Parent->BorderT + Window->Y;
387 Window->RealX = Window->X;
388 Window->RealY = Window->Y;
391 Window->Renderer->Redraw(Window);
392 Window->Flags |= WINFLAG_CLEAN;
396 if( !(Window->Flags & WINFLAG_CHILDCLEAN) )
399 for( child = Window->FirstChild; child; child = child->NextSibling )
401 WM_int_UpdateWindow(child);
403 Window->Flags |= WINFLAG_CHILDCLEAN;
406 if( bDecoratorRedraw )
407 Decorator_Redraw(Window);
410 void WM_int_BlitWindow(tWindow *Window)
414 // Ignore hidden windows
415 if( !(Window->Flags & WINFLAG_SHOW) )
418 // _SysDebug("Blit %p (%p) to (%i,%i) %ix%i", Window, Window->RenderBuffer,
419 // Window->RealX, Window->RealY, Window->RealW, Window->RealH);
420 Video_Blit(Window->RenderBuffer, Window->RealX, Window->RealY, Window->RealW, Window->RealH);
422 if( Window == gpWM_FocusedWindow && Window->CursorW )
425 Window->RealX + Window->BorderL + Window->CursorX,
426 Window->RealY + Window->BorderT + Window->CursorY,
427 Window->CursorW, Window->CursorH,
432 for( child = Window->FirstChild; child; child = child->NextSibling )
434 WM_int_BlitWindow(child);
440 // Don't redraw if nothing has changed
441 if( (gpWM_RootWindow->Flags & WINFLAG_CHILDCLEAN) )
444 // - Iterate through visible windows, updating them as needed
445 WM_int_UpdateWindow(gpWM_RootWindow);
447 // - Draw windows from back to front to the render buffer
448 WM_int_BlitWindow(gpWM_RootWindow);