namespace AxWin {
CClient::CClient(::AxWin::IIPCChannel& channel):
- m_channel(channel)
+ m_channel(channel),
+ m_id(0)
{
}
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)
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()
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)
{
BIN := AxWinServer
LIBS += -lc++
-CXXFLAGS += -O3
+#CXXFLAGS += -O3
USE_CXX_LINK = 1
include ../../Makefile.tpl
*/
#include <video.hpp>
#include <CCompositor.hpp>
+#include <CClient.hpp>
+#include <ipc.hpp>
#include <cassert>
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);
_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);
}
}
{
_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)
_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
#include "CWindow.hpp"
#include "serialisation.hpp"
#include <map>
+#include <cassert>
namespace AxWin {
class CClient
{
+ unsigned int m_id;
IIPCChannel& m_channel;
::std::map<unsigned int,CWindow*> m_windows;
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);
class CClient;
class CVideo;
-struct TWindowID
-{
- uint16_t Client;
- uint16_t Window;
-};
enum eMouseButton
{
MOUSEBTN_BTN5,
};
+class CWindowIDBuffer
+{
+ struct TWindowID
+ {
+ uint16_t Client;
+ uint16_t Window;
+ };
+ unsigned int m_w;
+ ::std::vector<TWindowID> 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<CRect> m_damageRects;
::std::list<CWindow*> m_windows;
- ::std::vector<TWindowID> m_windowIDBuffer; // One 32-bit value per pixel
+ CWindowIDBuffer m_windowIDBuffer; // One 32-bit value per pixel
public:
CCompositor(CVideo& video);
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);
};
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);
private:
CCompositor& m_compositor;
CClient& m_client;
+ unsigned int m_id;
const ::std::string m_name;
::std::vector<CRegion*> m_regions;
};
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);
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();
CCompositor* gpCompositor;
::std::list<IIPCChannel*> glChannels;
-//::std::map<uint16_t,CClient*> glClients;
+::std::map<uint16_t,CClient*> glClients;
+uint16_t giNextClient = 1;
void Initialise(const CConfigIPC& config, CCompositor& compositor)
{
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<uint16_t,CClient*>(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() );
}
::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)
#include <vector>
#include <algorithm>
#include <mutex>
+#include <cassert>
namespace AxWin {
{
// Allocate a window ID
::std::lock_guard<std::mutex> 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)");
}
{
gWindowList.push_back(nullptr);
}
+ assert(gWindowList[id] == nullptr);
// Create window structure locally
tAxWin4_Window *ret = new tAxWin4_Window();