From 8b16265b4394af76f64c30393e27d08c294c4bac Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Fri, 7 Nov 2014 16:44:29 +0800 Subject: [PATCH 1/1] Usermode/AxWin4 - Fixing ID lookups of windows and clients --- .../axwin4_src/Server/CClient.cpp | 12 ++-- .../axwin4_src/Server/CSurface.cpp | 7 +++ .../axwin4_src/Server/CWindow.cpp | 3 +- .../Applications/axwin4_src/Server/Makefile | 2 +- .../axwin4_src/Server/compositor.cpp | 59 ++++++++++++++++--- .../axwin4_src/Server/include/CClient.hpp | 5 ++ .../axwin4_src/Server/include/CCompositor.hpp | 25 ++++++-- .../axwin4_src/Server/include/CWindow.hpp | 6 +- .../axwin4_src/Server/include/ipc.hpp | 1 + .../axwin4_src/Server/include/video.hpp | 2 + .../Applications/axwin4_src/Server/ipc.cpp | 28 +++++++-- Usermode/Libraries/libaxwin4.so_src/wm.cpp | 4 +- 12 files changed, 127 insertions(+), 27 deletions(-) diff --git a/Usermode/Applications/axwin4_src/Server/CClient.cpp b/Usermode/Applications/axwin4_src/Server/CClient.cpp index 6c9fe685..8640bf3b 100644 --- a/Usermode/Applications/axwin4_src/Server/CClient.cpp +++ b/Usermode/Applications/axwin4_src/Server/CClient.cpp @@ -12,7 +12,8 @@ namespace AxWin { CClient::CClient(::AxWin::IIPCChannel& channel): - m_channel(channel) + m_channel(channel), + m_id(0) { } @@ -35,10 +36,13 @@ CWindow* CClient::GetWindow(int ID) void CClient::SetWindow(int ID, CWindow* window) { _SysDebug("SetWindow(ID=%i,window=%p)", ID, window); - if( m_windows[ID] ) { - delete m_windows[ID]; + auto it = m_windows.find(ID); + if( it != m_windows.end() ) { + _SysDebug("CLIENT BUG: Window ID %i is already used by %p", ID, it->second); + } + else { + m_windows[ID] = window; } - m_windows[ID] = window; } void CClient::HandleMessage(CDeserialiser& message) diff --git a/Usermode/Applications/axwin4_src/Server/CSurface.cpp b/Usermode/Applications/axwin4_src/Server/CSurface.cpp index 27078d87..91bbb9ae 100644 --- a/Usermode/Applications/axwin4_src/Server/CSurface.cpp +++ b/Usermode/Applications/axwin4_src/Server/CSurface.cpp @@ -27,6 +27,13 @@ CSurface::CSurface(int x, int y, unsigned int w, unsigned int h): CSurface::~CSurface() { + if( m_fd == -1 ) { + delete[] m_data; + } + else { + size_t size = m_rect.m_w*m_rect.m_h*4; + _SysMUnMap(m_data, size); + } } uint64_t CSurface::GetSHMHandle() diff --git a/Usermode/Applications/axwin4_src/Server/CWindow.cpp b/Usermode/Applications/axwin4_src/Server/CWindow.cpp index 392fd47f..55c24823 100644 --- a/Usermode/Applications/axwin4_src/Server/CWindow.cpp +++ b/Usermode/Applications/axwin4_src/Server/CWindow.cpp @@ -12,10 +12,11 @@ namespace AxWin { -CWindow::CWindow(CCompositor& compositor, CClient& client, const ::std::string& name): +CWindow::CWindow(CCompositor& compositor, CClient& client, const ::std::string& name, unsigned int id): m_surface(0,0,0,0), m_compositor(compositor), m_client(client), + m_id(id), m_name(name), m_is_shown(false) { diff --git a/Usermode/Applications/axwin4_src/Server/Makefile b/Usermode/Applications/axwin4_src/Server/Makefile index c7d79833..87ed9afe 100644 --- a/Usermode/Applications/axwin4_src/Server/Makefile +++ b/Usermode/Applications/axwin4_src/Server/Makefile @@ -14,7 +14,7 @@ OBJ += draw_control.o BIN := AxWinServer LIBS += -lc++ -CXXFLAGS += -O3 +#CXXFLAGS += -O3 USE_CXX_LINK = 1 include ../../Makefile.tpl diff --git a/Usermode/Applications/axwin4_src/Server/compositor.cpp b/Usermode/Applications/axwin4_src/Server/compositor.cpp index 7a18747a..42bb8b9b 100644 --- a/Usermode/Applications/axwin4_src/Server/compositor.cpp +++ b/Usermode/Applications/axwin4_src/Server/compositor.cpp @@ -7,21 +7,20 @@ */ #include #include +#include +#include #include namespace AxWin { CCompositor::CCompositor(CVideo& video): - m_video(video) + // TODO: Support multiple screens + m_video(video), + m_windowIDBuffer(video.width(), video.height()) { // } -CWindow* CCompositor::CreateWindow(CClient& client, const ::std::string& name) -{ - return new CWindow(*this, client, name); -} - void CCompositor::ShowWindow(CWindow* window) { DamageArea(window->m_surface.m_rect); @@ -75,6 +74,7 @@ void CCompositor::Redraw() _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); } } @@ -109,13 +109,23 @@ void CCompositor::MouseMove(unsigned int Cursor, unsigned int X, unsigned int Y, { _SysDebug("MouseButton(%i, %i,%i, %+i,%+i)", Cursor, X, Y, dX, dY); m_video.SetCursorPos(X+dX, Y+dY); - // TODO: Pass event on to window + CWindow *dstwin = getWindowForCoord(X, Y); + if( dstwin ) + { + // TODO: Pass event on to window + } } 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); - // TODO: Pass event on to window + CWindow *dstwin = getWindowForCoord(X, Y); + if( dstwin ) + { + // 1. Give focus and bring to front + // 2. Send event + // TODO: Pass event on to window + } } void CCompositor::KeyState(unsigned int KeyboardID, uint32_t KeySym, bool Press, uint32_t Codepoint) @@ -123,5 +133,38 @@ void CCompositor::KeyState(unsigned int KeyboardID, uint32_t KeySym, bool Press, _SysDebug("KeyState(%i, 0x%x, %b, 0x%x)", KeyboardID, KeySym, Press, Codepoint); } +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(), + }; + +} +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]; + auto client = ::AxWin::IPC::GetClientByID(id.Client); + if( client == nullptr ) + return nullptr; + return client->GetWindow(id.Window); +} + } // namespace AxWin diff --git a/Usermode/Applications/axwin4_src/Server/include/CClient.hpp b/Usermode/Applications/axwin4_src/Server/include/CClient.hpp index a42d9fac..24e7daba 100644 --- a/Usermode/Applications/axwin4_src/Server/include/CClient.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/CClient.hpp @@ -11,6 +11,7 @@ #include "CWindow.hpp" #include "serialisation.hpp" #include +#include namespace AxWin { @@ -18,6 +19,7 @@ class IIPCChannel; class CClient { + unsigned int m_id; IIPCChannel& m_channel; ::std::map m_windows; @@ -26,6 +28,9 @@ public: CClient(::AxWin::IIPCChannel& channel); virtual ~CClient(); + void set_id(unsigned int id) { assert(m_id == 0); m_id = id; } + unsigned int id() const { return m_id; } + CWindow* GetWindow(int ID); void SetWindow(int ID, CWindow* window); diff --git a/Usermode/Applications/axwin4_src/Server/include/CCompositor.hpp b/Usermode/Applications/axwin4_src/Server/include/CCompositor.hpp index 7c1272a6..ec40d369 100644 --- a/Usermode/Applications/axwin4_src/Server/include/CCompositor.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/CCompositor.hpp @@ -19,11 +19,6 @@ namespace AxWin { class CClient; class CVideo; -struct TWindowID -{ - uint16_t Client; - uint16_t Window; -}; enum eMouseButton { @@ -34,13 +29,29 @@ enum eMouseButton MOUSEBTN_BTN5, }; +class CWindowIDBuffer +{ + struct TWindowID + { + uint16_t Client; + uint16_t Window; + }; + unsigned int m_w; + ::std::vector m_buf; +public: + CWindowIDBuffer(unsigned int W, unsigned int H); + + void set(unsigned int X, unsigned int Y, unsigned int W, unsigned int H, CWindow* win); + CWindow* get(unsigned int X, unsigned int Y); +}; + class CCompositor { CVideo& m_video; ::std::list m_damageRects; ::std::list m_windows; - ::std::vector m_windowIDBuffer; // One 32-bit value per pixel + CWindowIDBuffer m_windowIDBuffer; // One 32-bit value per pixel public: CCompositor(CVideo& video); @@ -60,6 +71,8 @@ public: void MouseButton(unsigned int Cursor, unsigned int X, unsigned int Y, eMouseButton Button, bool Press); void KeyState(unsigned int KeyboardID, uint32_t KeySym, bool Press, uint32_t Codepoint); +public: + CWindow* getWindowForCoord(unsigned int X, unsigned int Y); }; diff --git a/Usermode/Applications/axwin4_src/Server/include/CWindow.hpp b/Usermode/Applications/axwin4_src/Server/include/CWindow.hpp index 3c763de2..5161f035 100644 --- a/Usermode/Applications/axwin4_src/Server/include/CWindow.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/CWindow.hpp @@ -23,9 +23,12 @@ class CRegion; class CWindow { public: - CWindow(CCompositor& compositor, CClient& client, const ::std::string &name); + CWindow(CCompositor& compositor, CClient& client, const ::std::string &name, unsigned int id); ~CWindow(); + const CClient& client() const { return m_client; } + const unsigned int id() const { return m_id; } + void Repaint(const CRect& rect); void Show(bool bShow); @@ -46,6 +49,7 @@ public: private: CCompositor& m_compositor; CClient& m_client; + unsigned int m_id; const ::std::string m_name; ::std::vector m_regions; }; diff --git a/Usermode/Applications/axwin4_src/Server/include/ipc.hpp b/Usermode/Applications/axwin4_src/Server/include/ipc.hpp index 729f1535..5706a85b 100644 --- a/Usermode/Applications/axwin4_src/Server/include/ipc.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/ipc.hpp @@ -28,6 +28,7 @@ extern void Initialise(const CConfigIPC& config, CCompositor& compositor); extern int FillSelect(::fd_set& rfds); extern void HandleSelect(const ::fd_set& rfds); extern void RegisterClient(CClient& client); +extern CClient* GetClientByID(uint16_t id); extern void DeregisterClient(CClient& client); extern void SendMessage_NotifyDims(CClient& client, unsigned int NewW, unsigned int NewH); diff --git a/Usermode/Applications/axwin4_src/Server/include/video.hpp b/Usermode/Applications/axwin4_src/Server/include/video.hpp index 9ca7b42f..3738099b 100644 --- a/Usermode/Applications/axwin4_src/Server/include/video.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/video.hpp @@ -23,6 +23,8 @@ public: CVideo(const CConfigVideo& config); void GetDims(unsigned int& w, unsigned int& h); + unsigned int width() const { return m_width; } + unsigned int height() const { return m_height; } void BlitLine(const uint32_t* src, unsigned int dst_y, unsigned int dst_x, unsigned int width); void Flush(); diff --git a/Usermode/Applications/axwin4_src/Server/ipc.cpp b/Usermode/Applications/axwin4_src/Server/ipc.cpp index 58cda2b8..c5072853 100644 --- a/Usermode/Applications/axwin4_src/Server/ipc.cpp +++ b/Usermode/Applications/axwin4_src/Server/ipc.cpp @@ -25,7 +25,8 @@ namespace IPC { CCompositor* gpCompositor; ::std::list glChannels; -//::std::map glClients; +::std::map glClients; +uint16_t giNextClient = 1; void Initialise(const CConfigIPC& config, CCompositor& compositor) { @@ -65,13 +66,30 @@ void HandleSelect(const fd_set& rfds) void RegisterClient(CClient& client) { // allocate a client ID, and save - //client.m_id = 123; - //glClients[client.m_id] = &client; + for( int i = 0; i < 100; i ++ ) + { + uint16_t id = giNextClient++; + if(giNextClient == 0) giNextClient = 1; + auto r = glClients.insert( ::std::pair(id, &client) ); + if( r.second == true ) + { + client.set_id(id); + return; + } + } + // Wut? 100 attempts and fail! + assert(!"Todo - Better way of handling client ID reuse"); +} + +CClient* GetClientByID(uint16_t id) +{ + auto it = glClients.find(id); + return (it == glClients.end() ? nullptr : it->second); } void DeregisterClient(CClient& client) { - //glClients.erase( client.m_id ); + glClients.erase( client.id() ); } @@ -163,7 +181,7 @@ void HandleMessage_CreateWindow(CClient& client, CDeserialiser& message) ::std::string name = message.ReadString(); ::_SysDebug("_CreateWindow: (%i, '%s')", new_id, name.c_str()); - client.SetWindow( new_id, gpCompositor->CreateWindow(client, name) ); + client.SetWindow( new_id, new CWindow(*gpCompositor, client, name, new_id) ); } void HandleMessage_DestroyWindow(CClient& client, CDeserialiser& message) diff --git a/Usermode/Libraries/libaxwin4.so_src/wm.cpp b/Usermode/Libraries/libaxwin4.so_src/wm.cpp index 3672078f..cae79c71 100644 --- a/Usermode/Libraries/libaxwin4.so_src/wm.cpp +++ b/Usermode/Libraries/libaxwin4.so_src/wm.cpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace AxWin { @@ -22,7 +23,7 @@ extern "C" tAxWin4_Window *AxWin4_CreateWindow(const char *Name) { // Allocate a window ID ::std::lock_guard lock(glWindowList); - int id = ::std::find(gWindowList.begin(), gWindowList.end(), nullptr) - gWindowList.end(); + int id = ::std::find(gWindowList.begin(), gWindowList.end(), nullptr) - gWindowList.begin(); if( id >= MAX_WINDOW_ID ) { throw ::std::runtime_error("AxWin4_CreateWindow - Out of IDs (TODO: Better exception)"); } @@ -30,6 +31,7 @@ extern "C" tAxWin4_Window *AxWin4_CreateWindow(const char *Name) { gWindowList.push_back(nullptr); } + assert(gWindowList[id] == nullptr); // Create window structure locally tAxWin4_Window *ret = new tAxWin4_Window(); -- 2.20.1