3 * - By John Hodge (thePowersGang)
9 #include <CCompositor.hpp>
10 #include <CClient.hpp>
16 CCompositor::CCompositor(CVideo& video):
17 // TODO: Support multiple screens
19 m_focussed_window(nullptr),
20 m_windowIDBuffer(video.width(), video.height())
25 void CCompositor::ShowWindow(CWindow* window)
27 DamageArea(window->m_surface.m_rect);
28 // TODO: Append to separate sub-lists (or to separate lists all together)
29 // if flags AXWIN4_WNDFLAG_KEEPBELOW or AXWIN4_WNDFLAG_KEEPABOVE are set
30 m_windows.push_back(window);
32 void CCompositor::HideWindow(CWindow* window)
34 DamageArea(window->m_surface.m_rect);
35 m_windows.remove(window);
38 bool CCompositor::GetScreenDims(unsigned int ScreenID, unsigned int* W, unsigned int* H)
49 m_video.GetDims(*W, *H);
54 void CCompositor::Redraw()
56 // Redraw the screen and clear damage rects
57 if( m_damageRects.empty() ) {
58 //_SysDebug("- No damaged regions");
62 // Build up foreground grid (Rects and windows)
63 // - This should already be built (mutated on window move/resize/reorder)
65 // For all windows, check for intersection with damage rects
66 for( auto rect : m_damageRects )
68 // window list should be sorted by draw order (lowest first)
69 for( auto window : m_windows )
71 if( window->m_is_shown && rect.HasIntersection( window->m_surface.m_rect ) )
74 CRect rel_rect = window->m_surface.m_rect.RelativeIntersection(rect);
75 _SysDebug("Reblit (%i,%i) %ix%i", rel_rect.m_x, rel_rect.m_y, rel_rect.m_w, rel_rect.m_h);
76 BlitFromSurface( window->m_surface, rel_rect );
77 //window->Repaint( rel_rect );
78 m_windowIDBuffer.set(rel_rect.m_x, rel_rect.m_y, rel_rect.m_w, rel_rect.m_h, window);
82 // TODO: Blit from windows to a local surface, then blit from there to screen here
85 m_damageRects.clear();
89 void CCompositor::DamageArea(const CRect& area)
91 m_damageRects.push_back( area );
92 // 1. Locate intersection with any existing damaged areas
93 // 2. Append after removing intersections
96 void CCompositor::BlitFromSurface(const CSurface& dest, const CRect& src_rect)
98 for( unsigned int i = 0; i < src_rect.m_h; i ++ )
101 dest.GetScanline(src_rect.m_y+i, src_rect.m_x),
102 dest.m_rect.m_y + src_rect.m_y + i,
103 dest.m_rect.m_x + src_rect.m_x,
109 void CCompositor::MouseMove(unsigned int Cursor, unsigned int X, unsigned int Y, int dX, int dY)
111 //_SysDebug("MouseButton(%i, %i,%i, %+i,%+i)", Cursor, X, Y, dX, dY);
112 m_video.SetCursorPos(X+dX, Y+dY);
113 CWindow *dstwin = getWindowForCoord(X, Y);
116 // Pass event on to window
117 dstwin->MouseMove(X, Y);
121 void CCompositor::MouseButton(unsigned int Cursor, unsigned int X, unsigned int Y, eMouseButton Button, bool Press)
123 _SysDebug("MouseButton(%i, %i,%i, %i=%i)", Cursor, X, Y, Button, Press);
124 CWindow *dstwin = getWindowForCoord(X, Y);
125 _SysDebug("- dstwin = %p", dstwin);
128 // 1. Give focus and bring to front
130 dstwin->MouseButton(Button, X, Y, Press);
134 void CCompositor::KeyState(unsigned int KeyboardID, uint32_t KeySym, bool Press, uint32_t Codepoint)
136 _SysDebug("KeyState(%i, 0x%x, %b, 0x%x)", KeyboardID, KeySym, Press, Codepoint);
137 // TODO: Global hotkeys
138 if( m_focussed_window )
140 m_focussed_window->KeyEvent(KeySym, "", Press);
144 CWindow* CCompositor::getWindowForCoord(unsigned int X, unsigned int Y)
146 return m_windowIDBuffer.get(X, Y);
149 // --------------------------------------------------------------------
150 CWindowIDBuffer::CWindowIDBuffer(unsigned int W, unsigned int H):
155 void CWindowIDBuffer::set(unsigned int X, unsigned int Y, unsigned int W, unsigned int H, CWindow* win)
158 .Client = win->client().id(),
161 for( unsigned int row = 0; row < H; row ++ )
163 TWindowID* dst = &m_buf[ (Y+row) * m_w ];
164 for( unsigned int col = 0; col < W; col ++ )
168 CWindow* CWindowIDBuffer::get(unsigned int X, unsigned int Y)
172 unsigned int pos = Y*m_w + X;
173 if( pos >= m_buf.size() )
175 auto id = m_buf[pos];
176 //_SysDebug("CWindowIDBuffer::get id = {%i,%i}", id.Client, id.Window);
177 auto client = ::AxWin::IPC::GetClientByID(id.Client);
178 if( client == nullptr ) {
179 //_SysDebug("CWindowIDBuffer::get client=%p", client);
182 return client->GetWindow(id.Window);