X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FApplications%2Faxwin4_src%2FServer%2Fcompositor.cpp;h=cf8192ec2b6beac1440071976cad3c9db7962d96;hb=8b72370eae1a3cfa8916136fd8ffc1460e9291ba;hp=db943c5747701e7852adcec47b3a6fb146bb179b;hpb=12b7fdacb831478b4fdc648f6a146c9d2285b9d6;p=tpg%2Facess2.git diff --git a/Usermode/Applications/axwin4_src/Server/compositor.cpp b/Usermode/Applications/axwin4_src/Server/compositor.cpp index db943c57..cf8192ec 100644 --- a/Usermode/Applications/axwin4_src/Server/compositor.cpp +++ b/Usermode/Applications/axwin4_src/Server/compositor.cpp @@ -5,42 +5,180 @@ * compositor.cpp * - Window compositor */ -#include +#include #include +#include +#include +#include namespace AxWin { -CCompositor* CCompositor::s_instance; - -void CCompositor::Initialise(const CConfigCompositor& config) +CCompositor::CCompositor(CVideo& video): + // TODO: Support multiple screens + m_video(video), + m_focussed_window(nullptr), + m_windowIDBuffer(video.width(), video.height()) { - assert(!CCompositor::s_instance); - CCompositor::s_instance = new CCompositor(config); + // } -CCompositor::CCompositor(const CConfigCompositor& config): - m_config(config) +void CCompositor::ShowWindow(CWindow* window) { - // + DamageArea(window->m_surface.m_rect); + // TODO: Append to separate sub-lists (or to separate lists all together) + // if flags AXWIN4_WNDFLAG_KEEPBELOW or AXWIN4_WNDFLAG_KEEPABOVE are set + m_windows.push_back(window); +} +void CCompositor::HideWindow(CWindow* window) +{ + DamageArea(window->m_surface.m_rect); + m_windows.remove(window); } -IWindow* CCompositor::CreateWindow(CClient& client) +bool CCompositor::GetScreenDims(unsigned int ScreenID, unsigned int* W, unsigned int* H) { - return new CWindow(client); + assert(W && H); + if( ScreenID != 0 ) + { + *W = 0; + *H = 0; + return false; + } + else + { + m_video.GetDims(*W, *H); + return true; + } } void CCompositor::Redraw() { // Redraw the screen and clear damage rects - if( m_damageRects.empty() ) + if( m_damageRects.empty() ) { + //_SysDebug("- No damaged regions"); return ; + } + + // Build up foreground grid (Rects and windows) + // - This should already be built (mutated on window move/resize/reorder) - // For all windows, check for intersection with damage rect + // For all windows, check for intersection with damage rects + for( auto rect : m_damageRects ) + { + // window list should be sorted by draw order (lowest first) + for( auto window : m_windows ) + { + if( window->m_is_shown && rect.HasIntersection( window->m_surface.m_rect ) ) + { + // TODO: just reblit + CRect rel_rect = window->m_surface.m_rect.RelativeIntersection(rect); + _SysDebug("Reblit (%i,%i) %ix%i", rel_rect.m_x, rel_rect.m_y, rel_rect.m_w, rel_rect.m_h); + BlitFromSurface( window->m_surface, rel_rect ); + //window->Repaint( rel_rect ); + m_windowIDBuffer.set(rel_rect.m_x, rel_rect.m_y, rel_rect.m_w, rel_rect.m_h, window); + } + } + + // TODO: Blit from windows to a local surface, then blit from there to screen here + } + + m_damageRects.clear(); + m_video.Flush(); +} + +void CCompositor::DamageArea(const CRect& area) +{ + m_damageRects.push_back( area ); + // 1. Locate intersection with any existing damaged areas + // 2. Append after removing intersections +} + +void CCompositor::BlitFromSurface(const CSurface& dest, const CRect& src_rect) +{ + for( unsigned int i = 0; i < src_rect.m_h; i ++ ) + { + m_video.BlitLine( + dest.GetScanline(src_rect.m_y+i, src_rect.m_x), + dest.m_rect.m_y + src_rect.m_y + i, + dest.m_rect.m_x + src_rect.m_x, + src_rect.m_w + ); + } +} + +void CCompositor::MouseMove(unsigned int Cursor, unsigned int X, unsigned int Y, int dX, int dY) +{ + //_SysDebug("MouseButton(%i, %i,%i, %+i,%+i)", Cursor, X, Y, dX, dY); + m_video.SetCursorPos(X+dX, Y+dY); + CWindow *dstwin = getWindowForCoord(X, Y); + if( dstwin ) + { + // Pass event on to window + dstwin->MouseMove(X, Y); + } +} + +void CCompositor::MouseButton(unsigned int Cursor, unsigned int X, unsigned int Y, eMouseButton Button, bool Press) +{ + _SysDebug("MouseButton(%i, %i,%i, %i=%i)", Cursor, X, Y, Button, Press); + CWindow *dstwin = getWindowForCoord(X, Y); + _SysDebug("- dstwin = %p", dstwin); + if( dstwin ) + { + // 1. Give focus and bring to front + // 2. Send event + dstwin->MouseButton(Button, X, Y, Press); + } +} + +void CCompositor::KeyState(unsigned int KeyboardID, uint32_t KeySym, bool Press, uint32_t Codepoint) +{ + _SysDebug("KeyState(%i, 0x%x, %b, 0x%x)", KeyboardID, KeySym, Press, Codepoint); + if( m_focussed_window ) + { + m_focussed_window->KeyEvent(KeySym, "", Press); + } } -void CCompositor::DamageArea(const Rect& area) +CWindow* CCompositor::getWindowForCoord(unsigned int X, unsigned int Y) { + return m_windowIDBuffer.get(X, Y); +} +// -------------------------------------------------------------------- +CWindowIDBuffer::CWindowIDBuffer(unsigned int W, unsigned int H): + m_w(W), + m_buf(W*H) +{ +} +void CWindowIDBuffer::set(unsigned int X, unsigned int Y, unsigned int W, unsigned int H, CWindow* win) +{ + TWindowID ent = { + .Client = win->client().id(), + .Window = win->id(), + }; + for( unsigned int row = 0; row < H; row ++ ) + { + TWindowID* dst = &m_buf[ (Y+row) * m_w ]; + for( unsigned int col = 0; col < W; col ++ ) + dst[col] = ent; + } +} +CWindow* CWindowIDBuffer::get(unsigned int X, unsigned int Y) +{ + if( X >= m_w ) + return nullptr; + unsigned int pos = Y*m_w + X; + if( pos >= m_buf.size() ) + return nullptr; + auto id = m_buf[pos]; + //_SysDebug("CWindowIDBuffer::get id = {%i,%i}", id.Client, id.Window); + auto client = ::AxWin::IPC::GetClientByID(id.Client); + if( client == nullptr ) { + //_SysDebug("CWindowIDBuffer::get client=%p", client); + return nullptr; + } + return client->GetWindow(id.Window); } } // namespace AxWin