2 * Acess2 Window Manager v3
3 * - By John Hodge (thePowersGang)
6 * - Window manager core
9 #include <wm_renderer.h>
13 #include <wm_messages.h>
16 tWMRenderer *gpWM_Renderers;
17 tWindow *gpWM_RootWindow;
20 void WM_Initialise(void)
22 WM_CreateWindow(NULL, 0x0088FF, "Background");
23 gpWM_RootWindow->W = giScreenWidth;
24 gpWM_RootWindow->H = giScreenHeight;
25 gpWM_RootWindow->Flags = WINFLAG_SHOW;
28 void WM_RegisterRenderer(tWMRenderer *Renderer)
30 // TODO: Catch out duplicates
31 Renderer->Next = gpWM_Renderers;
32 gpWM_Renderers = Renderer;
36 tWindow *WM_CreateWindow(tWindow *Parent, int RendererArg, const char *RendererName)
38 tWMRenderer *renderer;
42 for( renderer = gpWM_Renderers; renderer; renderer = renderer->Next )
44 if(strcmp(RendererName, renderer->Name) == 0)
51 Parent = gpWM_RootWindow;
53 // - Call create window function
54 ret = renderer->CreateWindow(RendererArg);
56 ret->Renderer = renderer;
57 ret->Flags = WINFLAG_CLEAN; // Note, not acutally clean, but it makes invaidate work
63 Parent->LastChild->NextSibling = ret;
65 Parent->FirstChild = ret;
66 ret->PrevSibling = Parent->LastChild;
67 Parent->LastChild = ret;
71 gpWM_RootWindow = ret;
78 tWindow *WM_CreateWindowStruct(size_t ExtraSize)
82 ret = calloc( sizeof(tWindow) + ExtraSize, 1 );
83 ret->RendererInfo = ret + 1; // Get end of tWindow
88 void WM_ShowWindow(tWindow *Window, int bShow)
90 // TODO: Message window
92 Window->Flags |= WINFLAG_SHOW;
94 Window->Flags &= ~WINFLAG_SHOW;
95 WM_Invalidate(Window);
98 int WM_MoveWindow(tWindow *Window, int X, int Y)
101 if(X + Window->W < 0) X = -Window->W + 1;
102 if(Y + Window->H < 0) Y = -Window->H + 1;
103 if(X >= giScreenWidth) X = giScreenWidth - 1;
104 if(Y >= giScreenHeight) Y = giScreenHeight - 1;
106 Window->X = X; Window->Y = Y;
108 WM_Invalidate(Window);
113 int WM_ResizeWindow(tWindow *Window, int W, int H)
115 if(W <= 0 || H <= 0 ) return 1;
116 if(Window->X + W < 0) Window->X = -W + 1;
117 if(Window->Y + H < 0) Window->Y = -H + 1;
119 Window->W = W; Window->H = H;
121 WM_Invalidate(Window);
124 struct sWndMsg_Resize msg;
127 WM_SendMessage(NULL, Window, WNDMSG_RESIZE, sizeof(msg), &msg);
133 int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, void *Data)
135 if(Dest == NULL) return -2;
136 if(Length > 0 && Data == NULL) return -1;
138 // ->HandleMessage returns 1 when the message was not handled
139 if( Dest->Renderer->HandleMessage(Dest, Message, Length, Data) != 1 )
141 // TODO: Catch errors from ->HandleMessage
145 // TODO: Pass on to user
146 _SysDebug("WM_SendMessage: TODO - Implement sending to client application");
151 void WM_Invalidate(tWindow *Window)
153 // Don't invalidate twice (speedup)
154 if( !(Window->Flags & WINFLAG_CLEAN) ) return;
156 // _SysDebug("Invalidating %p");
158 // Mark for re-render
159 Window->Flags &= ~WINFLAG_CLEAN;
161 // Mark up the tree that a child window has changed
162 while( (Window = Window->Parent) )
164 // _SysDebug("Childclean removed from %p", Window);
165 Window->Flags &= ~WINFLAG_CHILDCLEAN;
169 // --- Rendering / Update
170 void WM_int_UpdateWindow(tWindow *Window)
174 // Ignore hidden windows
175 if( !(Window->Flags & WINFLAG_SHOW) )
179 if( !(Window->Flags & WINFLAG_CLEAN) )
181 Window->Renderer->Redraw(Window);
182 Window->Flags |= WINFLAG_CLEAN;
186 if( !(Window->Flags & WINFLAG_CHILDCLEAN) )
188 for( child = Window->FirstChild; child; child = child->NextSibling )
190 WM_int_UpdateWindow(child);
192 Window->Flags |= WINFLAG_CHILDCLEAN;
197 void WM_int_BlitWindow(tWindow *Window)
201 // Ignore hidden windows
202 if( !(Window->Flags & WINFLAG_SHOW) )
205 Video_Blit(Window->RenderBuffer, Window->X, Window->Y, Window->W, Window->H);
207 for( child = Window->FirstChild; child; child = child->NextSibling )
209 WM_int_BlitWindow(child);
215 // Don't redraw if nothing has changed
216 if( (gpWM_RootWindow->Flags & WINFLAG_CHILDCLEAN) )
219 // - Iterate through visible windows, updating them as needed
220 WM_int_UpdateWindow(gpWM_RootWindow);
222 // - Draw windows from back to front to the render buffer
223 WM_int_BlitWindow(gpWM_RootWindow);
228 // --- WM Render Routines
229 // TODO: Move to another file?
230 void WM_Render_FillRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour)
234 // _SysDebug("WM_Render_FilledRect(%p, 0x%x...", Window, Colour);
235 // _SysDebug(" (%i,%i), %ix%i)", X, Y, W, H);
236 // Clip to window dimensions
237 if(X < 0) { W += X; X = 0; }
238 if(Y < 0) { H += Y; Y = 0; }
239 if(X >= Window->W) return;
240 if(Y >= Window->H) return;
241 if(X + W > Window->W) W = Window->W - X;
242 if(Y + H > Window->H) H = Window->H - Y;
243 // _SysDebug(" Clipped to (%i,%i), %ix%i", X, Y, W, H);
248 if(!Window->RenderBuffer) {
249 Window->RenderBuffer = malloc(Window->W*Window->H*4);
252 dest = (uint32_t*)Window->RenderBuffer + Y*Window->W + X;
257 dest += Window->W - W;
261 void WM_Render_DrawRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour)
263 WM_Render_FillRect(Window, X, Y, W, 1, Colour);
264 WM_Render_FillRect(Window, X, Y+H-1, W, 1, Colour);
265 WM_Render_FillRect(Window, X, Y, 1, H, Colour);
266 WM_Render_FillRect(Window, X+W-1, Y, 1, H, Colour);
269 void WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, void *Font, tColour Colour, const char *Text)
272 _SysDebug("WM_Render_DrawText - TODO: Implement");
276 * \brief Draw an image to the screen
277 * \todo Maybe have support for an offset in the image
279 void WM_Render_DrawImage(tWindow *Window, int X, int Y, int W, int H, tImage *Image)
286 if( !Image ) return ;
289 if(!Window->RenderBuffer) {
290 Window->RenderBuffer = malloc(Window->W*Window->H*4);
294 if( X >= Window->W ) return ;
295 if( Y >= Window->H ) return ;
297 // Wrap to image size
298 if( W > Image->Width ) W = Image->Width;
299 if( H > Image->Height ) H = Image->Height;
301 // Wrap to screen size
302 if( X + W > Window->W ) W = Window->W - X;
303 if( Y + H > Window->H ) H = Window->H - Y;
305 dest = (uint32_t*)Window->RenderBuffer + Y * Window->W + X;
309 switch( Image->Format )
312 for( y = 0; y < H; y ++ )
314 int r, g, b, a; // New
315 int or, og, ob; // Original
316 for( x = 0; x < W; x ++ )
318 b = data[x*4+0]; g = data[x*4+1]; r = data[x*4+2]; a = data[x*4+3];
319 if( a == 0 ) continue; // 100% transparent
320 ob = dest[x]&0xFF; og = (dest[x] >> 8)&0xFF; or = (dest[x] >> 16)&0xFF;
324 // Transparent: Handled above
335 r = (or * (255-a) + r * a) / 255;
336 g = (og * (255-a) + g * a) / 255;
337 b = (ob * (255-a) + b * a) / 255;
340 dest[x] = b | (g << 8) | (r << 16);
342 data += Image->Width * 4;
349 for( y = 0; y < H; y ++ )
351 for( x = 0; x < W; x ++ )
354 dest[x] = data[x*3+2] | (data[x*3+1] << 8) | (data[x*3+0] << 16);
361 _SysDebug("ERROR: Unknown image format %i\n", Image->Format);